Трассировка лучей: тени от нескольких источников света

[Edit] Как это обычно бывает в программировании, я понял это вскоре после публикации! смотри мой ответ, если тебе интересно :)

Я работаю над трассировщиком лучей на C ++, и мне нужна была помощь. У меня есть 2 источника света в моей сцене: точечный свет и направленный свет, а также несколько сфер (вместе с плоскостью, выступающей в роли «пола»).

Если я запускаю трассировщик лучей с одним из источников света (но без другого источника), он создает тени, как и ожидалось (см. Изображения ниже).

Изображение теней направленного света

Изображение точечных световых теней

Проблема в том, что когда я запускаю свой трассировщик лучей с обоими источниками света, появляются только тени точечного света, я могу сказать, что свет включен, потому что сцена ярче:

Смотрите мой код ниже для обнаружения теней:

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;
}

Если обнаруживается тень, точке присваивается только окружающий свет, в противном случае приписывается окружающий + диффузный (я еще не дошел до добавления зеркального отражения).

Любые предложения были бы замечательными!


person NOSHEDMANTIS    schedule 24.02.2017    source источник
comment
(Ссылка для вывода с обоими источниками света [puu.sh/ui6Ka/e81edc5f6e.jpg] - потому что SO позволяет мне размещать только 2 ссылки в вопросе)   -  person NOSHEDMANTIS    schedule 24.02.2017


Ответы (1)


Ложная тревога, ребята! Я понял!!

перед каждым циклом списка объектов я добавил:

obj = obj_list;

чтобы вернуться к первому объекту, это решило проблему :)

person NOSHEDMANTIS    schedule 24.02.2017