1 // This file has been automatically generated from resource file src/Shaders/RaytraceBase.fs
3 static const char Shaders_RaytraceBase_fs[] =
4 "#ifdef ADAPTIVE_SAMPLING\n"
5 " #extension GL_ARB_shader_image_load_store : require\n"
6 " #extension GL_NV_shader_atomic_float : require\n"
9 "#ifdef USE_TEXTURES\n"
10 " #extension GL_ARB_bindless_texture : require\n"
13 "//! Normalized pixel coordinates.\n"
16 "//! Sub-pixel offset in X direction for FSAA.\n"
17 "uniform float uOffsetX = 0.f;\n"
18 "//! Sub-pixel offset in Y direction for FSAA.\n"
19 "uniform float uOffsetY = 0.f;\n"
21 "//! Origin of viewing ray in left-top corner.\n"
22 "uniform vec3 uOriginLT;\n"
23 "//! Origin of viewing ray in left-bottom corner.\n"
24 "uniform vec3 uOriginLB;\n"
25 "//! Origin of viewing ray in right-top corner.\n"
26 "uniform vec3 uOriginRT;\n"
27 "//! Origin of viewing ray in right-bottom corner.\n"
28 "uniform vec3 uOriginRB;\n"
30 "//! Width of the rendering window.\n"
31 "uniform int uWinSizeX;\n"
32 "//! Height of the rendering window.\n"
33 "uniform int uWinSizeY;\n"
35 "//! Direction of viewing ray in left-top corner.\n"
36 "uniform vec3 uDirectLT;\n"
37 "//! Direction of viewing ray in left-bottom corner.\n"
38 "uniform vec3 uDirectLB;\n"
39 "//! Direction of viewing ray in right-top corner.\n"
40 "uniform vec3 uDirectRT;\n"
41 "//! Direction of viewing ray in right-bottom corner.\n"
42 "uniform vec3 uDirectRB;\n"
44 "//! Inverse model-view-projection matrix.\n"
45 "uniform mat4 uUnviewMat;\n"
47 "//! Model-view-projection matrix.\n"
48 "uniform mat4 uViewMat;\n"
50 "//! Texture buffer of data records of bottom-level BVH nodes.\n"
51 "uniform isamplerBuffer uSceneNodeInfoTexture;\n"
52 "//! Texture buffer of minimum points of bottom-level BVH nodes.\n"
53 "uniform samplerBuffer uSceneMinPointTexture;\n"
54 "//! Texture buffer of maximum points of bottom-level BVH nodes.\n"
55 "uniform samplerBuffer uSceneMaxPointTexture;\n"
56 "//! Texture buffer of transformations of high-level BVH nodes.\n"
57 "uniform samplerBuffer uSceneTransformTexture;\n"
59 "//! Texture buffer of vertex coords.\n"
60 "uniform samplerBuffer uGeometryVertexTexture;\n"
61 "//! Texture buffer of vertex normals.\n"
62 "uniform samplerBuffer uGeometryNormalTexture;\n"
63 "#ifdef USE_TEXTURES\n"
64 " //! Texture buffer of per-vertex UV-coordinates.\n"
65 " uniform samplerBuffer uGeometryTexCrdTexture;\n"
67 "//! Texture buffer of triangle indices.\n"
68 "uniform isamplerBuffer uGeometryTriangTexture;\n"
70 "//! Texture buffer of material properties.\n"
71 "uniform samplerBuffer uRaytraceMaterialTexture;\n"
72 "//! Texture buffer of light source properties.\n"
73 "uniform samplerBuffer uRaytraceLightSrcTexture;\n"
74 "//! Environment map texture.\n"
75 "uniform sampler2D uEnvironmentMapTexture;\n"
77 "//! Total number of light sources.\n"
78 "uniform int uLightCount;\n"
79 "//! Intensity of global ambient light.\n"
80 "uniform vec4 uGlobalAmbient;\n"
82 "//! Enables/disables hard shadows.\n"
83 "uniform int uShadowsEnabled;\n"
84 "//! Enables/disables specular reflections.\n"
85 "uniform int uReflectEnabled;\n"
86 "//! Enables/disables spherical environment map.\n"
87 "uniform int uSphereMapEnabled;\n"
88 "//! Enables/disables environment map background.\n"
89 "uniform int uSphereMapForBack;\n"
91 "//! Radius of bounding sphere of the scene.\n"
92 "uniform float uSceneRadius;\n"
93 "//! Scene epsilon to prevent self-intersections.\n"
94 "uniform float uSceneEpsilon;\n"
96 "#ifdef USE_TEXTURES\n"
97 " //! Unique 64-bit handles of OpenGL textures.\n"
98 " uniform uvec2 uTextureSamplers[MAX_TEX_NUMBER];\n"
101 "#ifdef ADAPTIVE_SAMPLING\n"
102 " //! OpenGL image used for accumulating rendering result.\n"
103 " volatile restrict layout(size1x32) uniform image2D uRenderImage;\n"
105 " //! OpenGL image storing offsets of sampled pixels blocks.\n"
106 " coherent restrict layout(size2x32) uniform iimage2D uOffsetImage;\n"
109 "//! Top color of gradient background.\n"
110 "uniform vec4 uBackColorTop = vec4 (0.0);\n"
111 "//! Bottom color of gradient background.\n"
112 "uniform vec4 uBackColorBot = vec4 (0.0);\n"
114 "/////////////////////////////////////////////////////////////////////////////////////////\n"
115 "// Specific data types\n"
117 "//! Stores ray parameters.\n"
125 "//! Stores intersection parameters.\n"
126 "struct SIntersect\n"
135 "/////////////////////////////////////////////////////////////////////////////////////////\n"
136 "// Some useful constants\n"
138 "#define MAXFLOAT 1e15f\n"
140 "#define SMALL vec3 (exp2 (-80.0f))\n"
142 "#define ZERO vec3 (0.0f, 0.0f, 0.0f)\n"
143 "#define UNIT vec3 (1.0f, 1.0f, 1.0f)\n"
145 "#define AXIS_X vec3 (1.0f, 0.0f, 0.0f)\n"
146 "#define AXIS_Y vec3 (0.0f, 1.0f, 0.0f)\n"
147 "#define AXIS_Z vec3 (0.0f, 0.0f, 1.0f)\n"
149 "#define M_PI 3.141592653f\n"
150 "#define M_2_PI 6.283185307f\n"
151 "#define M_PI_2 1.570796327f\n"
153 "#define LUMA vec3 (0.2126f, 0.7152f, 0.0722f)\n"
155 "// =======================================================================\n"
156 "// function : MatrixRowMultiplyDir\n"
157 "// purpose : Multiplies a vector by matrix\n"
158 "// =======================================================================\n"
159 "vec3 MatrixRowMultiplyDir (in vec3 v,\n"
164 " return vec3 (dot (m0.xyz, v),\n"
165 " dot (m1.xyz, v),\n"
166 " dot (m2.xyz, v));\n"
169 "//! 32-bit state of random number generator.\n"
172 "// =======================================================================\n"
173 "// function : SeedRand\n"
174 "// purpose : Applies hash function by Thomas Wang to randomize seeds\n"
175 "// (see http://www.burtleburtle.net/bob/hash/integer.html)\n"
176 "// =======================================================================\n"
177 "void SeedRand (in int theSeed, in int theSizeX, in int theRadius)\n"
179 " RandState = uint (int (gl_FragCoord.y) / theRadius * theSizeX + int (gl_FragCoord.x) / theRadius + theSeed);\n"
181 " RandState = (RandState + 0x479ab41du) + (RandState << 8);\n"
182 " RandState = (RandState ^ 0xe4aa10ceu) ^ (RandState >> 5);\n"
183 " RandState = (RandState + 0x9942f0a6u) - (RandState << 14);\n"
184 " RandState = (RandState ^ 0x5aedd67du) ^ (RandState >> 3);\n"
185 " RandState = (RandState + 0x17bea992u) + (RandState << 7);\n"
188 "// =======================================================================\n"
189 "// function : RandInt\n"
190 "// purpose : Generates integer using Xorshift algorithm by G. Marsaglia\n"
191 "// =======================================================================\n"
194 " RandState ^= (RandState << 13);\n"
195 " RandState ^= (RandState >> 17);\n"
196 " RandState ^= (RandState << 5);\n"
198 " return RandState;\n"
201 "// =======================================================================\n"
202 "// function : RandFloat\n"
203 "// purpose : Generates a random float in 0 <= x < 1 range\n"
204 "// =======================================================================\n"
205 "float RandFloat()\n"
207 " return float (RandInt()) * (1.f / 4294967296.f);\n"
210 "// =======================================================================\n"
211 "// function : MatrixColMultiplyPnt\n"
212 "// purpose : Multiplies a vector by matrix\n"
213 "// =======================================================================\n"
214 "vec3 MatrixColMultiplyPnt (in vec3 v,\n"
220 " return vec3 (m0.x * v.x + m1.x * v.y + m2.x * v.z + m3.x,\n"
221 " m0.y * v.x + m1.y * v.y + m2.y * v.z + m3.y,\n"
222 " m0.z * v.x + m1.z * v.y + m2.z * v.z + m3.z);\n"
225 "// =======================================================================\n"
226 "// function : MatrixColMultiplyDir\n"
227 "// purpose : Multiplies a vector by matrix\n"
228 "// =======================================================================\n"
229 "vec3 MatrixColMultiplyDir (in vec3 v,\n"
234 " return vec3 (m0.x * v.x + m1.x * v.y + m2.x * v.z,\n"
235 " m0.y * v.x + m1.y * v.y + m2.y * v.z,\n"
236 " m0.z * v.x + m1.z * v.y + m2.z * v.z);\n"
239 "//=======================================================================\n"
240 "// function : InverseDirection\n"
241 "// purpose : Returns safely inverted direction of the given one\n"
242 "//=======================================================================\n"
243 "vec3 InverseDirection (in vec3 theInput)\n"
245 " vec3 anInverse = 1.f / max (abs (theInput), SMALL);\n"
247 " return mix (-anInverse, anInverse, step (ZERO, theInput));\n"
250 "//=======================================================================\n"
251 "// function : BackgroundColor\n"
252 "// purpose : Returns color of gradient background\n"
253 "//=======================================================================\n"
254 "vec4 BackgroundColor()\n"
256 "#ifdef ADAPTIVE_SAMPLING\n"
258 " ivec2 aFragCoord = ivec2 (gl_FragCoord.xy);\n"
260 " ivec2 aTileXY = imageLoad (uOffsetImage, ivec2 (aFragCoord.x / BLOCK_SIZE,\n"
261 " aFragCoord.y / BLOCK_SIZE)).xy;\n"
263 " aTileXY.y += aFragCoord.y % min (uWinSizeY - aTileXY.y, BLOCK_SIZE);\n"
265 " return mix (uBackColorBot, uBackColorTop, float (aTileXY.y) / uWinSizeY);\n"
269 " return mix (uBackColorBot, uBackColorTop, vPixel.y);\n"
274 "/////////////////////////////////////////////////////////////////////////////////////////\n"
275 "// Functions for compute ray-object intersection\n"
277 "// =======================================================================\n"
278 "// function : GenerateRay\n"
280 "// =======================================================================\n"
281 "SRay GenerateRay (in vec2 thePixel)\n"
283 " vec3 aP0 = mix (uOriginLB, uOriginRB, thePixel.x);\n"
284 " vec3 aP1 = mix (uOriginLT, uOriginRT, thePixel.x);\n"
286 " vec3 aD0 = mix (uDirectLB, uDirectRB, thePixel.x);\n"
287 " vec3 aD1 = mix (uDirectLT, uDirectRT, thePixel.x);\n"
289 " vec3 aDirection = normalize (mix (aD0, aD1, thePixel.y));\n"
291 " return SRay (mix (aP0, aP1, thePixel.y), aDirection);\n"
294 "// =======================================================================\n"
295 "// function : IntersectSphere\n"
296 "// purpose : Computes ray-sphere intersection\n"
297 "// =======================================================================\n"
298 "float IntersectSphere (in SRay theRay, in float theRadius)\n"
300 " float aDdotD = dot (theRay.Direct, theRay.Direct);\n"
301 " float aDdotO = dot (theRay.Direct, theRay.Origin);\n"
302 " float aOdotO = dot (theRay.Origin, theRay.Origin);\n"
304 " float aD = aDdotO * aDdotO - aDdotD * (aOdotO - theRadius * theRadius);\n"
308 " float aTime = (sqrt (aD) - aDdotO) * (1.0f / aDdotD);\n"
310 " return aTime > 0.0f ? aTime : MAXFLOAT;\n"
313 " return MAXFLOAT;\n"
316 "// =======================================================================\n"
317 "// function : IntersectTriangle\n"
318 "// purpose : Computes ray-triangle intersection (branchless version)\n"
319 "// =======================================================================\n"
320 "void IntersectTriangle (in SRay theRay,\n"
321 " in vec3 thePnt0,\n"
322 " in vec3 thePnt1,\n"
323 " in vec3 thePnt2,\n"
324 " out vec3 theUVT,\n"
325 " out vec3 theNorm)\n"
327 " vec3 aToTrg = thePnt0 - theRay.Origin;\n"
329 " vec3 aEdge0 = thePnt1 - thePnt0;\n"
330 " vec3 aEdge1 = thePnt0 - thePnt2;\n"
332 " theNorm = cross (aEdge1, aEdge0);\n"
334 " vec3 theVect = cross (theRay.Direct, aToTrg);\n"
336 " theUVT = vec3 (dot (theNorm, aToTrg),\n"
337 " dot (theVect, aEdge1),\n"
338 " dot (theVect, aEdge0)) * (1.f / dot (theNorm, theRay.Direct));\n"
340 " theUVT.x = any (lessThan (theUVT, ZERO)) || (theUVT.y + theUVT.z) > 1.f ? MAXFLOAT : theUVT.x;\n"
343 "#define EMPTY_ROOT ivec4(0)\n"
345 "//! Utility structure containing information about\n"
346 "//! currently traversing sub-tree of scene's BVH.\n"
349 " //! Transformed ray.\n"
352 " //! Inversed ray direction.\n"
355 " //! Parameters of sub-root node.\n"
359 "#define MATERIAL_AMBN(index) (19 * index + 0)\n"
360 "#define MATERIAL_DIFF(index) (19 * index + 1)\n"
361 "#define MATERIAL_SPEC(index) (19 * index + 2)\n"
362 "#define MATERIAL_EMIS(index) (19 * index + 3)\n"
363 "#define MATERIAL_REFL(index) (19 * index + 4)\n"
364 "#define MATERIAL_REFR(index) (19 * index + 5)\n"
365 "#define MATERIAL_TRAN(index) (19 * index + 6)\n"
366 "#define MATERIAL_TRS1(index) (19 * index + 7)\n"
367 "#define MATERIAL_TRS2(index) (19 * index + 8)\n"
368 "#define MATERIAL_TRS3(index) (19 * index + 9)\n"
370 "#define TRS_OFFSET(treelet) treelet.SubData.x\n"
371 "#define BVH_OFFSET(treelet) treelet.SubData.y\n"
372 "#define VRT_OFFSET(treelet) treelet.SubData.z\n"
373 "#define TRG_OFFSET(treelet) treelet.SubData.w\n"
375 "//! Identifies the absence of intersection.\n"
376 "#define INALID_HIT ivec4 (-1)\n"
378 "//! Global stack shared between traversal functions.\n"
379 "int Stack[STACK_SIZE];\n"
381 "// =======================================================================\n"
382 "// function : pop\n"
384 "// =======================================================================\n"
385 "int pop (inout int theHead)\n"
387 " int aData = Stack[theHead];\n"
389 " int aMask = aData >> 26;\n"
390 " int aNode = aMask & 0x3;\n"
394 " if ((aMask & 0x3) == aNode)\n"
400 " aMask |= (aMask << 2) & 0x30;\n"
402 " Stack[theHead] = (aData & 0x03FFFFFF) | (aMask << 26);\n"
405 " return (aData & 0x03FFFFFF) + aNode;\n"
408 "// =======================================================================\n"
409 "// function : SceneNearestHit\n"
410 "// purpose : Finds intersection with nearest scene triangle\n"
411 "// =======================================================================\n"
412 "ivec4 SceneNearestHit (in SRay theRay, in vec3 theInverse, inout SIntersect theHit, out int theTrsfId)\n"
414 " ivec4 aTriIndex = INALID_HIT;\n"
416 " int aNode = 0; // node to traverse\n"
417 " int aHead = -1; // pointer of stack\n"
418 " int aStop = -1; // BVH level switch\n"
420 " SSubTree aSubTree = SSubTree (theRay, theInverse, EMPTY_ROOT);\n"
422 " for (bool toContinue = true; toContinue; /* none */)\n"
424 " ivec4 aData = texelFetch (uSceneNodeInfoTexture, aNode);\n"
426 " if (aData.x == 0) // if inner node\n"
428 " aData.y += BVH_OFFSET (aSubTree);\n"
430 " vec4 aHitTimes = vec4 (MAXFLOAT,\n"
435 " vec3 aRayOriginInverse = -aSubTree.TrsfRay.Origin * aSubTree.Inverse;\n"
437 " vec3 aNodeMin0 = texelFetch (uSceneMinPointTexture, aData.y + 0).xyz * aSubTree.Inverse + aRayOriginInverse;\n"
438 " vec3 aNodeMin1 = texelFetch (uSceneMinPointTexture, aData.y + 1).xyz * aSubTree.Inverse + aRayOriginInverse;\n"
439 " vec3 aNodeMin2 = texelFetch (uSceneMinPointTexture, aData.y + min (2, aData.z)).xyz * aSubTree.Inverse + aRayOriginInverse;\n"
440 " vec3 aNodeMin3 = texelFetch (uSceneMinPointTexture, aData.y + min (3, aData.z)).xyz * aSubTree.Inverse + aRayOriginInverse;\n"
441 " vec3 aNodeMax0 = texelFetch (uSceneMaxPointTexture, aData.y + 0).xyz * aSubTree.Inverse + aRayOriginInverse;\n"
442 " vec3 aNodeMax1 = texelFetch (uSceneMaxPointTexture, aData.y + 1).xyz * aSubTree.Inverse + aRayOriginInverse;\n"
443 " vec3 aNodeMax2 = texelFetch (uSceneMaxPointTexture, aData.y + min (2, aData.z)).xyz * aSubTree.Inverse + aRayOriginInverse;\n"
444 " vec3 aNodeMax3 = texelFetch (uSceneMaxPointTexture, aData.y + min (3, aData.z)).xyz * aSubTree.Inverse + aRayOriginInverse;\n"
446 " vec3 aTimeMax = max (aNodeMin0, aNodeMax0);\n"
447 " vec3 aTimeMin = min (aNodeMin0, aNodeMax0);\n"
449 " float aTimeLeave = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z));\n"
450 " float aTimeEnter = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));\n"
452 " aHitTimes.x = (aTimeEnter <= aTimeLeave && aTimeEnter <= theHit.Time && aTimeLeave >= 0.f) ? aTimeEnter : MAXFLOAT;\n"
454 " aTimeMax = max (aNodeMin1, aNodeMax1);\n"
455 " aTimeMin = min (aNodeMin1, aNodeMax1);\n"
457 " aTimeLeave = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z));\n"
458 " aTimeEnter = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));\n"
460 " aHitTimes.y = (aTimeEnter <= aTimeLeave && aTimeEnter <= theHit.Time && aTimeLeave >= 0.f) ? aTimeEnter : MAXFLOAT;\n"
462 " aTimeMax = max (aNodeMin2, aNodeMax2);\n"
463 " aTimeMin = min (aNodeMin2, aNodeMax2);\n"
465 " aTimeLeave = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z));\n"
466 " aTimeEnter = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));\n"
468 " aHitTimes.z = (aTimeEnter <= aTimeLeave && aTimeEnter <= theHit.Time && aTimeLeave >= 0.f && aData.z > 1) ? aTimeEnter : MAXFLOAT;\n"
470 " aTimeMax = max (aNodeMin3, aNodeMax3);\n"
471 " aTimeMin = min (aNodeMin3, aNodeMax3);\n"
473 " aTimeLeave = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z));\n"
474 " aTimeEnter = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));\n"
476 " aHitTimes.w = (aTimeEnter <= aTimeLeave && aTimeEnter <= theHit.Time && aTimeLeave >= 0.f && aData.z > 2) ? aTimeEnter : MAXFLOAT;\n"
478 " ivec4 aChildren = ivec4 (0, 1, 2, 3);\n"
480 " aChildren.xy = aHitTimes.y < aHitTimes.x ? aChildren.yx : aChildren.xy;\n"
481 " aHitTimes.xy = aHitTimes.y < aHitTimes.x ? aHitTimes.yx : aHitTimes.xy;\n"
482 " aChildren.zw = aHitTimes.w < aHitTimes.z ? aChildren.wz : aChildren.zw;\n"
483 " aHitTimes.zw = aHitTimes.w < aHitTimes.z ? aHitTimes.wz : aHitTimes.zw;\n"
484 " aChildren.xz = aHitTimes.z < aHitTimes.x ? aChildren.zx : aChildren.xz;\n"
485 " aHitTimes.xz = aHitTimes.z < aHitTimes.x ? aHitTimes.zx : aHitTimes.xz;\n"
486 " aChildren.yw = aHitTimes.w < aHitTimes.y ? aChildren.wy : aChildren.yw;\n"
487 " aHitTimes.yw = aHitTimes.w < aHitTimes.y ? aHitTimes.wy : aHitTimes.yw;\n"
488 " aChildren.yz = aHitTimes.z < aHitTimes.y ? aChildren.zy : aChildren.yz;\n"
489 " aHitTimes.yz = aHitTimes.z < aHitTimes.y ? aHitTimes.zy : aHitTimes.yz;\n"
491 " if (aHitTimes.x != MAXFLOAT)\n"
493 " int aHitMask = (aHitTimes.w != MAXFLOAT ? aChildren.w : aChildren.z) << 2\n"
494 " | (aHitTimes.z != MAXFLOAT ? aChildren.z : aChildren.y);\n"
496 " if (aHitTimes.y != MAXFLOAT)\n"
497 " Stack[++aHead] = aData.y | (aHitMask << 2 | aChildren.y) << 26;\n"
499 " aNode = aData.y + aChildren.x;\n"
503 " toContinue = (aHead >= 0);\n"
505 " if (aHead == aStop) // go to top-level BVH\n"
507 " aStop = -1; aSubTree = SSubTree (theRay, theInverse, EMPTY_ROOT);\n"
511 " aNode = pop (aHead);\n"
514 " else if (aData.x < 0) // leaf node (contains triangles)\n"
519 " for (int anIdx = aData.y; anIdx <= aData.z; ++anIdx)\n"
521 " ivec4 aTriangle = texelFetch (uGeometryTriangTexture, anIdx + TRG_OFFSET (aSubTree));\n"
523 " vec3 aPoint0 = texelFetch (uGeometryVertexTexture, aTriangle.x += VRT_OFFSET (aSubTree)).xyz;\n"
524 " vec3 aPoint1 = texelFetch (uGeometryVertexTexture, aTriangle.y += VRT_OFFSET (aSubTree)).xyz;\n"
525 " vec3 aPoint2 = texelFetch (uGeometryVertexTexture, aTriangle.z += VRT_OFFSET (aSubTree)).xyz;\n"
527 " IntersectTriangle (aSubTree.TrsfRay, aPoint0, aPoint1, aPoint2, aTimeUV, aNormal);\n"
529 " if (aTimeUV.x < theHit.Time)\n"
531 " aTriIndex = aTriangle;\n"
533 " theTrsfId = TRS_OFFSET (aSubTree);\n"
535 " theHit = SIntersect (aTimeUV.x, aTimeUV.yz, aNormal);\n"
539 " toContinue = (aHead >= 0);\n"
541 " if (aHead == aStop) // go to top-level BVH\n"
543 " aStop = -1; aSubTree = SSubTree (theRay, theInverse, EMPTY_ROOT);\n"
547 " aNode = pop (aHead);\n"
549 " else if (aData.x > 0) // switch node\n"
551 " aSubTree.SubData = ivec4 (4 * aData.x - 4, aData.yzw); // store BVH sub-root\n"
553 " vec4 aInvTransf0 = texelFetch (uSceneTransformTexture, TRS_OFFSET (aSubTree) + 0);\n"
554 " vec4 aInvTransf1 = texelFetch (uSceneTransformTexture, TRS_OFFSET (aSubTree) + 1);\n"
555 " vec4 aInvTransf2 = texelFetch (uSceneTransformTexture, TRS_OFFSET (aSubTree) + 2);\n"
556 " vec4 aInvTransf3 = texelFetch (uSceneTransformTexture, TRS_OFFSET (aSubTree) + 3);\n"
558 " aSubTree.TrsfRay.Direct = MatrixColMultiplyDir (theRay.Direct,\n"
563 " aSubTree.Inverse = mix (-UNIT, UNIT, step (ZERO, aSubTree.TrsfRay.Direct)) /\n"
564 " max (abs (aSubTree.TrsfRay.Direct), SMALL);\n"
566 " aSubTree.TrsfRay.Origin = MatrixColMultiplyPnt (theRay.Origin,\n"
572 " aNode = BVH_OFFSET (aSubTree); // go to sub-root node\n"
574 " aStop = aHead; // store current stack pointer\n"
578 " return aTriIndex;\n"
581 "// =======================================================================\n"
582 "// function : SceneAnyHit\n"
583 "// purpose : Finds intersection with any scene triangle\n"
584 "// =======================================================================\n"
585 "float SceneAnyHit (in SRay theRay, in vec3 theInverse, in float theDistance)\n"
587 " float aFactor = 1.f;\n"
589 " int aNode = 0; // node to traverse\n"
590 " int aHead = -1; // pointer of stack\n"
591 " int aStop = -1; // BVH level switch\n"
593 " SSubTree aSubTree = SSubTree (theRay, theInverse, EMPTY_ROOT);\n"
595 " for (bool toContinue = true; toContinue; /* none */)\n"
597 " ivec4 aData = texelFetch (uSceneNodeInfoTexture, aNode);\n"
599 " if (aData.x == 0) // if inner node\n"
601 " aData.y += BVH_OFFSET (aSubTree);\n"
603 " vec4 aHitTimes = vec4 (MAXFLOAT,\n"
608 " vec3 aRayOriginInverse = -aSubTree.TrsfRay.Origin * aSubTree.Inverse;\n"
610 " vec3 aNodeMin0 = texelFetch (uSceneMinPointTexture, aData.y + 0).xyz * aSubTree.Inverse + aRayOriginInverse;\n"
611 " vec3 aNodeMin1 = texelFetch (uSceneMinPointTexture, aData.y + 1).xyz * aSubTree.Inverse + aRayOriginInverse;\n"
612 " vec3 aNodeMin2 = texelFetch (uSceneMinPointTexture, aData.y + min (2, aData.z)).xyz * aSubTree.Inverse + aRayOriginInverse;\n"
613 " vec3 aNodeMin3 = texelFetch (uSceneMinPointTexture, aData.y + min (3, aData.z)).xyz * aSubTree.Inverse + aRayOriginInverse;\n"
614 " vec3 aNodeMax0 = texelFetch (uSceneMaxPointTexture, aData.y + 0).xyz * aSubTree.Inverse + aRayOriginInverse;\n"
615 " vec3 aNodeMax1 = texelFetch (uSceneMaxPointTexture, aData.y + 1).xyz * aSubTree.Inverse + aRayOriginInverse;\n"
616 " vec3 aNodeMax2 = texelFetch (uSceneMaxPointTexture, aData.y + min (2, aData.z)).xyz * aSubTree.Inverse + aRayOriginInverse;\n"
617 " vec3 aNodeMax3 = texelFetch (uSceneMaxPointTexture, aData.y + min (3, aData.z)).xyz * aSubTree.Inverse + aRayOriginInverse;\n"
619 " vec3 aTimeMax = max (aNodeMin0, aNodeMax0);\n"
620 " vec3 aTimeMin = min (aNodeMin0, aNodeMax0);\n"
622 " float aTimeLeave = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z));\n"
623 " float aTimeEnter = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));\n"
625 " aHitTimes.x = (aTimeEnter <= aTimeLeave && aTimeEnter <= theDistance && aTimeLeave >= 0.f) ? aTimeEnter : MAXFLOAT;\n"
627 " aTimeMax = max (aNodeMin1, aNodeMax1);\n"
628 " aTimeMin = min (aNodeMin1, aNodeMax1);\n"
630 " aTimeLeave = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z));\n"
631 " aTimeEnter = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));\n"
633 " aHitTimes.y = (aTimeEnter <= aTimeLeave && aTimeEnter <= theDistance && aTimeLeave >= 0.f) ? aTimeEnter : MAXFLOAT;\n"
635 " aTimeMax = max (aNodeMin2, aNodeMax2);\n"
636 " aTimeMin = min (aNodeMin2, aNodeMax2);\n"
638 " aTimeLeave = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z));\n"
639 " aTimeEnter = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));\n"
641 " aHitTimes.z = (aTimeEnter <= aTimeLeave && aTimeEnter <= theDistance && aTimeLeave >= 0.f && aData.z > 1) ? aTimeEnter : MAXFLOAT;\n"
643 " aTimeMax = max (aNodeMin3, aNodeMax3);\n"
644 " aTimeMin = min (aNodeMin3, aNodeMax3);\n"
646 " aTimeLeave = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z));\n"
647 " aTimeEnter = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));\n"
649 " aHitTimes.w = (aTimeEnter <= aTimeLeave && aTimeEnter <= theDistance && aTimeLeave >= 0.f && aData.z > 2) ? aTimeEnter : MAXFLOAT;\n"
651 " ivec4 aChildren = ivec4 (0, 1, 2, 3);\n"
653 " aChildren.xy = aHitTimes.y < aHitTimes.x ? aChildren.yx : aChildren.xy;\n"
654 " aHitTimes.xy = aHitTimes.y < aHitTimes.x ? aHitTimes.yx : aHitTimes.xy;\n"
655 " aChildren.zw = aHitTimes.w < aHitTimes.z ? aChildren.wz : aChildren.zw;\n"
656 " aHitTimes.zw = aHitTimes.w < aHitTimes.z ? aHitTimes.wz : aHitTimes.zw;\n"
657 " aChildren.xz = aHitTimes.z < aHitTimes.x ? aChildren.zx : aChildren.xz;\n"
658 " aHitTimes.xz = aHitTimes.z < aHitTimes.x ? aHitTimes.zx : aHitTimes.xz;\n"
659 " aChildren.yw = aHitTimes.w < aHitTimes.y ? aChildren.wy : aChildren.yw;\n"
660 " aHitTimes.yw = aHitTimes.w < aHitTimes.y ? aHitTimes.wy : aHitTimes.yw;\n"
661 " aChildren.yz = aHitTimes.z < aHitTimes.y ? aChildren.zy : aChildren.yz;\n"
662 " aHitTimes.yz = aHitTimes.z < aHitTimes.y ? aHitTimes.zy : aHitTimes.yz;\n"
664 " if (aHitTimes.x != MAXFLOAT)\n"
666 " int aHitMask = (aHitTimes.w != MAXFLOAT ? aChildren.w : aChildren.z) << 2\n"
667 " | (aHitTimes.z != MAXFLOAT ? aChildren.z : aChildren.y);\n"
669 " if (aHitTimes.y != MAXFLOAT)\n"
670 " Stack[++aHead] = aData.y | (aHitMask << 2 | aChildren.y) << 26;\n"
672 " aNode = aData.y + aChildren.x;\n"
676 " toContinue = (aHead >= 0);\n"
678 " if (aHead == aStop) // go to top-level BVH\n"
680 " aStop = -1; aSubTree = SSubTree (theRay, theInverse, EMPTY_ROOT);\n"
684 " aNode = pop (aHead);\n"
687 " else if (aData.x < 0) // leaf node\n"
692 " for (int anIdx = aData.y; anIdx <= aData.z; ++anIdx)\n"
694 " ivec4 aTriangle = texelFetch (uGeometryTriangTexture, anIdx + TRG_OFFSET (aSubTree));\n"
696 " vec3 aPoint0 = texelFetch (uGeometryVertexTexture, aTriangle.x += VRT_OFFSET (aSubTree)).xyz;\n"
697 " vec3 aPoint1 = texelFetch (uGeometryVertexTexture, aTriangle.y += VRT_OFFSET (aSubTree)).xyz;\n"
698 " vec3 aPoint2 = texelFetch (uGeometryVertexTexture, aTriangle.z += VRT_OFFSET (aSubTree)).xyz;\n"
700 " IntersectTriangle (aSubTree.TrsfRay, aPoint0, aPoint1, aPoint2, aTimeUV, aNormal);\n"
702 "#ifdef TRANSPARENT_SHADOWS\n"
703 " if (aTimeUV.x < theDistance)\n"
705 " aFactor *= 1.f - texelFetch (uRaytraceMaterialTexture, MATERIAL_TRAN (aTriangle.w)).x;\n"
708 " if (aTimeUV.x < theDistance)\n"
715 " toContinue = (aHead >= 0) && (aFactor > 0.1f);\n"
717 " if (aHead == aStop) // go to top-level BVH\n"
719 " aStop = -1; aSubTree = SSubTree (theRay, theInverse, EMPTY_ROOT);\n"
723 " aNode = pop (aHead);\n"
725 " else if (aData.x > 0) // switch node\n"
727 " aSubTree.SubData = ivec4 (4 * aData.x - 4, aData.yzw); // store BVH sub-root\n"
729 " vec4 aInvTransf0 = texelFetch (uSceneTransformTexture, TRS_OFFSET (aSubTree) + 0);\n"
730 " vec4 aInvTransf1 = texelFetch (uSceneTransformTexture, TRS_OFFSET (aSubTree) + 1);\n"
731 " vec4 aInvTransf2 = texelFetch (uSceneTransformTexture, TRS_OFFSET (aSubTree) + 2);\n"
732 " vec4 aInvTransf3 = texelFetch (uSceneTransformTexture, TRS_OFFSET (aSubTree) + 3);\n"
734 " aSubTree.TrsfRay.Direct = MatrixColMultiplyDir (theRay.Direct,\n"
739 " aSubTree.TrsfRay.Origin = MatrixColMultiplyPnt (theRay.Origin,\n"
745 " aSubTree.Inverse = mix (-UNIT, UNIT, step (ZERO, aSubTree.TrsfRay.Direct)) / max (abs (aSubTree.TrsfRay.Direct), SMALL);\n"
747 " aNode = BVH_OFFSET (aSubTree); // go to sub-root node\n"
749 " aStop = aHead; // store current stack pointer\n"
756 "#define PI 3.1415926f\n"
758 "// =======================================================================\n"
759 "// function : Latlong\n"
760 "// purpose : Converts world direction to environment texture coordinates\n"
761 "// =======================================================================\n"
762 "vec2 Latlong (in vec3 thePoint, in float theRadius)\n"
764 " float aPsi = acos (-thePoint.z / theRadius);\n"
766 " float aPhi = atan (thePoint.y, thePoint.x) + PI;\n"
768 " return vec2 (aPhi * 0.1591549f,\n"
769 " aPsi * 0.3183098f);\n"
772 "// =======================================================================\n"
773 "// function : SmoothNormal\n"
774 "// purpose : Interpolates normal across the triangle\n"
775 "// =======================================================================\n"
776 "vec3 SmoothNormal (in vec2 theUV, in ivec4 theTriangle)\n"
778 " vec3 aNormal0 = texelFetch (uGeometryNormalTexture, theTriangle.x).xyz;\n"
779 " vec3 aNormal1 = texelFetch (uGeometryNormalTexture, theTriangle.y).xyz;\n"
780 " vec3 aNormal2 = texelFetch (uGeometryNormalTexture, theTriangle.z).xyz;\n"
782 " return normalize (aNormal1 * theUV.x +\n"
783 " aNormal2 * theUV.y +\n"
784 " aNormal0 * (1.0f - theUV.x - theUV.y));\n"
787 "#define POLYGON_OFFSET_UNIT 0.f\n"
788 "#define POLYGON_OFFSET_FACTOR 1.f\n"
789 "#define POLYGON_OFFSET_SCALE 0.006f\n"
791 "// =======================================================================\n"
792 "// function : PolygonOffset\n"
793 "// purpose : Computes OpenGL polygon offset\n"
794 "// =======================================================================\n"
795 "float PolygonOffset (in vec3 theNormal, in vec3 thePoint)\n"
797 " vec4 aProjectedNorm = vec4 (theNormal, -dot (theNormal, thePoint)) * uUnviewMat;\n"
799 " float aPolygonOffset = POLYGON_OFFSET_UNIT;\n"
801 " if (aProjectedNorm.z * aProjectedNorm.z > 1e-20f)\n"
803 " aProjectedNorm.xy *= 1.f / aProjectedNorm.z;\n"
805 " aPolygonOffset += POLYGON_OFFSET_FACTOR * max (abs (aProjectedNorm.x),\n"
806 " abs (aProjectedNorm.y));\n"
809 " return aPolygonOffset;\n"
812 "// =======================================================================\n"
813 "// function : SmoothUV\n"
814 "// purpose : Interpolates UV coordinates across the triangle\n"
815 "// =======================================================================\n"
816 "#ifdef USE_TEXTURES\n"
817 "vec2 SmoothUV (in vec2 theUV, in ivec4 theTriangle)\n"
819 " vec2 aTexCrd0 = texelFetch (uGeometryTexCrdTexture, theTriangle.x).st;\n"
820 " vec2 aTexCrd1 = texelFetch (uGeometryTexCrdTexture, theTriangle.y).st;\n"
821 " vec2 aTexCrd2 = texelFetch (uGeometryTexCrdTexture, theTriangle.z).st;\n"
823 " return aTexCrd1 * theUV.x +\n"
824 " aTexCrd2 * theUV.y +\n"
825 " aTexCrd0 * (1.0f - theUV.x - theUV.y);\n"
829 "// =======================================================================\n"
830 "// function : FetchEnvironment\n"
832 "// =======================================================================\n"
833 "vec4 FetchEnvironment (in vec2 theTexCoord)\n"
835 " return uSphereMapEnabled == 0 ?\n"
836 " vec4 (0.f, 0.f, 0.f, 1.f) : textureLod (uEnvironmentMapTexture, theTexCoord, 0.f);\n"
839 "// =======================================================================\n"
840 "// function : Refract\n"
841 "// purpose : Computes refraction ray (also handles TIR)\n"
842 "// =======================================================================\n"
843 "#ifndef PATH_TRACING\n"
844 "vec3 Refract (in vec3 theInput,\n"
845 " in vec3 theNormal,\n"
846 " in float theRefractIndex,\n"
847 " in float theInvRefractIndex)\n"
849 " float aNdotI = dot (theInput, theNormal);\n"
851 " float anIndex = aNdotI < 0.0f\n"
852 " ? theInvRefractIndex\n"
853 " : theRefractIndex;\n"
855 " float aSquare = anIndex * anIndex * (1.0f - aNdotI * aNdotI);\n"
857 " if (aSquare > 1.0f)\n"
859 " return reflect (theInput, theNormal);\n"
862 " float aNdotT = sqrt (1.0f - aSquare);\n"
864 " return normalize (anIndex * theInput -\n"
865 " (anIndex * aNdotI + (aNdotI < 0.0f ? aNdotT : -aNdotT)) * theNormal);\n"
869 "#define MIN_SLOPE 0.0001f\n"
870 "#define EPS_SCALE 8.0000f\n"
872 "#define THRESHOLD vec3 (0.1f)\n"
874 "#define INVALID_BOUNCES 1000\n"
876 "#define LIGHT_POS(index) (2 * index + 1)\n"
877 "#define LIGHT_PWR(index) (2 * index + 0)\n"
879 "// =======================================================================\n"
880 "// function : Radiance\n"
881 "// purpose : Computes color along the given ray\n"
882 "// =======================================================================\n"
883 "#ifndef PATH_TRACING\n"
884 "vec4 Radiance (in SRay theRay, in vec3 theInverse)\n"
886 " vec3 aResult = vec3 (0.0f);\n"
887 " vec4 aWeight = vec4 (1.0f);\n"
891 " float aRaytraceDepth = MAXFLOAT;\n"
893 " for (int aDepth = 0; aDepth < NB_BOUNCES; ++aDepth)\n"
895 " SIntersect aHit = SIntersect (MAXFLOAT, vec2 (ZERO), ZERO);\n"
897 " ivec4 aTriIndex = SceneNearestHit (theRay, theInverse, aHit, aTrsfId);\n"
899 " if (aTriIndex.x == -1)\n"
901 " vec4 aColor = vec4 (0.0);\n"
903 " if (bool(uSphereMapForBack) || aWeight.w == 0.0f /* reflection */)\n"
905 " float aTime = IntersectSphere (theRay, uSceneRadius);\n"
907 " aColor = FetchEnvironment (Latlong (\n"
908 " theRay.Direct * aTime + theRay.Origin, uSceneRadius));\n"
912 " aColor = BackgroundColor();\n"
915 " aResult += aWeight.xyz * aColor.xyz; aWeight.w *= aColor.w;\n"
917 " break; // terminate path\n"
920 " vec3 aInvTransf0 = texelFetch (uSceneTransformTexture, aTrsfId + 0).xyz;\n"
921 " vec3 aInvTransf1 = texelFetch (uSceneTransformTexture, aTrsfId + 1).xyz;\n"
922 " vec3 aInvTransf2 = texelFetch (uSceneTransformTexture, aTrsfId + 2).xyz;\n"
924 " aHit.Normal = normalize (vec3 (dot (aInvTransf0, aHit.Normal),\n"
925 " dot (aInvTransf1, aHit.Normal),\n"
926 " dot (aInvTransf2, aHit.Normal)));\n"
928 " theRay.Origin += theRay.Direct * aHit.Time; // intersection point\n"
930 " // Evaluate depth on first hit\n"
931 " if (aDepth == 0)\n"
933 " vec4 aNDCPoint = uViewMat * vec4 (theRay.Origin, 1.f);\n"
935 " float aPolygonOffset = PolygonOffset (aHit.Normal, theRay.Origin);\n"
936 " aRaytraceDepth = (aNDCPoint.z / aNDCPoint.w + aPolygonOffset * POLYGON_OFFSET_SCALE) * 0.5f + 0.5f;\n"
939 " vec3 aNormal = SmoothNormal (aHit.UV, aTriIndex);\n"
941 " aNormal = normalize (vec3 (dot (aInvTransf0, aNormal),\n"
942 " dot (aInvTransf1, aNormal),\n"
943 " dot (aInvTransf2, aNormal)));\n"
945 " vec3 aAmbient = texelFetch (\n"
946 " uRaytraceMaterialTexture, MATERIAL_AMBN (aTriIndex.w)).rgb;\n"
947 " vec4 aDiffuse = texelFetch (\n"
948 " uRaytraceMaterialTexture, MATERIAL_DIFF (aTriIndex.w));\n"
949 " vec4 aSpecular = texelFetch (\n"
950 " uRaytraceMaterialTexture, MATERIAL_SPEC (aTriIndex.w));\n"
951 " vec4 aOpacity = texelFetch (\n"
952 " uRaytraceMaterialTexture, MATERIAL_TRAN (aTriIndex.w));\n"
954 "#ifdef USE_TEXTURES\n"
955 " if (aDiffuse.w >= 0.f)\n"
957 " vec4 aTexCoord = vec4 (SmoothUV (aHit.UV, aTriIndex), 0.f, 1.f);\n"
959 " vec4 aTrsfRow1 = texelFetch (\n"
960 " uRaytraceMaterialTexture, MATERIAL_TRS1 (aTriIndex.w));\n"
961 " vec4 aTrsfRow2 = texelFetch (\n"
962 " uRaytraceMaterialTexture, MATERIAL_TRS2 (aTriIndex.w));\n"
964 " aTexCoord.st = vec2 (dot (aTrsfRow1, aTexCoord),\n"
965 " dot (aTrsfRow2, aTexCoord));\n"
967 " vec4 aTexColor = textureLod (\n"
968 " sampler2D (uTextureSamplers[int(aDiffuse.w)]), aTexCoord.st, 0.f);\n"
970 " aDiffuse.rgb *= aTexColor.rgb;\n"
971 " aAmbient.rgb *= aTexColor.rgb;\n"
973 " // keep refractive index untouched (Z component)\n"
974 " aOpacity.xy = vec2 (aTexColor.w * aOpacity.x, 1.0f - aTexColor.w * aOpacity.x);\n"
978 " vec3 aEmission = texelFetch (\n"
979 " uRaytraceMaterialTexture, MATERIAL_EMIS (aTriIndex.w)).rgb;\n"
981 " float aGeomFactor = dot (aNormal, theRay.Direct);\n"
983 " aResult.xyz += aWeight.xyz * aOpacity.x * (\n"
984 " uGlobalAmbient.xyz * aAmbient * max (abs (aGeomFactor), 0.5f) + aEmission);\n"
986 " vec3 aSidedNormal = mix (aNormal, -aNormal, step (0.0f, aGeomFactor));\n"
988 " for (int aLightIdx = 0; aLightIdx < uLightCount; ++aLightIdx)\n"
990 " vec4 aLight = texelFetch (\n"
991 " uRaytraceLightSrcTexture, LIGHT_POS (aLightIdx));\n"
993 " float aDistance = MAXFLOAT;\n"
995 " if (aLight.w != 0.0f) // point light source\n"
997 " aDistance = length (aLight.xyz -= theRay.Origin);\n"
999 " aLight.xyz *= 1.0f / aDistance;\n"
1002 " float aLdotN = dot (aLight.xyz, aSidedNormal);\n"
1004 " if (aLdotN > 0.0f) // first check if light source is important\n"
1006 " float aVisibility = 1.0f;\n"
1008 " if (bool(uShadowsEnabled))\n"
1010 " SRay aShadow = SRay (theRay.Origin, aLight.xyz);\n"
1012 " aShadow.Origin += uSceneEpsilon * (aLight.xyz +\n"
1013 " mix (-aHit.Normal, aHit.Normal, step (0.0f, dot (aHit.Normal, aLight.xyz))));\n"
1015 " vec3 aInverse = 1.0f / max (abs (aLight.xyz), SMALL);\n"
1017 " aVisibility = SceneAnyHit (\n"
1018 " aShadow, mix (-aInverse, aInverse, step (ZERO, aLight.xyz)), aDistance);\n"
1021 " if (aVisibility > 0.0f)\n"
1023 " vec3 aIntensity = min (UNIT, vec3 (texelFetch (\n"
1024 " uRaytraceLightSrcTexture, LIGHT_PWR (aLightIdx))));\n"
1026 " float aRdotV = dot (reflect (aLight.xyz, aSidedNormal), theRay.Direct);\n"
1028 " aResult.xyz += aWeight.xyz * (aOpacity.x * aVisibility) * aIntensity *\n"
1029 " (aDiffuse.xyz * aLdotN + aSpecular.xyz * pow (max (0.f, aRdotV), aSpecular.w));\n"
1034 " if (aOpacity.x != 1.0f)\n"
1036 " aWeight *= aOpacity.y;\n"
1038 " if (aOpacity.z != 1.0f)\n"
1040 " theRay.Direct = Refract (theRay.Direct, aNormal, aOpacity.z, aOpacity.w);\n"
1045 " aWeight *= bool(uReflectEnabled) ?\n"
1046 " texelFetch (uRaytraceMaterialTexture, MATERIAL_REFL (aTriIndex.w)) : vec4 (0.0f);\n"
1048 " vec3 aReflect = reflect (theRay.Direct, aNormal);\n"
1050 " if (dot (aReflect, aHit.Normal) * dot (theRay.Direct, aHit.Normal) > 0.0f)\n"
1052 " aReflect = reflect (theRay.Direct, aHit.Normal);\n"
1055 " theRay.Direct = aReflect;\n"
1058 " if (all (lessThanEqual (aWeight.xyz, THRESHOLD)))\n"
1060 " aDepth = INVALID_BOUNCES;\n"
1062 " else if (aOpacity.x == 1.0f || aOpacity.z != 1.0f) // if no simple transparency\n"
1064 " theRay.Origin += aHit.Normal * mix (\n"
1065 " -uSceneEpsilon, uSceneEpsilon, step (0.0f, dot (aHit.Normal, theRay.Direct)));\n"
1067 " theInverse = 1.0f / max (abs (theRay.Direct), SMALL);\n"
1069 " theInverse = mix (-theInverse, theInverse, step (ZERO, theRay.Direct));\n"
1072 " theRay.Origin += theRay.Direct * uSceneEpsilon;\n"
1075 " gl_FragDepth = aRaytraceDepth;\n"
1077 " return vec4 (aResult.x,\n"