2 #extension GL_ARB_bindless_texture : require
5 //! Normalized pixel coordinates.
8 //! Sub-pixel offset in X direction for FSAA.
9 uniform float uOffsetX = 0.f;
10 //! Sub-pixel offset in Y direction for FSAA.
11 uniform float uOffsetY = 0.f;
13 //! Origin of viewing ray in left-top corner.
14 uniform vec3 uOriginLT;
15 //! Origin of viewing ray in left-bottom corner.
16 uniform vec3 uOriginLB;
17 //! Origin of viewing ray in right-top corner.
18 uniform vec3 uOriginRT;
19 //! Origin of viewing ray in right-bottom corner.
20 uniform vec3 uOriginRB;
22 //! Direction of viewing ray in left-top corner.
23 uniform vec3 uDirectLT;
24 //! Direction of viewing ray in left-bottom corner.
25 uniform vec3 uDirectLB;
26 //! Direction of viewing ray in right-top corner.
27 uniform vec3 uDirectRT;
28 //! Direction of viewing ray in right-bottom corner.
29 uniform vec3 uDirectRB;
31 //! Inverse model-view-projection matrix.
32 uniform mat4 uUnviewMat;
34 //! Texture buffer of data records of high-level BVH nodes.
35 uniform isamplerBuffer uSceneNodeInfoTexture;
36 //! Texture buffer of minimum points of high-level BVH nodes.
37 uniform samplerBuffer uSceneMinPointTexture;
38 //! Texture buffer of maximum points of high-level BVH nodes.
39 uniform samplerBuffer uSceneMaxPointTexture;
40 //! Texture buffer of transformations of high-level BVH nodes.
41 uniform samplerBuffer uSceneTransformTexture;
43 //! Texture buffer of data records of bottom-level BVH nodes.
44 uniform isamplerBuffer uObjectNodeInfoTexture;
45 //! Texture buffer of minimum points of bottom-level BVH nodes.
46 uniform samplerBuffer uObjectMinPointTexture;
47 //! Texture buffer of maximum points of bottom-level BVH nodes.
48 uniform samplerBuffer uObjectMaxPointTexture;
50 //! Texture buffer of vertex coords.
51 uniform samplerBuffer uGeometryVertexTexture;
52 //! Texture buffer of vertex normals.
53 uniform samplerBuffer uGeometryNormalTexture;
55 //! Texture buffer of per-vertex UV-coordinates.
56 uniform samplerBuffer uGeometryTexCrdTexture;
58 //! Texture buffer of triangle indices.
59 uniform isamplerBuffer uGeometryTriangTexture;
61 //! Texture buffer of material properties.
62 uniform samplerBuffer uRaytraceMaterialTexture;
63 //! Texture buffer of light source properties.
64 uniform samplerBuffer uRaytraceLightSrcTexture;
65 //! Environment map texture.
66 uniform sampler2D uEnvironmentMapTexture;
68 //! Input pre-raytracing image rendered by OpenGL.
69 uniform sampler2D uOpenGlColorTexture;
70 //! Input pre-raytracing depth image rendered by OpenGL.
71 uniform sampler2D uOpenGlDepthTexture;
73 //! Total number of light sources.
74 uniform int uLightCount;
75 //! Intensity of global ambient light.
76 uniform vec4 uGlobalAmbient;
78 //! Enables/disables environment map.
79 uniform int uEnvironmentEnable;
80 //! Enables/disables computation of shadows.
81 uniform int uShadowsEnable;
82 //! Enables/disables computation of reflections.
83 uniform int uReflectionsEnable;
85 //! Radius of bounding sphere of the scene.
86 uniform float uSceneRadius;
87 //! Scene epsilon to prevent self-intersections.
88 uniform float uSceneEpsilon;
91 //! Unique 64-bit handles of OpenGL textures.
92 uniform sampler2D uTextureSamplers[MAX_TEX_NUMBER];
95 /////////////////////////////////////////////////////////////////////////////////////////
96 // Specific data types
98 //! Stores ray parameters.
106 //! Stores intersection parameters.
116 /////////////////////////////////////////////////////////////////////////////////////////
117 // Some useful constants
119 #define MAXFLOAT 1e15f
121 #define SMALL vec3 (exp2 (-80.0f))
123 #define ZERO vec3 (0.0f, 0.0f, 0.0f)
124 #define UNIT vec3 (1.0f, 1.0f, 1.0f)
126 #define AXIS_X vec3 (1.0f, 0.0f, 0.0f)
127 #define AXIS_Y vec3 (0.0f, 1.0f, 0.0f)
128 #define AXIS_Z vec3 (0.0f, 0.0f, 1.0f)
130 // =======================================================================
131 // function : MatrixRowMultiplyDir
132 // purpose : Multiplies a vector by matrix
133 // =======================================================================
134 vec3 MatrixRowMultiplyDir (in vec3 v,
139 return vec3 (dot (m0.xyz, v),
144 // =======================================================================
145 // function : MatrixColMultiplyPnt
146 // purpose : Multiplies a vector by matrix
147 // =======================================================================
148 vec3 MatrixColMultiplyPnt (in vec3 v,
154 return vec3 (m0[0] * v.x + m1[0] * v.y + m2[0] * v.z + m3[0],
155 m0[1] * v.x + m1[1] * v.y + m2[1] * v.z + m3[1],
156 m0[2] * v.x + m1[2] * v.y + m2[2] * v.z + m3[2]);
159 // =======================================================================
160 // function : MatrixColMultiplyDir
161 // purpose : Multiplies a vector by matrix
162 // =======================================================================
163 vec3 MatrixColMultiplyDir (in vec3 v,
169 return vec3 (m0[0] * v.x + m1[0] * v.y + m2[0] * v.z,
170 m0[1] * v.x + m1[1] * v.y + m2[1] * v.z,
171 m0[2] * v.x + m1[2] * v.y + m2[2] * v.z);
174 /////////////////////////////////////////////////////////////////////////////////////////
175 // Functions for compute ray-object intersection
177 // =======================================================================
178 // function : GenerateRay
180 // =======================================================================
181 SRay GenerateRay (in vec2 thePixel)
183 vec3 aP0 = mix (uOriginLB, uOriginRB, thePixel.x);
184 vec3 aP1 = mix (uOriginLT, uOriginRT, thePixel.x);
186 vec3 aD0 = mix (uDirectLB, uDirectRB, thePixel.x);
187 vec3 aD1 = mix (uDirectLT, uDirectRT, thePixel.x);
189 vec3 aDirection = normalize (mix (aD0, aD1, thePixel.y));
191 return SRay (mix (aP0, aP1, thePixel.y), aDirection);
194 // =======================================================================
195 // function : ComputeOpenGlDepth
197 // =======================================================================
198 float ComputeOpenGlDepth (in SRay theRay)
200 // a depth in range [0,1]
201 float anOpenGlDepth = texelFetch (uOpenGlDepthTexture, ivec2 (gl_FragCoord.xy), 0).r;
202 // pixel point in NDC-space [-1,1]
203 vec4 aPoint = vec4 (2.0f * vPixel.x - 1.0f,
204 2.0f * vPixel.y - 1.0f,
205 2.0f * anOpenGlDepth - 1.0f,
207 vec4 aFinal = uUnviewMat * aPoint;
208 aFinal.xyz *= 1.f / aFinal.w;
210 return (anOpenGlDepth < 1.f) ? length (aFinal.xyz - theRay.Origin) : MAXFLOAT;
213 // =======================================================================
214 // function : ComputeOpenGlColor
216 // =======================================================================
217 vec4 ComputeOpenGlColor (in SRay theRay)
219 vec4 anOpenGlColor = texelFetch (uOpenGlColorTexture, ivec2 (gl_FragCoord.xy), 0);
220 // During blending with factors GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA (for text and markers)
221 // the alpha channel (written in the color buffer) was squared.
222 anOpenGlColor.a = 1.f - sqrt (anOpenGlColor.a);
224 return anOpenGlColor;
227 // =======================================================================
228 // function : IntersectSphere
229 // purpose : Computes ray-sphere intersection
230 // =======================================================================
231 float IntersectSphere (in SRay theRay, in float theRadius)
233 float aDdotD = dot (theRay.Direct, theRay.Direct);
234 float aDdotO = dot (theRay.Direct, theRay.Origin);
235 float aOdotO = dot (theRay.Origin, theRay.Origin);
237 float aD = aDdotO * aDdotO - aDdotD * (aOdotO - theRadius * theRadius);
241 float aTime = (sqrt (aD) - aDdotO) * (1.0f / aDdotD);
243 return aTime > 0.0f ? aTime : MAXFLOAT;
249 // =======================================================================
250 // function : IntersectTriangle
251 // purpose : Computes ray-triangle intersection (branchless version)
252 // =======================================================================
253 float IntersectTriangle (in SRay theRay,
260 vec3 aEdge0 = thePnt1 - thePnt0;
261 vec3 aEdge1 = thePnt0 - thePnt2;
263 theNorm = cross (aEdge1, aEdge0);
265 vec3 aEdge2 = (1.0f / dot (theNorm, theRay.Direct)) * (thePnt0 - theRay.Origin);
267 float aTime = dot (theNorm, aEdge2);
269 vec3 theVec = cross (theRay.Direct, aEdge2);
271 theUV.x = dot (theVec, aEdge1);
272 theUV.y = dot (theVec, aEdge0);
274 return bool (int(aTime >= 0.0f) &
275 int(theUV.x >= 0.0f) &
276 int(theUV.y >= 0.0f) &
277 int(theUV.x + theUV.y <= 1.0f)) ? aTime : MAXFLOAT;
280 //! Identifies the absence of intersection.
281 #define INALID_HIT ivec4 (-1)
283 //! Global stack shared between traversal functions.
284 int Stack[STACK_SIZE];
286 // =======================================================================
287 // function : ObjectNearestHit
288 // purpose : Finds intersection with nearest object triangle
289 // =======================================================================
290 ivec4 ObjectNearestHit (in int theBVHOffset, in int theVrtOffset, in int theTrgOffset,
291 in SRay theRay, in vec3 theInverse, inout SIntersect theHit, in int theSentinel)
293 int aHead = theSentinel; // stack pointer
294 int aNode = theBVHOffset; // node to visit
296 ivec4 aTriIndex = INALID_HIT;
300 ivec3 aData = texelFetch (uObjectNodeInfoTexture, aNode).xyz;
302 if (aData.x == 0) // if inner node
308 aData.y += theBVHOffset;
309 aData.z += theBVHOffset;
311 vec3 aNodeMinLft = texelFetch (uObjectMinPointTexture, aData.y).xyz;
312 vec3 aNodeMaxLft = texelFetch (uObjectMaxPointTexture, aData.y).xyz;
313 vec3 aNodeMinRgh = texelFetch (uObjectMinPointTexture, aData.z).xyz;
314 vec3 aNodeMaxRgh = texelFetch (uObjectMaxPointTexture, aData.z).xyz;
316 vec3 aTime0 = (aNodeMinLft - theRay.Origin) * theInverse;
317 vec3 aTime1 = (aNodeMaxLft - theRay.Origin) * theInverse;
319 vec3 aTimeMax = max (aTime0, aTime1);
320 vec3 aTimeMin = min (aTime0, aTime1);
322 aTime0 = (aNodeMinRgh - theRay.Origin) * theInverse;
323 aTime1 = (aNodeMaxRgh - theRay.Origin) * theInverse;
325 aTimeOut = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z));
326 aTimeLft = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));
328 int aHitLft = int(aTimeLft <= aTimeOut) & int(aTimeOut >= 0.0f) & int(aTimeLft <= theHit.Time);
330 aTimeMax = max (aTime0, aTime1);
331 aTimeMin = min (aTime0, aTime1);
333 aTimeOut = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z));
334 aTimeRgh = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));
336 int aHitRgh = int(aTimeRgh <= aTimeOut) & int(aTimeOut >= 0.0f) & int(aTimeRgh <= theHit.Time);
338 if (bool(aHitLft & aHitRgh))
340 aNode = (aTimeLft < aTimeRgh) ? aData.y : aData.z;
342 Stack[++aHead] = (aTimeLft < aTimeRgh) ? aData.z : aData.y;
346 if (bool(aHitLft | aHitRgh))
348 aNode = bool(aHitLft) ? aData.y : aData.z;
352 if (aHead == theSentinel)
355 aNode = Stack[aHead--];
364 for (int anIdx = aData.y; anIdx <= aData.z; ++anIdx)
366 ivec4 aTriangle = texelFetch (uGeometryTriangTexture, anIdx + theTrgOffset);
368 vec3 aPoint0 = texelFetch (uGeometryVertexTexture, aTriangle.x += theVrtOffset).xyz;
369 vec3 aPoint1 = texelFetch (uGeometryVertexTexture, aTriangle.y += theVrtOffset).xyz;
370 vec3 aPoint2 = texelFetch (uGeometryVertexTexture, aTriangle.z += theVrtOffset).xyz;
372 float aTime = IntersectTriangle (theRay,
379 if (aTime < theHit.Time)
381 aTriIndex = aTriangle;
383 theHit = SIntersect (aTime, aParams, aNormal);
387 if (aHead == theSentinel)
390 aNode = Stack[aHead--];
397 #define MATERIAL_AMBN(index) (11 * index + 0)
398 #define MATERIAL_DIFF(index) (11 * index + 1)
399 #define MATERIAL_SPEC(index) (11 * index + 2)
400 #define MATERIAL_EMIS(index) (11 * index + 3)
401 #define MATERIAL_REFL(index) (11 * index + 4)
402 #define MATERIAL_REFR(index) (11 * index + 5)
403 #define MATERIAL_TRAN(index) (11 * index + 6)
404 #define MATERIAL_TRS1(index) (11 * index + 7)
405 #define MATERIAL_TRS2(index) (11 * index + 8)
406 #define MATERIAL_TRS3(index) (11 * index + 9)
408 // =======================================================================
409 // function : ObjectAnyHit
410 // purpose : Finds intersection with any object triangle
411 // =======================================================================
412 float ObjectAnyHit (in int theBVHOffset, in int theVrtOffset, in int theTrgOffset,
413 in SRay theRay, in vec3 theInverse, in float theDistance, in int theSentinel)
415 int aHead = theSentinel; // stack pointer
416 int aNode = theBVHOffset; // node to visit
418 #ifdef TRANSPARENT_SHADOWS
419 float aFactor = 1.0f;
424 ivec4 aData = texelFetch (uObjectNodeInfoTexture, aNode);
426 if (aData.x == 0) // if inner node
432 aData.y += theBVHOffset;
433 aData.z += theBVHOffset;
435 vec3 aNodeMinLft = texelFetch (uObjectMinPointTexture, aData.y).xyz;
436 vec3 aNodeMaxLft = texelFetch (uObjectMaxPointTexture, aData.y).xyz;
437 vec3 aNodeMinRgh = texelFetch (uObjectMinPointTexture, aData.z).xyz;
438 vec3 aNodeMaxRgh = texelFetch (uObjectMaxPointTexture, aData.z).xyz;
440 vec3 aTime0 = (aNodeMinLft - theRay.Origin) * theInverse;
441 vec3 aTime1 = (aNodeMaxLft - theRay.Origin) * theInverse;
443 vec3 aTimeMax = max (aTime0, aTime1);
444 vec3 aTimeMin = min (aTime0, aTime1);
446 aTime0 = (aNodeMinRgh - theRay.Origin) * theInverse;
447 aTime1 = (aNodeMaxRgh - theRay.Origin) * theInverse;
449 aTimeOut = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z));
450 aTimeLft = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));
452 int aHitLft = int(aTimeLft <= aTimeOut) & int(aTimeOut >= 0.0f) & int(aTimeLft <= theDistance);
454 aTimeMax = max (aTime0, aTime1);
455 aTimeMin = min (aTime0, aTime1);
457 aTimeOut = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z));
458 aTimeRgh = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));
460 int aHitRgh = int(aTimeRgh <= aTimeOut) & int(aTimeOut >= 0.0f) & int(aTimeRgh <= theDistance);
462 if (bool(aHitLft & aHitRgh))
464 aNode = (aTimeLft < aTimeRgh) ? aData.y : aData.z;
466 Stack[++aHead] = (aTimeLft < aTimeRgh) ? aData.z : aData.y;
470 if (bool(aHitLft | aHitRgh))
472 aNode = bool(aHitLft) ? aData.y : aData.z;
476 #ifdef TRANSPARENT_SHADOWS
477 if (aHead == theSentinel)
480 if (aHead == theSentinel)
484 aNode = Stack[aHead--];
493 for (int anIdx = aData.y; anIdx <= aData.z; ++anIdx)
495 ivec4 aTriangle = texelFetch (uGeometryTriangTexture, anIdx + theTrgOffset);
497 vec3 aPoint0 = texelFetch (uGeometryVertexTexture, aTriangle.x + theVrtOffset).xyz;
498 vec3 aPoint1 = texelFetch (uGeometryVertexTexture, aTriangle.y + theVrtOffset).xyz;
499 vec3 aPoint2 = texelFetch (uGeometryVertexTexture, aTriangle.z + theVrtOffset).xyz;
501 float aTime = IntersectTriangle (theRay,
508 #ifdef TRANSPARENT_SHADOWS
509 if (aTime < theDistance)
511 aFactor *= 1.0f - texelFetch (uRaytraceMaterialTexture, MATERIAL_TRAN (aTriangle.w)).x;
514 if (aTime < theDistance)
519 #ifdef TRANSPARENT_SHADOWS
520 if (aHead == theSentinel || aFactor < 0.1f)
523 if (aHead == theSentinel)
527 aNode = Stack[aHead--];
531 #ifdef TRANSPARENT_SHADOWS
538 // =======================================================================
539 // function : SceneNearestHit
540 // purpose : Finds intersection with nearest scene triangle
541 // =======================================================================
542 ivec4 SceneNearestHit (in SRay theRay, in vec3 theInverse, inout SIntersect theHit, out int theObjectId)
544 int aHead = -1; // stack pointer
545 int aNode = 0; // node to visit
547 ivec4 aHitObject = INALID_HIT;
551 ivec4 aData = texelFetch (uSceneNodeInfoTexture, aNode);
553 if (aData.x != 0) // if leaf node
555 vec3 aNodeMin = texelFetch (uSceneMinPointTexture, aNode).xyz;
556 vec3 aNodeMax = texelFetch (uSceneMaxPointTexture, aNode).xyz;
558 vec3 aTime0 = (aNodeMin - theRay.Origin) * theInverse;
559 vec3 aTime1 = (aNodeMax - theRay.Origin) * theInverse;
561 vec3 aTimes = min (aTime0, aTime1);
563 if (max (aTimes.x, max (aTimes.y, aTimes.z)) < theHit.Time)
565 // fetch object transformation
566 int anObjectId = aData.x - 1;
568 vec4 aInvTransf0 = texelFetch (uSceneTransformTexture, anObjectId * 4 + 0);
569 vec4 aInvTransf1 = texelFetch (uSceneTransformTexture, anObjectId * 4 + 1);
570 vec4 aInvTransf2 = texelFetch (uSceneTransformTexture, anObjectId * 4 + 2);
571 vec4 aInvTransf3 = texelFetch (uSceneTransformTexture, anObjectId * 4 + 3);
573 SRay aTrsfRay = SRay (
574 MatrixColMultiplyPnt (theRay.Origin, aInvTransf0, aInvTransf1, aInvTransf2, aInvTransf3),
575 MatrixColMultiplyDir (theRay.Direct, aInvTransf0, aInvTransf1, aInvTransf2, aInvTransf3));
577 vec3 aTrsfInverse = 1.0f / max (abs (aTrsfRay.Direct), SMALL);
579 aTrsfInverse.x = aTrsfRay.Direct.x < 0.f ? -aTrsfInverse.x : aTrsfInverse.x;
580 aTrsfInverse.y = aTrsfRay.Direct.y < 0.f ? -aTrsfInverse.y : aTrsfInverse.y;
581 aTrsfInverse.z = aTrsfRay.Direct.z < 0.f ? -aTrsfInverse.z : aTrsfInverse.z;
583 ivec4 aTriIndex = ObjectNearestHit (
584 aData.y, aData.z, aData.w, aTrsfRay, aTrsfInverse, theHit, aHead);
586 if (aTriIndex.x != -1)
588 aHitObject = ivec4 (aTriIndex.x, // vertex 0
589 aTriIndex.y, // vertex 1
590 aTriIndex.z, // vertex 2
591 aTriIndex.w); // material
593 theObjectId = anObjectId;
600 aNode = Stack[aHead--];
602 else // if inner node
608 vec3 aNodeMinLft = texelFetch (uSceneMinPointTexture, aData.y).xyz;
609 vec3 aNodeMaxLft = texelFetch (uSceneMaxPointTexture, aData.y).xyz;
610 vec3 aNodeMinRgh = texelFetch (uSceneMinPointTexture, aData.z).xyz;
611 vec3 aNodeMaxRgh = texelFetch (uSceneMaxPointTexture, aData.z).xyz;
613 vec3 aTime0 = (aNodeMinLft - theRay.Origin) * theInverse;
614 vec3 aTime1 = (aNodeMaxLft - theRay.Origin) * theInverse;
616 vec3 aTimeMax = max (aTime0, aTime1);
617 vec3 aTimeMin = min (aTime0, aTime1);
619 aTimeOut = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z));
620 aTimeLft = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));
622 int aHitLft = int(aTimeLft <= aTimeOut) & int(aTimeOut >= 0.0f) & int(aTimeLft <= theHit.Time);
624 aTime0 = (aNodeMinRgh - theRay.Origin) * theInverse;
625 aTime1 = (aNodeMaxRgh - theRay.Origin) * theInverse;
627 aTimeMax = max (aTime0, aTime1);
628 aTimeMin = min (aTime0, aTime1);
630 aTimeOut = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z));
631 aTimeRgh = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));
633 int aHitRgh = int(aTimeRgh <= aTimeOut) & int(aTimeOut >= 0.0f) & int(aTimeRgh <= theHit.Time);
635 if (bool(aHitLft & aHitRgh))
637 aNode = (aTimeLft < aTimeRgh) ? aData.y : aData.z;
639 Stack[++aHead] = (aTimeLft < aTimeRgh) ? aData.z : aData.y;
643 if (bool(aHitLft | aHitRgh))
645 aNode = bool(aHitLft) ? aData.y : aData.z;
652 aNode = Stack[aHead--];
661 // =======================================================================
662 // function : SceneAnyHit
663 // purpose : Finds intersection with any scene triangle
664 // =======================================================================
665 float SceneAnyHit (in SRay theRay, in vec3 theInverse, in float theDistance)
667 int aHead = -1; // stack pointer
668 int aNode = 0; // node to visit
670 #ifdef TRANSPARENT_SHADOWS
671 float aFactor = 1.0f;
676 ivec4 aData = texelFetch (uSceneNodeInfoTexture, aNode);
678 if (aData.x != 0) // if leaf node
680 // fetch object transformation
681 int anObjectId = aData.x - 1;
683 vec4 aInvTransf0 = texelFetch (uSceneTransformTexture, anObjectId * 4 + 0);
684 vec4 aInvTransf1 = texelFetch (uSceneTransformTexture, anObjectId * 4 + 1);
685 vec4 aInvTransf2 = texelFetch (uSceneTransformTexture, anObjectId * 4 + 2);
686 vec4 aInvTransf3 = texelFetch (uSceneTransformTexture, anObjectId * 4 + 3);
688 SRay aTrsfRay = SRay (
689 MatrixColMultiplyPnt (theRay.Origin, aInvTransf0, aInvTransf1, aInvTransf2, aInvTransf3),
690 MatrixColMultiplyDir (theRay.Direct, aInvTransf0, aInvTransf1, aInvTransf2, aInvTransf3));
692 vec3 aTrsfInverse = 1.0f / max (abs (aTrsfRay.Direct), SMALL);
694 aTrsfInverse.x = aTrsfRay.Direct.x < 0.0f ? -aTrsfInverse.x : aTrsfInverse.x;
695 aTrsfInverse.y = aTrsfRay.Direct.y < 0.0f ? -aTrsfInverse.y : aTrsfInverse.y;
696 aTrsfInverse.z = aTrsfRay.Direct.z < 0.0f ? -aTrsfInverse.z : aTrsfInverse.z;
698 #ifdef TRANSPARENT_SHADOWS
699 aFactor *= ObjectAnyHit (
700 aData.y, aData.z, aData.w, aTrsfRay, aTrsfInverse, theDistance, aHead);
702 if (aHead < 0 || aFactor < 0.1f)
705 bool isShadow = 0.0f == ObjectAnyHit (
706 aData.y, aData.z, aData.w, aTrsfRay, aTrsfInverse, theDistance, aHead);
708 if (aHead < 0 || isShadow)
709 return isShadow ? 0.0f : 1.0f;
712 aNode = Stack[aHead--];
714 else // if inner node
720 vec3 aNodeMinLft = texelFetch (uSceneMinPointTexture, aData.y).xyz;
721 vec3 aNodeMaxLft = texelFetch (uSceneMaxPointTexture, aData.y).xyz;
722 vec3 aNodeMinRgh = texelFetch (uSceneMinPointTexture, aData.z).xyz;
723 vec3 aNodeMaxRgh = texelFetch (uSceneMaxPointTexture, aData.z).xyz;
725 vec3 aTime0 = (aNodeMinLft - theRay.Origin) * theInverse;
726 vec3 aTime1 = (aNodeMaxLft - theRay.Origin) * theInverse;
728 vec3 aTimeMax = max (aTime0, aTime1);
729 vec3 aTimeMin = min (aTime0, aTime1);
731 aTimeOut = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z));
732 aTimeLft = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));
734 int aHitLft = int(aTimeLft <= aTimeOut) & int(aTimeOut >= 0.0f) & int(aTimeLft <= theDistance);
736 aTime0 = (aNodeMinRgh - theRay.Origin) * theInverse;
737 aTime1 = (aNodeMaxRgh - theRay.Origin) * theInverse;
739 aTimeMax = max (aTime0, aTime1);
740 aTimeMin = min (aTime0, aTime1);
742 aTimeOut = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z));
743 aTimeRgh = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));
745 int aHitRgh = int(aTimeRgh <= aTimeOut) & int(aTimeOut >= 0.0f) & int(aTimeRgh <= theDistance);
747 if (bool(aHitLft & aHitRgh))
749 aNode = (aTimeLft < aTimeRgh) ? aData.y : aData.z;
751 Stack[++aHead] = (aTimeLft < aTimeRgh) ? aData.z : aData.y;
755 if (bool(aHitLft | aHitRgh))
757 aNode = bool(aHitLft) ? aData.y : aData.z;
761 #ifdef TRANSPARENT_SHADOWS
769 aNode = Stack[aHead--];
775 #ifdef TRANSPARENT_SHADOWS
782 #define PI 3.1415926f
784 // =======================================================================
785 // function : Latlong
786 // purpose : Converts world direction to environment texture coordinates
787 // =======================================================================
788 vec2 Latlong (in vec3 thePoint, in float theRadius)
790 float aPsi = acos (-thePoint.z / theRadius);
792 float aPhi = atan (thePoint.y, thePoint.x) + PI;
794 return vec2 (aPhi * 0.1591549f,
798 // =======================================================================
799 // function : SmoothNormal
800 // purpose : Interpolates normal across the triangle
801 // =======================================================================
802 vec3 SmoothNormal (in vec2 theUV, in ivec4 theTriangle)
804 vec3 aNormal0 = texelFetch (uGeometryNormalTexture, theTriangle.x).xyz;
805 vec3 aNormal1 = texelFetch (uGeometryNormalTexture, theTriangle.y).xyz;
806 vec3 aNormal2 = texelFetch (uGeometryNormalTexture, theTriangle.z).xyz;
808 return normalize (aNormal1 * theUV.x +
810 aNormal0 * (1.0f - theUV.x - theUV.y));
813 // =======================================================================
814 // function : SmoothUV
815 // purpose : Interpolates UV coordinates across the triangle
816 // =======================================================================
818 vec2 SmoothUV (in vec2 theUV, in ivec4 theTriangle)
820 vec2 aTexCrd0 = texelFetch (uGeometryTexCrdTexture, theTriangle.x).st;
821 vec2 aTexCrd1 = texelFetch (uGeometryTexCrdTexture, theTriangle.y).st;
822 vec2 aTexCrd2 = texelFetch (uGeometryTexCrdTexture, theTriangle.z).st;
824 return aTexCrd1 * theUV.x +
826 aTexCrd0 * (1.0f - theUV.x - theUV.y);
830 // =======================================================================
831 // function : Refract
832 // purpose : Computes refraction ray (also handles TIR)
833 // =======================================================================
834 vec3 Refract (in vec3 theInput,
836 in float theRefractIndex,
837 in float theInvRefractIndex)
839 float aNdotI = dot (theInput, theNormal);
841 float anIndex = aNdotI < 0.0f
845 float aSquare = anIndex * anIndex * (1.0f - aNdotI * aNdotI);
849 return reflect (theInput, theNormal);
852 float aNdotT = sqrt (1.0f - aSquare);
854 return normalize (anIndex * theInput -
855 (anIndex * aNdotI + (aNdotI < 0.0f ? aNdotT : -aNdotT)) * theNormal);
858 #define MIN_SLOPE 0.0001f
859 #define EPS_SCALE 8.0000f
861 #define THRESHOLD vec3 (0.1f)
863 #define LIGHT_POS(index) (2 * index + 1)
864 #define LIGHT_PWR(index) (2 * index + 0)
866 // =======================================================================
867 // function : Radiance
868 // purpose : Computes color along the given ray
869 // =======================================================================
870 vec4 Radiance (in SRay theRay, in vec3 theInverse)
872 vec3 aResult = vec3 (0.0f);
873 vec4 aWeight = vec4 (1.0f);
877 float anOpenGlDepth = ComputeOpenGlDepth (theRay);
879 for (int aDepth = 0; aDepth < NB_BOUNCES; ++aDepth)
881 SIntersect aHit = SIntersect (MAXFLOAT, vec2 (ZERO), ZERO);
883 ivec4 aTriIndex = SceneNearestHit (theRay, theInverse, aHit, anObjectId);
885 if (aTriIndex.x == -1)
887 vec4 aColor = vec4 (0.0f, 0.0f, 0.0f, 1.0f);
889 if (aWeight.w != 0.0f)
891 if (anOpenGlDepth != MAXFLOAT)
892 aColor = ComputeOpenGlColor (theRay);
894 else if (bool(uEnvironmentEnable))
896 float aTime = IntersectSphere (theRay, uSceneRadius);
898 aColor = textureLod (uEnvironmentMapTexture, Latlong (
899 theRay.Direct * aTime + theRay.Origin, uSceneRadius), 0.0f);
902 return vec4 (aResult.xyz + aWeight.xyz * aColor.xyz, aWeight.w * aColor.w);
905 aHit.Normal = normalize (aHit.Normal);
907 // For polygons that are parallel to the screen plane, the depth slope
908 // is equal to 1, resulting in small polygon offset. For polygons that
909 // that are at a large angle to the screen, the depth slope tends to 1,
910 // resulting in a larger polygon offset
911 float aPolygonOffset = uSceneEpsilon * min (
912 EPS_SCALE / abs (dot (theRay.Direct, aHit.Normal)), EPS_SCALE / MIN_SLOPE);
914 if (anOpenGlDepth - aPolygonOffset < aHit.Time)
916 vec4 aColor = ComputeOpenGlColor (theRay);
918 aResult += aWeight.xyz * aColor.xyz;
922 vec3 aPoint = theRay.Direct * aHit.Time + theRay.Origin;
924 vec3 aAmbient = texelFetch (
925 uRaytraceMaterialTexture, MATERIAL_AMBN (aTriIndex.w)).rgb;
926 vec4 aDiffuse = texelFetch (
927 uRaytraceMaterialTexture, MATERIAL_DIFF (aTriIndex.w));
928 vec4 aSpecular = texelFetch (
929 uRaytraceMaterialTexture, MATERIAL_SPEC (aTriIndex.w));
930 vec4 aOpacity = texelFetch (
931 uRaytraceMaterialTexture, MATERIAL_TRAN (aTriIndex.w));
932 vec3 aEmission = texelFetch (
933 uRaytraceMaterialTexture, MATERIAL_EMIS (aTriIndex.w)).rgb;
936 if (aDiffuse.w >= 0.f)
938 vec4 aTexCoord = vec4 (SmoothUV (aHit.UV, aTriIndex), 0.f, 1.f);
940 vec4 aTrsfRow1 = texelFetch (
941 uRaytraceMaterialTexture, MATERIAL_TRS1 (aTriIndex.w));
942 vec4 aTrsfRow2 = texelFetch (
943 uRaytraceMaterialTexture, MATERIAL_TRS2 (aTriIndex.w));
945 aTexCoord.st = vec2 (dot (aTrsfRow1, aTexCoord),
946 dot (aTrsfRow2, aTexCoord));
948 vec3 aTexColor = textureLod (
949 uTextureSamplers[int(aDiffuse.w)], aTexCoord.st, 0.f).rgb;
951 aDiffuse.rgb *= aTexColor;
952 aAmbient.rgb *= aTexColor;
956 vec4 aInvTransf0 = texelFetch (uSceneTransformTexture, anObjectId * 4 + 0);
957 vec4 aInvTransf1 = texelFetch (uSceneTransformTexture, anObjectId * 4 + 1);
958 vec4 aInvTransf2 = texelFetch (uSceneTransformTexture, anObjectId * 4 + 2);
960 vec3 aNormal = SmoothNormal (aHit.UV, aTriIndex);
962 aNormal = normalize (MatrixRowMultiplyDir (
963 aNormal, aInvTransf0, aInvTransf1, aInvTransf2));
965 for (int aLightIdx = 0; aLightIdx < uLightCount; ++aLightIdx)
967 vec4 aLight = texelFetch (
968 uRaytraceLightSrcTexture, LIGHT_POS (aLightIdx));
970 float aDistance = MAXFLOAT;
972 if (aLight.w != 0.0f) // point light source
974 aDistance = length (aLight.xyz -= aPoint);
976 aLight.xyz *= 1.0f / aDistance;
979 SRay aShadow = SRay (aPoint + aLight.xyz * uSceneEpsilon, aLight.xyz);
981 aShadow.Origin += aHit.Normal * uSceneEpsilon *
982 (dot (aHit.Normal, aLight.xyz) >= 0.0f ? 1.0f : -1.0f);
984 float aVisibility = 1.0f;
986 if (bool(uShadowsEnable))
988 vec3 aInverse = 1.0f / max (abs (aLight.xyz), SMALL);
990 aInverse.x = aLight.x < 0.0f ? -aInverse.x : aInverse.x;
991 aInverse.y = aLight.y < 0.0f ? -aInverse.y : aInverse.y;
992 aInverse.z = aLight.z < 0.0f ? -aInverse.z : aInverse.z;
994 aVisibility = SceneAnyHit (aShadow, aInverse, aDistance);
997 if (aVisibility > 0.0f)
999 vec3 aIntensity = vec3 (texelFetch (
1000 uRaytraceLightSrcTexture, LIGHT_PWR (aLightIdx)));
1002 float aLdotN = dot (aShadow.Direct, aNormal);
1004 if (aOpacity.y > 0.0f) // force two-sided lighting
1005 aLdotN = abs (aLdotN); // for transparent surfaces
1009 float aRdotV = dot (reflect (aShadow.Direct, aNormal), theRay.Direct);
1011 aResult.xyz += aWeight.xyz * (aOpacity.x * aVisibility) * aIntensity *
1012 (aDiffuse.rgb * aLdotN + aSpecular.xyz * pow (max (0.0f, aRdotV), aSpecular.w));
1017 aResult.xyz += aWeight.xyz * aOpacity.x * (uGlobalAmbient.xyz *
1018 aAmbient * max (abs (dot (aNormal, theRay.Direct)), 0.5f) + aEmission);
1020 if (aOpacity.x != 1.0f)
1022 aWeight *= aOpacity.y;
1024 if (aOpacity.z != 1.0f)
1026 theRay.Direct = Refract (theRay.Direct, aNormal, aOpacity.z, aOpacity.w);
1028 theInverse = 1.0f / max (abs (theRay.Direct), SMALL);
1030 theInverse.x = theRay.Direct.x < 0.0f ? -theInverse.x : theInverse.x;
1031 theInverse.y = theRay.Direct.y < 0.0f ? -theInverse.y : theInverse.y;
1032 theInverse.z = theRay.Direct.z < 0.0f ? -theInverse.z : theInverse.z;
1034 aPoint += aHit.Normal * (dot (aHit.Normal, theRay.Direct) >= 0.0f ? uSceneEpsilon : -uSceneEpsilon);
1036 // Disable combining image with OpenGL output
1037 anOpenGlDepth = MAXFLOAT;
1041 anOpenGlDepth -= aHit.Time + uSceneEpsilon;
1046 aWeight *= bool(uReflectionsEnable) ?
1047 texelFetch (uRaytraceMaterialTexture, MATERIAL_REFL (aTriIndex.w)) : vec4 (0.0f);
1049 theRay.Direct = reflect (theRay.Direct, aNormal);
1051 if (dot (theRay.Direct, aHit.Normal) < 0.0f)
1053 theRay.Direct = reflect (theRay.Direct, aHit.Normal);
1056 theInverse = 1.0f / max (abs (theRay.Direct), SMALL);
1058 theInverse.x = theRay.Direct.x < 0.0f ? -theInverse.x : theInverse.x;
1059 theInverse.y = theRay.Direct.y < 0.0f ? -theInverse.y : theInverse.y;
1060 theInverse.z = theRay.Direct.z < 0.0f ? -theInverse.z : theInverse.z;
1062 aPoint += aHit.Normal * (dot (aHit.Normal, theRay.Direct) >= 0.0f ? uSceneEpsilon : -uSceneEpsilon);
1064 // Disable combining image with OpenGL output
1065 anOpenGlDepth = MAXFLOAT;
1068 if (all (lessThanEqual (aWeight.xyz, THRESHOLD)))
1070 return vec4 (aResult.x,
1076 theRay.Origin = theRay.Direct * uSceneEpsilon + aPoint;
1079 return vec4 (aResult.x,