El mapeo de sombras o proyección de sombras es un proceso mediante el cual se agregan sombras a gráficos de computadora en 3D . Este concepto fue introducido por Lance Williams en 1978, en un artículo titulado "Proyección de sombras curvas sobre superficies curvas". [1] Desde entonces, se ha utilizado tanto en escenas pre-renderizadas como en tiempo real en muchos juegos de consola y PC.
Las sombras se crean probando si un píxel es visible desde la fuente de luz, comparando el píxel con un búfer z [2] o una imagen de profundidad de la vista de la fuente de luz, almacenada en forma de textura .
Si mirases desde una fuente de luz, todos los objetos que ves aparecerían iluminados. Sin embargo, todo lo que estuviera detrás de esos objetos estaría en sombra. Este es el principio básico que se utiliza para crear un mapa de sombras. Se renderiza la vista de la luz, almacenando la profundidad de cada superficie que ve (el mapa de sombras). A continuación, se renderiza la escena normal comparando la profundidad de cada punto dibujado (como si lo estuviera viendo la luz, en lugar del ojo) con este mapa de profundidad.
Esta técnica es menos precisa que los volúmenes de sombra , pero el mapa de sombras puede ser una alternativa más rápida según el tiempo de relleno que se requiera para cada técnica en una aplicación particular y, por lo tanto, puede ser más adecuado para aplicaciones en tiempo real. Además, los mapas de sombras no requieren el uso de un búfer de esténcil adicional y se pueden modificar para producir sombras con un borde suave. Sin embargo, a diferencia de los volúmenes de sombras, la precisión de un mapa de sombras está limitada por su resolución.
La representación de una escena sombreada implica dos pasos de dibujo principales. El primero produce el mapa de sombras en sí y el segundo lo aplica a la escena. Según la implementación (y la cantidad de luces), esto puede requerir dos o más pasos de dibujo.
El primer paso es representar la escena desde el punto de vista de la luz. Para una fuente de luz puntual, la vista debe ser una proyección en perspectiva tan amplia como el ángulo de efecto deseado (será una especie de foco cuadrado). Para la luz direccional (por ejemplo, la del Sol ), se debe utilizar una proyección ortográfica .
A partir de esta representación, se extrae y se guarda el búfer de profundidad. Dado que solo es relevante la información de profundidad, es habitual evitar la actualización de los búferes de color y desactivar todos los cálculos de iluminación y textura para esta representación, a fin de ahorrar tiempo de dibujo. Este mapa de profundidad suele almacenarse como una textura en la memoria gráfica.
Este mapa de profundidad debe actualizarse cada vez que se produzcan cambios en la luz o en los objetos de la escena, pero puede reutilizarse en otras situaciones, como aquellas en las que solo se mueve la cámara de visualización. (Si hay varias luces, se debe utilizar un mapa de profundidad independiente para cada una).
En muchas implementaciones, resulta práctico renderizar solo un subconjunto de los objetos de la escena en el mapa de sombras para ahorrar algo del tiempo que lleva volver a dibujar el mapa. Además, se puede aplicar un desplazamiento de profundidad que aleje los objetos de la luz a la renderización del mapa de sombras en un intento de resolver problemas de unión donde el valor del mapa de profundidad está cerca de la profundidad de una superficie que se está dibujando (es decir, la superficie que proyecta la sombra) en el siguiente paso. Como alternativa, a veces se utiliza descartar las caras frontales y solo renderizar la parte posterior de los objetos en el mapa de sombras para obtener un resultado similar.
El segundo paso es dibujar la escena desde el punto de vista habitual de la cámara , aplicando el mapa de sombras. Este proceso tiene tres componentes principales. El primer paso es encontrar las coordenadas del objeto tal como se ve desde la luz, ya que un objeto 3D solo utiliza coordenadas 2D con ejes X e Y para representar su forma geométrica en la pantalla, estas coordenadas de vértice coincidirán con los bordes correspondientes de las partes de sombra dentro del mapa de sombras (mapa de profundidad) en sí. El segundo paso es la prueba de profundidad que compara los valores z del objeto con los valores z del mapa de profundidad y, finalmente, una vez realizado, el objeto debe dibujarse en la sombra o en la luz.
Para probar un punto en el mapa de profundidad, su posición en las coordenadas de la escena debe transformarse en la posición equivalente tal como se ve con la luz. Esto se logra mediante una multiplicación de matrices . La ubicación del objeto en la pantalla se determina mediante la transformación de coordenadas habitual , pero se debe generar un segundo conjunto de coordenadas para ubicar el objeto en el espacio de luz.
La matriz utilizada para transformar las coordenadas del mundo en las coordenadas de visualización de la luz es la misma que la utilizada para renderizar el mapa de sombras en el primer paso (en OpenGL, este es el producto de las matrices de proyección y vista del modelo). Esto producirá un conjunto de coordenadas homogéneas que necesitan una división en perspectiva ( ver proyección 3D ) para convertirse en coordenadas de dispositivo normalizadas , en las que cada componente ( x , y o z ) cae entre −1 y 1 (si es visible desde la vista de la luz). Muchas implementaciones (como OpenGL y Direct3D ) requieren una multiplicación adicional de la matriz de escala y sesgo para mapear esos valores de −1 a 1 a 0 a 1, que son coordenadas más habituales para la búsqueda de mapas de profundidad (mapa de textura). Este escalado se puede realizar antes de la división en perspectiva y se incorpora fácilmente al cálculo de transformación anterior multiplicando esa matriz por lo siguiente:
Si se realiza con un sombreador u otra extensión de hardware gráfico, esta transformación generalmente se aplica en el nivel de vértice y el valor generado se interpola entre otros vértices y se pasa al nivel de fragmento.
Una vez que se encuentran las coordenadas del espacio de luz, los valores x e y generalmente corresponden a una ubicación en la textura del mapa de profundidad, y el valor z corresponde a su profundidad asociada, que ahora se puede probar contra el mapa de profundidad.
Si el valor z es mayor que el valor almacenado en el mapa de profundidad en la ubicación ( x , y ) adecuada, se considera que el objeto está detrás de un objeto que lo ocluye y debe marcarse como un error , para que el proceso de dibujo lo dibuje en sombra. De lo contrario, debe dibujarse iluminado.
Si la ubicación ( x , y ) queda fuera del mapa de profundidad, el programador debe decidir si la superficie debe estar iluminada o sombreada de manera predeterminada (generalmente iluminada).
En una implementación de sombreador , esta prueba se realizaría a nivel de fragmento. Además, se debe tener cuidado al seleccionar el tipo de almacenamiento de mapas de textura que utilizará el hardware: si no se puede realizar la interpolación, la sombra parecerá tener un borde afilado y dentado (un efecto que se puede reducir con una mayor resolución del mapa de sombras).
Es posible modificar la prueba del mapa de profundidad para producir sombras con un borde suave utilizando un rango de valores (basado en la proximidad al borde de la sombra) en lugar de simplemente aprobar o reprobar.
La técnica de mapeo de sombras también se puede modificar para dibujar una textura sobre las regiones iluminadas, simulando el efecto de un proyector . La imagen de arriba titulada "visualización del mapa de profundidad proyectado sobre la escena" es un ejemplo de dicho proceso.
El dibujo de la escena con sombras se puede realizar de varias maneras diferentes. Si se dispone de sombreadores programables , la prueba del mapa de profundidad se puede realizar mediante un sombreador de fragmentos que simplemente dibuja el objeto en sombra o iluminado según el resultado, dibujando la escena en una sola pasada (después de una pasada inicial anterior para generar el mapa de sombras).
Si los sombreadores no están disponibles, la prueba del mapa de profundidad generalmente debe implementarse mediante alguna extensión de hardware (como GL_ARB_shadow), que generalmente no permite elegir entre dos modelos de iluminación (iluminado y sombreado) y requiere más pasadas de renderizado:
Las imágenes de ejemplo de este artículo utilizaron la extensión OpenGL GL_ARB_shadow_ambient para realizar el proceso del mapa de sombras en dos pasadas.
Una de las principales desventajas del mapeo de sombras en tiempo real es que el tamaño y la profundidad del mapa de sombras determinan la calidad de las sombras finales. Esto suele ser visible como aliasing o fallas en la continuidad de las sombras. Una forma sencilla de superar esta limitación es aumentar el tamaño del mapa de sombras, pero debido a limitaciones de memoria, computacionales o de hardware, no siempre es posible. Se han desarrollado técnicas comúnmente utilizadas para el mapeo de sombras en tiempo real para sortear esta limitación. Estas incluyen mapas de sombras en cascada, [3] mapas de sombras trapezoidales, [4] mapas de sombras en perspectiva del espacio de luz, [5] o mapas de sombras con división paralela. [6]
También es notable que las sombras generadas, incluso si no tienen aliasing, tienen bordes duros, lo que no siempre es deseable. Para emular sombras suaves del mundo real , se han desarrollado varias soluciones, ya sea haciendo varias búsquedas en el mapa de sombras, generando geometría destinada a emular el borde suave o creando mapas de sombras de profundidad no estándar. Ejemplos notables de estos son el filtrado porcentual más cercano, [7] los suavizados [8] y los mapas de sombras de varianza. [9]
{{cite journal}}
: Requiere citar revista |journal=
( ayuda ){{cite journal}}
: Requiere citar revista |journal=
( ayuda ){{cite journal}}
: Requiere citar revista |journal=
( ayuda ){{cite journal}}
: Requiere citar revista |journal=
( ayuda ){{cite journal}}
: Requiere citar revista |journal=
( ayuda )Mantenimiento de CS1: varios nombres: lista de autores ( enlace )