Un esquema general:
Crea un mapa de profundidad de tu escena sin el escudo. Puede obtener esto de forma gratuita, ya que los objetos transparentes a menudo se representan en un pase posterior de todos modos. De lo contrario, puede crear el mapa de profundidad al representar la escena sin escudo en un RTT con un sombreador de profundidad.
Renderice su escena normalmente, pase el mapa de profundidad a su sombreador de escudo.
En el sombreador, calcule la diferencia en la profundidad de la escena desde la profundidad del fragmento de escudo y use esa diferencia para modificar el color del fragmento.
Manifestación
Escribí una demostración simple de WebGL de eso.
Linea por linea
Repasemos en detalle el código del sombreador de fragmentos:
float solidsDepth = texture2D(depthMap, gl_FragCoord.xy / dims).r;
Muestree el mapa de profundidad en cada fragmento. Recuerde dividir por las dimensiones de su ventana gráfica para convertir su fragmento del espacio de pantalla [0, ancho / alto] a coordenadas normalizadas [0.0, 1.0]. En este punto, si simplemente establece el color del fragmento en el píxel del mapa de profundidad muestreado, se vería así:
El mapa de profundidad es en escala de grises, por lo que puede obtener el valor de cualquier canal (que usé r
aquí).
float solidsDiff = 1.0 - smoothstep(
zNear,
zFar,
gl_FragCoord.z / gl_FragCoord.w
) - solidsDepth;
Luego puede usar esa muestra de profundidad para encontrar la diferencia entre la profundidad de la escena y la profundidad del fragmento de escudo. Recuerde normalizar su profundidad también, para tomarla de [zNear, zFar] (los planos cercano y lejano de su cámara) a [0.0, 1.0]. smoothstep
hace esto muy bien El 1.0 -
es invertir el valor tal que solidsDiff
sea 1.0 cuando la diferencia es máxima (zFar - zNear) y 0.0 como mínimo (0.0).
Tenga en cuenta que supuse que solidsDepth
ya estaba normalizado en el sombreador de profundidad que creó el mapa de profundidad.
float alpha = 0.3 + max(0.0, 1.0 - log(100.0 * (solidsDiff - 0.005) + 1.0));
Luego puede modificar el canal alfa de su escudo dependiendo de la diferencia de profundidad. Aquí comenzamos con un alfa mínimo de 0.3
, luego creamos un agradable aumento agudo en alfa a medida que nos acercamos a la 0.0
diferencia.
El - 0.005
desplazamiento solo agrega un margen blanco para hacer que la "intersección" sea más gruesa. ¡Intenta modificarlo!
gl_FragColor = vec4(vec3(1.0), alpha);
Y finalmente, aplique ese alfa a su color de fragmento.
Mejoras
Puede hacer un escudo curvo, agregar plasma para una apariencia de "escudo de energía" (demostración) o explorar efectos con solo las intersecciones que muestran (demostración) .
El cielo ¡ Tu tarjeta gráfica es el límite!