Frage

Ich habe ein Phong Beleuchtungsschema mit einer Kamera implementiert, die primitive bei (0,0,0) und suchte direkt auf der Kugel zentriert ist. 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:

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   

Hier

Das resultierende Bild produziert von OpenGL.

Hier

Das Bild, das meine Rendering-Anwendung erzeugt.

Wie Sie sehen können, gibt es verschiedene Unterschiede zwischen den beiden:

  1. Das Glanzlicht auf meinem Bild ist kleiner als die in OpenGL.
  2. Die diffuse Oberfläche scheint in der richtigen Art und Weise nicht zu diffundieren, im gelben Bereich resultierenden unnötig in meinem Bild groß zu sein, während sie in OpenGL gibt es einen schönen dunkelgrünen Bereich ist näher an die Unterseite der Kugel
  3. Die Farbe von OpenGL hergestellt ist viel dunkler als das in meinem Bild.

Das sind die prominentesten drei Unterschiede, die ich sehe. Im Folgenden ist 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 schätzen irgendwelche Vorschläge hinsichtlich etwaiger Implementierungsfehler, die offensichtlich sind. Ich frage mich, ob die Unterschiede einfach für die Anzeige wegen der Gamma-Werte auftreten könnten, die von OpenGL und dem Standard-Gamma-Wert für meine Anzeige. Ich weiß auch, dass OpenGL (oder zumindest tha Teile, dass ich zur Verfügung gestellt wurde) kann nicht auf Objekte werfen Schatten. Nicht, dass dies für den Punkt in Frage relevant ist, aber es führt mich nur zu fragen, ob es einfach das Display und die Fähigkeit, Unterschiede zwischen OpenGL und was ich versuche zu tun.

Vielen Dank für Ihre Hilfe.

War es hilfreich?

Lösung 2

In meinem Fall meine erste Vermutung über die Unterschiede in Gamma-Werte korrekt war. Das Hauptprogramm, das meinen Rendering-Algorithmus genannt ausgeführt Gammakorrektur von jedem Pixel des RGB-Wert meines Bildes zu korrigieren, indem sie einen image->TosRGB() Anruf zu tun. Nach dem Aufruf auszukommen erhielt ich das Bild von OpenGL hergestellt.

Andere Tipps

Als erster Schritt, würde ich prüfen, ob die Schnittfläche normale normiert ist, vor allem dann wichtig, wenn Produkten diffuse und spiegelnde Begriff Punkt berechnet wird.

Für Debugging-Zwecke können Sie die Ausgänge Ihrer Beleuchtung Bedingungen überprüfen (zB Szene Umgebungsausgang, Lichtraum-diffusen Spiegelausgang, Lichtdämpfungsfaktoren, etc.) eines nach dem anderen, die anderen Bedingungen in den Gleichungen 0'ing . Einige einfachen Begriffe sind wahrscheinlich identisch Ausgabe erzeugen, und Sie können Ihre Suche eingrenzen zu weniger Codezeilen mit diesem Ansatz. Es kann sogar entpuppen sich andere Objekte / Methoden in Ihrer Implementierung bezogen werden.

Auch bitte beachten Sie, dass OpenGL Phong-Shading nicht das Phong-Shading-Modell streng folgt, weil die Normalen pro Vertex berechnet werden und dann innerhalb der Dreiecke interpoliert, werden sie nicht pro Punkt berechnet auf der Oberfläche. Ihre Kugel-Modell scheint genug tessellated werden, so dass dies kein praktisches Problem sein sollte.

OpenGL nicht führt nicht Gammakorrektur, wenn Sie sRGB-Farbraum als Ziel machen verwenden, soweit ich weiß. Ich würde eine korrekte Implementierung der Software erwartet sehr ähnliche Ergebnisse einer Hardware-OpenGL-Implementierung zu erzeugen. Glückliche Debugging:)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top