Skip to content

Commit 6b6f746

Browse files
keep my code DRY
1 parent 75b0063 commit 6b6f746

File tree

3 files changed

+115
-148
lines changed

3 files changed

+115
-148
lines changed

examples_tests/42.FragmentShaderPathTracer/common.glsl

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ Light lights[LIGHT_COUNT] =
299299
{
300300
{
301301
vec3(30.0,25.0,15.0),
302-
#if defined(TRIANGLE_METHOD)||defined(RECTANGLE_METHOD)
302+
#ifdef POLYGON_METHOD
303303
0u
304304
#else
305305
8u
@@ -316,7 +316,7 @@ struct ImmutableRay_t
316316
{
317317
vec3 origin;
318318
vec3 direction;
319-
#if defined(TRIANGLE_METHOD)||defined(RECTANGLE_METHOD)
319+
#if POLYGON_METHOD==2
320320
vec3 normalAtOrigin;
321321
bool wasBSDFAtOrigin;
322322
#endif
@@ -486,7 +486,54 @@ mat2x3 rand3d(in uint protoDimension, in uint _sample, inout nbl_glsl_xoroshiro6
486486
return retval;
487487
}
488488

489-
int traceRay(inout float intersectionT, in vec3 origin, in vec3 direction);
489+
490+
void traceRay_extraShape(inout int objectID, inout float intersectionT, in vec3 origin, in vec3 direction);
491+
int traceRay(inout float intersectionT, in vec3 origin, in vec3 direction)
492+
{
493+
const bool anyHit = intersectionT!=FLT_MAX;
494+
495+
int objectID = -1;
496+
for (int i=0; i<SPHERE_COUNT; i++)
497+
{
498+
float t = Sphere_intersect(spheres[i],origin,direction);
499+
bool closerIntersection = t>0.0 && t<intersectionT;
500+
501+
intersectionT = closerIntersection ? t : intersectionT;
502+
objectID = closerIntersection ? i:objectID;
503+
504+
// allowing early out results in a performance regression, WTF!?
505+
//if (anyHit && closerIntersection)
506+
//break;
507+
}
508+
traceRay_extraShape(objectID,intersectionT,origin,direction);
509+
return objectID;
510+
}
511+
512+
//
513+
float nbl_glsl_light_deferred_pdf(in Light light, in Ray_t ray);
514+
vec3 nbl_glsl_light_deferred_eval_and_prob(out float pdf, in Light light, in Ray_t ray)
515+
{
516+
// 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 (because lights have no BSDFs here)
517+
pdf = scene_getLightChoicePdf(light);
518+
pdf *= nbl_glsl_light_deferred_pdf(light,ray);
519+
return Light_getRadiance(light);
520+
}
521+
522+
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);
523+
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 xi, in uint depth)
524+
{
525+
// normally we'd pick from set of lights, using `xi.z`
526+
const Light light = lights[0];
527+
528+
vec3 L = nbl_glsl_light_generate_and_pdf(pdf,newRayMaxT,origin,interaction,isBSDF,xi,Light_getObjectID(light));
529+
530+
newRayMaxT *= getEndTolerance(depth);
531+
pdf *= scene_getLightChoicePdf(light);
532+
remainder = Light_getRadiance(light)/pdf;
533+
return nbl_glsl_createLightSample(L,interaction);
534+
}
535+
536+
490537
bool closestHitProgram(in uint depth, in uint _sample, inout Ray_t ray, inout nbl_glsl_xoroshiro64star_state_t scramble_state);
491538

492539
void main()
@@ -535,7 +582,7 @@ void main()
535582
tmp = invMVP*tmp;
536583
ray._immutable.direction = normalize(tmp.xyz/tmp.w-camPos);
537584

538-
#if defined(TRIANGLE_METHOD)||defined(RECTANGLE_METHOD)
585+
#if POLYGON_METHOD==2
539586
ray._immutable.normalAtOrigin = vec3(0.0,0.0,0.0);
540587
ray._immutable.wasBSDFAtOrigin = false;
541588
#endif

examples_tests/42.FragmentShaderPathTracer/litBySphere.frag

Lines changed: 28 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -9,75 +9,50 @@
99
#include "common.glsl"
1010

1111

12-
13-
int traceRay(inout float intersectionT, in vec3 origin, in vec3 direction)
12+
void traceRay_extraShape(inout int objectID, inout float intersectionT, in vec3 origin, in vec3 direction)
1413
{
15-
const bool anyHit = intersectionT!=FLT_MAX;
16-
17-
int objectID = -1;
18-
for (int i=0; i<SPHERE_COUNT; i++)
19-
{
20-
float t = Sphere_intersect(spheres[i],origin,direction);
21-
bool closerIntersection = t>0.0 && t<intersectionT;
22-
23-
objectID = closerIntersection ? i:objectID;
24-
intersectionT = closerIntersection ? t:intersectionT;
25-
26-
// allowing early out results in a performance regression, WTF!?
27-
//if (anyHit && closerIntersection)
28-
//break;
29-
}
30-
return objectID;
3114
}
3215

33-
34-
// the interaction here is the interaction at the illuminator-end of the ray, not the receiver
35-
vec3 nbl_glsl_light_deferred_eval_and_prob(out float pdf, in Sphere sphere, in vec3 origin, in nbl_glsl_AnisotropicViewSurfaceInteraction interaction, in Light light)
16+
float nbl_glsl_light_deferred_pdf(in Light light, in Ray_t ray)
3617
{
37-
// 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
38-
pdf = scene_getLightChoicePdf(light)/Sphere_getSolidAngle(sphere,origin);
39-
return Light_getRadiance(light);
18+
const Sphere sphere = spheres[ray._mutable.objectID];
19+
return 1.0/Sphere_getSolidAngle(sphere,ray._immutable.origin);
4020
}
4121

42-
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 vec3 u, in uint depth)
22+
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)
4323
{
44-
// normally we'd pick from set of lights, using `u.z`
45-
const Light light = lights[0];
46-
const float choicePdf = scene_getLightChoicePdf(light);
47-
48-
const Sphere sphere = spheres[Light_getObjectID(light)];
24+
const Sphere sphere = spheres[objectID];
4925

5026
vec3 Z = sphere.position-origin;
5127
const float distanceSQ = dot(Z,Z);
5228
const float cosThetaMax2 = 1.0-sphere.radius2/distanceSQ;
53-
const float rcpDistance = inversesqrt(distanceSQ);
54-
55-
const bool possibilityOfLightVisibility = cosThetaMax2>0.0;
56-
Z *= rcpDistance;
29+
if (cosThetaMax2>0.0)
30+
{
31+
const float rcpDistance = inversesqrt(distanceSQ);
32+
Z *= rcpDistance;
5733

58-
// following only have valid values if `possibilityOfLightVisibility` is true
59-
const float cosThetaMax = sqrt(cosThetaMax2);
60-
const float cosTheta = mix(1.0,cosThetaMax,u.x);
34+
const float cosThetaMax = sqrt(cosThetaMax2);
35+
const float cosTheta = mix(1.0,cosThetaMax,xi.x);
6136

62-
vec3 L = Z*cosTheta;
37+
vec3 L = Z*cosTheta;
6338

64-
const float cosTheta2 = cosTheta*cosTheta;
65-
const float sinTheta = sqrt(1.0-cosTheta2);
66-
float sinPhi,cosPhi;
67-
nbl_glsl_sincos(2.0*nbl_glsl_PI*u.y-nbl_glsl_PI,sinPhi,cosPhi);
68-
mat2x3 XY = nbl_glsl_frisvad(Z);
69-
70-
L += (XY[0]*cosPhi+XY[1]*sinPhi)*sinTheta;
39+
const float cosTheta2 = cosTheta*cosTheta;
40+
const float sinTheta = sqrt(1.0-cosTheta2);
41+
float sinPhi,cosPhi;
42+
nbl_glsl_sincos(2.0*nbl_glsl_PI*xi.y-nbl_glsl_PI,sinPhi,cosPhi);
43+
mat2x3 XY = nbl_glsl_frisvad(Z);
7144

72-
const float rcpPdf = Sphere_getSolidAngle_impl(cosThetaMax)/choicePdf;
73-
remainder = Light_getRadiance(light)*(possibilityOfLightVisibility ? rcpPdf:0.0); // this ternary operator kills invalid rays
74-
pdf = 1.0/rcpPdf;
45+
L += (XY[0]*cosPhi+XY[1]*sinPhi)*sinTheta;
7546

76-
newRayMaxT = (cosTheta-sqrt(cosTheta2-cosThetaMax2))/rcpDistance*getEndTolerance(depth);
77-
78-
return nbl_glsl_createLightSample(L,interaction);
47+
newRayMaxT = (cosTheta-sqrt(cosTheta2-cosThetaMax2))/rcpDistance;
48+
pdf = 1.0/Sphere_getSolidAngle_impl(cosThetaMax);
49+
return L;
50+
}
51+
pdf = 0.0;
52+
return vec3(0.0,0.0,0.0);
7953
}
8054

55+
8156
bool closestHitProgram(in uint depth, in uint _sample, inout Ray_t ray, inout nbl_glsl_xoroshiro64star_state_t scramble_state)
8257
{
8358
const MutableRay_t _mutable = ray._mutable;
@@ -110,8 +85,7 @@ bool closestHitProgram(in uint depth, in uint _sample, inout Ray_t ray, inout nb
11085
if (lightID!=INVALID_ID_16BIT) // has emissive
11186
{
11287
float lightPdf;
113-
vec3 lightVal = nbl_glsl_light_deferred_eval_and_prob(lightPdf,sphere,ray._immutable.origin,interaction,lights[lightID]);
114-
ray._payload.accumulation += lightVal*throughput/(1.0+lightPdf*lightPdf*ray._payload.otherTechniqueHeuristic);
88+
ray._payload.accumulation += nbl_glsl_light_deferred_eval_and_prob(lightPdf,lights[lightID],ray)*throughput/(1.0+lightPdf*lightPdf*ray._payload.otherTechniqueHeuristic);
11589
}
11690

11791
// check if we even have a BSDF at all
@@ -144,7 +118,7 @@ bool closestHitProgram(in uint depth, in uint _sample, inout Ray_t ray, inout nb
144118
if (nbl_glsl_partitionRandVariable(neeSkipProbability,epsilon[0].z,rcpChoiceProb))
145119
{
146120
vec3 neeContrib; float lightPdf, t;
147-
nbl_glsl_LightSample nee_sample = nbl_glsl_light_generate_and_remainder_and_pdf(neeContrib,lightPdf,t,intersection,interaction,epsilon[0],depth);
121+
nbl_glsl_LightSample nee_sample = nbl_glsl_light_generate_and_remainder_and_pdf(neeContrib,lightPdf,t,intersection,interaction,false,epsilon[0],depth);
148122
// We don't allow non watertight transmitters in this renderer
149123
bool validPath = nee_sample.NdotL>0.0;
150124
// but if we allowed non-watertight transmitters (single water surface), it would make sense just to apply this line by itself

examples_tests/42.FragmentShaderPathTracer/litByTriangle.frag

Lines changed: 36 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -6,129 +6,84 @@
66
#extension GL_GOOGLE_include_directive : require
77

88
#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
1010
#include "common.glsl"
1111

1212
#define TRIANGLE_COUNT 1
1313
Triangle triangles[TRIANGLE_COUNT] = {
1414
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)
1515
};
1616

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)
1818
{
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-
}
3419
for (int i=0; i<TRIANGLE_COUNT; i++)
3520
{
3621
float t = Triangle_intersect(triangles[i],origin,direction);
3722
bool closerIntersection = t>0.0 && t<intersectionT;
3823

3924
objectID = closerIntersection ? (i+SPHERE_COUNT):objectID;
4025
intersectionT = closerIntersection ? t:intersectionT;
41-
42-
// allowing early out results in a performance regression, WTF!?
43-
//if (anyHit && closerIntersection)
44-
//break;
4526
}
46-
return objectID;
4727
}
4828

4929

5030
#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)
6532
{
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)];
6834

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));
7239
#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);
7744
// 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);
8148
// 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;
8350
#endif
8451
#endif
85-
return Light_getRadiance(light);
8652
}
8753

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)
9055
{
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];
9657

97-
#if TRIANGLE_METHOD==0
58+
#if POLYGON_METHOD==0
9859
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;
10263

10364
const float distanceSq = dot(L,L);
10465
const float rcpDistance = inversesqrt(distanceSq);
105-
L *= rcpDistance;
106-
107-
const float dist = 1.0/rcpDistance;
10866

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;
11070
#else
11171
float rcpPdf;
11272

11373
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);
11878
#endif
79+
11980
// 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;
12182

12283
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;
12486
#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);
13287
}
13388

13489

@@ -175,18 +130,7 @@ bool closestHitProgram(in uint depth, in uint _sample, inout Ray_t ray, inout nb
175130
if (lightID!=INVALID_ID_16BIT) // has emissive
176131
{
177132
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);
190134
}
191135

192136
// 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
263207
// trace new ray
264208
ray._immutable.origin = intersection+bsdfSampleL*(1.0/*kSceneSize*/)*getStartTolerance(depth);
265209
ray._immutable.direction = bsdfSampleL;
210+
#if POLYGON_METHOD==2
266211
ray._immutable.normalAtOrigin = interaction.isotropic.N;
267212
ray._immutable.wasBSDFAtOrigin = isBSDF;
213+
#endif
268214
return true;
269215
}
270216
}

0 commit comments

Comments
 (0)