Ich habe ein Phong Illumination-Schema mit einer Kamera implementiert, die um (0,0,0) zentriert ist und direkt auf das Sphärengrundelement schaut. Im Folgenden werden die relevanten Inhalte der Szene-Datei, die verwendet wird, um die Szene als auch mit OpenGL zu sehen, die Szene mit meiner eigenen Implementierung zu machen:OpenGL render vs. eigene Phong Illumination Implementierung
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
Das resultierende Bild von OpenGL erzeugt.
Das Bild, das meine Rendering-Anwendung erzeugt.
Wie Sie sehen können, gibt es verschiedene Unterschiede zwischen den beiden:
- Das Glanzlicht auf meinem Bild ist kleiner als die in OpenGL.
- Die diffuse Oberfläche scheint nicht in der richtigen Weise zu diffundieren, was dazu führt, dass der gelbe Bereich in meinem Bild unnötig groß ist, während in OpenGL ein schöner dunkelgrüner Bereich näher am unteren Ende der Kugel liegt
- Die Farbe produziert durch OpenGL ist viel dunkler als das in meinem Bild.
Das sind die prominentesten drei Unterschiede, die ich sehe. Hier finden Sie meine Umsetzung der Phong-Beleuchtung:
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;
}
Hier sind die damit verbundene Lichtintensität (...) und LightDirection (...) Funktionen:
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;
}
Ich würde sehr Anregungen zu schätzen wissen, wie zu irgendwelchen Implementierungsfehlern, die offensichtlich sind. Ich frage mich, ob die Unterschiede einfach aufgrund der Gamma-Werte, die für die Anzeige durch OpenGL verwendet werden, und des Standard-Gammawerts für meine Anzeige auftreten können. Ich weiß auch, dass OpenGL (oder zumindest die Teile, die mir zur Verfügung gestellt wurden) keine Schatten auf Objekte werfen kann. Nicht, dass das für den fraglichen Punkt relevant wäre, aber ich frage mich nur, ob es einfach Unterschiede in der Darstellung und der Funktionalität zwischen OpenGL und dem, was ich versuche, gibt.
Vielen Dank für Ihre Hilfe.