自定义问题中奇怪的直接照明
weird direct illumination in custom problem
我目前正在实现一个自定义光线追踪渲染器,我坚持直接照明的问题
这是我的结果:
normalOnLight
sphereNormal
max(normalOnLight.dot(sphereNormal), 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;
}
我的打点结果对吗?因为我认为我的 lightNormalOnSphere 和 sphereNormal 是正确的我认为 ..
我通过替换 :
解决了我的问题
lightNormal = Vec3<double>(std::fabs(lightNormal.x()), std::fabs(lightNormal.y()), std::fabs(lightNormal.z()));
来自
lightNormal = Vec3<double>((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();
但上面的解决方案似乎不太正确。首先,您不必重新规范化球体法线。 fabs
调用将改变一些符号,但幅度 none,因此额外的规范化只是在浪费时间。
但是为什么 fabs
调用。我猜你添加了那是因为球体法线似乎指向了错误的方向。因此,当您采用点积时,您会在较轻的一侧得到负值。您添加了 fabs,这恰好将球体法线 所有 转向光,甚至是黑暗面的法线。这就是为什么您会看到开始出现阴影,但随后光线会逐渐恢复而不是完全变暗的原因。
这也解释了为什么您提出的解决方案似乎有效。您将法线偏向(我认为)您放置灯光的位置。
如果我的理论是正确的,那么您需要翻转球体法线,使它们指向外而不是指向球体。一种快速检查的方法是从交点减去球体的中心,这应该给你一个指向外的矢量,然后你可以对其进行归一化。如果这与您当前正在计算的球体法线不匹配(具体来说,如果符号全部翻转),我的理论将得到证实。
在那种情况下,解决方案就是在计算点积之前翻转球体。
最后,您在灯光上循环,但仅使用列表中最后一个灯光的贡献。 (很难准确判断,因为问题中有一些不匹配的括号。)
我目前正在实现一个自定义光线追踪渲染器,我坚持直接照明的问题 这是我的结果:
normalOnLight
sphereNormal
max(normalOnLight.dot(sphereNormal), 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;
}
我的打点结果对吗?因为我认为我的 lightNormalOnSphere 和 sphereNormal 是正确的我认为 ..
我通过替换 :
解决了我的问题lightNormal = Vec3<double>(std::fabs(lightNormal.x()), std::fabs(lightNormal.y()), std::fabs(lightNormal.z()));
来自
lightNormal = Vec3<double>((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();
但上面的解决方案似乎不太正确。首先,您不必重新规范化球体法线。 fabs
调用将改变一些符号,但幅度 none,因此额外的规范化只是在浪费时间。
但是为什么 fabs
调用。我猜你添加了那是因为球体法线似乎指向了错误的方向。因此,当您采用点积时,您会在较轻的一侧得到负值。您添加了 fabs,这恰好将球体法线 所有 转向光,甚至是黑暗面的法线。这就是为什么您会看到开始出现阴影,但随后光线会逐渐恢复而不是完全变暗的原因。
这也解释了为什么您提出的解决方案似乎有效。您将法线偏向(我认为)您放置灯光的位置。
如果我的理论是正确的,那么您需要翻转球体法线,使它们指向外而不是指向球体。一种快速检查的方法是从交点减去球体的中心,这应该给你一个指向外的矢量,然后你可以对其进行归一化。如果这与您当前正在计算的球体法线不匹配(具体来说,如果符号全部翻转),我的理论将得到证实。
在那种情况下,解决方案就是在计算点积之前翻转球体。
最后,您在灯光上循环,但仅使用列表中最后一个灯光的贡献。 (很难准确判断,因为问题中有一些不匹配的括号。)