Utilizzo di più shader


53

Attualmente sto studiando shader opengl ma non riesco a capire qualcosa: come applicare diversi shader agli oggetti, ad esempio una teiera resa usando toon shader e un altro nella stessa scena usando una superficie molto riflettente e altri distorti da una funzione di rumore, come in questo video

http://www.youtube.com/watch?v=1ogg4ZfdBqU

Un altro sta applicando uno shader di fioritura in una scena e uno shader di motion blur in seguito. Come ottenere questi effetti quando puoi avere solo uno shader di vertice e uno shader di frammenti? C'è qualche trucco come usare più di un programma shader?


Le buone risposte di Re Nathan e David, ecco perché vedi il termine render pass o shader pass ; sono necessari più passaggi per comporre l'immagine / il fotogramma finale. Uno dei motivi per cui l'elaborazione della GPU è diventata così dannatamente parallela e quindi così veloce è la necessità di più passaggi per frame. Torna ai renderer del software Quake II o Half Life per ricordare a te stesso quanto i passaggi di shader d'amore si aggiungono all'intera esperienza grafica 3D.
Ingegnere

Risposte:


59

La semplice risposta è cambiarli tra una chiamata e l'altra. Imposta uno shader, disegna una teiera, imposta un altro shader, disegna un'altra teiera.

Per cose più complesse in cui è necessario applicare più shader a un solo oggetto come sfocatura, luminosità e così via. Fondamentalmente hai tutto il rendering in trama (s). Quindi esegui il rendering di un quad su tutto lo schermo con quella trama applicata mentre usi un altro shader.

Ad esempio, se vuoi renderizzare un effetto bagliore, devi prima renderizzare la tua normale scena non luminosa, quindi renderizzare solo la sagoma colorata delle cose che vuoi illuminare su una trama, quindi passa a uno shader di sfocatura e rendi il tuo quadruplo con quella trama attaccata sulla scena non luminosa.

Esiste un'altra tecnica chiamata ombreggiatura differita in cui si esegue il rendering della scena senza illuminazione e la si applica successivamente nello spazio dello schermo. L'obiettivo principale è ridurre il costo dell'illuminazione per pixel.

Normalmente si esegue il rendering di un buffer di colore che viene messo sullo schermo. Con l'ombreggiatura differita si esegue invece il rendering di un buffer di colore e di un buffer normale e di profondità in un passaggio shader (è possibile memorizzare i vettori normali e la profondità in una trama come con la mappatura normale e di altezza).

Ciò significa che, per ogni pixel, conosci la posizione del pezzo più vicino di geometria non trasparente (profondità o distanza dall'occhio) il colore e il normale. Per questo motivo puoi applicare l'illuminazione a ciascun pixel sullo schermo anziché a ciascun pixel visibile di ogni oggetto che visualizzi. Ricorda che alcuni oggetti verranno disegnati sopra gli altri oggetti se la scena non è resa perfettamente in ordine da davanti a dietro.

Per le ombre si esegue il rendering solo del buffer di profondità dal punto di vista della propria luce, quindi si utilizzano le informazioni di profondità per capire dove colpisce la luce. Si chiama shadow mapping (esiste anche un altro approccio chiamato volume shadow che elabora una sagoma della geometria e la espelle, ma continuerai a utilizzare gli shader).

Con OpenGL più moderno (3.0+) usi un oggetto Framebuffer con gli oggetti Renderbuffers collegati. Poiché i renderbuffer possono essere trattati come una trama. Potresti fare cose come avere un rendering shader su più renderbuffer diversi (quindi non devi rendere la tua trama quindi le tue normali quindi i componenti bagliore) ma la pratica sottostante è sempre la stessa.

Inoltre, è consigliabile ridurre al minimo il numero di interruttori shader per risparmiare sulle spese generali. Quindi alcuni motori raggrupperanno tutto con lo stesso materiale insieme in modo che possano essere disegnati tutti in una volta.


16

Devi solo associare uno shader, renderizzare tutti gli oggetti usando quello shader, quindi associare lo shader successivo, renderizzare gli oggetti usando quello shader, ecc.

Puoi avere tutti gli oggetti shader (shader caricati in memoria e compilati) che desideri; solo uno può essere associato (attivo) alla volta.


5
In termini di implementazione, in ogni frame utilizzo glUseProgram (1) e glUseProgram (2) per cambiare shader? Quanto è costoso per le prestazioni?
ibrabeicker,

4
È un costo non banale (anche se meno sulle GPU recenti rispetto a quelle precedenti). Ecco perché la maggior parte delle persone ordina i propri oggetti in base al materiale, trasformando tutti gli oggetti con lo stesso materiale insieme. Ma puoi sicuramente permetterti di cambiare i programmi da decine a centinaia di volte per frame, se non di più.
Nathan Reed, l'

9

Usare più di uno shader in una scena è abbastanza semplice; cambia lo shader, imposta i valori per esso, quindi esegui il rendering dell'oggetto.

Attenzione, tuttavia, la commutazione degli shader può essere costosa, quindi la commutazione degli shader dovrebbe essere ridotta al minimo. Esistono alcuni modi per ridurre questo impatto e ottenere tutti gli effetti desiderati.

Il primo metodo, e di solito il più desiderabile, è quello di aggiungere la funzionalità di tutte le tecniche dello shader a un solo shader e utilizzare le condizioni impostate per eseguire il rendering di ogni oggetto in modo diverso con lo stesso shader. Non conosco gli shader OpenGL e GLSL ma con gli shader HLSL e DirectX questi possono essere raggruppati come "tecnica" e puoi impostare la tecnica invece di cambiare lo shader. Ciò consente di avere effettivamente diversi shader di pixel e vertici nello stesso file.

Il secondo modo per ridurre l'impatto sulle prestazioni è impostare lo shader, eseguire il rendering di ogni oggetto che lo utilizza, quindi ripetere. In altre parole, raggruppare il rendering.

Se desideri applicare due effetti diversi allo stesso oggetto (ad esempio, applica uno shaon toon quindi un po 'di illuminazione) puoi farlo in due modi diversi. Il primo è scrivere uno shader che applica più effetti nella stessa funzione. Il secondo modo è rendere il modello una volta con ogni shader e fondere i risultati impostando diverse opzioni di fusione. Tuttavia, questo è molto più lavoro e non realizzabile in tutte le circostanze. Pertanto l'opzione migliore è combinare tutti i tuoi effetti in un unico shader.


7

Un altro modo di fare ciò che ho scoperto è attraverso qualcosa chiamato subroutine glsl, in cui ogni tipo di shader è definito in una funzione, e nell'applicazione OpenGL, possiamo definire la subroutine corrente, disegnare il vertice di un buffer, cambiare la subroutine e rendering di un altro buffer


4
Ciò richiede hardware compatibile con GL 4.x, che è un hardware di classe DX11.
Nicol Bolas,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.