射线追踪:来自多个灯的阴影

Ray Tracing: Shadows from Multiple Lights

本文关键字:阴影 追踪      更新时间:2023-10-16

[edit]和编程中的典型情况,我在发布后不久就弄清楚了!如果您有兴趣,请参阅我的答案:)

我正在使用C 的射线示踪剂,并希望提供一些帮助。我的场景中有2个灯,一个点灯和一个方向的光,还有一堆球(以及一架飞机作为"地板")。

如果我用一个存在的任何一个灯(但没有其他灯)运行射线示踪剂,则它会按预期产生阴影(请参见下图)。

定向光阴影图像

点灯阴影图像

麻烦是,当我用两个灯都有两个灯的射线示踪剂时,只有点灯阴影出现,我才能说明灯是" on"的,因为场景更明亮:

请参阅下面的代码以获取阴影:

bool Scene::shadowtrace( Ray &ray, double t )
{
    Object *obj = obj_list;
    Light *lt = light_list;
    Vector v1, v2; // hit -> light vector
    Hit   hit;
    Vertex intersect = (ray.position( t ));
    intersect.plus( ray.D, -0.001 ); // offset  intersection ever so slightly away from object, to avoid self-shadowing
    v1.set( 0.0, 0.0, 0.0 );
    v2.set( 0.0, 0.0, 0.0 ); // initialise
    while (lt != (Light *)0)
    {
        Ray shadowRay;
        shadowRay.P = (intersect);
        Vertex lightPos = Vertex( 0.0, 0.0, 0.0, 0.0 );
        lt->getPosition( lightPos ); // sets value of lightPos
        if (lightPos.x > T_LIMIT) // If set absurdly high, we're dealing with a directional light
        {
            lt->getDirection( v1 ); // sets v1 to light direction (reversed)
            v1.normalise( );
            shadowRay.D = v1; // set hit-to-light vector as shadowray direction
            while (obj != (Object *)0)
            {
                if (obj->intersect( shadowRay, &hit ) == true)
                {
                    if (!((hit.t * hit.t) < 0.001)) // Self-shadow if very very small t number
                    {
                        return true; // ray hits an onject, and the object occurs before the light
                    }
                }
                obj = obj->next( );
            }
        }
        else    // otherwise, it's a point light :)
        {
            v1 = (lightPos.minus( intersect )); // find vector from intersection to light
            v2 = v1; // keep un-normalised version for preventing mis-shadowing from objects behind the light source
            v1.normalise( );
            shadowRay.D = v1; // set ray direction to hit-to-light vector
            while (obj != (Object *)0)
            {
                if (obj->intersect( shadowRay, &hit ) == true)
                {
                    if (!((hit.t * hit.t) > (v2.lengthSq( ))))  // Check hit.t against magnitude of (un-normalised) intersection-to-light vector
                        if (!((hit.t * hit.t) < 0.001)) // Self-shadow if very very small t number
                        { // Used hit.t^2 to avoid having to SQRT the length. Is acceptable for comparisons
                            return true; // ray hits an onject, and the object occurs before the light
                        }
                }
                obj = obj->next( );
            }
        }
        lt = lt->next( );
    }
    return false;
}

如果检测到阴影,则仅将环境光归因于该点,否则将归因于环境 散布(我还没有添加镜头)。

任何建议都很棒!

错误警报伙计们!我发现了!

在每个对象列表循环之前,我添加了:

obj = obj_list;

要重置第一个对象,这解决了问题:)