summaryrefslogtreecommitdiffstats
path: root/tests/fcpw/aggregate.slang
blob: f83fa126a4a35fc32ea2e29409029aa9474e76bd (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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
implementing fcpw;
__include ray;
__include interaction;
__include bounding_volumes;
__include transform;

public interface IBranchTraversalWeight
{
    // computes the traversal weight for a given squared distance
    float compute(float r2);
};

public struct ConstantBranchTraversalWeight : IBranchTraversalWeight
{
    // computes the traversal weight for a given squared distance
    public float compute(float r2)
    {
        return 1.0;
    }
};

public interface IAggregate
{
    // updates the bounding volume of an aggregate node
    [mutating]
    void refit(uint nodeIndex);

    // intersects aggregate geometry with ray
    bool intersect(inout Ray r, bool checkForOcclusion, inout Interaction i);

    // intersects aggregate geometry with sphere
    bool intersect<T : IBranchTraversalWeight>(BoundingSphere s, float3 randNums,
                                               T branchTraversalWeight,
                                               inout Interaction i);

    // finds closest point on aggregate geometry from sphere center
    bool findClosestPoint(inout BoundingSphere s, inout Interaction i,
                          bool recordNormal = false);

    // finds closest silhouette point on aggregate geometry from sphere center
    bool findClosestSilhouettePoint(inout BoundingSphere s, bool flipNormalOrientation,
                                    float squaredMinRadius, float precision,
                                    inout Interaction i);
};

public struct TransformedAggregate<A : IAggregate> : IAggregate
{
    public A aggregate;
    public float3x4 t;
    public float3x4 tInv;

    // updates the bounding volume of an aggregate node
    // NOTE: refitting of transformed aggregates is currently quite inefficient, since the
    // shared aggregate is refit every time this function is called
    [mutating]
    public void refit(uint nodeIndex)
    {
        aggregate.refit(nodeIndex);
    }

    // intersects aggregate geometry with ray
    public bool intersect(inout Ray r, bool checkForOcclusion, inout Interaction i)
    {
        // apply inverse transform to ray
        Ray rInv = transformRay(tInv, r);

        // intersect
        bool didIntersect = aggregate.intersect(rInv, checkForOcclusion, i);

        // apply transform to ray and interaction
        r.tMax = transformRay(t, rInv).tMax;
        if (didIntersect)
        {
            transformInteraction(t, tInv, r.o, true, i);
            return true;
        }

        return false;
    }

    // intersects aggregate geometry with sphere
    public bool intersect<T : IBranchTraversalWeight>(BoundingSphere s, float3 randNums,
                                                      T branchTraversalWeight,
                                                      inout Interaction i)
    {
        // apply inverse transform to sphere
        BoundingSphere sInv = transformSphere(tInv, s);

        // intersect
        bool didIntersect = aggregate.intersect(sInv, randNums, branchTraversalWeight, i);

        // apply transform to interaction
        if (didIntersect)
        {
            transformInteraction(t, tInv, s.c, false, i);
            return true;
        }

        return false;
    }

    // finds closest point on aggregate geometry from sphere center
    public bool findClosestPoint(inout BoundingSphere s, inout Interaction i,
                                 bool recordNormal = false)
    {
        // apply inverse transform to sphere
        BoundingSphere sInv = transformSphere(tInv, s);

        // find closest point
        bool didFindClosestPoint = aggregate.findClosestPoint(sInv, i, recordNormal);

        // apply transform to sphere and interaction
        s.r2 = transformSphere(t, sInv).r2;
        if (didFindClosestPoint)
        {
            transformInteraction(t, tInv, s.c, true, i);
            return true;
        }

        return false;
    }

    // finds closest silhouette point on aggregate geometry from sphere center
    public bool findClosestSilhouettePoint(inout BoundingSphere s, bool flipNormalOrientation,
                                           float squaredMinRadius, float precision,
                                           inout Interaction i)
    {
        // apply inverse transform to sphere
        BoundingSphere sInv = transformSphere(tInv, s);
        BoundingSphere sMin = BoundingSphere(s.c, squaredMinRadius);
        BoundingSphere sMinInv = transformSphere(tInv, sMin);

        // find closest silhouette point
        bool didFindClosestSilhouettePoint = aggregate.findClosestSilhouettePoint(
            sInv, flipNormalOrientation, sMinInv.r2, precision, i);

        // apply transform to sphere and interaction
        s.r2 = transformSphere(t, sInv).r2;
        if (didFindClosestSilhouettePoint)
        {
            transformInteraction(t, tInv, s.c, true, i);
            return true;
        }

        return false;
    }
};