0031135: Visualization, TKOpenGl - texture sRGB -> linear conversion is applied twice...
[occt.git] / src / Shaders / Shaders_PathtraceBase_fs.pxx
CommitLineData
ee5befae 1// This file has been automatically generated from resource file src/Shaders/PathtraceBase.fs
2
3static const char Shaders_PathtraceBase_fs[] =
6e728f3b 4 "#ifdef _MSC_VER\n"
5 " #define PATH_TRACING // just for editing in MS VS\n"
6 "\n"
7 " #define in\n"
8 " #define out\n"
9 " #define inout\n"
10 "\n"
11 " typedef struct { float x; float y; } vec2;\n"
12 " typedef struct { float x; float y; float z; } vec3;\n"
13 " typedef struct { float x; float y; float z; float w; } vec4;\n"
14 "#endif\n"
15 "\n"
ee5befae 16 "#ifdef PATH_TRACING\n"
17 "\n"
18 "///////////////////////////////////////////////////////////////////////////////////////\n"
19 "// Specific data types\n"
20 "\n"
21 "//! Describes local space at the hit point (visualization space).\n"
22 "struct SLocalSpace\n"
23 "{\n"
24 " //! Local X axis.\n"
25 " vec3 AxisX;\n"
26 "\n"
27 " //! Local Y axis.\n"
28 " vec3 AxisY;\n"
29 "\n"
30 " //! Local Z axis.\n"
31 " vec3 AxisZ;\n"
32 "};\n"
33 "\n"
34 "//! Describes material properties (BSDF).\n"
05aa616d 35 "struct SBSDF\n"
ee5befae 36 "{\n"
05aa616d 37 " //! Weight of coat specular/glossy BRDF.\n"
38 " vec4 Kc;\n"
39 "\n"
40 " //! Weight of base diffuse BRDF.\n"
ee5befae 41 " vec4 Kd;\n"
42 "\n"
05aa616d 43 " //! Weight of base specular/glossy BRDF.\n"
44 " vec4 Ks;\n"
ee5befae 45 "\n"
05aa616d 46 " //! Weight of base specular/glossy BTDF.\n"
ee5befae 47 " vec3 Kt;\n"
48 "\n"
05aa616d 49 " //! Fresnel coefficients of coat layer.\n"
50 " vec3 FresnelCoat;\n"
ee5befae 51 "\n"
05aa616d 52 " //! Fresnel coefficients of base layer.\n"
53 " vec3 FresnelBase;\n"
ee5befae 54 "};\n"
55 "\n"
56 "///////////////////////////////////////////////////////////////////////////////////////\n"
57 "// Support subroutines\n"
58 "\n"
59 "//=======================================================================\n"
6e728f3b 60 "// function : buildLocalSpace\n"
ee5befae 61 "// purpose : Generates local space for the given normal\n"
62 "//=======================================================================\n"
6e728f3b 63 "SLocalSpace buildLocalSpace (in vec3 theNormal)\n"
ee5befae 64 "{\n"
6e728f3b 65 " vec3 anAxisX = vec3 (theNormal.z, 0.f, -theNormal.x);\n"
66 " vec3 anAxisY = vec3 (0.f, -theNormal.z, theNormal.y);\n"
ee5befae 67 "\n"
68 " float aSqrLenX = dot (anAxisX, anAxisX);\n"
69 " float aSqrLenY = dot (anAxisY, anAxisY);\n"
70 "\n"
71 " if (aSqrLenX > aSqrLenY)\n"
72 " {\n"
73 " anAxisX *= inversesqrt (aSqrLenX);\n"
74 " anAxisY = cross (anAxisX, theNormal);\n"
75 " }\n"
76 " else\n"
77 " {\n"
78 " anAxisY *= inversesqrt (aSqrLenY);\n"
79 " anAxisX = cross (anAxisY, theNormal);\n"
80 " }\n"
81 "\n"
82 " return SLocalSpace (anAxisX, anAxisY, theNormal);\n"
83 "}\n"
84 "\n"
85 "//=======================================================================\n"
86 "// function : toLocalSpace\n"
87 "// purpose : Transforms the vector to local space from world space\n"
88 "//=======================================================================\n"
89 "vec3 toLocalSpace (in vec3 theVector, in SLocalSpace theSpace)\n"
90 "{\n"
91 " return vec3 (dot (theVector, theSpace.AxisX),\n"
92 " dot (theVector, theSpace.AxisY),\n"
93 " dot (theVector, theSpace.AxisZ));\n"
94 "}\n"
95 "\n"
96 "//=======================================================================\n"
97 "// function : fromLocalSpace\n"
98 "// purpose : Transforms the vector from local space to world space\n"
99 "//=======================================================================\n"
100 "vec3 fromLocalSpace (in vec3 theVector, in SLocalSpace theSpace)\n"
101 "{\n"
102 " return theVector.x * theSpace.AxisX +\n"
103 " theVector.y * theSpace.AxisY +\n"
104 " theVector.z * theSpace.AxisZ;\n"
105 "}\n"
106 "\n"
107 "//=======================================================================\n"
108 "// function : convolve\n"
109 "// purpose : Performs a linear convolution of the vector components\n"
110 "//=======================================================================\n"
111 "float convolve (in vec3 theVector, in vec3 theFactor)\n"
112 "{\n"
113 " return dot (theVector, theFactor) * (1.f / max (theFactor.x + theFactor.y + theFactor.z, 1e-15f));\n"
114 "}\n"
115 "\n"
116 "//=======================================================================\n"
ee5befae 117 "// function : fresnelSchlick\n"
118 "// purpose : Computes the Fresnel reflection formula using\n"
119 "// Schlick's approximation.\n"
120 "//=======================================================================\n"
121 "vec3 fresnelSchlick (in float theCosI, in vec3 theSpecularColor)\n"
122 "{\n"
123 " return theSpecularColor + (UNIT - theSpecularColor) * pow (1.f - theCosI, 5.f);\n"
124 "}\n"
125 "\n"
126 "//=======================================================================\n"
127 "// function : fresnelDielectric\n"
128 "// purpose : Computes the Fresnel reflection formula for dielectric in\n"
129 "// case of circularly polarized light (Based on PBRT code).\n"
130 "//=======================================================================\n"
131 "float fresnelDielectric (in float theCosI,\n"
132 " in float theCosT,\n"
133 " in float theEtaI,\n"
134 " in float theEtaT)\n"
135 "{\n"
136 " float aParl = (theEtaT * theCosI - theEtaI * theCosT) /\n"
137 " (theEtaT * theCosI + theEtaI * theCosT);\n"
138 "\n"
139 " float aPerp = (theEtaI * theCosI - theEtaT * theCosT) /\n"
140 " (theEtaI * theCosI + theEtaT * theCosT);\n"
141 "\n"
142 " return (aParl * aParl + aPerp * aPerp) * 0.5f;\n"
143 "}\n"
144 "\n"
145 "#define ENVIRONMENT_IOR 1.f\n"
146 "\n"
147 "//=======================================================================\n"
148 "// function : fresnelDielectric\n"
149 "// purpose : Computes the Fresnel reflection formula for dielectric in\n"
150 "// case of circularly polarized light (based on PBRT code)\n"
151 "//=======================================================================\n"
152 "float fresnelDielectric (in float theCosI, in float theIndex)\n"
153 "{\n"
05aa616d 154 " float aFresnel = 1.f;\n"
155 "\n"
ee5befae 156 " float anEtaI = theCosI > 0.f ? 1.f : theIndex;\n"
157 " float anEtaT = theCosI > 0.f ? theIndex : 1.f;\n"
158 "\n"
05aa616d 159 " float aSinT2 = (anEtaI * anEtaI) / (anEtaT * anEtaT) * (1.f - theCosI * theCosI);\n"
ee5befae 160 "\n"
05aa616d 161 " if (aSinT2 < 1.f)\n"
ee5befae 162 " {\n"
05aa616d 163 " aFresnel = fresnelDielectric (abs (theCosI), sqrt (1.f - aSinT2), anEtaI, anEtaT);\n"
ee5befae 164 " }\n"
165 "\n"
05aa616d 166 " return aFresnel;\n"
ee5befae 167 "}\n"
168 "\n"
169 "//=======================================================================\n"
170 "// function : fresnelConductor\n"
171 "// purpose : Computes the Fresnel reflection formula for conductor in case\n"
172 "// of circularly polarized light (based on PBRT source code)\n"
173 "//=======================================================================\n"
174 "float fresnelConductor (in float theCosI, in float theEta, in float theK)\n"
175 "{\n"
176 " float aTmp = 2.f * theEta * theCosI;\n"
177 "\n"
178 " float aTmp1 = theEta * theEta + theK * theK;\n"
179 "\n"
180 " float aSPerp = (aTmp1 - aTmp + theCosI * theCosI) /\n"
181 " (aTmp1 + aTmp + theCosI * theCosI);\n"
182 "\n"
183 " float aTmp2 = aTmp1 * theCosI * theCosI;\n"
184 "\n"
185 " float aSParl = (aTmp2 - aTmp + 1.f) /\n"
186 " (aTmp2 + aTmp + 1.f);\n"
187 "\n"
188 " return (aSPerp + aSParl) * 0.5f;\n"
189 "}\n"
190 "\n"
191 "#define FRESNEL_SCHLICK -0.5f\n"
192 "#define FRESNEL_CONSTANT -1.5f\n"
193 "#define FRESNEL_CONDUCTOR -2.5f\n"
194 "#define FRESNEL_DIELECTRIC -3.5f\n"
195 "\n"
196 "//=======================================================================\n"
197 "// function : fresnelMedia\n"
198 "// purpose : Computes the Fresnel reflection formula for general medium\n"
199 "// in case of circularly polarized light.\n"
200 "//=======================================================================\n"
6e728f3b 201 "vec3 fresnelMedia (in float theCosI, in vec3 theFresnel)\n"
ee5befae 202 "{\n"
05aa616d 203 " vec3 aFresnel;\n"
204 "\n"
6e728f3b 205 " if (theFresnel.x > FRESNEL_SCHLICK)\n"
ee5befae 206 " {\n"
05aa616d 207 " aFresnel = fresnelSchlick (abs (theCosI), theFresnel);\n"
ee5befae 208 " }\n"
05aa616d 209 " else if (theFresnel.x > FRESNEL_CONSTANT)\n"
ee5befae 210 " {\n"
05aa616d 211 " aFresnel = vec3 (theFresnel.z);\n"
ee5befae 212 " }\n"
05aa616d 213 " else if (theFresnel.x > FRESNEL_CONDUCTOR)\n"
214 " {\n"
215 " aFresnel = vec3 (fresnelConductor (abs (theCosI), theFresnel.y, theFresnel.z));\n"
216 " }\n"
217 " else\n"
ee5befae 218 " {\n"
05aa616d 219 " aFresnel = vec3 (fresnelDielectric (theCosI, theFresnel.y));\n"
ee5befae 220 " }\n"
221 "\n"
05aa616d 222 " return aFresnel;\n"
ee5befae 223 "}\n"
224 "\n"
225 "//=======================================================================\n"
226 "// function : transmitted\n"
227 "// purpose : Computes transmitted direction in tangent space\n"
228 "// (in case of TIR returned result is undefined!)\n"
229 "//=======================================================================\n"
230 "void transmitted (in float theIndex, in vec3 theIncident, out vec3 theTransmit)\n"
231 "{\n"
232 " // Compute relative index of refraction\n"
233 " float anEta = (theIncident.z > 0.f) ? 1.f / theIndex : theIndex;\n"
234 "\n"
6e728f3b 235 " // Handle total internal reflection (TIR)\n"
ee5befae 236 " float aSinT2 = anEta * anEta * (1.f - theIncident.z * theIncident.z);\n"
237 "\n"
6e728f3b 238 " // Compute direction of transmitted ray\n"
239 " float aCosT = sqrt (1.f - min (aSinT2, 1.f)) * sign (-theIncident.z);\n"
ee5befae 240 "\n"
241 " theTransmit = normalize (vec3 (-anEta * theIncident.x,\n"
242 " -anEta * theIncident.y,\n"
243 " aCosT));\n"
244 "}\n"
245 "\n"
246 "//////////////////////////////////////////////////////////////////////////////////////////////\n"
247 "// Handlers and samplers for materials\n"
248 "//////////////////////////////////////////////////////////////////////////////////////////////\n"
249 "\n"
250 "//=======================================================================\n"
b4327ba8 251 "// function : EvalLambertianReflection\n"
252 "// purpose : Evaluates Lambertian BRDF, with cos(N, PSI)\n"
ee5befae 253 "//=======================================================================\n"
b4327ba8 254 "float EvalLambertianReflection (in vec3 theWi, in vec3 theWo)\n"
ee5befae 255 "{\n"
b4327ba8 256 " return (theWi.z <= 0.f || theWo.z <= 0.f) ? 0.f : theWi.z * (1.f / M_PI);\n"
ee5befae 257 "}\n"
258 "\n"
05aa616d 259 "#define FLT_EPSILON 1.0e-5f\n"
260 "\n"
ee5befae 261 "//=======================================================================\n"
6e728f3b 262 "// function : SmithG1\n"
263 "// purpose :\n"
ee5befae 264 "//=======================================================================\n"
6e728f3b 265 "float SmithG1 (in vec3 theDirection, in vec3 theM, in float theRoughness)\n"
ee5befae 266 "{\n"
05aa616d 267 " float aResult = 0.f;\n"
ee5befae 268 "\n"
05aa616d 269 " if (dot (theDirection, theM) * theDirection.z > 0.f)\n"
6e728f3b 270 " {\n"
05aa616d 271 " float aTanThetaM = sqrt (1.f - theDirection.z * theDirection.z) / theDirection.z;\n"
ee5befae 272 "\n"
05aa616d 273 " if (aTanThetaM == 0.f)\n"
274 " {\n"
275 " aResult = 1.f;\n"
276 " }\n"
277 " else\n"
278 " {\n"
279 " float aVal = 1.f / (theRoughness * aTanThetaM);\n"
ee5befae 280 "\n"
05aa616d 281 " // Use rational approximation to shadowing-masking function (from Mitsuba)\n"
282 " aResult = (3.535f + 2.181f * aVal) / (1.f / aVal + 2.276f + 2.577f * aVal);\n"
283 " }\n"
6e728f3b 284 " }\n"
ee5befae 285 "\n"
05aa616d 286 " return min (aResult, 1.f);\n"
6e728f3b 287 "}\n"
ee5befae 288 "\n"
6e728f3b 289 "//=======================================================================\n"
b4327ba8 290 "// function : EvalBlinnReflection\n"
291 "// purpose : Evaluates Blinn glossy BRDF, with cos(N, PSI)\n"
6e728f3b 292 "//=======================================================================\n"
b4327ba8 293 "vec3 EvalBlinnReflection (in vec3 theWi, in vec3 theWo, in vec3 theFresnel, in float theRoughness)\n"
6e728f3b 294 "{\n"
295 " // calculate the reflection half-vec\n"
b4327ba8 296 " vec3 aH = normalize (theWi + theWo);\n"
ee5befae 297 "\n"
6e728f3b 298 " // roughness value -> Blinn exponent\n"
299 " float aPower = max (2.f / (theRoughness * theRoughness) - 2.f, 0.f);\n"
ee5befae 300 "\n"
6e728f3b 301 " // calculate microfacet distribution\n"
302 " float aD = (aPower + 2.f) * (1.f / M_2_PI) * pow (aH.z, aPower);\n"
ee5befae 303 "\n"
6e728f3b 304 " // calculate shadow-masking function\n"
b4327ba8 305 " float aG = SmithG1 (theWo, aH, theRoughness) *\n"
306 " SmithG1 (theWi, aH, theRoughness);\n"
ee5befae 307 "\n"
6e728f3b 308 " // return total amount of reflection\n"
b4327ba8 309 " return (theWi.z <= 0.f || theWo.z <= 0.f) ? ZERO :\n"
310 " aD * aG / (4.f * theWo.z) * fresnelMedia (dot (theWo, aH), theFresnel);\n"
ee5befae 311 "}\n"
312 "\n"
313 "//=======================================================================\n"
05aa616d 314 "// function : EvalBsdfLayered\n"
b4327ba8 315 "// purpose : Evaluates BSDF for specified material, with cos(N, PSI)\n"
ee5befae 316 "//=======================================================================\n"
05aa616d 317 "vec3 EvalBsdfLayered (in SBSDF theBSDF, in vec3 theWi, in vec3 theWo)\n"
ee5befae 318 "{\n"
b4327ba8 319 "#ifdef TWO_SIDED_BXDF\n"
320 " theWi.z *= sign (theWi.z);\n"
321 " theWo.z *= sign (theWo.z);\n"
322 "#endif\n"
323 "\n"
05aa616d 324 " vec3 aBxDF = theBSDF.Kd.rgb * EvalLambertianReflection (theWi, theWo);\n"
325 "\n"
326 " if (theBSDF.Ks.w > FLT_EPSILON)\n"
327 " {\n"
328 " aBxDF += theBSDF.Ks.rgb * EvalBlinnReflection (theWi, theWo, theBSDF.FresnelBase, theBSDF.Ks.w);\n"
329 " }\n"
330 "\n"
331 " aBxDF *= UNIT - fresnelMedia (theWo.z, theBSDF.FresnelCoat);\n"
332 "\n"
333 " if (theBSDF.Kc.w > FLT_EPSILON)\n"
334 " {\n"
335 " aBxDF += theBSDF.Kc.rgb * EvalBlinnReflection (theWi, theWo, theBSDF.FresnelCoat, theBSDF.Kc.w);\n"
336 " }\n"
337 "\n"
338 " return aBxDF;\n"
ee5befae 339 "}\n"
340 "\n"
341 "//=======================================================================\n"
6e728f3b 342 "// function : SampleLambertianReflection\n"
ee5befae 343 "// purpose : Samples Lambertian BRDF, W = BRDF * cos(N, PSI) / PDF(PSI)\n"
344 "//=======================================================================\n"
b4327ba8 345 "vec3 SampleLambertianReflection (in vec3 theWo, out vec3 theWi, inout float thePDF)\n"
ee5befae 346 "{\n"
347 " float aKsi1 = RandFloat();\n"
348 " float aKsi2 = RandFloat();\n"
349 "\n"
b4327ba8 350 " theWi = vec3 (cos (M_2_PI * aKsi1),\n"
351 " sin (M_2_PI * aKsi1),\n"
352 " sqrt (1.f - aKsi2));\n"
353 "\n"
354 " theWi.xy *= sqrt (aKsi2);\n"
ee5befae 355 "\n"
b4327ba8 356 "#ifdef TWO_SIDED_BXDF\n"
357 " theWi.z *= sign (theWo.z);\n"
358 "#endif\n"
ee5befae 359 "\n"
b4327ba8 360 " thePDF *= theWi.z * (1.f / M_PI);\n"
ee5befae 361 "\n"
b4327ba8 362 "#ifdef TWO_SIDED_BXDF\n"
363 " return UNIT;\n"
364 "#else\n"
06e06389 365 " return UNIT * step (0.f, theWo.z);\n"
b4327ba8 366 "#endif\n"
6e728f3b 367 "}\n"
ee5befae 368 "\n"
369 "//=======================================================================\n"
05aa616d 370 "// function : SampleGlossyBlinnReflection\n"
6e728f3b 371 "// purpose : Samples Blinn BRDF, W = BRDF * cos(N, PSI) / PDF(PSI)\n"
372 "// The BRDF is a product of three main terms, D, G, and F,\n"
373 "// which is then divided by two cosine terms. Here we perform\n"
374 "// importance sample the D part of the Blinn model; trying to\n"
375 "// develop a sampling procedure that accounted for all of the\n"
376 "// terms would be complex, and it is the D term that accounts\n"
377 "// for most of the variation.\n"
ee5befae 378 "//=======================================================================\n"
05aa616d 379 "vec3 SampleGlossyBlinnReflection (in vec3 theWo, out vec3 theWi, in vec3 theFresnel, in float theRoughness, inout float thePDF)\n"
ee5befae 380 "{\n"
6e728f3b 381 " float aKsi1 = RandFloat();\n"
382 " float aKsi2 = RandFloat();\n"
ee5befae 383 "\n"
6e728f3b 384 " // roughness value --> Blinn exponent\n"
385 " float aPower = max (2.f / (theRoughness * theRoughness) - 2.f, 0.f);\n"
ee5befae 386 "\n"
6e728f3b 387 " // normal from microface distribution\n"
388 " float aCosThetaM = pow (aKsi1, 1.f / (aPower + 2.f));\n"
ee5befae 389 "\n"
6e728f3b 390 " vec3 aM = vec3 (cos (M_2_PI * aKsi2),\n"
391 " sin (M_2_PI * aKsi2),\n"
392 " aCosThetaM);\n"
ee5befae 393 "\n"
6e728f3b 394 " aM.xy *= sqrt (1.f - aCosThetaM * aCosThetaM);\n"
ee5befae 395 "\n"
6e728f3b 396 " // calculate PDF of sampled direction\n"
397 " thePDF *= (aPower + 2.f) * (1.f / M_2_PI) * pow (aCosThetaM, aPower + 1.f);\n"
398 "\n"
b4327ba8 399 "#ifdef TWO_SIDED_BXDF\n"
400 " bool toFlip = theWo.z < 0.f;\n"
401 "\n"
402 " if (toFlip)\n"
403 " theWo.z = -theWo.z;\n"
404 "#endif\n"
405 "\n"
406 " float aCosDelta = dot (theWo, aM);\n"
6e728f3b 407 "\n"
408 " // pick input based on half direction\n"
b4327ba8 409 " theWi = -theWo + 2.f * aCosDelta * aM;\n"
6e728f3b 410 "\n"
b4327ba8 411 " if (theWi.z <= 0.f || theWo.z <= 0.f)\n"
6e728f3b 412 " {\n"
413 " return ZERO;\n"
ee5befae 414 " }\n"
415 "\n"
6e728f3b 416 " // Jacobian of half-direction mapping\n"
05aa616d 417 " thePDF /= 4.f * aCosDelta;\n"
6e728f3b 418 "\n"
419 " // compute shadow-masking coefficient\n"
b4327ba8 420 " float aG = SmithG1 (theWo, aM, theRoughness) *\n"
421 " SmithG1 (theWi, aM, theRoughness);\n"
422 "\n"
423 "#ifdef TWO_SIDED_BXDF\n"
424 " if (toFlip)\n"
425 " theWi.z = -theWi.z;\n"
426 "#endif\n"
6e728f3b 427 "\n"
b4327ba8 428 " return (aG * aCosDelta) / (theWo.z * aM.z) * fresnelMedia (aCosDelta, theFresnel);\n"
ee5befae 429 "}\n"
430 "\n"
431 "//=======================================================================\n"
05aa616d 432 "// function : BsdfPdfLayered\n"
433 "// purpose : Calculates BSDF of sampling input knowing output\n"
ee5befae 434 "//=======================================================================\n"
05aa616d 435 "float BsdfPdfLayered (in SBSDF theBSDF, in vec3 theWo, in vec3 theWi, in vec3 theWeight)\n"
ee5befae 436 "{\n"
05aa616d 437 " float aPDF = 0.f; // PDF of sampling input direction\n"
ee5befae 438 "\n"
05aa616d 439 " // We choose whether the light is reflected or transmitted\n"
440 " // by the coating layer according to the Fresnel equations\n"
441 " vec3 aCoatF = fresnelMedia (theWo.z, theBSDF.FresnelCoat);\n"
ee5befae 442 "\n"
05aa616d 443 " // Coat BRDF is scaled by its Fresnel reflectance term. For\n"
444 " // reasons of simplicity we scale base BxDFs only by coat's\n"
445 " // Fresnel transmittance term\n"
446 " vec3 aCoatT = UNIT - aCoatF;\n"
ee5befae 447 "\n"
05aa616d 448 " float aPc = dot (theBSDF.Kc.rgb * aCoatF, theWeight);\n"
449 " float aPd = dot (theBSDF.Kd.rgb * aCoatT, theWeight);\n"
450 " float aPs = dot (theBSDF.Ks.rgb * aCoatT, theWeight);\n"
451 " float aPt = dot (theBSDF.Kt.rgb * aCoatT, theWeight);\n"
ee5befae 452 "\n"
05aa616d 453 " if (theWi.z * theWo.z > 0.f)\n"
ee5befae 454 " {\n"
05aa616d 455 " vec3 aH = normalize (theWi + theWo);\n"
6e728f3b 456 "\n"
05aa616d 457 " aPDF = aPd * abs (theWi.z / M_PI);\n"
ee5befae 458 "\n"
05aa616d 459 " if (theBSDF.Kc.w > FLT_EPSILON)\n"
460 " {\n"
461 " float aPower = max (2.f / (theBSDF.Kc.w * theBSDF.Kc.w) - 2.f, 0.f); // roughness --> exponent\n"
ee5befae 462 "\n"
05aa616d 463 " aPDF += aPc * (aPower + 2.f) * (0.25f / M_2_PI) * pow (abs (aH.z), aPower + 1.f) / dot (theWi, aH);\n"
464 " }\n"
ee5befae 465 "\n"
05aa616d 466 " if (theBSDF.Ks.w > FLT_EPSILON)\n"
467 " {\n"
468 " float aPower = max (2.f / (theBSDF.Ks.w * theBSDF.Ks.w) - 2.f, 0.f); // roughness --> exponent\n"
ee5befae 469 "\n"
05aa616d 470 " aPDF += aPs * (aPower + 2.f) * (0.25f / M_2_PI) * pow (abs (aH.z), aPower + 1.f) / dot (theWi, aH);\n"
471 " }\n"
6e728f3b 472 " }\n"
ee5befae 473 "\n"
05aa616d 474 " return aPDF / (aPc + aPd + aPs + aPt);\n"
ee5befae 475 "}\n"
476 "\n"
6e728f3b 477 "//! Tool macro to handle sampling of particular BxDF\n"
05aa616d 478 "#define PICK_BXDF_LAYER(p, k) aPDF = p / aTotalR; theWeight *= k / aPDF;\n"
6e728f3b 479 "\n"
ee5befae 480 "//=======================================================================\n"
05aa616d 481 "// function : SampleBsdfLayered\n"
ee5befae 482 "// purpose : Samples specified composite material (BSDF)\n"
483 "//=======================================================================\n"
05aa616d 484 "float SampleBsdfLayered (in SBSDF theBSDF, in vec3 theWo, out vec3 theWi, inout vec3 theWeight, inout bool theInside)\n"
ee5befae 485 "{\n"
05aa616d 486 " // NOTE: OCCT uses two-layer material model. We have base diffuse, glossy, or transmissive\n"
487 " // layer, covered by one glossy/specular coat. In the current model, the layers themselves\n"
488 " // have no thickness; they can simply reflect light or transmits it to the layer under it.\n"
489 " // We use actual BRDF model only for direct reflection by the coat layer. For transmission\n"
490 " // through this layer, we approximate it as a flat specular surface.\n"
491 "\n"
492 " float aPDF = 0.f; // PDF of sampled direction\n"
493 "\n"
494 " // We choose whether the light is reflected or transmitted\n"
495 " // by the coating layer according to the Fresnel equations\n"
496 " vec3 aCoatF = fresnelMedia (theWo.z, theBSDF.FresnelCoat);\n"
497 "\n"
498 " // Coat BRDF is scaled by its Fresnel term. According to\n"
499 " // Wilkie-Weidlich layered BSDF model, transmission term\n"
500 " // for light passing through the coat at direction I and\n"
501 " // leaving it in O is T = ( 1 - F (O) ) x ( 1 - F (I) ).\n"
502 " // For reasons of simplicity, we discard the second term\n"
503 " // and scale base BxDFs only by the first term.\n"
504 " vec3 aCoatT = UNIT - aCoatF;\n"
505 "\n"
506 " float aPc = dot (theBSDF.Kc.rgb * aCoatF, theWeight);\n"
507 " float aPd = dot (theBSDF.Kd.rgb * aCoatT, theWeight);\n"
508 " float aPs = dot (theBSDF.Ks.rgb * aCoatT, theWeight);\n"
509 " float aPt = dot (theBSDF.Kt.rgb * aCoatT, theWeight);\n"
510 "\n"
511 " // Calculate total reflection probability\n"
512 " float aTotalR = (aPc + aPd) + (aPs + aPt);\n"
513 "\n"
514 " // Generate random variable to select BxDF\n"
515 " float aKsi = aTotalR * RandFloat();\n"
516 "\n"
517 " if (aKsi < aPc) // REFLECTION FROM COAT\n"
518 " {\n"
519 " PICK_BXDF_LAYER (aPc, theBSDF.Kc.rgb)\n"
ee5befae 520 "\n"
05aa616d 521 " if (theBSDF.Kc.w < FLT_EPSILON)\n"
522 " {\n"
523 " theWeight *= aCoatF;\n"
ee5befae 524 "\n"
05aa616d 525 " theWi = vec3 (-theWo.x,\n"
526 " -theWo.y,\n"
527 " theWo.z);\n"
528 " }\n"
529 " else\n"
530 " {\n"
531 " theWeight *= SampleGlossyBlinnReflection (theWo, theWi, theBSDF.FresnelCoat, theBSDF.Kc.w, aPDF);\n"
532 " }\n"
ee5befae 533 "\n"
05aa616d 534 " aPDF = mix (aPDF, MAXFLOAT, theBSDF.Kc.w < FLT_EPSILON);\n"
ee5befae 535 " }\n"
05aa616d 536 " else if (aKsi < aTotalR) // REFLECTION FROM BASE\n"
ee5befae 537 " {\n"
05aa616d 538 " theWeight *= aCoatT;\n"
6e728f3b 539 "\n"
05aa616d 540 " if (aKsi < aPc + aPd) // diffuse BRDF\n"
541 " {\n"
542 " PICK_BXDF_LAYER (aPd, theBSDF.Kd.rgb)\n"
543 "\n"
544 " theWeight *= SampleLambertianReflection (theWo, theWi, aPDF);\n"
545 " }\n"
546 " else if (aKsi < (aPc + aPd) + aPs) // specular/glossy BRDF\n"
547 " {\n"
548 " PICK_BXDF_LAYER (aPs, theBSDF.Ks.rgb)\n"
6e728f3b 549 "\n"
05aa616d 550 " if (theBSDF.Ks.w < FLT_EPSILON)\n"
551 " {\n"
552 " theWeight *= fresnelMedia (theWo.z, theBSDF.FresnelBase);\n"
ee5befae 553 "\n"
05aa616d 554 " theWi = vec3 (-theWo.x,\n"
555 " -theWo.y,\n"
556 " theWo.z);\n"
557 " }\n"
558 " else\n"
559 " {\n"
560 " theWeight *= SampleGlossyBlinnReflection (theWo, theWi, theBSDF.FresnelBase, theBSDF.Ks.w, aPDF);\n"
561 " }\n"
6e728f3b 562 "\n"
05aa616d 563 " aPDF = mix (aPDF, MAXFLOAT, theBSDF.Ks.w < FLT_EPSILON);\n"
564 " }\n"
565 " else // specular transmission\n"
566 " {\n"
567 " PICK_BXDF_LAYER (aPt, theBSDF.Kt.rgb)\n"
6e728f3b 568 "\n"
05aa616d 569 " // refracted direction should exist if we are here\n"
570 " transmitted (theBSDF.FresnelCoat.y, theWo, theWi);\n"
571 "\n"
572 " theInside = !theInside; aPDF = MAXFLOAT;\n"
573 " }\n"
ee5befae 574 " }\n"
575 "\n"
576 " // path termination for extra small weights\n"
05aa616d 577 " theWeight = mix (ZERO, theWeight, step (FLT_EPSILON, aTotalR));\n"
6e728f3b 578 "\n"
579 " return aPDF;\n"
ee5befae 580 "}\n"
581 "\n"
582 "//////////////////////////////////////////////////////////////////////////////////////////////\n"
583 "// Handlers and samplers for light sources\n"
584 "//////////////////////////////////////////////////////////////////////////////////////////////\n"
585 "\n"
6e728f3b 586 "// =======================================================================\n"
587 "// function : Latlong\n"
588 "// purpose : Converts world direction to environment texture coordinates\n"
589 "// =======================================================================\n"
590 "vec2 Latlong (in vec3 thePoint)\n"
ee5befae 591 "{\n"
6e728f3b 592 " float aPsi = acos (-thePoint.z);\n"
ee5befae 593 "\n"
6e728f3b 594 " float aPhi = atan (thePoint.y, thePoint.x) + M_PI;\n"
ee5befae 595 "\n"
6e728f3b 596 " return vec2 (aPhi * 0.1591549f,\n"
597 " aPsi * 0.3183098f);\n"
ee5befae 598 "}\n"
599 "\n"
600 "//=======================================================================\n"
6e728f3b 601 "// function : SampleLight\n"
ee5befae 602 "// purpose : General sampling function for directional and point lights\n"
603 "//=======================================================================\n"
6e728f3b 604 "vec3 SampleLight (in vec3 theToLight, inout float theDistance, in bool isInfinite, in float theSmoothness, inout float thePDF)\n"
ee5befae 605 "{\n"
6e728f3b 606 " SLocalSpace aSpace = buildLocalSpace (theToLight * (1.f / theDistance));\n"
ee5befae 607 "\n"
608 " // for point lights smoothness defines radius\n"
609 " float aCosMax = isInfinite ? theSmoothness :\n"
610 " inversesqrt (1.f + theSmoothness * theSmoothness / (theDistance * theDistance));\n"
611 "\n"
612 " float aKsi1 = RandFloat();\n"
613 " float aKsi2 = RandFloat();\n"
614 "\n"
615 " float aTmp = 1.f - aKsi2 * (1.f - aCosMax);\n"
616 "\n"
6e728f3b 617 " vec3 anInput = vec3 (cos (M_2_PI * aKsi1),\n"
618 " sin (M_2_PI * aKsi1),\n"
ee5befae 619 " aTmp);\n"
620 "\n"
621 " anInput.xy *= sqrt (1.f - aTmp * aTmp);\n"
622 "\n"
6e728f3b 623 " thePDF = (aCosMax < 1.f) ? (thePDF / M_2_PI) / (1.f - aCosMax) : MAXFLOAT;\n"
ee5befae 624 "\n"
625 " return normalize (fromLocalSpace (anInput, aSpace));\n"
626 "}\n"
627 "\n"
6e728f3b 628 "//=======================================================================\n"
629 "// function : HandlePointLight\n"
630 "// purpose :\n"
631 "//=======================================================================\n"
632 "float HandlePointLight (in vec3 theInput, in vec3 theToLight, in float theRadius, in float theDistance, inout float thePDF)\n"
ee5befae 633 "{\n"
6e728f3b 634 " float aCosMax = inversesqrt (1.f + theRadius * theRadius / (theDistance * theDistance));\n"
ee5befae 635 "\n"
6e728f3b 636 " float aVisibility = step (aCosMax, dot (theInput, theToLight));\n"
ee5befae 637 "\n"
6e728f3b 638 " thePDF *= step (-1.f, -aCosMax) * aVisibility * (1.f / M_2_PI) / (1.f - aCosMax);\n"
639 "\n"
640 " return aVisibility;\n"
641 "}\n"
642 "\n"
643 "//=======================================================================\n"
644 "// function : HandleDistantLight\n"
645 "// purpose :\n"
646 "//=======================================================================\n"
647 "float HandleDistantLight (in vec3 theInput, in vec3 theToLight, in float theCosMax, inout float thePDF)\n"
648 "{\n"
649 " float aVisibility = step (theCosMax, dot (theInput, theToLight));\n"
650 "\n"
651 " thePDF *= step (-1.f, -theCosMax) * aVisibility * (1.f / M_2_PI) / (1.f - theCosMax);\n"
652 "\n"
653 " return aVisibility;\n"
ee5befae 654 "}\n"
655 "\n"
656 "// =======================================================================\n"
6e728f3b 657 "// function: IntersectLight\n"
ee5befae 658 "// purpose : Checks intersections with light sources\n"
659 "// =======================================================================\n"
6e728f3b 660 "vec3 IntersectLight (in SRay theRay, in int theDepth, in float theHitDistance, out float thePDF)\n"
ee5befae 661 "{\n"
6e728f3b 662 " vec3 aTotalRadiance = ZERO;\n"
ee5befae 663 "\n"
6e728f3b 664 " thePDF = 0.f; // PDF of sampling light sources\n"
ee5befae 665 "\n"
6e728f3b 666 " for (int aLightIdx = 0; aLightIdx < uLightCount; ++aLightIdx)\n"
ee5befae 667 " {\n"
668 " vec4 aLight = texelFetch (\n"
669 " uRaytraceLightSrcTexture, LIGHT_POS (aLightIdx));\n"
670 " vec4 aParam = texelFetch (\n"
671 " uRaytraceLightSrcTexture, LIGHT_PWR (aLightIdx));\n"
672 "\n"
6e728f3b 673 " // W component: 0 for infinite light and 1 for point light\n"
674 " aLight.xyz -= mix (ZERO, theRay.Origin, aLight.w);\n"
675 "\n"
676 " float aPDF = 1.f / uLightCount;\n"
677 "\n"
ee5befae 678 " if (aLight.w != 0.f) // point light source\n"
679 " {\n"
6e728f3b 680 " float aCenterDst = length (aLight.xyz);\n"
681 "\n"
682 " if (aCenterDst < theHitDistance)\n"
683 " {\n"
684 " float aVisibility = HandlePointLight (\n"
685 " theRay.Direct, normalize (aLight.xyz), aParam.w /* radius */, aCenterDst, aPDF);\n"
686 "\n"
687 " if (aVisibility > 0.f)\n"
688 " {\n"
689 " theHitDistance = aCenterDst;\n"
690 " aTotalRadiance = aParam.rgb;\n"
691 "\n"
692 " thePDF = aPDF;\n"
693 " }\n"
694 " }\n"
ee5befae 695 " }\n"
6e728f3b 696 " else if (theHitDistance == MAXFLOAT) // directional light source\n"
ee5befae 697 " {\n"
6e728f3b 698 " aTotalRadiance += aParam.rgb * HandleDistantLight (\n"
699 " theRay.Direct, aLight.xyz, aParam.w /* angle cosine */, aPDF);\n"
700 "\n"
701 " thePDF += aPDF;\n"
ee5befae 702 " }\n"
703 " }\n"
704 "\n"
6e728f3b 705 " if (thePDF == 0.f && theHitDistance == MAXFLOAT) // light source not found\n"
706 " {\n"
707 " if (theDepth + uSphereMapForBack == 0) // view ray and map is hidden\n"
708 " {\n"
ba00aab7 709 " aTotalRadiance = BackgroundColor().rgb;\n"
6e728f3b 710 " }\n"
711 " else\n"
712 " {\n"
ba00aab7 713 " aTotalRadiance = FetchEnvironment (Latlong (theRay.Direct)).rgb;\n"
6e728f3b 714 " }\n"
ba00aab7 715 " #ifdef THE_SHIFT_sRGB\n"
716 " aTotalRadiance = pow (aTotalRadiance, vec3 (2.f));\n"
717 " #endif\n"
6e728f3b 718 " }\n"
719 " \n"
720 " return aTotalRadiance;\n"
ee5befae 721 "}\n"
722 "\n"
6e728f3b 723 "#define MIN_THROUGHPUT vec3 (1.0e-3f)\n"
724 "#define MIN_CONTRIBUTION vec3 (1.0e-2f)\n"
ee5befae 725 "\n"
05aa616d 726 "#define MATERIAL_KC(index) (19 * index + 11)\n"
727 "#define MATERIAL_KD(index) (19 * index + 12)\n"
728 "#define MATERIAL_KS(index) (19 * index + 13)\n"
729 "#define MATERIAL_KT(index) (19 * index + 14)\n"
730 "#define MATERIAL_LE(index) (19 * index + 15)\n"
731 "#define MATERIAL_FRESNEL_COAT(index) (19 * index + 16)\n"
732 "#define MATERIAL_FRESNEL_BASE(index) (19 * index + 17)\n"
733 "#define MATERIAL_ABSORPT_BASE(index) (19 * index + 18)\n"
ee5befae 734 "\n"
05aa616d 735 "//! Enables experimental Russian roulette sampling path termination.\n"
4eaaf9d8 736 "//! In most cases, it provides faster image convergence with minimal\n"
737 "//! bias, so it is enabled by default.\n"
ee5befae 738 "#define RUSSIAN_ROULETTE\n"
739 "\n"
4eaaf9d8 740 "//! Frame step to increase number of bounces. This mode is used\n"
741 "//! for interaction with the model, when path length is limited\n"
742 "//! for the first samples, and gradually increasing when camera\n"
743 "//! is stabilizing.\n"
744 "#ifdef ADAPTIVE_SAMPLING\n"
745 " #define FRAME_STEP 4\n"
746 "#else\n"
747 " #define FRAME_STEP 5\n"
748 "#endif\n"
383c6c9f 749 "\n"
ee5befae 750 "//=======================================================================\n"
05aa616d 751 "// function : IsNotZero\n"
752 "// purpose : Checks whether BSDF reflects direct light\n"
753 "//=======================================================================\n"
754 "bool IsNotZero (in SBSDF theBSDF, in vec3 theThroughput)\n"
755 "{\n"
756 " vec3 aGlossy = theBSDF.Kc.rgb * step (FLT_EPSILON, theBSDF.Kc.w) +\n"
757 " theBSDF.Ks.rgb * step (FLT_EPSILON, theBSDF.Ks.w);\n"
758 "\n"
759 " return convolve (theBSDF.Kd.rgb + aGlossy, theThroughput) > FLT_EPSILON;\n"
760 "}\n"
761 "\n"
762 "//=======================================================================\n"
ee5befae 763 "// function : PathTrace\n"
764 "// purpose : Calculates radiance along the given ray\n"
765 "//=======================================================================\n"
4eaaf9d8 766 "vec4 PathTrace (in SRay theRay, in vec3 theInverse, in int theNbSamples)\n"
ee5befae 767 "{\n"
768 " float aRaytraceDepth = MAXFLOAT;\n"
769 "\n"
770 " vec3 aRadiance = ZERO;\n"
771 " vec3 aThroughput = UNIT;\n"
772 "\n"
6e728f3b 773 " int aTransfID = 0; // ID of object transformation\n"
774 " bool aInMedium = false; // is the ray inside an object\n"
ee5befae 775 "\n"
6e728f3b 776 " float aExpPDF = 1.f;\n"
777 " float aImpPDF = 1.f;\n"
ee5befae 778 "\n"
779 " for (int aDepth = 0; aDepth < NB_BOUNCES; ++aDepth)\n"
780 " {\n"
781 " SIntersect aHit = SIntersect (MAXFLOAT, vec2 (ZERO), ZERO);\n"
782 "\n"
6e728f3b 783 " ivec4 aTriIndex = SceneNearestHit (theRay, theInverse, aHit, aTransfID);\n"
ee5befae 784 "\n"
785 " // check implicit path\n"
6e728f3b 786 " vec3 aLe = IntersectLight (theRay, aDepth, aHit.Time, aExpPDF);\n"
ee5befae 787 "\n"
788 " if (any (greaterThan (aLe, ZERO)) || aTriIndex.x == -1)\n"
789 " {\n"
6e728f3b 790 " float aMIS = (aDepth == 0 || aImpPDF == MAXFLOAT) ? 1.f :\n"
791 " aImpPDF * aImpPDF / (aExpPDF * aExpPDF + aImpPDF * aImpPDF);\n"
792 "\n"
793 " aRadiance += aThroughput * aLe * aMIS; break; // terminate path\n"
ee5befae 794 " }\n"
795 "\n"
6e728f3b 796 " vec3 aInvTransf0 = texelFetch (uSceneTransformTexture, aTransfID + 0).xyz;\n"
797 " vec3 aInvTransf1 = texelFetch (uSceneTransformTexture, aTransfID + 1).xyz;\n"
798 " vec3 aInvTransf2 = texelFetch (uSceneTransformTexture, aTransfID + 2).xyz;\n"
ee5befae 799 "\n"
800 " // compute geometrical normal\n"
801 " aHit.Normal = normalize (vec3 (dot (aInvTransf0, aHit.Normal),\n"
802 " dot (aInvTransf1, aHit.Normal),\n"
803 " dot (aInvTransf2, aHit.Normal)));\n"
804 "\n"
805 " theRay.Origin += theRay.Direct * aHit.Time; // get new intersection point\n"
806 "\n"
6e728f3b 807 " // evaluate depth on first hit\n"
ee5befae 808 " if (aDepth == 0)\n"
809 " {\n"
810 " vec4 aNDCPoint = uViewMat * vec4 (theRay.Origin, 1.f);\n"
811 "\n"
812 " float aPolygonOffset = PolygonOffset (aHit.Normal, theRay.Origin);\n"
813 " aRaytraceDepth = (aNDCPoint.z / aNDCPoint.w + aPolygonOffset * POLYGON_OFFSET_SCALE) * 0.5f + 0.5f;\n"
814 " }\n"
815 "\n"
05aa616d 816 " SBSDF aBSDF;\n"
817 "\n"
818 " // fetch BxDF weights\n"
819 " aBSDF.Kc = texelFetch (uRaytraceMaterialTexture, MATERIAL_KC (aTriIndex.w));\n"
820 " aBSDF.Kd = texelFetch (uRaytraceMaterialTexture, MATERIAL_KD (aTriIndex.w));\n"
821 " aBSDF.Ks = texelFetch (uRaytraceMaterialTexture, MATERIAL_KS (aTriIndex.w));\n"
822 " aBSDF.Kt = texelFetch (uRaytraceMaterialTexture, MATERIAL_KT (aTriIndex.w)).rgb;\n"
823 "\n"
824 " // compute smooth normal (in parallel with fetch)\n"
825 " vec3 aNormal = SmoothNormal (aHit.UV, aTriIndex);\n"
826 "\n"
827 " aNormal = normalize (vec3 (dot (aInvTransf0, aNormal),\n"
828 " dot (aInvTransf1, aNormal),\n"
829 " dot (aInvTransf2, aNormal)));\n"
830 "\n"
831 " SLocalSpace aSpace = buildLocalSpace (aNormal);\n"
ee5befae 832 "\n"
833 "#ifdef USE_TEXTURES\n"
05aa616d 834 " if (aBSDF.Kd.w >= 0.f)\n"
ee5befae 835 " {\n"
836 " vec4 aTexCoord = vec4 (SmoothUV (aHit.UV, aTriIndex), 0.f, 1.f);\n"
a1a9b249 837 " vec4 aTrsfRow1 = texelFetch (uRaytraceMaterialTexture, MATERIAL_TRS1 (aTriIndex.w));\n"
838 " vec4 aTrsfRow2 = texelFetch (uRaytraceMaterialTexture, MATERIAL_TRS2 (aTriIndex.w));\n"
ee5befae 839 " aTexCoord.st = vec2 (dot (aTrsfRow1, aTexCoord),\n"
840 " dot (aTrsfRow2, aTexCoord));\n"
841 "\n"
a1a9b249 842 " vec4 aTexColor = textureLod (sampler2D (uTextureSamplers[int (aBSDF.Kd.w)]), aTexCoord.st, 0.f);\n"
843 " aBSDF.Kd.rgb *= aTexColor.rgb * aTexColor.w;\n"
f411f94f 844 " if (aTexColor.w != 1.0f)\n"
845 " {\n"
846 " // mix transparency BTDF with texture alpha-channel\n"
05aa616d 847 " aBSDF.Kt = (UNIT - aTexColor.www) + aTexColor.w * aBSDF.Kt;\n"
f411f94f 848 " }\n"
ee5befae 849 " }\n"
850 "#endif\n"
851 "\n"
05aa616d 852 " // fetch Fresnel reflectance for both layers\n"
853 " aBSDF.FresnelCoat = texelFetch (uRaytraceMaterialTexture, MATERIAL_FRESNEL_COAT (aTriIndex.w)).xyz;\n"
854 " aBSDF.FresnelBase = texelFetch (uRaytraceMaterialTexture, MATERIAL_FRESNEL_BASE (aTriIndex.w)).xyz;\n"
ee5befae 855 "\n"
05aa616d 856 " if (uLightCount > 0 && IsNotZero (aBSDF, aThroughput))\n"
ee5befae 857 " {\n"
6e728f3b 858 " aExpPDF = 1.f / uLightCount;\n"
859 "\n"
ee5befae 860 " int aLightIdx = min (int (floor (RandFloat() * uLightCount)), uLightCount - 1);\n"
861 "\n"
862 " vec4 aLight = texelFetch (\n"
863 " uRaytraceLightSrcTexture, LIGHT_POS (aLightIdx));\n"
864 " vec4 aParam = texelFetch (\n"
865 " uRaytraceLightSrcTexture, LIGHT_PWR (aLightIdx));\n"
866 "\n"
867 " // 'w' component is 0 for infinite light and 1 for point light\n"
868 " aLight.xyz -= mix (ZERO, theRay.Origin, aLight.w);\n"
869 "\n"
6e728f3b 870 " float aDistance = length (aLight.xyz);\n"
ee5befae 871 "\n"
6e728f3b 872 " aLight.xyz = SampleLight (aLight.xyz, aDistance,\n"
873 " aLight.w == 0.f /* is infinite */, aParam.w /* max cos or radius */, aExpPDF);\n"
ee5befae 874 "\n"
05aa616d 875 " aImpPDF = BsdfPdfLayered (aBSDF,\n"
6e728f3b 876 " toLocalSpace (-theRay.Direct, aSpace), toLocalSpace (aLight.xyz, aSpace), aThroughput);\n"
877 "\n"
878 " // MIS weight including division by explicit PDF\n"
879 " float aMIS = (aExpPDF == MAXFLOAT) ? 1.f : aExpPDF / (aExpPDF * aExpPDF + aImpPDF * aImpPDF);\n"
880 "\n"
05aa616d 881 " vec3 aContrib = aMIS * aParam.rgb /* Le */ * EvalBsdfLayered (\n"
882 " aBSDF, toLocalSpace (aLight.xyz, aSpace), toLocalSpace (-theRay.Direct, aSpace));\n"
ee5befae 883 "\n"
6e728f3b 884 " if (any (greaterThan (aContrib, MIN_CONTRIBUTION))) // check if light source is important\n"
ee5befae 885 " {\n"
886 " SRay aShadow = SRay (theRay.Origin + aLight.xyz * uSceneEpsilon, aLight.xyz);\n"
887 "\n"
888 " aShadow.Origin += aHit.Normal * mix (\n"
889 " -uSceneEpsilon, uSceneEpsilon, step (0.f, dot (aHit.Normal, aLight.xyz)));\n"
890 "\n"
891 " float aVisibility = SceneAnyHit (aShadow,\n"
892 " InverseDirection (aLight.xyz), aLight.w == 0.f ? MAXFLOAT : aDistance);\n"
893 "\n"
05aa616d 894 " aRadiance += aVisibility * (aThroughput * aContrib);\n"
ee5befae 895 " }\n"
896 " }\n"
897 "\n"
05aa616d 898 " // account for self-emission\n"
899 " aRadiance += aThroughput * texelFetch (uRaytraceMaterialTexture, MATERIAL_LE (aTriIndex.w)).rgb;\n"
900 "\n"
6e728f3b 901 " if (aInMedium) // handle attenuation\n"
ee5befae 902 " {\n"
05aa616d 903 " vec4 aScattering = texelFetch (uRaytraceMaterialTexture, MATERIAL_ABSORPT_BASE (aTriIndex.w));\n"
904 "\n"
905 " aThroughput *= exp (-aHit.Time * aScattering.w * (UNIT - aScattering.rgb));\n"
ee5befae 906 " }\n"
907 "\n"
6e728f3b 908 " vec3 anInput = UNIT; // sampled input direction\n"
ee5befae 909 "\n"
05aa616d 910 " aImpPDF = SampleBsdfLayered (aBSDF,\n"
6e728f3b 911 " toLocalSpace (-theRay.Direct, aSpace), anInput, aThroughput, aInMedium);\n"
912 "\n"
05aa616d 913 " float aSurvive = float (any (greaterThan (aThroughput, MIN_THROUGHPUT)));\n"
6e728f3b 914 "\n"
915 "#ifdef RUSSIAN_ROULETTE\n"
05aa616d 916 " aSurvive = aDepth < 3 ? aSurvive : min (dot (LUMA, aThroughput), 0.95f);\n"
6e728f3b 917 "#endif\n"
ee5befae 918 "\n"
4eaaf9d8 919 " // here, we additionally increase path length for non-diffuse bounces\n"
920 " if (RandFloat() > aSurvive || all (lessThan (aThroughput, MIN_THROUGHPUT)) || aDepth >= theNbSamples / FRAME_STEP + step (1.f / M_PI, aImpPDF))\n"
ee5befae 921 " {\n"
922 " aDepth = INVALID_BOUNCES; // terminate path\n"
923 " }\n"
924 "\n"
6e728f3b 925 "#ifdef RUSSIAN_ROULETTE\n"
ee5befae 926 " aThroughput /= aSurvive;\n"
927 "#endif\n"
928 "\n"
929 " anInput = normalize (fromLocalSpace (anInput, aSpace));\n"
930 "\n"
931 " theRay = SRay (theRay.Origin + anInput * uSceneEpsilon +\n"
932 " aHit.Normal * mix (-uSceneEpsilon, uSceneEpsilon, step (0.f, dot (aHit.Normal, anInput))), anInput);\n"
933 "\n"
934 " theInverse = InverseDirection (anInput);\n"
935 " }\n"
936 "\n"
937 " gl_FragDepth = aRaytraceDepth;\n"
938 "\n"
939 " return vec4 (aRadiance, aRaytraceDepth);\n"
940 "}\n"
941 "\n"
942 "#endif\n";