C++ 自定义问题中的怪异直接照明

C++ 自定义问题中的怪异直接照明,c++,raytracing,radiance,C++,Raytracing,Radiance,我目前正在实现一个自定义光线跟踪渲染器,我坚持直接照明的问题 以下是我的结果: 正常光 球形 最大值(法线光点(球面),0.0) 我不明白最后一个结果,我认为第一个和第二个是正确的,但不是最后一个(点…) 该灯光是点光源 const Vec4<double> LambertianSampler::radiance(const Ray& ray, const Scene& scene) const { Context ctx; ct

我目前正在实现一个自定义光线跟踪渲染器,我坚持直接照明的问题 以下是我的结果:

正常光

球形

最大值(法线光点(球面),0.0)

我不明白最后一个结果,我认为第一个和第二个是正确的,但不是最后一个(点…) 该灯光是点光源

    const Vec4<double> LambertianSampler::radiance(const Ray& ray, const Scene& scene) const
  {
     Context ctx;
     ctx.setCamtoWorld(scene.getCamera()->getLookAt());
     Vec4<double> maxColor(1.0, 1.0, 1.0, 1.0);
     Vec4<double> ambient(0.4, 0.4, 0.4, 1.0);

     Vec4<double> finaleRadiance = ambient;
     for(const auto & light : scene.getLights())
     {
       for(const auto & shape : scene.getShapes())
       {
          shape->intersect(ray, ctx);
       }

      if(ctx.intersectionFound())
      {
      Vec3<double> lightPosition = light->getPos();
      Vec4<double> lightColor    = light->getRadiance();
      Vec3<double> lightNormal   = ctx.getPoint() - lightPosition;
      lightNormal = Vec3<double>(std::fabs(lightNormal.x()), std::fabs(lightNormal.y()), std::fabs(lightNormal.z()));
      lightNormal.normalize();

      Vec3<double> sphereNormal = ctx.getNormal();
      sphereNormal   = Vec3<double>(std::fabs(sphereNormal.x()), std::fabs(sphereNormal.y()), std::fabs(sphereNormal.z())) ;
      sphereNormal.normalize();

      double dot     = lightNormal.dot(sphereNormal);
      finaleRadiance = maxColor*std::max(0.0,dot);
      finaleRadiance = Vec4<double>(finaleRadiance.x(), finaleRadiance.y(), finaleRadiance.z(), 1.0);

      //finaleRadiance = Vec4<double>(sphereNormal.x(), sphereNormal.y(), sphereNormal.z(), 1.0);
      //finaleRadiance = Vec4<double>(lightNormal.x(), lightNormal.y(), lightNormal.z(), 1.0);

    }
  }
  return finaleRadiance;
}
const Vec4 LambertianSampler::radiance(const光线和光线,const场景和场景)const
{
上下文ctx;
setCamtoWorld(scene.getCamera()->getLookAt());
vec4maxcolor(1.0,1.0,1.0,1.0);
Vec4环境(0.4,0.4,0.4,1.0);
Vec4最终公差=环境温度;
对于(const auto&light:scene.getLights())
{
for(const auto&shape:scene.getShapes())
{
形状->相交(射线,ctx);
}
if(ctx.intersectionFound())
{
Vec3 lightPosition=light->getPos();
Vec4 lightColor=light->getRadiance();
Vec3 lightNormal=ctx.getPoint()-lightPosition;
lightNormal=Vec3(std::fabs(lightNormal.x()),std::fabs(lightNormal.y()),std::fabs(lightNormal.z());
lightNormal.normalize();
Vec3 sphereNormal=ctx.getNormal();
sphereNormal=Vec3(std::fabs(sphereNormal.x()),std::fabs(sphereNormal.y()),std::fabs(sphereNormal.z());
球面归一化();
双点=光法线点(球面);
最终公差=最大颜色*标准::最大值(0.0,点);
finalleradiance=Vec4(finalleradiance.x(),finalleradiance.y(),finalleradiance.z(),1.0);
//最终误差=Vec4(sphereNormal.x(),sphereNormal.y(),sphereNormal.z(),1.0);
//finaleRadiance=Vec4(lightNormal.x(),lightNormal.y(),lightNormal.z(),1.0);
}
}
回报金融宽容;
}

我的网点结果对吗?因为我认为我的LightNormalSphere和sphereNormal是正确的,所以我认为..

我通过删除以下内容来解决我的问题:

lightNormal = Vec3<double>(std::fabs(lightNormal.x()), std::fabs(lightNormal.y()), std::fabs(lightNormal.z()));
lightNormal=Vec3(std::fabs(lightNormal.x()),std::fabs(lightNormal.y()),std::fabs(lightNormal.z());

lightNormal=Vec3((lightNormal.x()+1)*0.5,(lightNormal.y()+1)*0.5,(lightNormal.z()+1)*0.5);

主要问题在于:

  Vec3<double> sphereNormal = ctx.getNormal();
  sphereNormal   = Vec3<double>(std::fabs(sphereNormal.x()), std::fabs(sphereNormal.y()), std::fabs(sphereNormal.z())) ;
  sphereNormal.normalize();
Vec3 sphereNormal=ctx.getNormal();
sphereNormal=Vec3(std::fabs(sphereNormal.x()),std::fabs(sphereNormal.y()),std::fabs(sphereNormal.z());
球面归一化();
但上述解决方案似乎并不完全正确。首先,不必重新规范化球体法线。
fabs
调用将改变一些符号,但没有改变任何大小,因此额外的规范化只是浪费时间

但是为什么
fabs
调用。我猜你是因为球体法线似乎指向错误的方向才加上的。因此,当你使用点积时,你在光的一面得到负值。您添加了晶圆厂,它碰巧使所有球体法线朝向灯光,甚至是黑暗面上的法线。这就是为什么你会看到阴影开始,但随后光线会逐渐恢复,而不是完全变暗

这也解释了为什么您提出的解决方案似乎有效。你将法线偏向(我认为)你放置灯光的位置

如果我的理论是正确的,那么你需要翻转球体法线,使它们指向球体,而不是指向球体。一个快速的检查方法是从交点减去球体的中心,这应该给你一个指向的向量,然后你可以将其规格化。如果这与您当前计算的球体法线不匹配(特别是,如果符号全部翻转),我的理论将得到证实

在这种情况下,解决方案就是在计算点积之前翻转球体法线


最后,在灯光上循环,但仅使用列表中最后一个灯光的贡献。(很难说清楚,因为问题中有一些不匹配的大括号。)

你确定法线可视化是正确的(或者球体的法线是正确的)吗?为什么这行:
lightNormal=Vec3(std::fabs(lightNormal.x()),std::fabs(lightNormal.y()),std::fabs(lightNormal.y()),std::fabs(lightNormal.z())这应该做什么?你是对的,我只需
  Vec3<double> sphereNormal = ctx.getNormal();
  sphereNormal   = Vec3<double>(std::fabs(sphereNormal.x()), std::fabs(sphereNormal.y()), std::fabs(sphereNormal.z())) ;
  sphereNormal.normalize();