Implementé un esquema de iluminación de Phong usando una cámara centrada en (0,0,0) y mirando directamente a la esfera primitiva. Los siguientes son los contenidos pertinentes del archivo de escena que se utiliza para ver la escena usando OpenGL, así como para hacer que la escena usando mi propia aplicación:renderizado OpenGL versus implementación de iluminación propia de Phong
ambient 0 1 0
dir_light 1 1 1 -3 -4 -5
# A red sphere with 0.5 green ambiance, centered at (0,0,0) with radius 1
material 0 0.5 0 1 0 0 1 0 0 0 0 0 0 0 0 10 1 0
sphere 0 0 0 0 1
La imagen resultante producida por OpenGL.
La imagen que produce mi aplicación de renderización.
Como se puede ver, hay varias diferencias entre los dos:
- El reflejo especular en mi imagen es más pequeña que la de OpenGL.
- La superficie difusa parece no difuminarse correctamente, lo que hace que la región amarilla sea innecesariamente grande en mi imagen, mientras que en OpenGL hay una bonita región verde oscuro más cerca de la esfera
- El color producido por OpenGL es mucho más oscuro que el de mi imagen.
Esas son las tres diferencias más importantes que veo. Lo que sigue es mi implementación de la iluminación de Phong:
R3Rgb Phong(R3Scene *scene, R3Ray *ray, R3Intersection *intersection)
{
R3Rgb radiance;
if(intersection->hit == 0)
{
radiance = scene->background;
return radiance;
}
R3Vector normal = intersection->normal;
R3Rgb Kd = intersection->node->material->kd;
R3Rgb Ks = intersection->node->material->ks;
// obtain ambient term
R3Rgb intensity_ambient = intersection->node->material->ka*scene->ambient;
// obtain emissive term
R3Rgb intensity_emission = intersection->node->material->emission;
// for each light in the scene, obtain calculate the diffuse and specular terms
R3Rgb intensity_diffuse(0,0,0,1);
R3Rgb intensity_specular(0,0,0,1);
for(unsigned int i = 0; i < scene->lights.size(); i++)
{
R3Light *light = scene->Light(i);
R3Rgb light_color = LightIntensity(scene->Light(i), intersection->position);
R3Vector light_vector = -LightDirection(scene->Light(i), intersection->position);
// calculate diffuse reflection
intensity_diffuse += Kd*normal.Dot(light_vector)*light_color;
// calculate specular reflection
R3Vector reflection_vector = 2.*normal.Dot(light_vector)*normal-light_vector;
reflection_vector.Normalize();
R3Vector viewing_vector = ray->Start() - intersection->position;
viewing_vector.Normalize();
double n = intersection->node->material->shininess;
intensity_specular += Ks*pow(max(0.,viewing_vector.Dot(reflection_vector)),n)*light_color;
}
radiance = intensity_emission+intensity_ambient+intensity_diffuse+intensity_specular;
return radiance;
}
Aquí están los LightIntensity relacionado (...) y LightDirection (...) funciones:
R3Vector LightDirection(R3Light *light, R3Point position)
{
R3Vector light_direction;
switch(light->type)
{
case R3_DIRECTIONAL_LIGHT:
light_direction = light->direction;
break;
case R3_POINT_LIGHT:
light_direction = position-light->position;
break;
case R3_SPOT_LIGHT:
light_direction = position-light->position;
break;
}
light_direction.Normalize();
return light_direction;
}
R3Rgb LightIntensity(R3Light *light, R3Point position)
{
R3Rgb light_intensity;
double distance;
double denominator;
if(light->type != R3_DIRECTIONAL_LIGHT)
{
distance = (position-light->position).Length();
denominator = light->constant_attenuation +
light->linear_attenuation*distance +
light->quadratic_attenuation*distance*distance;
}
switch(light->type)
{
case R3_DIRECTIONAL_LIGHT:
light_intensity = light->color;
break;
case R3_POINT_LIGHT:
light_intensity = light->color/denominator;
break;
case R3_SPOT_LIGHT:
R3Vector from_light_to_point = position - light->position;
light_intensity = light->color*(
pow(light->direction.Dot(from_light_to_point),
light->angle_attenuation));
break;
}
return light_intensity;
}
Le agradecería alguna sugerencia en cuanto a cualquier error de implementación que sea evidente. Me pregunto si las diferencias podrían estar ocurriendo simplemente debido a los valores gamma utilizados para la visualización por OpenGL y el valor gamma predeterminado para mi pantalla. También sé que OpenGL (o al menos las partes que me proporcionaron) no puede proyectar sombras sobre los objetos. No es que esto sea relevante para el punto en cuestión, pero me lleva a preguntarme si se trata simplemente de diferencias de visualización y capacidad entre OpenGL y lo que estoy tratando de hacer.
Gracias por su ayuda.