|
6 | 6 | #extension GL_GOOGLE_include_directive : require
|
7 | 7 |
|
8 | 8 | #define SPHERE_COUNT 8
|
9 |
| -#define TRIANGLE_METHOD 2 // 0 area sampling, 1 solid angle sampling, 2 approximate projected solid angle sampling |
| 9 | +#define POLYGON_METHOD 0 // 0 area sampling, 1 solid angle sampling, 2 approximate projected solid angle sampling |
10 | 10 | #include "common.glsl"
|
11 | 11 |
|
12 | 12 | #define TRIANGLE_COUNT 1
|
13 | 13 | Triangle triangles[TRIANGLE_COUNT] = {
|
14 | 14 | Triangle_Triangle(mat3(vec3(-1.8,0.35,0.3),vec3(-1.2,0.35,0.0),vec3(-1.5,0.8,-0.3)),INVALID_ID_16BIT,0u)
|
15 | 15 | };
|
16 | 16 |
|
17 |
| -int traceRay(inout float intersectionT, in vec3 origin, in vec3 direction) |
| 17 | +void traceRay_extraShape(inout int objectID, inout float intersectionT, in vec3 origin, in vec3 direction) |
18 | 18 | {
|
19 |
| - const bool anyHit = intersectionT!=FLT_MAX; |
20 |
| - |
21 |
| - int objectID = -1; |
22 |
| - for (int i=0; i<SPHERE_COUNT; i++) |
23 |
| - { |
24 |
| - float t = Sphere_intersect(spheres[i],origin,direction); |
25 |
| - bool closerIntersection = t>0.0 && t<intersectionT; |
26 |
| - |
27 |
| - objectID = closerIntersection ? i:objectID; |
28 |
| - intersectionT = closerIntersection ? t:intersectionT; |
29 |
| - |
30 |
| - // allowing early out results in a performance regression, WTF!? |
31 |
| - //if (anyHit && closerIntersection) |
32 |
| - //break; |
33 |
| - } |
34 | 19 | for (int i=0; i<TRIANGLE_COUNT; i++)
|
35 | 20 | {
|
36 | 21 | float t = Triangle_intersect(triangles[i],origin,direction);
|
37 | 22 | bool closerIntersection = t>0.0 && t<intersectionT;
|
38 | 23 |
|
39 | 24 | objectID = closerIntersection ? (i+SPHERE_COUNT):objectID;
|
40 | 25 | intersectionT = closerIntersection ? t:intersectionT;
|
41 |
| - |
42 |
| - // allowing early out results in a performance regression, WTF!? |
43 |
| - //if (anyHit && closerIntersection) |
44 |
| - //break; |
45 | 26 | }
|
46 |
| - return objectID; |
47 | 27 | }
|
48 | 28 |
|
49 | 29 |
|
50 | 30 | #include <nbl/builtin/glsl/sampling/projected_spherical_triangle.glsl>
|
51 |
| - |
52 |
| - |
53 |
| -// the interaction here is the interaction at the illuminator-end of the ray, not the receiver |
54 |
| -vec3 nbl_glsl_light_deferred_eval_and_prob( |
55 |
| - out float pdf, in Light light, in vec3 L |
56 |
| -#if TRIANGLE_METHOD==0 |
57 |
| - ,in float intersectionT |
58 |
| -#else |
59 |
| - ,in vec3 origin |
60 |
| -#if TRIANGLE_METHOD==2 |
61 |
| - ,in vec3 normalAtOrigin, in bool wasBSDFAtOrigin |
62 |
| -#endif |
63 |
| -#endif |
64 |
| -) |
| 31 | +float nbl_glsl_light_deferred_pdf(in Light light, in Ray_t ray) |
65 | 32 | {
|
66 |
| - // we don't have to worry about solid angle of the light w.r.t. surface of the light because this function only ever gets called from closestHit routine, so such ray cannot be produced |
67 |
| - pdf = scene_getLightChoicePdf(light); |
| 33 | + const Triangle tri = triangles[Light_getObjectID(light)]; |
68 | 34 |
|
69 |
| - Triangle tri = triangles[Light_getObjectID(light)]; |
70 |
| -#if TRIANGLE_METHOD==0 |
71 |
| - pdf *= intersectionT*intersectionT/abs(dot(Triangle_getNormalTimesArea(tri),L)); |
| 35 | + const vec3 L = ray._immutable.direction; |
| 36 | +#if POLYGON_METHOD==0 |
| 37 | + const float dist = ray._mutable.intersectionT; |
| 38 | + return dist*dist/abs(dot(Triangle_getNormalTimesArea(tri),L)); |
72 | 39 | #else
|
73 |
| - const mat3 sphericalVertices = nbl_glsl_shapes_getSphericalTriangle(mat3(tri.vertex0,tri.vertex1,tri.vertex2),origin); |
74 |
| - Triangle tmpTri = Triangle_Triangle(mat3(tri.vertex0,tri.vertex1,tri.vertex2),0u,0u); |
75 |
| - #if TRIANGLE_METHOD==1 |
76 |
| - float rcpProb = nbl_glsl_shapes_SolidAngleOfTriangle(sphericalVertices); |
| 40 | + const ImmutableRay_t _immutable = ray._immutable; |
| 41 | + const mat3 sphericalVertices = nbl_glsl_shapes_getSphericalTriangle(mat3(tri.vertex0,tri.vertex1,tri.vertex2),_immutable.origin); |
| 42 | + #if POLYGON_METHOD==1 |
| 43 | + const float rcpProb = nbl_glsl_shapes_SolidAngleOfTriangle(sphericalVertices); |
77 | 44 | // if `rcpProb` is NAN then the triangle's solid angle was close to 0.0
|
78 |
| - pdf = rcpProb>FLT_MIN ? (pdf/rcpProb):FLT_MAX; |
79 |
| - #elif TRIANGLE_METHOD==2 |
80 |
| - pdf *= nbl_glsl_sampling_probProjectedSphericalTriangleSample(sphericalVertices,normalAtOrigin,wasBSDFAtOrigin,L); |
| 45 | + return rcpProb>FLT_MIN ? (1.0/rcpProb):FLT_MAX; |
| 46 | + #elif POLYGON_METHOD==2 |
| 47 | + const float pdf = nbl_glsl_sampling_probProjectedSphericalTriangleSample(sphericalVertices,_immutable.normalAtOrigin,_immutable.wasBSDFAtOrigin,L); |
81 | 48 | // if `pdf` is NAN then the triangle's projected solid angle was close to 0.0, if its close to INF then the triangle was very small
|
82 |
| - pdf = pdf<FLT_MAX ? pdf:0.0; |
| 49 | + return pdf<FLT_MAX ? pdf:0.0; |
83 | 50 | #endif
|
84 | 51 | #endif
|
85 |
| - return Light_getRadiance(light); |
86 | 52 | }
|
87 | 53 |
|
88 |
| - |
89 |
| -nbl_glsl_LightSample nbl_glsl_light_generate_and_remainder_and_pdf(out vec3 remainder, out float pdf, out float newRayMaxT, in vec3 origin, in nbl_glsl_AnisotropicViewSurfaceInteraction interaction, in bool isBSDF, in vec3 u, in uint depth) |
| 54 | +vec3 nbl_glsl_light_generate_and_pdf(out float pdf, out float newRayMaxT, in vec3 origin, in nbl_glsl_AnisotropicViewSurfaceInteraction interaction, in bool isBSDF, in vec3 xi, in uint objectID) |
90 | 55 | {
|
91 |
| - // normally we'd pick from set of lights, using `u.z` |
92 |
| - const Light light = lights[0]; |
93 |
| - const float choicePdf = scene_getLightChoicePdf(light); |
94 |
| - |
95 |
| - const Triangle tri = triangles[Light_getObjectID(light)]; |
| 56 | + const Triangle tri = triangles[objectID]; |
96 | 57 |
|
97 |
| -#if TRIANGLE_METHOD==0 |
| 58 | +#if POLYGON_METHOD==0 |
98 | 59 | const mat2x3 edges = mat2x3(tri.vertex1-tri.vertex0,tri.vertex2-tri.vertex0);
|
99 |
| - const float sqrtU = sqrt(u.x); |
100 |
| - vec3 point = tri.vertex0+edges[0]*(1.0-sqrtU)+edges[1]*sqrtU*u.y; |
101 |
| - vec3 L = point-origin; |
| 60 | + const float sqrtU = sqrt(xi.x); |
| 61 | + vec3 point = tri.vertex0+edges[0]*(1.0-sqrtU)+edges[1]*sqrtU*xi.y; |
| 62 | + const vec3 L = point-origin; |
102 | 63 |
|
103 | 64 | const float distanceSq = dot(L,L);
|
104 | 65 | const float rcpDistance = inversesqrt(distanceSq);
|
105 |
| - L *= rcpDistance; |
106 |
| - |
107 |
| - const float dist = 1.0/rcpDistance; |
108 | 66 |
|
109 |
| - const float rcpPdf = abs(dot(Triangle_getNormalTimesArea_impl(edges),L))/(distanceSq*choicePdf); |
| 67 | + pdf = distanceSq/abs(dot(Triangle_getNormalTimesArea_impl(edges),L)); |
| 68 | + newRayMaxT = 1.0/rcpDistance; |
| 69 | + return L*rcpDistance; |
110 | 70 | #else
|
111 | 71 | float rcpPdf;
|
112 | 72 |
|
113 | 73 | const mat3 sphericalVertices = nbl_glsl_shapes_getSphericalTriangle(mat3(tri.vertex0,tri.vertex1,tri.vertex2),origin);
|
114 |
| -#if TRIANGLE_METHOD==1 |
115 |
| - const vec3 L = nbl_glsl_sampling_generateSphericalTriangleSample(rcpPdf,sphericalVertices,u.xy); |
116 |
| -#elif TRIANGLE_METHOD==2 |
117 |
| - const vec3 L = nbl_glsl_sampling_generateProjectedSphericalTriangleSample(rcpPdf,sphericalVertices,interaction.isotropic.N,isBSDF,u.xy); |
| 74 | +#if POLYGON_METHOD==1 |
| 75 | + const vec3 L = nbl_glsl_sampling_generateSphericalTriangleSample(rcpPdf,sphericalVertices,xi.xy); |
| 76 | +#elif POLYGON_METHOD==2 |
| 77 | + const vec3 L = nbl_glsl_sampling_generateProjectedSphericalTriangleSample(rcpPdf,sphericalVertices,interaction.isotropic.N,isBSDF,xi.xy); |
118 | 78 | #endif
|
| 79 | + |
119 | 80 | // if `rcpProb` is NAN or negative then the triangle's solidAngle or projectedSolidAngle was close to 0.0
|
120 |
| - rcpPdf = rcpPdf>FLT_MIN ? rcpPdf:0.0; |
| 81 | + pdf = rcpPdf>FLT_MIN ? (1.0/rcpPdf):0.0; |
121 | 82 |
|
122 | 83 | const vec3 N = Triangle_getNormalTimesArea(tri);
|
123 |
| - const float dist = dot(N,tri.vertex0-origin)/dot(N,L); |
| 84 | + newRayMaxT = dot(N,tri.vertex0-origin)/dot(N,L); |
| 85 | + return L; |
124 | 86 | #endif
|
125 |
| - |
126 |
| - remainder = Light_getRadiance(light)*rcpPdf; |
127 |
| - pdf = 1.0/rcpPdf; |
128 |
| - |
129 |
| - newRayMaxT = getEndTolerance(depth)*dist; |
130 |
| - |
131 |
| - return nbl_glsl_createLightSample(L,interaction); |
132 | 87 | }
|
133 | 88 |
|
134 | 89 |
|
@@ -175,18 +130,7 @@ bool closestHitProgram(in uint depth, in uint _sample, inout Ray_t ray, inout nb
|
175 | 130 | if (lightID!=INVALID_ID_16BIT) // has emissive
|
176 | 131 | {
|
177 | 132 | float lightPdf;
|
178 |
| - vec3 lightVal = nbl_glsl_light_deferred_eval_and_prob( |
179 |
| - lightPdf,lights[lightID],_immutable.direction |
180 |
| - #if TRIANGLE_METHOD==0 |
181 |
| - ,_mutable.intersectionT |
182 |
| - #else |
183 |
| - ,_immutable.origin |
184 |
| - #if TRIANGLE_METHOD==2 |
185 |
| - ,_immutable.normalAtOrigin,_immutable.wasBSDFAtOrigin |
186 |
| - #endif |
187 |
| - #endif |
188 |
| - ); |
189 |
| - ray._payload.accumulation += lightVal*throughput/(1.0+lightPdf*lightPdf*ray._payload.otherTechniqueHeuristic); |
| 133 | + ray._payload.accumulation += nbl_glsl_light_deferred_eval_and_prob(lightPdf,lights[lightID],ray)*throughput/(1.0+lightPdf*lightPdf*ray._payload.otherTechniqueHeuristic); |
190 | 134 | }
|
191 | 135 |
|
192 | 136 | // check if we even have a BSDF at all
|
@@ -263,8 +207,10 @@ bool closestHitProgram(in uint depth, in uint _sample, inout Ray_t ray, inout nb
|
263 | 207 | // trace new ray
|
264 | 208 | ray._immutable.origin = intersection+bsdfSampleL*(1.0/*kSceneSize*/)*getStartTolerance(depth);
|
265 | 209 | ray._immutable.direction = bsdfSampleL;
|
| 210 | + #if POLYGON_METHOD==2 |
266 | 211 | ray._immutable.normalAtOrigin = interaction.isotropic.N;
|
267 | 212 | ray._immutable.wasBSDFAtOrigin = isBSDF;
|
| 213 | + #endif |
268 | 214 | return true;
|
269 | 215 | }
|
270 | 216 | }
|
|
0 commit comments