Трассировка лучей: проблемы с выводом теневых лучей

До того, как это будет помечено как дубликат, у меня точно такая же проблема, как и у человека, который задал этот вопрос.

К сожалению, у него нет ответа, который помог бы вообще, так что, надеюсь, это вызовет лучшую дискуссию. Используя C++, задача состоит в том, чтобы запрограммировать классический трассировщик лучей. Я использую модель затенения Фонга и могу точно освещать свои сцены до тех пор, пока мне не понадобится отбрасывать теневые лучи.

Просто для справки, вот картина того, что я имею до сих пор, не пытаясь тени:

Следуя традиционному алгоритму трассировки лучей, где я ищу ближайший объект к своей камере-обскуре, я вызываю следующую функцию, которая вычисляет результирующий цвет пикселя:

glm::vec3 Scene::illuminate(Ray* primary, Surface* object, glm::vec3 hitPt)
{
    float red, green, blue;
    Material m = object->getMaterial();
    float p = m.phongCoef;
    glm::vec3 kD = m.diffuse;
    glm::vec3 kS = m.specular;
    glm::vec3 kA = m.ambient;
    float iA = m.ambienceIntensity;
    float i = lightSrc.lightIntensity;
    glm::vec3 n = object->getSurfaceNormalAt(hitPt); //normalized before return.
    glm::vec3 viewRay = primary->getDirection();   //normalized class member.

    glm::vec3 lightRay = glm::normalize((lightSrc.getOrigin()) - hitPt); //origin not normalized before here
    glm::vec3 h = glm::normalize(viewRay + lightRay);
    float nDotlightRay = glm::dot(n,lightRay);
    float nDoth = glm::dot(n, h);

    bool inShadow = false;
    Ray shadowRay;
    //hitPt = glm::normalize(hitPt);
    shadowRay.setOrigin(hitPt);
    shadowRay.setDirectionVector(lightRay);
    for (int k = 0; k < objects.size(); ++k) {
        if (objects.at(k)->intersect(shadowRay)) {
            //std::cout<<shadowRay.getDirection().x<<","<< shadowRay.getDirection().y <<","<<shadowRay.getDirection().z<<"\n";
            inShadow = true;
            break;}}

    //plug in to shading model
    if (inShadow)
    {
        red = kA.x*iA;
        green = kA.y*iA ;
        blue = kA.z*iA ;
    }
    else{
        red = kA.x*iA  +  kD.x*i*(fmax(0,nDotlightRay))  +  kS.x*i*(powf((fmax(0, nDoth)),p));
        green = kA.y*iA  +  kD.y*i*(fmax(0,nDotlightRay))  +  kS.y*i*(powf((fmax(0, nDoth)),p));
        blue = kA.z*iA  +  kD.z*i*(fmax(0,nDotlightRay))  +  kS.z*i*(powf((fmax(0, nDoth)),p));
    }

    glm::vec3 pixelColor = glm::vec3(red, green, blue);
    return pixelColor;
}

Я попытался использовать описательные имена переменных / функций, чтобы минимизировать объяснение, сопровождающее мой код. glm::vec3 это просто структура данных из математической библиотеки GLM, которая содержит трехмерный вектор, на котором можно выполнять матричные / векторные манипуляции.

Как и в приведенном выше вопросе, вот как выглядит моя сцена после попытки создания теней.

Положение света для этой сцены (0, 2,5, -7,75) выражено в системе отсчета камеры (которая имеет начало координат (0,0,0) и направлена ​​в отрицательное направление z). Для другой сцены источник света находится в точке (4, 6, -1), и для этого выходной сигнал даже не согласуется с проблемами другой сцены, которую я пытался воспроизвести, как вы можете видеть здесь; у него только тонкая серая линия на вершине сцены, где-нибудь еще нет теней? Я полностью потерян и потратил около 10 часов на эту проблему в одиночку; Будем признательны любому совету.

Пожалуйста, дайте мне знать, если есть какая-либо другая информация, которую я могу предоставить, например, как я вычисляю расстояние и HitPoint? Я не знаю, стоит ли мне смотреть на них, так как часть затенения работает отлично, или вы, ребята, думаете, что это все еще может вызвать эту проблему? Глубина и тому подобное не должны быть проблемой, так как объекты выглядят корректно вплоть до теней?

1 ответ

Отвечая на мой собственный вопрос: конкретные артефакты теней, упомянутые выше, были результатом пропуска источника луча в моих вычислениях пересечения. Первоначально я не беспокоился, так как моя система отсчета камеры была в (0,0,0). Но для теневых лучей начало координат не является нулевым вектором, и поэтому повторное использование тех же самых тестовых функций пересечения дало результаты, которые были полностью отключены. Удостоверьтесь, что использование нормализованных векторов направления также является ключевым моментом, иначе выходные данные не будут иметь смысла, что затруднит определение возможной ошибки.

Другие вопросы по тегам