سؤال

لقد قمت بتطبيق مخطط إضاءة 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. يبدو أن السطح المنتشر لا ينتشر بالطريقة الصحيحة ، مما يؤدي إلى أن تكون المنطقة الصفراء كبيرة في صورتي ، في حين أن هناك منطقة خضراء داكنة لطيفة أقرب إلى أسفل الكرة
  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;
}

فيما يلي وظائف الإضاءة ذات الصلة (...) وتوجيهات الضوء (...):

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

سأقدر كثيرا أي اقتراحات بشأن أي أخطاء تنفيذ واضحة. أتساءل عما إذا كان يمكن أن تحدث الاختلافات ببساطة بسبب قيم Gamma المستخدمة للعرض بواسطة OpenGL وقيمة Gamma الافتراضية للعرض الخاص بي. أعلم أيضًا أن OpenGL (أو على الأقل أجزاء Tha التي تم تقديمها) لا يمكنها إلقاء الظلال على الأشياء. لا يعني ذلك أن هذا أمر مناسب للأسئلة المعروضة ، لكنه يقودني فقط إلى التساؤل عما إذا كان ببساطة عرض اختلافات وقدرة بين OpenGL وما أحاول القيام به.

شكرا لك على مساعدتك.

هل كانت مفيدة؟

المحلول 2

في حالتي ، كان تخميني الأولي حول الاختلافات في قيم Gamma صحيحة. أجرى البرنامج الرئيسي الذي أطلق على خوارزمية التقديم تصحيح GAMMA عن طريق تصحيح قيمة RGB لكل بكسل عن طريق القيام بـ image->TosRGB() يتصل. بعد التعليق على المكالمة ، حصلت على الصورة التي تنتجها OpenGL.

نصائح أخرى

كخطوة أولى ، أود أن أتحقق مما إذا كان سطح التقاطع الطبيعي يتم تطبيعه ، مهمًا بشكل خاص عند حساب منتجات DOT المنتشر والمصطلح.

لأغراض تصحيح الأخطاء ، يمكنك التحقق من مخرجات مصطلحات الإضاءة الخاصة بك (مثل الإخراج المحيط للمشهد ، والإخراج المحدد للضوء ، وعوامل التوهين الخفيفة ، وما إلى ذلك) واحد تلو الآخر ، 0'ing المصطلحات الأخرى في المعادلات. من المحتمل أن تنتج بعض المصطلحات البسيطة إخراجًا متطابقًا ، ويمكنك تضييق نطاق البحث وصولاً إلى خطوط كود أقل مع هذا النهج. قد يتحول إلى أن يكون مرتبطًا بالكائنات / الأساليب الأخرى في التنفيذ.

أيضًا ، يرجى مراعاة أن تظليل OpenGL من Phong لا يتبع نموذج تظليل Phong بدقة ، لأن القواعد الطبيعية يتم حسابها لكل قمة ثم يتم استقراءها داخل المثلثات ، ولا يتم حسابها لكل نقطة على السطح. يبدو أن نموذج المجال الخاص بك هو مفصل بما فيه الكفاية ، لذلك لا ينبغي أن يكون هذا مشكلة عملية.

لا يقوم OpenGL بتصحيح Gamma إلا إذا كنت تستخدم مساحة ألوان SRGB كهدف عرض ، على حد علمي. أتوقع أن يؤدي تطبيق البرنامج الصحيح إلى نتائج مماثلة للغاية لتطبيق OpenGL للأجهزة. تصحيح أخطاء سعيد :)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top