【发布时间】:2013-12-27 19:58:18
【问题描述】:
我正在编写一个基本的光线追踪器,以便更好地理解整个事情。我遇到了一个困扰我一段时间的问题,球体的漫反射阴影。我使用以下来源的公式来计算球体交叉点和漫反射阴影。
http://www.ccs.neu.edu/home/fell/CSU540/programs/RayTracingFormulas.htm
我的计算阴影的代码(尝试复制链接上的源代码)如前所示。在大多数情况下,某些球体上的计算有时看起来是正确的,但取决于灯光的位置,取决于球体阴影的正确/损坏程度。
TVector intersect (ray.getRayOrigin().getVectX() + t * (ray.getRayDirection().getVectX() - ray.getRayOrigin().getVectX()),
ray.getRayOrigin().getVectY() + t * (ray.getRayDirection().getVectY() - ray.getRayOrigin().getVectY()),
ray.getRayOrigin().getVectZ() + t * (ray.getRayDirection().getVectZ() - ray.getRayOrigin().getVectZ()));
//Calculate the normal at the intersect point
TVector NormalIntersect (intersect.getVectX() - (position.getVectX()/r),
intersect.getVectY() - (position.getVectY()/r),
intersect.getVectZ() - (position.getVectZ()/r));
NormalIntersect = NormalIntersect.normalize();
//Find unit vector from intersect(x,y,z) to the light(x,y,z)
TVector L1 (light.GetPosition().getVectX() - intersect.getVectX(),
light.GetPosition().getVectY() - intersect.getVectY(),
light.GetPosition().getVectZ() - intersect.getVectZ());
L1 = L1.normalize();
double Magnitude = L1.magnitude();
TVector UnitVector(L1.getVectX() / Magnitude,
L1.getVectY() / Magnitude,
L1.getVectZ() / Magnitude);
//Normalized or not, the result is the same
UnitVector = UnitVector.normalize();
float Factor = (NormalIntersect.dotProduct(UnitVector));
float kd = 0.9; //diffuse-coefficient
float ka = 0.1; //Ambient-coefficient
Color pixelFinalColor(kd * Factor * (color.getcolorRed()) + (ka * color.getcolorRed()) ,
kd * Factor * (color.getcolorGreen()) + (ka * color.getcolorGreen()) ,
kd * Factor * (color.getcolorBlue()) + (ka * color.getcolorBlue()) ,1);
从图片中可以看出,一些球体似乎被正确着色,而其他球体则完全破碎。起初我认为问题可能在于 UnitVector 计算,但是当我查看它时,我无法找到问题。谁能看出问题的原因?
注意:我正在使用 OpenGL 来渲染我的场景。
更新: 我仍然遇到一些问题,但是我认为在你们的帮助下,它们大部分已经得到解决,并且对我计算单位向量的方式进行了一些更改。更新如下所示。非常感谢所有给出答案的人。
TVector UnitVector (light.GetPosition().getVectX() - intersect.getVectX(),
light.GetPosition().getVectY() - intersect.getVectY(),
light.GetPosition().getVectZ() - intersect.getVectZ());
UnitVector = UnitVector.normalize();
float Factor = NormalIntersect.dotProduct(UnitVector);
//Set Pixel Final Color
Color pixelFinalColor(min(1,kd * Factor * color.getcolorRed()) + (ka * color.getcolorRed()) ,
min(1,kd * Factor * color.getcolorGreen()) + (ka * color.getcolorGreen()) ,
min(1,kd * Factor * color.getcolorBlue()) + (ka * color.getcolorBlue()) ,1);
【问题讨论】:
-
确保最终颜色不超过颜色范围(0 到 1 或 255)。根据库的不同,太亮的颜色可能会覆盖并变成黑色。插入分钟:
pixelFinalColor(min(1, kd * Factor...对Factor = max(0, NormalIntersect...执行相同操作 -
谢谢,好建议。在将 min(1) 添加到像素颜色之后,它似乎已经解决了某些球体上的问题,但是在不同位置的其他球体也出现了同样的问题。如果我还将 max(0) 添加到因子中,则所有对象都会变成单色调的平面阴影,根本没有漫反射阴影。感谢您的帮助。谢谢您
-
如果一切看起来都是单一的色调,它可能没有点亮,只是显示您的环境照明。你确定你的灯在你认为的位置吗?
-
正,在添加 max(0) 之前根据我移动光的位置 (x,y,z) 改变球体的着色方式,对于那些没有被破坏的球体,它看起来准确。我已经测试了多个照明位置,这绝对不是问题。感谢您的宝贵时间和意见。
标签: c++ opengl raytracing pixel-shading