Specular Highlight es el brillo que aparecen en los objetos cuando la luz incidente es reflejada directamente hacia nuestros ojos.
La propuesta, a bote pronto, es sencilla: Calcular el vector de "rebote" de la luz y hacer el dot product con el vector de la vista; mientras menor sea el ángulo entre estos 2 vectores, más brillo vamos a apreciar.
L es el vector de dirección de la luz (invertido), N es el vector normal del pixel (sacado del normal map), V es la vista (o cámara), H es el Half Vectror que yo no voy a usar porque es más preciso utilizar el vector de la luz reflejado (R).
Los cambios del shader creado en los post anteriores serían los siguientes:
//Calculamos el "rebote" de la luz según su dirección y hacia donde "mira el pixel"
float3 R = normalize(reflect(LightDirectionN, normal));
//realizamos el dot product con el vector de vista y nos cuidamos que el valor quede ente 0 y 1
float3 S = saturate(dot(R, V));
//al color final se le agregan los brillos especulares
tex.rbg *= ((AmbientLight * AmbientLightColor) + (A * ( S + (D * LightColor))));
Y ya tenemos una versión rústica y un poco bruta.
Pasamos de esto:
A esto:
Ahora tenemos que conseguir refinar esto puesto que sumar S al color final no es del todo preciso y, además, diferentes materiales tienen diferente propiedades de reflexión de la luz. Para especificar el nivel de dispersión del brillo del material elevamos S a una potencia que suele estar entre 5 y 50, lo que nos dará brillos más finos o dispersos:
float S = (pow( saturate(dot(R, V)), 50));
Con potencia 5 se puede apreciar que los brillos son dispersos:
Aún con todo esto, todavía podemos mejorar la cosa. Los materiales, además, reflejan más o menos luz, o pueden tener una estructura granulada donde algunos puntos reflejan y otros no, independientemente de que la luz reflejada llegue a nuestros ojos. Para simular esto podemos utilizar un mapa especular, que es una textura con un solo canal en blanco y negro (y gris) donde se representa la intensidad de la luz especular en cada pixel.
Mapa especular representando microfacetas granuladas:
Para utilizar el mapa especular le pasamos al shader esta textura:
sampler SpecularSampler : register(s2);
Y la utilizamos para modular la intensidad de los brillos:
float3 SpecularIntensity= tex2D(SpecularSampler, texCoord);
S *= SpecularIntensity.r; //sólo un canal porque lo estoy haciendo a lo bruto y no optimizo
El resultado final es este:
Se puede observar claramente las microfacetas del material reflejando o no los brillos.
Disclaimer: La calidad de las texturas influye mucho en el resultado final. Yo estoy usando un mapa especular con ruido aleatorio que no tiene coherencia con respecto a la textura a mostrar y el resultado no es muy preciso.
No hay comentarios:
Publicar un comentario