@@ -16,15 +16,15 @@ Sphere spheres[SPHERE_COUNT] = {
16
16
};
17
17
#define TRIANGLE_COUNT 1
18
18
Triangle triangles[TRIANGLE_COUNT] = {
19
- 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)
20
- // Triangle_Triangle(mat3(vec3(-4,0.7,-4),vec3(0.0,0.7,0.0),vec3(-4.0,0.8,4.0)),INVALID_ID_16BIT,0u)
19
+ // 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)
20
+ Triangle_Triangle(mat3 (vec3 (- 4 ,0.7 ,- 4 ),vec3 (0.0 ,0.7 ,0.0 ),vec3 (- 4.0 ,0.8 ,4.0 )),INVALID_ID_16BIT,0u)
21
21
};
22
22
23
23
24
24
#define LIGHT_COUNT 1
25
25
Light lights[LIGHT_COUNT] = {
26
- {vec3 (30.0 ,25.0 ,15.0 ),0u}
27
- // {vec3(30.0,25.0,15.0)*0.01,0u}
26
+ // {vec3(30.0,25.0,15.0),0u}
27
+ {vec3 (30.0 ,25.0 ,15.0 )* 0.01 ,0u}
28
28
};
29
29
30
30
@@ -82,13 +82,20 @@ vec3 irr_glsl_slerp_impl_impl(in vec3 start, in vec3 preScaledWaypoint, float co
82
82
83
83
// @Crisspl move this to `irr/builtin/glsl/shapes/triangle.glsl`
84
84
85
+ //
86
+ mat3 irr_glsl_shapes_getSphericalTriangle(in mat3 vertices, in vec3 origin)
87
+ {
88
+ // the `normalize` cannot be optimized out
89
+ return mat3 (normalize (vertices[0 ]- origin),normalize (vertices[1 ]- origin),normalize (vertices[2 ]- origin));
90
+ }
91
+
85
92
// returns solid angle of a spherical triangle
86
93
// WARNING: can and will return NAN if one or three of the triangle edges are near zero length
87
94
// this function is beyond optimized.
88
- float irr_glsl_SolidAngleOfTriangle (in vec3 A, in vec3 B, in vec3 C , out vec3 cos_vertices, out vec3 sin_vertices, out float cosC, out float cscB)
95
+ float irr_glsl_shapes_SolidAngleOfTriangle (in mat3 sphericalVertices , out vec3 cos_vertices, out vec3 sin_vertices, out float cosC, out float cscB)
89
96
{
90
97
// The sides are denoted by lower-case letters a, b, and c. On the unit sphere their lengths are numerically equal to the radian measure of the angles that the great circle arcs subtend at the centre. The sides of proper spherical triangles are (by convention) less than PI
91
- const vec3 cos_sides = vec3 (dot (B,C ),dot (C,A ),dot (A,B ));
98
+ const vec3 cos_sides = vec3 (dot (sphericalVertices[ 1 ],sphericalVertices[ 2 ] ),dot (sphericalVertices[ 2 ],sphericalVertices[ 0 ] ),dot (sphericalVertices[ 0 ],sphericalVertices[ 1 ] ));
92
99
const vec3 csc_sides = inversesqrt (vec3 (1.0 )- cos_sides* cos_sides);
93
100
94
101
// these variables might eventually get optimized out
@@ -109,32 +116,48 @@ float irr_glsl_SolidAngleOfTriangle(in vec3 A, in vec3 B, in vec3 C, out vec3 co
109
116
return ((something0 ? something2: something1) ? (- absArccosSumABC): absArccosSumABC)+ (something0|| something1 ? irr_glsl_PI: (- irr_glsl_PI));
110
117
}
111
118
// returns solid angle of a triangle given by its world-space vertices and world-space viewing position
112
- float irr_glsl_SolidAngleOfTriangle (in mat3 vertices, in vec3 origin)
119
+ float irr_glsl_shapes_SolidAngleOfTriangle (in mat3 vertices, in vec3 origin)
113
120
{
114
- // the `normalize` cannot be optimized out
115
- const vec3 A = normalize (vertices[0 ]- origin);
116
- const vec3 B = normalize (vertices[1 ]- origin);
117
- const vec3 C = normalize (vertices[2 ]- origin);
118
-
119
121
vec3 dummy0,dummy1;
120
122
float dummy2,dummy3;
121
- return irr_glsl_SolidAngleOfTriangle(A,B,C,dummy0,dummy1,dummy2,dummy3);
123
+ return irr_glsl_shapes_SolidAngleOfTriangle(irr_glsl_shapes_getSphericalTriangle(vertices,origin),dummy0,dummy1,dummy2,dummy3);
124
+ }
125
+
126
+ // @Crisspl move this to `irr/builtin/glsl/sampling/bilinear.glsl`
127
+
128
+ float irr_glsl_sampling_generateLinearSample(in vec2 linearCoeffs, in float u)
129
+ {
130
+ const float rcpDiff = 1.0 / (linearCoeffs[0 ]- linearCoeffs[1 ]);
131
+ const vec2 squaredCoeffs = linearCoeffs* linearCoeffs;
132
+ return abs (rcpDiff)< FLT_MAX ? (linearCoeffs[0 ]- sqrt (mix (squaredCoeffs[0 ],squaredCoeffs[1 ],u)))* rcpDiff: u;
133
+ }
134
+
135
+ // The square's vertex values are defined in Z-order, so indices 0,1,2,3 (xyzw) correspond to (0,0),(1,0),(0,1),(1,1)
136
+ vec2 irr_glsl_sampling_generateBilinearSample(out float rcpPdf, in vec4 bilinearCoeffs, vec2 u)
137
+ {
138
+ const vec2 twiceAreasUnderXCurve = vec2 (bilinearCoeffs[0 ]+ bilinearCoeffs[1 ],bilinearCoeffs[2 ]+ bilinearCoeffs[3 ]);
139
+ u.y = irr_glsl_sampling_generateLinearSample(twiceAreasUnderXCurve,u.y);
140
+
141
+ const vec2 ySliceEndPoints = vec2 (mix (bilinearCoeffs[0 ],bilinearCoeffs[2 ],u.y),mix (bilinearCoeffs[1 ],bilinearCoeffs[3 ],u.y));
142
+ u.x = irr_glsl_sampling_generateLinearSample(ySliceEndPoints,u.x);
143
+
144
+ rcpPdf = (twiceAreasUnderXCurve[0 ]+ twiceAreasUnderXCurve[1 ])/ (4.0 * mix (ySliceEndPoints[0 ],ySliceEndPoints[1 ],u.x));
145
+
146
+ return u;
122
147
}
148
+
149
+ // @Crisspl move this to `irr/builtin/glsl/sampling/triangle.glsl`
150
+
123
151
// WARNING: can and will return NAN if one or three of the triangle edges are near zero length
124
152
// this function could use some more optimizing
125
- vec3 irr_glsl_sampling_generateSphericalTriangleSample(out float rcpPdf, in mat3 vertices, in vec3 origin , in vec2 u)
153
+ vec3 irr_glsl_sampling_generateSphericalTriangleSample(out float rcpPdf, in mat3 sphericalVertices , in vec2 u)
126
154
{
127
- // the `normalize` cannot be optimized out
128
- const vec3 A = normalize (vertices[0 ]- origin);
129
- const vec3 B = normalize (vertices[1 ]- origin);
130
- const vec3 C = normalize (vertices[2 ]- origin);
131
-
132
155
// for angles between view-to-vertex vectors
133
156
float cosC,cscB;
134
157
// Both vertices and angles at the vertices are denoted by the same upper case letters A, B, and C. The angles A, B, C of the triangle are equal to the angles between the planes that intersect the surface of the sphere or, equivalently, the angles between the tangent vectors of the great circle arcs where they meet at the vertices. Angles are in radians. The angles of proper spherical triangles are (by convention) less than PI
135
158
vec3 cos_vertices,sin_vertices;
136
159
// get solid angle, which is also the reciprocal of the probability
137
- rcpPdf = irr_glsl_SolidAngleOfTriangle(A,B,C ,cos_vertices,sin_vertices,cosC,cscB);
160
+ rcpPdf = irr_glsl_shapes_SolidAngleOfTriangle(sphericalVertices ,cos_vertices,sin_vertices,cosC,cscB);
138
161
139
162
// this part literally cannot be optimized further
140
163
float negSinSubSolidAngle,negCosSubSolidAngle;
@@ -149,14 +172,64 @@ vec3 irr_glsl_sampling_generateSphericalTriangleSample(out float rcpPdf, in mat3
149
172
150
173
const float cosAngleAlongAC = clamp (((v_* q - u_* p)* cos_vertices[0 ] - v_) / ((v_* p + u_* q)* sin_vertices[0 ]), - 1.0 , 1.0 ); // TODO: get rid of this clamp (by improving the precision here)
151
174
152
- vec3 C_s = irr_glsl_slerp_impl_impl(A, C * cscB, cosAngleAlongAC);
175
+ vec3 C_s = irr_glsl_slerp_impl_impl(sphericalVertices[ 0 ], sphericalVertices[ 2 ] * cscB, cosAngleAlongAC);
153
176
154
- const float cosBC_s = dot (C_s,B );
177
+ const float cosBC_s = dot (C_s,sphericalVertices[ 1 ] );
155
178
const float cosAngleAlongBC_s = cosBC_s* u.y - u.y + 1.0 ;
156
179
157
- return irr_glsl_slerp_impl_impl(B, C_s* inversesqrt (1.0 - cosBC_s* cosBC_s), cosAngleAlongBC_s);
180
+ return irr_glsl_slerp_impl_impl(sphericalVertices[1 ], C_s* inversesqrt (1.0 - cosBC_s* cosBC_s), cosAngleAlongBC_s);
181
+ }
182
+ vec3 irr_glsl_sampling_generateSphericalTriangleSample(out float rcpPdf, in mat3 vertices, in vec3 origin, in vec2 u)
183
+ {
184
+ return irr_glsl_sampling_generateSphericalTriangleSample(rcpPdf,irr_glsl_shapes_getSphericalTriangle(vertices,origin),u);
185
+ }
186
+
187
+ // There are two different modes of sampling, one for BSDF and one for BRDF (depending if we throw away bottom hemisphere or not)
188
+ vec3 irr_glsl_sampling_generateProjectedSphericalTriangleSample(out float rcpPdf, in mat3 sphericalVertices, in vec3 receiverNormal, vec2 u, in bool isBSDF)
189
+ {
190
+ // I don't see any problems with this being 0
191
+ const float minimumProjSolidAngle = 0.0 ;
192
+
193
+ vec3 bxdfPdfAtVertex = transpose (sphericalVertices)* receiverNormal;
194
+ // take abs of the value is we have a BSDF
195
+ bxdfPdfAtVertex = uintBitsToFloat(floatBitsToUint(bxdfPdfAtVertex)& uvec3 (isBSDF ? 0x7fFFffFFu: 0xffFFffFFu));
196
+ bxdfPdfAtVertex = max (bxdfPdfAtVertex,vec3 (minimumProjSolidAngle));
197
+
198
+ // the swizzle needs to match the mapping of the [0,1]^2 square to the triangle vertices
199
+ const vec4 bilinearDist = bxdfPdfAtVertex.yyxz;
200
+ // pre-warp according to proj solid angle approximation
201
+ u = irr_glsl_sampling_generateBilinearSample(rcpPdf,bilinearDist,u);
202
+
203
+ // now warp the points onto a spherical triangle
204
+ float solidAngle;
205
+ const vec3 L = irr_glsl_sampling_generateSphericalTriangleSample(solidAngle,sphericalVertices,u);
206
+ rcpPdf *= solidAngle;
207
+
208
+ return L;
209
+ }
210
+ vec3 irr_glsl_sampling_generateProjectedSphericalTriangleSample(out float rcpPdf, in mat3 vertices, in vec3 origin, in vec3 receiverNormal, in vec2 u, in bool isBSDF)
211
+ {
212
+ return irr_glsl_sampling_generateProjectedSphericalTriangleSample(rcpPdf,irr_glsl_shapes_getSphericalTriangle(vertices,origin),receiverNormal,u,isBSDF);
213
+ }
214
+ /*
215
+ //
216
+ vec2 irr_glsl_sampling_generateSphericalTriangleSampleInverse(out float rcpPdf, in mat3 sphericalVertices, in vec3 L)
217
+ {
218
+ // for angles between view-to-vertex vectors
219
+ float cosC,cscB;
220
+ // Both vertices and angles at the vertices are denoted by the same upper case letters A, B, and C. The angles A, B, C of the triangle are equal to the angles between the planes that intersect the surface of the sphere or, equivalently, the angles between the tangent vectors of the great circle arcs where they meet at the vertices. Angles are in radians. The angles of proper spherical triangles are (by convention) less than PI
221
+ vec3 cos_vertices,sin_vertices;
222
+ // get solid angle, which is also the reciprocal of the probability
223
+ rcpPdf = irr_glsl_shapes_SolidAngleOfTriangle(sphericalVertices,cos_vertices,sin_vertices,cosC,cscB);
224
+
225
+ return vec2(0.5,0.5);
226
+ }
227
+ vec2 irr_glsl_sampling_generateSphericalTriangleSampleInverse(out float rcpPdf, in mat3 vertices, in vec3 origin, in vec3 L)
228
+ {
229
+ return irr_glsl_sampling_generateSphericalTriangleSample(rcpPdf,irr_glsl_shapes_getSphericalTriangle(vertices,origin),L);
158
230
}
159
- // End-of @Crisspl move this to `irr/builtin/glsl/shapes/triangle.glsl`
231
+ */
232
+ // End-of @Crisspl move this to `irr/builtin/glsl/sampling/triangle.glsl`
160
233
161
234
// the interaction here is the interaction at the illuminator-end of the ray, not the receiver
162
235
vec3 irr_glsl_light_deferred_eval_and_prob(out float pdf, in vec3 origin, in float intersectionT, in irr_glsl_AnisotropicViewSurfaceInteraction interaction, in Light light)
@@ -171,7 +244,7 @@ vec3 irr_glsl_light_deferred_eval_and_prob(out float pdf, in vec3 origin, in flo
171
244
float rcpProb = irr_glsl_SolidAngleOfTriangle(mat3 (tri.vertex0,tri.vertex1,tri.vertex2),origin);
172
245
pdf /= isnan(rcpProb) ? 0.0 : rcpProb;
173
246
#elif TRIANGLE_METHOD== 2
174
- pdf /= Triangle_getApproxProjSolidAngle(tri,origin,interaction.isotropic.V.dir);
247
+ // pdf /= Triangle_getApproxProjSolidAngle(tri,origin,interaction.isotropic.V.dir);
175
248
#endif
176
249
return Light_getRadiance(light);
177
250
}
@@ -198,15 +271,19 @@ irr_glsl_LightSample irr_glsl_light_generate_and_remainder_and_pdf(out vec3 rema
198
271
const float dist = 1.0 / rcpDistance;
199
272
200
273
const float rcpPdf = abs (dot (Triangle_getNormalTimesArea_impl(edges),L))/ (distanceSq* choicePdf);
201
- #elif TRIANGLE_METHOD == 1
274
+ #else
202
275
float rcpPdf;
203
- const vec3 L = irr_glsl_sampling_generateSphericalTriangleSample(rcpPdf,mat3 (tri.vertex0,tri.vertex1,tri.vertex2),origin,u.xy);
276
+
277
+ const mat3 sphericalVertices = irr_glsl_shapes_getSphericalTriangle(mat3 (tri.vertex0,tri.vertex1,tri.vertex2),origin);
278
+ #if TRIANGLE_METHOD== 1
279
+ const vec3 L = irr_glsl_sampling_generateSphericalTriangleSample(rcpPdf,sphericalVertices,u.xy);
280
+ #elif TRIANGLE_METHOD== 2
281
+ const vec3 L = irr_glsl_sampling_generateProjectedSphericalTriangleSample(rcpPdf,sphericalVertices,interaction.isotropic.N,u.xy,false);
282
+ #endif
204
283
rcpPdf = isnan(rcpPdf) ? 0.0 : rcpPdf;
205
284
206
285
const vec3 N = Triangle_getNormalTimesArea(tri);
207
286
const float dist = dot (N,tri.vertex0- origin)/ dot (N,L);
208
- #elif TRIANGLE_METHOD== 2
209
- const float rcpPdf = Triangle_getApproxProjSolidAngle(tri,origin,interaction.isotropic.V.dir);
210
287
#endif
211
288
212
289
remainder = Light_getRadiance(light)* rcpPdf;
0 commit comments