2010-03-28 3 views
6

Я реализовал схему освещения Фонга, используя камеру, расположенную по центру (0,0,0), и смотря прямо на примитив сферы. Ниже приведены соответствующие содержимое файла сцены, который используется для просмотра сцены с использованием OpenGL, а также для визуализации сцены с помощью моей собственной реализации: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 намного темнее, чем у моего изображения.

Это самые известные три отличия, которые я вижу. Ниже моя реализация освещения Фонга:

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 (или, по крайней мере, части, которые я предоставил) не может отбрасывать тени на объекты. Не то, чтобы это было актуально для рассматриваемой темы, но это просто заставляет меня задаться вопросом, просто ли это различия между OpenGL и возможностями OpenGL и что я пытаюсь сделать.

Благодарим за помощь.

ответ

0

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

3

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

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

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

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

 Смежные вопросы

  • Нет связанных вопросов^_^