在花了几天时间使用实现Phong照明(有阴影且无衰减)的简单光线跟踪程序取得了很少的进展之后,我确信我犯了一个我可以忽略的逻辑错误。

据我所知,伪代码应如下所示:

ambient light
for each light source
    direction of light = light point - point on the object
    test for an intersection starting at the point on the object, until you hit something
    if (the intersection test returned a distance > distance from point on object to light point)
    (do  diffuse and specular shading)


关于我的实现,有一件快速的事情要提:如果没有相交,则相交测试将返回9999999。

我尝试过的一些事情是:反转阴影射线的方向-无效果。进行比较的相交距离-光照距离>(一些小的epsilon值)-不变。手动将光源移到另一侧-镜面反射移到新的点,但是没有变化。

这是我最新输出的图片,我试图在浅灰色平面的左下角添加阴影。



任何帮助将不胜感激。

这是我代码的相关部分:

    //iterate through all lights
    if (myLights.size() > 0)
    {
        for (int i = 0; i < myLights.size(); i++)
        {
            //calculate the direction of the light
            glm::vec3 ldir = (myLights[i].position - surfacePoint);
            //this the length of the distance between the light and the surface
            float ldist= sqrt(pow(ldir.x, 2.0f) + pow(ldir.y, 2.0f) + pow(ldir.z, 2.0f)); 
//check if the light can see the surface point
            float intersections = myObjGroup->testIntersections(surfacePoint, normalize(ldir));
            if (abs(intersections-ldist)  > 0.0000001f)
            {
                //diffuse and specular shading have been cut for brevity
            }
        }
    }


编辑:新图像:


>

评论

专家提示:x * x比pow(x,2.0f)快得多。

#1 楼

您的if条件使我感到怀疑。如果相交测试没有碰到物体,则应包括漫反射和镜面反射阴影。也就是说,如果intersections > ldist。因此,您的代码应如下所示:

if (intersections > ldist)
{
    colour += diffuse(...);
    colour += specular(...);
}


与0.0000001f的比较表明,您在自相交方面也遇到了麻烦(即,光线与阴影对象相交)。在一次命中的跟踪器中,您不能仅通过丢弃相交来解决该问题,因为您仍然不知道阴影射线是否会进一步相交于另一个对象。为避免自相交,您需要通过epsilon沿射线的方向推动射线的起点:

glm::vec3 direction = normalize(ldir);
glm::vec3 start = surfacePoint + epsilon * direction;
float intersections = myObjGroup->testIntersections(start, direction);


另一件事:不要忘记测试光线在您要照明的表面的前面。您可以使用ldir的点积和表面法线来执行此操作:如果点积为正,则光线在正确的一侧;否则,该点为正。如果为负,则光线在表面后面,因此甚至在投射射线之前就被遮盖了。

评论


$ \ begingroup $
非常感谢您的帮助,非常感谢您抽出宝贵的时间来编写它。我已经执行了您的建议。不幸的是,我的影子仍然不见了。我最近的输出是在原始问题中。我假设这意味着问题在代码的上游。当然,这大约是我设定阶段的200-300行。如果您有足够的胃,我就把它放在pastebin上。如果您不这样做,我完全理解。非常感谢您的协助;我已经很久很接近这个了,我想我一直对自己的错误视而不见
$ \ endgroup $
–user1764241
2015年11月19日23:55

$ \ begingroup $
如果仍然遇到问题,只需应用常规的调试技术即可。继续简化代码以将问题空间减少一半。尝试删除所有阴影计算,然后将颜色设置为交叉点/ 999999,这样您未阴影的交叉点就是白色。在较浅的位置绘制一个对象,以确保它是正确的:在两个渲染中,看起来它都可能位于图像的右下角,在两个对象之间。在阴影坐标上设置一个断点,并逐步遍历您知道应该在阴影中的一个特定点的阴影。
$ \ endgroup $
–丹·赫尔姆
15年11月20日在9:19