Hay una gran cantidad de formas de hacer esto. Esto requerirá el uso de un sombreador y supongo que ya está haciendo iluminación por píxel. Las siguientes son algunas sugerencias, sin embargo, encontrar la técnica adecuada para usted podría requerir mucha más investigación.
Rápido y sucio
Puede especificar cuadros delimitadores que definan áreas interiores. Si la luz está fuera de las cajas, pero la geometría (que no está en la sombra) está dentro de la caja, entonces la luz debe haber sido afectada al pasar a través de una ventana (esto también es cierto si la geometría está fuera de la caja y la luz está dentro). El único problema aquí es cómo pasar la información del cuadro al sombreador y cómo indicar el efecto sobre la luz.
Otra opción es especificar ventanas como objetos que se encuentran en planos. Primero pruebe para ver si la geometría y la luz están en lados opuestos del plano y luego si el camino entre ellas intersecta el plano en un punto dentro de los límites de la ventana. Esto sería más preciso que el primer método y sería más fácil tener ventanas en los mismos interiores con diferentes colores de vidrio.
Siga siendo más detallado con la representación geométrica de las ventanas y obtendrá resultados más precisos, pero el cálculo también será más pesado.
Estas técnicas funcionarían razonablemente bien para un tirador de corredor, pero no tan bien para un mundo dinámico o abierto, ya que probablemente se necesitarían muchos ajustes para que se vea bien sin demasiados artefactos. Además, estas técnicas podrían volverse un poco intensas rápidamente, por lo que se recomienda pasar a una tubería de sombreado diferido.
Mapas de sombras
Otra opción es hacer algo similar al mapeo de sombras.
En el mapeo de sombras, genera una imagen de mapa de bits del mundo afectado por una luz. Cada píxel, aunque sigue siendo un color, es en realidad la distancia de la pieza de geometría no transparente más cercana (utiliza los cuatro bytes para 1 flotante en lugar de 4 colores). Si calcula la distancia desde la luz a una pieza de geometría y está más allá del valor correspondiente en el mapa de sombras, entonces su pieza de geometría está en sombra (generalmente usa el rayo entre la geometría y la luz para indexar el mapa).
Si aplica esta idea a su problema, entonces lo que haría sería almacenar un mapa de la distancia desde la luz de la pieza de geometría transparente más cercana y luego también hacer un segundo mapa del color de la luz después de pasar por esa geometría ( simplemente el color de la geometría si la luz es blanca).
Si su pieza de geometría está más lejos que la distancia en este mapa, use el color del mapa, si no es así, use el color claro original.
La función para calcular el color de cada píxel en el mapa debería ser aproximadamente; lightColor - invertedWindowColor. Entonces, para una luz blanca pura y una ventana roja pura que no absorbe nada del espectro rojo que obtenemos; (255,255,255) - (0,255,255) = (255,0,0). Entonces, el color de la luz en el otro lado es rojo puro. Para un objeto transparente más complejo, como una vidriera, es posible que desee realizar una búsqueda de textura para obtener el color del material.
Si está buscando algo similar, consulte Mapas de sombras reflectantes .
Esta técnica ofrece una gran cantidad de fidelidad y posiblemente sería la mejor si desea utilizar una geometría transparente compleja como vidrieras.
Intentando una solución general
Recientemente se ha vuelto popular codificar información de iluminación en una representación de vóxel (no son solo para geometría). El último motor crytek utiliza este tipo de estrategia para iluminación avanzada ( volúmenes de propagación de luz ).
Aquí está la idea general:
- Cree un mapa de cubos espaciados uniformemente que abarque su escena (considere usar curvas de orden z ).
- Encuentre una forma de almacenar información de iluminación incidente para cada vóxel (aquí son útiles las representaciones armónicas esféricas).
- Encuentra el vóxel que contiene una luz y representa esa luz en el vóxel.
- Propague la luz hacia afuera a través de los vóxeles adyacentes (algo así como el agua de Minecraft)
- Calcule cómo la geometría en cada vóxel afectará la luz que lo atraviesa (absorber, reflejar, transmitir)
- repite hasta que la luz se haya desvanecido
Hay muchas formas de construir esta información de vóxel, pero la lista anterior da una idea general. Por ejemplo; puede comenzar generando mapas / volúmenes de sombra y luego proyectando esa información en el mapa de voxel para que pueda hacer rápidamente el mapa de iluminación directa. Luego comienza la propagación desde los vóxeles a lo largo del borde del área afectada. Tenga en cuenta que, en este caso, querrá ignorar si la geometría es transparente o no al generar el mapa / volumen de sombra.
En el paso final de un renderizador diferido, al calcular la iluminación de un punto de geometría, simplemente usa la posición de geometría para indexar tu mapa de vóxel para descubrir cómo es la iluminación incidente en ese punto en el espacio. Luego puede construir un mapa de pantalla del lado de la CPU de iluminación incidente, o posiblemente hacer esto con cuda.