Рендеринг OpenGL по сравнению с собственной Реализацией Освещения Phong

Я реализовал Схему Освещения Phong с помощью камеры, это центрируется в (0,0,0) и смотрящий непосредственно на примитивную сферу. Следующее является соответствующим содержанием файла сцены, который используется, чтобы просмотреть сцену с помощью OpenGL, а также представить сцену с помощью моей собственной реализации:

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   

Here

Получающееся изображение производится OpenGL.

Here

Изображение, которое производит мое приложение рендеринга.

Как Вы видите, существуют различные различия между двумя:

  1. Зеркальная подсветка на моем изображении меньше, чем то в OpenGL.
  2. Рассеянная поверхность, кажется, не рассеивается корректным способом, приводящим к желтому региону, чтобы быть излишне большой в моем изображении, тогда как в OpenGL существует хороший темно-зеленый регион ближе к нижней части сферы
  3. Цвет, произведенный OpenGL, является намного более темным, чем тот в моем изображении.

Это - самые видные три различия, которые я вижу. Следующее является моей реализацией освещения 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;
}

Вот связанные LightIntensity (...), и LightDirection (...) функционирует:

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;
}

Я был бы очень признателен за любые предложения относительно любых ошибок реализации, которые очевидны. Я задаюсь вопросом, могли ли различия происходить просто из-за гамма значений, используемых для дисплея OpenGL и гамма значением по умолчанию для моего дисплея. Я также знаю, что OpenGL (или по крайней мере tha части, которые мне предоставили) не может наклонные тени на объектах. Не то, чтобы это важно для рассматриваемого вопроса, но он просто приводит меня задаваться вопросом, является ли это просто дисплей и различия в возможности между OpenGL и что я пытаюсь сделать.

Спасибо за помощь.

6
задан Myx 28 March 2010 в 22:08
поделиться

2 ответа

В моем случае мое первоначальное предположение о различиях в значениях гаммы было правильным. Основная программа, которая вызвала мой алгоритм рендеринга, выполнила гамма-коррекцию, скорректировав значение RGB каждого пикселя моего изображения, выполнив вызов image-> TosRGB () . Комментируя вызов, я получил изображение, созданное OpenGL.

0
ответ дан 17 December 2019 в 18:12
поделиться

В качестве первого шага я бы проверил, нормализована ли нормаль вашей поверхности пересечения, что особенно важно при вычислении точечных произведений диффузных и зеркальных составляющих.

В целях отладки вы можете проверять выходные параметры ваших условий освещения (например, выход окружающего освещения сцены, выход окружающего света-рассеянного-зеркального света, коэффициенты ослабления света и т. Д.) Один за другим, 0 'остальные члены в уравнениях . Некоторые простые термины могут дать идентичный результат, и с помощью этого подхода вы можете сузить поиск до меньшего количества строк кода. Это может даже оказаться связано с другими объектами / методами в вашей реализации.

Также имейте в виду, что затенение Фонга в OpenGL не следует строго модели затенения Фонга, потому что нормали вычисляются для каждой вершины, а затем интерполируются внутри треугольников, а не для каждой точки на поверхности. Ваша сферическая модель кажется достаточно мозаичной, так что это не должно быть практической проблемой.

OpenGL не выполняет гамма-коррекцию, если вы не используете цветовое пространство sRGB в качестве цели рендеринга, насколько мне известно. Я ожидал, что правильная программная реализация даст очень похожие результаты аппаратной реализации OpenGL. Удачной отладки :)

3
ответ дан 17 December 2019 в 18:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: