【问题标题】:Why are my specular highlights elliptical?为什么我的镜面高光是椭圆的?
【发布时间】:2017-07-27 14:39:47
【问题描述】:

我认为这些应该是循环的。我认为我的法线有问题,但我没有发现它们有任何问题。再说一次,为法线找到一个好的测试是很困难的。

这是图片:

这是我为每个灯光设置的着色代码,省略了反射的递归部分:

  lighting = ( hit.obj.ambient + hit.obj.emission );
  const glm::vec3 view_direction = glm::normalize(eye - hit.pos);
  const glm::vec3 reflection = glm::normalize(( static_cast<float>(2) * ( glm::dot(view_direction, hit.normal) * hit.normal ) ) - view_direction);
  for(int i = 0; i < numused; ++i)
    {

      glm::vec3 hit_to_light = (lights[i].pos - hit.pos);
      float dist = glm::length(hit_to_light);
      glm::vec3 light_direction = glm::normalize(hit_to_light);
      Ray lightray(hit.pos, light_direction);
      Intersection blocked = Intersect(lightray, scene, verbose ? verbose : false);
      if( blocked.dist >= dist)
        {
          glm::vec3 halfangle = glm::normalize(view_direction + light_direction);
          float specular_multiplier = pow(std::max(glm::dot(halfangle,hit.normal), 0.f), shininess);

          glm::vec3 attenuation_term = lights[i].rgb * (1.0f / (attenuation + dist * linear + dist*dist * quad));
          glm::vec3 diffuse_term = hit.obj.diffuse * ( std::max(glm::dot(light_direction,hit.normal) , 0.f) );
          glm::vec3 specular_term = hit.obj.specular * specular_multiplier;
        }
    }

这是我将对象空间法线转换为世界空间的线:

*norm = glm::normalize(transinv * glm::vec4(glm::normalize(p - sphere_center), 0));

使用完整的 phong 模型,而不是 blinn-phong,我得到泪珠高光:

如果我根据交点处的法线(的绝对值)对像素进行着色,我会得到以下图像(r = x,g = y,b = z):

【问题讨论】:

  • 如何转换法线?由于您可能从球体开始并对其进行非均匀缩放,因此您需要使用转置逆矩阵而不是常规变换矩阵(有关更多详细信息,请参阅this question
  • 我确实使用转置逆来转换法线,并且我使用的是glm::transpose(glm::inverse(object_transform)),所以我认为矩阵计算不正确。我会在这个问题中添加正常的转换线,以防万一那里出了问题。
  • 虽然它可能仍然不是完整的解决方案,但您是否尝试过从 Blinn-Phong 模型(这只是一个近似值)迁移到完整的 Phong 模型,即将dot(halfangle,normal) 替换为dot(reflection,light_direction)
  • 刚刚添加了使用完整 phong 模型生成的图像,但是,正如您所想的,它并没有完全解决问题。
  • 调试的下一步可能是法线的某种可视化,或者通过直接将它们映射到 RGB 值 ((value + 1) / 2) 或通过对环境贴图(即立方体map, ...) 使用法线并比较椭球的不同比例。不幸的是,如果没有更多信息,我无法提供任何更有帮助的猜测。如果您根本不缩放对象,高光是否有效?

标签: raytracing


【解决方案1】:

我已经解决了这个问题。事实证明,法线都只是稍微偏离了一点,但还不足以让法线着色的图像可以描绘出来。

我通过计算具有统一比例和平移的球体上的法线发现了这一点。

问题发生在我将法线转换为世界空间的那一行:

*norm = glm::normalize(transinv * glm::vec4(glm::normalize(p - sphere_center), 0));

我假设齐次坐标在变换后为 0,因为它事先为零(旋转和缩放不影响它,因为它是 0,所以平移也不能)。但是,由于矩阵是转置的,所以它不是0,所以最下面一行被逆平移填充,导致齐次坐标非零。

然后对 4 向量进行归一化,并将结果分配给 3 向量。 3-vector 的构造函数只是删除了最后一个条目,因此法线未归一化。

这是最终的图片:

【讨论】:

    猜你喜欢
    • 2014-08-10
    • 1970-01-01
    • 2012-03-03
    • 2020-07-24
    • 2013-01-10
    • 1970-01-01
    • 2016-09-13
    • 2021-11-19
    • 2016-04-21
    相关资源
    最近更新 更多