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