Iluminación - Tipos de Luces

En este tutorial OpenGL veremos tres tipos de luces que podemos implementar, ya aprendimos como utilizar el modelo de iluminación phong en el tutorial anterior, ahora utilizaremos los conceptos aprendidos para crear varios tipos de luces, como: luz direccional, luz puntual y luz focal.

Luz Direccional


Utilizado para simular fuentes de luz distantes, como la luz del sol, no indicamos su posición solo necesitamos la dirección de la misma.

Utilizaremos el mismo shader creado en el tutorial de iluminación, para crear la luz direccional creamos una variable uniform que almacene la dirección de la luz, calculamos la dirección en coordenadas del observador y la pasamos al shader.

glm::vec3 lightDir = glm::vec3(MV * glm::vec4(luz_direction, 0));
glUniform3fv(shader.getUniformLocation("light_direction"), 1, glm::value_ptr(lightDir));

El shader para este tipo de luz se llamara directional, usamos la tecla SPACE para cambiar el tipo de luz, estando en la luz direccional podemos usar las teclas de dirección ISQUIERDA y DERECHA para cambiar la dirección de la luz en X.

Captura de pantalla (236)
Para obtener una coordenada en términos del observador (coordenadas de ojo/vista) multiplicamos la matriz Model-View por la coordenada.

Luz Puntual


Una luz puntual simula luces cercanas a la escena o dentro de ella, como la luz de una lámpara de mesa, la luz de una bombilla en el techo, etc., este tipo de luz sufre un decremento en su intensidad a medida que aumenta su distancia de un objeto, a esto lo llamaremos atenuación.

La ecuación para el cálculo de la atenuación es la siguiente:

tutorial opengl moderno
En esta fórmula d es la distancia entre el vértice y la fuente de luz, y k1, k2, k3 son los coeficientes de atenuación constante, lineal y cuadrático respectivamente.

Para calcular la distancia transformamos la posición de la fuente de luz coordenadas de observador y usamos la función GLSL length.

vec3 light_position = (mv_matrix * vec4(light_pos, 1)).xyz;
vec3 L1 = light_position - P;
float d = length(L1);

Aplicamos la fórmula para obtener la atenuación y multiplicamos el valor obtenido por cada una de las componentes de luz.

float attenuationAmount = 1.0 / (k0 + (k1*d) + (k2*d*d));

diffuse *= attenuationAmount;
specular *= attenuationAmount;
ambient *= attenuationAmount;

tutorial opengl luz puntual
He agregado un marcado para indicar donde se encuentra la posición de la fuente de luz, esta gira alrededor del objeto central.

Luz de foco


Son similares a las luces puntuales, con la diferencia de se agrega una dirección a la luz, estos focos arrojan luz en forma cónica en la dirección indicada, para crear este tipo de luz requerimos la dirección del foco y los ángulos internos y externos que definen los respectivos conos de emisión.

luz de foco
Debemos calcular la dirección de la luz focal, para hacerlo restamos el vector posición del foco del vector que indica hacia a donde apunto el foco.

glm::vec3 spotPos(luz_position.x, 0, luz_position.z);
glm::vec3 spotDir = glm::normalize(glm::vec3(MV * glm::vec4(spotPos - luz_position, 0)));

Buscamos el ángulo entre la dirección de la luz focal y la dirección de la luz, almacenamos el resultado en la variable spotEffect.

vec3 D = normalize(spot_direction);
float spotEffect = dot(-L, D);

Si el ángulo encontrado es mayor que el ángulo spot cutoff calculamos las componentes difusa, emisiva y especular como lo habíamos hecho anteriormente.

if(spotEffect > spot_cutoff) {
 spotEffect = pow(spotEffect, spot_exponent);

 // Calculate R by reflecting -L around the plane defined by N
 vec3 R = reflect(-L, N);

 // Calculate ambient, difusse, specular contribution
 vec3 ambient  = ka * ambient_color;
 vec3 diffuse  = kd * light_color * max(0.0, dot(N, L));
 vec3 specular = ks * light_color * pow(max(0.0, dot(R, V)), n);

 float attenuationAmount = spotEffect / (k0 + (k1*d) + (k2*d*d));

 ambient  *= attenuationAmount;
 diffuse  *= attenuationAmount;
 specular *= attenuationAmount;

 // Send the color output to the fragment shader
 vec3 frag_color = ambient + diffuse + specular;
 color = vec4(frag_color, 1.0);
}

Podemos usar las teclas C y V para aumentar o disminuir el ángulo spot cutoff y las teclas F y G para aumentar o disminuir el spot exponent.

luz de foco opengl
En siguientes tutoriales veremos como aplicar diversos materiales a los objetos de nuestra escena 3D.

GitHub: Tipos de Luces.

Comentarios

Entradas populares de este blog

Conectar SQL Server con Java

Entrenar OpenCV en Detección de Objetos

Detección de figuras geométricas