Ho implementato uno schema di illuminazione Phong utilizzando una fotocamera centrata su (0,0,0) e guardando direttamente la primitiva della sfera. Di seguito sono riportati i contenuti pertinenti del file di scena che viene utilizzato per visualizzare la scena utilizzando OpenGL, così da rendere la scena usando la mia propria implementazione:Rendering OpenGL rispetto alla propria illuminazione di Phong Implementazione
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
L'immagine risultante prodotta da OpenGL.
L'immagine che la mia applicazione di rendering produce.
Come si può vedere, ci sono varie differenze tra i due:
- La luce speculare sulla mia immagine è più piccola di quella in OpenGL.
- La superficie diffusa sembra non diffondersi nel modo corretto, risultando nella regione gialla eccessivamente grande nella mia immagine, mentre in OpenGL c'è una bella regione verde scuro più vicina alla parte inferiore della sfera
- Il colore prodotto da OpenGL è molto più scuro di quello nella mia immagine.
Queste sono le tre differenze più importanti che vedo. Quello che segue è la mia realizzazione dell'illuminazione 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;
}
Ecco il relativo LightIntensity (...) e LightDirection (...) funzioni:
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;
}
Io apprezzo molto come tutti i suggerimenti a eventuali errori di implementazione che sono evidenti. Mi chiedo se le differenze potrebbero verificarsi semplicemente a causa dei valori gamma usati per la visualizzazione da OpenGL e il valore gamma predefinito per il mio display. So anche che OpenGL (o almeno le parti che mi sono state fornite) non possono proiettare ombre sugli oggetti. Non che questo sia rilevante per il punto in questione, ma mi porta solo a chiedermi se si tratta semplicemente di differenze di display e funzionalità tra OpenGL e quello che sto cercando di fare.
Grazie per il vostro aiuto.