aboutsummaryrefslogtreecommitdiff
path: root/src/illuminate/shadow.cpp
blob: 6057637389b4f6be5fc30a20cf5900212eb391e5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include "raytracer/raytracer.h"

bool RayTracer::isShadowed(
        glm::vec4 lightPosition,
        float distanceToLight,
        glm::vec4 directionFromIntersectionToLight,
        glm::vec4 intersectionWorld,
        const RayTraceScene &scene)
{
    // normalize direction
    directionFromIntersectionToLight = glm::normalize(directionFromIntersectionToLight);

     // acceleration causes "bad jaggies" so we disable it for now
    if (m_enableAcceleration)
    {
        RenderShapeData shapeData;
        auto pBias = intersectionWorld + .001f * directionFromIntersectionToLight;
        float t = traverseBVH(pBias, directionFromIntersectionToLight, shapeData, scene.m_bvh);
        return t != FINF;
    }

    for (const RenderShapeData &s: scene.getShapes()) {
        // convert this world ray to object space
        glm::vec4 dObject = glm::normalize(
                s.inverseCTM * directionFromIntersectionToLight);
        glm::vec4 pObject = s.inverseCTM * intersectionWorld;

        // see if there is an intersection
        bool isHit = false;
        glm::vec4 newIntersectionObj = findIntersection(pObject, dObject, s, isHit);

        if (newIntersectionObj.w == 1.f) // hit!
        {
            // check if the intersection is the same as the pObject
            if (floatEquals(glm::distance(newIntersectionObj, pObject), 0.f, 0.001f))
            {
                // don't consider self-intersections
                continue;
            }

            // check if this intersection is closer than the direction to the light
            auto newIntersectionWorld = s.ctm * newIntersectionObj;
            if (distanceToLight == FINF)
            {
                // if the light is infinitely far away light, then any non-self intersection is valid
                return true;
            }

            float newDist = glm::distance(newIntersectionWorld, lightPosition);
            if (newDist < distanceToLight - 0.001f)
            {
                // an object in front of the camera is the way -> shadow
                return true;
            }
        }
    }

    return false;
}