Usando múltiples sombreadores

53

Actualmente estoy estudiando sombreadores de opengl pero no puedo entender algo: cómo aplicar diferentes sombreadores a los objetos, por ejemplo, una tetera renderizada usando toon shader y otra en la misma escena usando una superficie muy reflectante y otras distorsionadas una función de ruido, como en este video

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

Otro es aplicar un sombreador de flores en una escena y un sombreador de desenfoque de movimiento después. ¿Cómo lograr esos efectos cuando solo puedes tener un sombreador de vértices y un sombreador de fragmentos? ¿Hay algún truco como usar más de un programa de sombreador?

ibrabeicker
fuente
Respecto a las buenas respuestas de Nathan y David, esta es la razón por la que ves el término pase de pase o pase de sombreador ; Se requieren múltiples pases para componer la imagen / fotograma final. Una de las razones por las cuales el procesamiento de GPU se ha vuelto tan paralelo y tan rápido es la necesidad de múltiples pases por cuadro. Vuelva a los renderizadores de software Quake II o Half Life para recordar cuánto le agregan los pases de Love Shader a toda la experiencia de gráficos en 3D.
Ingeniero

Respuestas:

59

La respuesta simple es cambiarlos entre cada llamada de sorteo. Establece un sombreador, dibuja una tetera, configura otro sombreador, dibuja otra tetera.

Para cosas más complejas donde necesita aplicar múltiples sombreadores a un solo objeto, como desenfoque, brillo, etc. Básicamente tienes todo renderizado a textura (s). Luego renderizas un quad sobre toda tu pantalla con esa textura aplicada mientras usas otro sombreador.

Por ejemplo, si desea renderizar un efecto de brillo, primero debe renderizar su escena no brillante normal, luego renderizar solo la silueta de color de las cosas que desea que brillen en una textura y luego cambiar a un sombreador borroso y renderizar su quad con esa textura unida sobre tu escena no brillante.

Existe otra técnica llamada sombreado diferido en la que renderiza la escena sin iluminación y la aplica más tarde en el espacio de la pantalla. El objetivo principal es reducir el gasto de iluminación por píxel.

Normalmente representa un búfer de color que se coloca en la pantalla. Con el sombreado diferido, en cambio, renderiza un búfer de color, así como un búfer normal y de profundidad en una pasada de sombreador (puede almacenar los vectores normales y la profundidad en una textura como con el mapeo normal y de altura).

Esto significa que, para cada píxel, conoce la posición de la pieza de geometría no transparente más cercana (profundidad o distancia del ojo), el color y la normalidad. Debido a esto, puede aplicar iluminación a cada píxel en la pantalla en lugar de a cada píxel visible de cada objeto que renderice. Recuerde que algún objeto se dibujará sobre la parte superior de otros objetos si la escena no se representa perfectamente en orden inverso.

Para las sombras, en realidad solo representa el búfer de profundidad desde el punto de vista de su luz y luego usa esa información de profundidad para determinar dónde incide la luz. Eso se llama mapeo de sombras (también hay otro enfoque llamado volúmenes de sombras que resuelve una silueta de la geometría y la extruye, pero aún usará sombreadores).

Con OpenGL más moderno (3.0+), usa un objeto Framebuffer con objetos Renderbuffers adjuntos. Dado que los renderbuffers se pueden tratar como una textura. Puede hacer cosas como hacer que 1 sombreador renderice en múltiples renderbuffers diferentes (para que no tenga que renderizar su textura, luego sus normales y luego los componentes de brillo), pero la práctica subyacente sigue siendo la misma.

También es deseable minimizar la cantidad de interruptores de sombreado tanto como sea posible para ahorrar en gastos generales. Por lo tanto, algunos motores agruparán todo con el mismo material para que se pueda dibujar a la vez.

David C. Bishop
fuente
16

Simplemente vincula un sombreador, renderiza todos los objetos usando ese sombreador, luego vincula el siguiente sombreador, renderiza los objetos usando ese, etc.

Puede tener tantos objetos de sombreador (sombreadores cargados en la memoria y compilados) como desee; solo uno puede estar vinculado (activo) a la vez.

Nathan Reed
fuente
55
En términos de implementación, ¿en cada cuadro uso glUseProgram (1) y glUseProgram (2) para cambiar los sombreadores? ¿Qué tan costoso es el rendimiento?
ibrabeicker
44
Es un costo no trivial (aunque menos en las GPU recientes que en las anteriores). Es por eso que la mayoría de las personas clasifican sus objetos por material, renderizando todos los objetos con el mismo material juntos. Pero ciertamente puede permitirse el lujo de cambiar los programas decenas a cientos de veces por cuadro, si no más.
Nathan Reed
9

Usar más de un sombreador en una escena es bastante simple; cambie el sombreador, establezca los valores para él y luego renderice el objeto.

Sin embargo, tenga cuidado, el cambio de sombreadores puede ser costoso, por lo que el cambio de sombreadores debe mantenerse al mínimo. Hay algunas maneras de reducir este impacto mientras obtienes todos los efectos que deseas.

El primer método, y generalmente el más deseable, es agregar la funcionalidad para todas sus técnicas de sombreado a un solo sombreador y usar las condiciones que establezca para representar cada objeto de manera diferente con el mismo sombreador. No sé acerca de los sombreadores OpenGL y GLSL, pero con los sombreadores HLSL y DirectX, estos se pueden agrupar como una "técnica" y puede configurar la técnica en lugar de cambiar el sombreador. Esto le permite tener varios sombreadores de píxeles y vértices diferentes en el mismo archivo.

La segunda forma de reducir el impacto en el rendimiento es configurar el sombreador, renderizar cada objeto que usa ese sombreador y luego repetir. En otras palabras, agrupando su renderizado.

Si desea aplicar dos efectos diferentes al mismo objeto (es decir, aplicar un sombreador de toons y luego algo de iluminación), puede hacerlo de dos maneras diferentes. El primero es escribir un sombreador que aplique múltiples efectos en la misma función. La segunda forma es renderizar el modelo una vez con cada sombreador y combinar los resultados configurando diferentes opciones de fusión. Sin embargo, esto es mucho más trabajo y no se puede lograr en todas las circunstancias. Por lo tanto, la mejor opción es combinar todos sus efectos en un solo sombreador.

OriginalDaemon
fuente
7

Otra forma de hacerlo que he descubierto es a través de algo llamado subrutinas glsl, donde cada tipo de sombreador se define en una función, y en la aplicación OpenGL, podemos definir la subrutina actual, dibujar el vértice de un búfer, cambiar la subrutina y renderizando otro buffer

ibrabeicker
fuente
44
Esto requiere hardware compatible con GL 4.x, que es hardware de clase DX11.
Nicol Bolas