Sombreado diferido: ¿cómo combinar varias luces?

9

Estoy comenzando con GLSL e implementé un sombreado diferido simple que genera G-buffer con posiciones, normales y albedo.

También he escrito un simple sombreador de luz puntual.

Ahora dibujo una esfera para el punto de luz y la salida entra en un búfer de iluminación.

El problema es, ¿cómo combino los resultados del búfer de iluminación al dibujar varias luces?

Por ejemplo, cuando estoy dibujando la segunda luz en el buffer de luz usando el sombreador de luz puntual, ¿cómo agrego la primera luz a la segunda luz en el buffer de iluminación? Quiero decir, ¿no puedes leer y escribir en el mismo búfer de salida?

JBeurer
fuente

Respuestas:

12

Mezcla aditiva, es decir, glBlendFunc (GL_ONE, GL_ONE) y glEnable (GL_BLEND).

Nathan Reed
fuente
¿Las pruebas de profundidad tienen que ser deshabilitadas para esto?
woojoo666
1
@ woojoo666 No. De hecho, debe habilitarse con la prueba de profundidad establecida en menos igual, de modo que las superficies que coincidan con precisión con el pase anterior pasarán. Si la prueba de profundidad está desactivada, entonces las superficies acumularán incorrectamente la luz de lo que esté detrás de ellas. :)
Nathan Reed
hmm, parece que eso es exactamente lo que está sucediendo. al activar la fusión, las caras frontales se mezclan con las caras posteriores, aunque mantuve las pruebas de profundidad habilitadas. ¿Necesito hacer algo con la máscara de profundidad también?
woojoo666
hizo un poco más de pruebas, parece que el orden de dibujo importa (dibujar de adelante hacia atrás hace que las pruebas de profundidad funcionen correctamente y la mezcla solo ocurre si las caras son equiplanar, de atrás hacia adelante hace que todo se mezcle). ¿Hay alguna manera de hacer esto sin ordenar todo?
woojoo666
2
@ woojoo666 Ajá, parece que lo resolviste por tu cuenta. Sí, debe establecer la profundidad en una pasada opaca antes de poder utilizar cualquier tipo de mezcla. Puede ser un z-prepass con escrituras en color deshabilitadas, u otra forma común es hacer luz ambiental / direccional en una primera pasada sin mezcla, luego agregar luces de punto / foco en pasadas posteriores con mezcla.
Nathan Reed
2

Para mi renderizador diferido, agrego todas las luces en un objetivo de renderizado de luz usando la información del g-buffer y luego muestro ese objetivo de render para la intensidad de la luz mientras creo mi imagen final de backbuffer.

Básicamente, ejecuto toda la geometría de mi juego a través de mi pase de geometría para construir los g-buffers. Desde allí, alimento los g-buffers a mi sombreador de paso de luz. Cada luz se ejecuta a través del pase utilizando un quad de pantalla completa. De esta manera, mi sombreador de píxeles puede calcular la intensidad de la luz para todas las superficies visibles desde el búfer g y luego agregarlas al objetivo de representación de luz. Simplemente agregue la intensidad de la luz para cada luz al búfer de luz, pero asegúrese de ajustar la intensidad de 0 a 1.

Todo lo que necesitaría hacer para manejar diferentes tipos de luces (punto, foco, paralelo) es hacer que la luz pase más robusta posiblemente utilizando un búfer constante para designar qué procedimientos de iluminación ejecutar.

KlashnikovKid
fuente
Sí, y la pregunta es: ¿cómo se agrega al objetivo de renderizado de luz? ¿Usando la mezcla alfa como sugirió Nathan Reed? Porque, que yo sepa, no puedes leer y escribir en el mismo búfer de salida (que es el búfer de luz en este caso).
JBeurer
Vaya, si. Dejo que la fusión de salida maneje eso con una mezcla aditiva. Al muestrear la imagen final es cuando desea fijar el valor a uno que funcione para mí como la intensidad de luz máxima posible que puede recibir una superficie. Desde allí, puede escalar sus luces según sea necesario.
KlashnikovKid
¿Cómo maneja los casos en que una luz está detrás de una pared y no debe iluminar cosas del otro lado de la pared?
jjxtra
@PsychoDad Ese es el dominio de las sombras, que es ... un tema más complicado. :)
Nathan Reed
0

Es probable que haya una respuesta mejor que esta, pero sé que si en su sombreador repite el código necesario para hacer una segunda luz, puede procesar dos luces en un solo objeto en lugar de uno. Es necesario agrupar una gran cantidad de código para la segunda luz y parece un poco redundante, pero sé que funciona. Sin embargo, creo que, como es de esperar que alguien le señale, podría haber una solución más elegante.

CodeNeko
fuente
No, eso no funciona de esa manera. Dibujo una esfera para cada punto de luz. A menos que el segundo punto de luz se encuentre dentro de la esfera de influencia de la primera luz, la segunda luz simplemente no se dibujará. Su método funcionaría si dibujo un quad de pantalla completa para todos los puntos de luz, sin embargo, ese no es el enfoque correcto porque los quads de pantalla completa se utilizan para la iluminación global. Digamos que tengo 16 puntos pequeños de luz, que me obligarían a pasar por ellos por cada píxel, incluso si el píxel no está iluminado por él. Y generalmente diría que cada píxel está iluminado por una o dos luces. ¿Y si tengo 100 luces? NO
JBeurer
La razón principal por la que dije esto es que si está usando solo dos o unas pocas luces, puede ayudar. Especialmente si está desgarrando muchos objetos, usar una combinación significa que necesita volver a dibujar la escena para cada luz, por lo que si tiene muchas formas, digamos un millón, o diez millones o mil millones, cada sorteo cuesta mucho más. . Hacerlo en el sombreador causa problemas si quieres muchas luces, pero la mezcla causa problemas si quieres muchas formas. Si tiene muchos de ambos, necesita encontrar un término medio, pero generalmente tiene algunas luces y muchos objetos en los juegos.
CodeNeko
No, el sombreado diferido no funciona de esa manera. Tengo que dibujar la escena solo una vez y almacenar información relevante en G-Buffer. Luego, una esfera de influencia para cada luz y mezclarlo con el búfer de luz. Y finalmente, combinando el buffer de luz con el buffer de color, obtengo el buffer de color sombreado final. La cantidad de cálculos de iluminación no depende de la complejidad de la escena. Esa es la principal ventaja del sombreado diferido en primer lugar.
JBeurer
Ah, eso tiene mucho más sentido y sería mucho mejor.
CodeNeko