0026437: Visualization - Improve path tracing rendering engine
[occt.git] / src / Shaders / RaytraceBase.fs
CommitLineData
25ef750e 1#ifdef USE_TEXTURES
2 #extension GL_ARB_bindless_texture : require
3#endif
4
fc73a202 5//! Normalized pixel coordinates.
6in vec2 vPixel;
7
50d0e1ce 8//! Sub-pixel offset in X direction for FSAA.
9uniform float uOffsetX = 0.f;
10//! Sub-pixel offset in Y direction for FSAA.
11uniform float uOffsetY = 0.f;
12
fc73a202 13//! Origin of viewing ray in left-top corner.
14uniform vec3 uOriginLT;
15//! Origin of viewing ray in left-bottom corner.
16uniform vec3 uOriginLB;
17//! Origin of viewing ray in right-top corner.
18uniform vec3 uOriginRT;
19//! Origin of viewing ray in right-bottom corner.
20uniform vec3 uOriginRB;
21
312a4043 22//! Width of the rendering window.
23uniform int uWinSizeX;
24//! Height of the rendering window.
25uniform int uWinSizeY;
26
fc73a202 27//! Direction of viewing ray in left-top corner.
28uniform vec3 uDirectLT;
29//! Direction of viewing ray in left-bottom corner.
30uniform vec3 uDirectLB;
31//! Direction of viewing ray in right-top corner.
32uniform vec3 uDirectRT;
33//! Direction of viewing ray in right-bottom corner.
34uniform vec3 uDirectRB;
35
a89742cf 36//! Inverse model-view-projection matrix.
25ef750e 37uniform mat4 uUnviewMat;
38
e2da917a 39//! Texture buffer of data records of bottom-level BVH nodes.
fc73a202 40uniform isamplerBuffer uSceneNodeInfoTexture;
e2da917a 41//! Texture buffer of minimum points of bottom-level BVH nodes.
fc73a202 42uniform samplerBuffer uSceneMinPointTexture;
e2da917a 43//! Texture buffer of maximum points of bottom-level BVH nodes.
fc73a202 44uniform samplerBuffer uSceneMaxPointTexture;
84c71f29 45//! Texture buffer of transformations of high-level BVH nodes.
46uniform samplerBuffer uSceneTransformTexture;
fc73a202 47
fc73a202 48//! Texture buffer of vertex coords.
49uniform samplerBuffer uGeometryVertexTexture;
50//! Texture buffer of vertex normals.
51uniform samplerBuffer uGeometryNormalTexture;
25ef750e 52#ifdef USE_TEXTURES
53 //! Texture buffer of per-vertex UV-coordinates.
54 uniform samplerBuffer uGeometryTexCrdTexture;
55#endif
fc73a202 56//! Texture buffer of triangle indices.
57uniform isamplerBuffer uGeometryTriangTexture;
58
59//! Texture buffer of material properties.
60uniform samplerBuffer uRaytraceMaterialTexture;
61//! Texture buffer of light source properties.
62uniform samplerBuffer uRaytraceLightSrcTexture;
63//! Environment map texture.
64uniform sampler2D uEnvironmentMapTexture;
65
a89742cf 66//! Input pre-raytracing image rendered by OpenGL.
67uniform sampler2D uOpenGlColorTexture;
68//! Input pre-raytracing depth image rendered by OpenGL.
69uniform sampler2D uOpenGlDepthTexture;
70
fc73a202 71//! Total number of light sources.
72uniform int uLightCount;
73//! Intensity of global ambient light.
74uniform vec4 uGlobalAmbient;
75
189f85a3 76//! Enables/disables hard shadows.
77uniform int uShadowsEnabled;
78//! Enables/disables specular reflections.
79uniform int uReflectEnabled;
80//! Enables/disables spherical environment map.
81uniform int uSphereMapEnabled;
82//! Enables/disables environment map background.
83uniform int uSphereMapForBack;
fc73a202 84
85//! Radius of bounding sphere of the scene.
86uniform float uSceneRadius;
87//! Scene epsilon to prevent self-intersections.
88uniform float uSceneEpsilon;
89
25ef750e 90#ifdef USE_TEXTURES
91 //! Unique 64-bit handles of OpenGL textures.
92 uniform sampler2D uTextureSamplers[MAX_TEX_NUMBER];
93#endif
94
189f85a3 95//! Top color of gradient background.
96uniform vec4 uBackColorTop = vec4 (0.0);
97//! Bottom color of gradient background.
98uniform vec4 uBackColorBot = vec4 (0.0);
99
fc73a202 100/////////////////////////////////////////////////////////////////////////////////////////
101// Specific data types
189f85a3 102
fc73a202 103//! Stores ray parameters.
104struct SRay
105{
106 vec3 Origin;
189f85a3 107
fc73a202 108 vec3 Direct;
109};
110
111//! Stores intersection parameters.
112struct SIntersect
113{
114 float Time;
189f85a3 115
fc73a202 116 vec2 UV;
189f85a3 117
fc73a202 118 vec3 Normal;
119};
120
121/////////////////////////////////////////////////////////////////////////////////////////
122// Some useful constants
123
124#define MAXFLOAT 1e15f
125
dc9ef964 126#define SMALL vec3 (exp2 (-80.0f))
fc73a202 127
dc9ef964 128#define ZERO vec3 (0.0f, 0.0f, 0.0f)
129#define UNIT vec3 (1.0f, 1.0f, 1.0f)
fc73a202 130
dc9ef964 131#define AXIS_X vec3 (1.0f, 0.0f, 0.0f)
132#define AXIS_Y vec3 (0.0f, 1.0f, 0.0f)
133#define AXIS_Z vec3 (0.0f, 0.0f, 1.0f)
fc73a202 134
189f85a3 135#define M_PI 3.14159265f
136
137#define LUMA vec3 (0.2126f, 0.7152f, 0.0722f)
138
139// =======================================================================
140// function : MatrixRowMultiplyDir
141// purpose : Multiplies a vector by matrix
142// =======================================================================
143vec3 MatrixRowMultiplyDir (in vec3 v,
144 in vec4 m0,
145 in vec4 m1,
146 in vec4 m2)
147{
148 return vec3 (dot (m0.xyz, v),
149 dot (m1.xyz, v),
150 dot (m2.xyz, v));
151}
152
312a4043 153//! 32-bit state of random number generator.
154uint RandState;
155
156// =======================================================================
157// function : SeedRand
158// purpose : Applies hash function by Thomas Wang to randomize seeds
159// (see http://www.burtleburtle.net/bob/hash/integer.html)
160// =======================================================================
8c820969 161void SeedRand (in int theSeed, in int theSizeX, in int theRadius)
312a4043 162{
8c820969 163 RandState = uint (int (gl_FragCoord.y) / theRadius * theSizeX + int (gl_FragCoord.x) / theRadius + theSeed);
312a4043 164
165 RandState = (RandState + 0x479ab41du) + (RandState << 8);
166 RandState = (RandState ^ 0xe4aa10ceu) ^ (RandState >> 5);
167 RandState = (RandState + 0x9942f0a6u) - (RandState << 14);
168 RandState = (RandState ^ 0x5aedd67du) ^ (RandState >> 3);
169 RandState = (RandState + 0x17bea992u) + (RandState << 7);
170}
171
172// =======================================================================
173// function : RandInt
174// purpose : Generates integer using Xorshift algorithm by G. Marsaglia
175// =======================================================================
176uint RandInt()
177{
178 RandState ^= (RandState << 13);
179 RandState ^= (RandState >> 17);
180 RandState ^= (RandState << 5);
181
182 return RandState;
183}
184
185// =======================================================================
186// function : RandFloat
187// purpose : Generates a random float in [0, 1) range
188// =======================================================================
189float RandFloat()
190{
191 return float (RandInt()) * (1.f / 4294967296.f);
192}
193
bc8c79bb 194// =======================================================================
195// function : MatrixColMultiplyPnt
196// purpose : Multiplies a vector by matrix
197// =======================================================================
198vec3 MatrixColMultiplyPnt (in vec3 v,
199 in vec4 m0,
200 in vec4 m1,
201 in vec4 m2,
202 in vec4 m3)
203{
204 return vec3 (m0[0] * v.x + m1[0] * v.y + m2[0] * v.z + m3[0],
205 m0[1] * v.x + m1[1] * v.y + m2[1] * v.z + m3[1],
206 m0[2] * v.x + m1[2] * v.y + m2[2] * v.z + m3[2]);
207}
84c71f29 208
209// =======================================================================
bc8c79bb 210// function : MatrixColMultiplyDir
84c71f29 211// purpose : Multiplies a vector by matrix
212// =======================================================================
bc8c79bb 213vec3 MatrixColMultiplyDir (in vec3 v,
214 in vec4 m0,
215 in vec4 m1,
216 in vec4 m2,
217 in vec4 m3)
84c71f29 218{
bc8c79bb 219 return vec3 (m0[0] * v.x + m1[0] * v.y + m2[0] * v.z,
220 m0[1] * v.x + m1[1] * v.y + m2[1] * v.z,
221 m0[2] * v.x + m1[2] * v.y + m2[2] * v.z);
84c71f29 222}
223
189f85a3 224//=======================================================================
225// function : InverseDirection
226// purpose : Returns safely inverted direction of the given one
227//=======================================================================
228vec3 InverseDirection (in vec3 theInput)
229{
230 vec3 anInverse = 1.f / max (abs (theInput), SMALL);
231
232 return mix (-anInverse, anInverse, step (ZERO, theInput));
233}
234
235//=======================================================================
236// function : BackgroundColor
237// purpose : Returns color of gradient background
238//=======================================================================
239vec4 BackgroundColor()
240{
241 return mix (uBackColorBot, uBackColorTop, vPixel.y);
242}
243
fc73a202 244/////////////////////////////////////////////////////////////////////////////////////////
245// Functions for compute ray-object intersection
246
247// =======================================================================
248// function : GenerateRay
249// purpose :
250// =======================================================================
251SRay GenerateRay (in vec2 thePixel)
252{
253 vec3 aP0 = mix (uOriginLB, uOriginRB, thePixel.x);
254 vec3 aP1 = mix (uOriginLT, uOriginRT, thePixel.x);
255
256 vec3 aD0 = mix (uDirectLB, uDirectRB, thePixel.x);
257 vec3 aD1 = mix (uDirectLT, uDirectRT, thePixel.x);
a89742cf 258
259 vec3 aDirection = normalize (mix (aD0, aD1, thePixel.y));
260
261 return SRay (mix (aP0, aP1, thePixel.y), aDirection);
a89742cf 262}
263
264// =======================================================================
265// function : ComputeOpenGlDepth
266// purpose :
267// =======================================================================
268float ComputeOpenGlDepth (in SRay theRay)
269{
270 // a depth in range [0,1]
271 float anOpenGlDepth = texelFetch (uOpenGlDepthTexture, ivec2 (gl_FragCoord.xy), 0).r;
272 // pixel point in NDC-space [-1,1]
273 vec4 aPoint = vec4 (2.0f * vPixel.x - 1.0f,
274 2.0f * vPixel.y - 1.0f,
275 2.0f * anOpenGlDepth - 1.0f,
276 1.0f);
25ef750e 277 vec4 aFinal = uUnviewMat * aPoint;
a89742cf 278 aFinal.xyz *= 1.f / aFinal.w;
279
280 return (anOpenGlDepth < 1.f) ? length (aFinal.xyz - theRay.Origin) : MAXFLOAT;
281}
282
283// =======================================================================
284// function : ComputeOpenGlColor
285// purpose :
286// =======================================================================
189f85a3 287vec4 ComputeOpenGlColor()
a89742cf 288{
289 vec4 anOpenGlColor = texelFetch (uOpenGlColorTexture, ivec2 (gl_FragCoord.xy), 0);
290 // During blending with factors GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA (for text and markers)
291 // the alpha channel (written in the color buffer) was squared.
292 anOpenGlColor.a = 1.f - sqrt (anOpenGlColor.a);
293
294 return anOpenGlColor;
fc73a202 295}
296
297// =======================================================================
298// function : IntersectSphere
299// purpose : Computes ray-sphere intersection
300// =======================================================================
301float IntersectSphere (in SRay theRay, in float theRadius)
302{
303 float aDdotD = dot (theRay.Direct, theRay.Direct);
304 float aDdotO = dot (theRay.Direct, theRay.Origin);
305 float aOdotO = dot (theRay.Origin, theRay.Origin);
e2da917a 306
fc73a202 307 float aD = aDdotO * aDdotO - aDdotD * (aOdotO - theRadius * theRadius);
e2da917a 308
dc9ef964 309 if (aD > 0.0f)
fc73a202 310 {
dc9ef964 311 float aTime = (sqrt (aD) - aDdotO) * (1.0f / aDdotD);
fc73a202 312
dc9ef964 313 return aTime > 0.0f ? aTime : MAXFLOAT;
fc73a202 314 }
e2da917a 315
fc73a202 316 return MAXFLOAT;
317}
318
319// =======================================================================
320// function : IntersectTriangle
321// purpose : Computes ray-triangle intersection (branchless version)
322// =======================================================================
323float IntersectTriangle (in SRay theRay,
324 in vec3 thePnt0,
325 in vec3 thePnt1,
326 in vec3 thePnt2,
327 out vec2 theUV,
328 out vec3 theNorm)
329{
330 vec3 aEdge0 = thePnt1 - thePnt0;
331 vec3 aEdge1 = thePnt0 - thePnt2;
e2da917a 332
fc73a202 333 theNorm = cross (aEdge1, aEdge0);
334
dc9ef964 335 vec3 aEdge2 = (1.0f / dot (theNorm, theRay.Direct)) * (thePnt0 - theRay.Origin);
e2da917a 336
fc73a202 337 float aTime = dot (theNorm, aEdge2);
338
339 vec3 theVec = cross (theRay.Direct, aEdge2);
e2da917a 340
fc73a202 341 theUV.x = dot (theVec, aEdge1);
342 theUV.y = dot (theVec, aEdge0);
e2da917a 343
dc9ef964 344 return bool (int(aTime >= 0.0f) &
345 int(theUV.x >= 0.0f) &
346 int(theUV.y >= 0.0f) &
347 int(theUV.x + theUV.y <= 1.0f)) ? aTime : MAXFLOAT;
fc73a202 348}
349
fc73a202 350//! Identifies the absence of intersection.
351#define INALID_HIT ivec4 (-1)
352
84c71f29 353//! Global stack shared between traversal functions.
354int Stack[STACK_SIZE];
355
fc73a202 356// =======================================================================
357// function : ObjectNearestHit
358// purpose : Finds intersection with nearest object triangle
359// =======================================================================
360ivec4 ObjectNearestHit (in int theBVHOffset, in int theVrtOffset, in int theTrgOffset,
361 in SRay theRay, in vec3 theInverse, inout SIntersect theHit, in int theSentinel)
362{
bc8c79bb 363 int aHead = theSentinel; // stack pointer
364 int aNode = theBVHOffset; // node to visit
fc73a202 365
366 ivec4 aTriIndex = INALID_HIT;
367
8c820969 368 for (bool toContinue = true; toContinue;)
fc73a202 369 {
e2da917a 370 ivec3 aData = texelFetch (uSceneNodeInfoTexture, aNode).xyz;
fc73a202 371
372 if (aData.x == 0) // if inner node
373 {
bc8c79bb 374 float aTimeOut;
375 float aTimeLft;
376 float aTimeRgh;
e2da917a 377
bc8c79bb 378 aData.y += theBVHOffset;
379 aData.z += theBVHOffset;
e2da917a 380
381 vec3 aNodeMinLft = texelFetch (uSceneMinPointTexture, aData.y).xyz;
382 vec3 aNodeMinRgh = texelFetch (uSceneMinPointTexture, aData.z).xyz;
383 vec3 aNodeMaxLft = texelFetch (uSceneMaxPointTexture, aData.y).xyz;
384 vec3 aNodeMaxRgh = texelFetch (uSceneMaxPointTexture, aData.z).xyz;
fc73a202 385
386 vec3 aTime0 = (aNodeMinLft - theRay.Origin) * theInverse;
387 vec3 aTime1 = (aNodeMaxLft - theRay.Origin) * theInverse;
e2da917a 388
fc73a202 389 vec3 aTimeMax = max (aTime0, aTime1);
390 vec3 aTimeMin = min (aTime0, aTime1);
391
392 aTime0 = (aNodeMinRgh - theRay.Origin) * theInverse;
393 aTime1 = (aNodeMaxRgh - theRay.Origin) * theInverse;
e2da917a 394
fc73a202 395 aTimeOut = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z));
396 aTimeLft = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));
397
dc9ef964 398 int aHitLft = int(aTimeLft <= aTimeOut) & int(aTimeOut >= 0.0f) & int(aTimeLft <= theHit.Time);
fc73a202 399
400 aTimeMax = max (aTime0, aTime1);
401 aTimeMin = min (aTime0, aTime1);
402
403 aTimeOut = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z));
404 aTimeRgh = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));
405
dc9ef964 406 int aHitRgh = int(aTimeRgh <= aTimeOut) & int(aTimeOut >= 0.0f) & int(aTimeRgh <= theHit.Time);
fc73a202 407
408 if (bool(aHitLft & aHitRgh))
409 {
410 aNode = (aTimeLft < aTimeRgh) ? aData.y : aData.z;
e2da917a 411
fc73a202 412 Stack[++aHead] = (aTimeLft < aTimeRgh) ? aData.z : aData.y;
413 }
414 else
415 {
416 if (bool(aHitLft | aHitRgh))
417 {
418 aNode = bool(aHitLft) ? aData.y : aData.z;
419 }
420 else
421 {
e2da917a 422 toContinue = (aHead != theSentinel);
25ef750e 423
e2da917a 424 if (toContinue)
425 aNode = Stack[aHead--];
fc73a202 426 }
427 }
428 }
429 else // if leaf node
430 {
431 vec3 aNormal;
432 vec2 aParams;
84c71f29 433
fc73a202 434 for (int anIdx = aData.y; anIdx <= aData.z; ++anIdx)
435 {
436 ivec4 aTriangle = texelFetch (uGeometryTriangTexture, anIdx + theTrgOffset);
437
bc8c79bb 438 vec3 aPoint0 = texelFetch (uGeometryVertexTexture, aTriangle.x += theVrtOffset).xyz;
439 vec3 aPoint1 = texelFetch (uGeometryVertexTexture, aTriangle.y += theVrtOffset).xyz;
440 vec3 aPoint2 = texelFetch (uGeometryVertexTexture, aTriangle.z += theVrtOffset).xyz;
fc73a202 441
442 float aTime = IntersectTriangle (theRay,
443 aPoint0,
444 aPoint1,
445 aPoint2,
446 aParams,
447 aNormal);
e2da917a 448
fc73a202 449 if (aTime < theHit.Time)
450 {
451 aTriIndex = aTriangle;
a89742cf 452
fc73a202 453 theHit = SIntersect (aTime, aParams, aNormal);
454 }
455 }
fc73a202 456
e2da917a 457 toContinue = (aHead != theSentinel);
458
459 if (toContinue)
460 aNode = Stack[aHead--];
fc73a202 461 }
462 }
463
464 return aTriIndex;
465}
466
189f85a3 467#define MATERIAL_AMBN(index) (18 * index + 0)
468#define MATERIAL_DIFF(index) (18 * index + 1)
469#define MATERIAL_SPEC(index) (18 * index + 2)
470#define MATERIAL_EMIS(index) (18 * index + 3)
471#define MATERIAL_REFL(index) (18 * index + 4)
472#define MATERIAL_REFR(index) (18 * index + 5)
473#define MATERIAL_TRAN(index) (18 * index + 6)
474#define MATERIAL_TRS1(index) (18 * index + 7)
475#define MATERIAL_TRS2(index) (18 * index + 8)
476#define MATERIAL_TRS3(index) (18 * index + 9)
bc8c79bb 477
fc73a202 478// =======================================================================
479// function : ObjectAnyHit
480// purpose : Finds intersection with any object triangle
481// =======================================================================
482float ObjectAnyHit (in int theBVHOffset, in int theVrtOffset, in int theTrgOffset,
483 in SRay theRay, in vec3 theInverse, in float theDistance, in int theSentinel)
484{
bc8c79bb 485 int aHead = theSentinel; // stack pointer
486 int aNode = theBVHOffset; // node to visit
fc73a202 487
8c820969 488 float aFactor = 1.f;
fc73a202 489
8c820969 490 for (bool toContinue = true; toContinue;)
fc73a202 491 {
e2da917a 492 ivec4 aData = texelFetch (uSceneNodeInfoTexture, aNode);
fc73a202 493
494 if (aData.x == 0) // if inner node
495 {
bc8c79bb 496 float aTimeOut;
497 float aTimeLft;
498 float aTimeRgh;
25ef750e 499
bc8c79bb 500 aData.y += theBVHOffset;
501 aData.z += theBVHOffset;
e2da917a 502
503 vec3 aNodeMinLft = texelFetch (uSceneMinPointTexture, aData.y).xyz;
504 vec3 aNodeMaxLft = texelFetch (uSceneMaxPointTexture, aData.y).xyz;
505 vec3 aNodeMinRgh = texelFetch (uSceneMinPointTexture, aData.z).xyz;
506 vec3 aNodeMaxRgh = texelFetch (uSceneMaxPointTexture, aData.z).xyz;
fc73a202 507
508 vec3 aTime0 = (aNodeMinLft - theRay.Origin) * theInverse;
509 vec3 aTime1 = (aNodeMaxLft - theRay.Origin) * theInverse;
510
511 vec3 aTimeMax = max (aTime0, aTime1);
512 vec3 aTimeMin = min (aTime0, aTime1);
513
514 aTime0 = (aNodeMinRgh - theRay.Origin) * theInverse;
515 aTime1 = (aNodeMaxRgh - theRay.Origin) * theInverse;
e2da917a 516
fc73a202 517 aTimeOut = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z));
518 aTimeLft = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));
519
dc9ef964 520 int aHitLft = int(aTimeLft <= aTimeOut) & int(aTimeOut >= 0.0f) & int(aTimeLft <= theDistance);
fc73a202 521
522 aTimeMax = max (aTime0, aTime1);
523 aTimeMin = min (aTime0, aTime1);
524
525 aTimeOut = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z));
526 aTimeRgh = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));
527
dc9ef964 528 int aHitRgh = int(aTimeRgh <= aTimeOut) & int(aTimeOut >= 0.0f) & int(aTimeRgh <= theDistance);
fc73a202 529
530 if (bool(aHitLft & aHitRgh))
531 {
532 aNode = (aTimeLft < aTimeRgh) ? aData.y : aData.z;
533
534 Stack[++aHead] = (aTimeLft < aTimeRgh) ? aData.z : aData.y;
535 }
536 else
537 {
538 if (bool(aHitLft | aHitRgh))
539 {
540 aNode = bool(aHitLft) ? aData.y : aData.z;
541 }
542 else
543 {
8c820969 544 toContinue = (aHead != theSentinel);
fc73a202 545
8c820969 546 if (toContinue)
547 aNode = Stack[aHead--];
fc73a202 548 }
549 }
550 }
551 else // if leaf node
552 {
553 vec3 aNormal;
554 vec2 aParams;
25ef750e 555
fc73a202 556 for (int anIdx = aData.y; anIdx <= aData.z; ++anIdx)
557 {
558 ivec4 aTriangle = texelFetch (uGeometryTriangTexture, anIdx + theTrgOffset);
559
560 vec3 aPoint0 = texelFetch (uGeometryVertexTexture, aTriangle.x + theVrtOffset).xyz;
561 vec3 aPoint1 = texelFetch (uGeometryVertexTexture, aTriangle.y + theVrtOffset).xyz;
562 vec3 aPoint2 = texelFetch (uGeometryVertexTexture, aTriangle.z + theVrtOffset).xyz;
563
564 float aTime = IntersectTriangle (theRay,
565 aPoint0,
566 aPoint1,
567 aPoint2,
568 aParams,
569 aNormal);
bc8c79bb 570
571#ifdef TRANSPARENT_SHADOWS
572 if (aTime < theDistance)
573 {
8c820969 574 aFactor *= 1.f - texelFetch (uRaytraceMaterialTexture, MATERIAL_TRAN (aTriangle.w)).x;
bc8c79bb 575 }
576#else
fc73a202 577 if (aTime < theDistance)
8c820969 578 {
579 aFactor = 0.f;
580 }
bc8c79bb 581#endif
fc73a202 582 }
25ef750e 583
8c820969 584 toContinue = (aHead != theSentinel) && (aFactor > 0.1f);
fc73a202 585
8c820969 586 if (toContinue)
587 aNode = Stack[aHead--];
fc73a202 588 }
589 }
590
bc8c79bb 591 return aFactor;
fc73a202 592}
593
594// =======================================================================
595// function : SceneNearestHit
596// purpose : Finds intersection with nearest scene triangle
597// =======================================================================
8c820969 598ivec4 SceneNearestHit (in SRay theRay, in vec3 theInverse, inout SIntersect theHit, out int theTrsfId)
fc73a202 599{
600 int aHead = -1; // stack pointer
601 int aNode = 0; // node to visit
602
603 ivec4 aHitObject = INALID_HIT;
fc73a202 604
8c820969 605 for (bool toContinue = true; toContinue;)
fc73a202 606 {
607 ivec4 aData = texelFetch (uSceneNodeInfoTexture, aNode);
608
609 if (aData.x != 0) // if leaf node
610 {
611 vec3 aNodeMin = texelFetch (uSceneMinPointTexture, aNode).xyz;
612 vec3 aNodeMax = texelFetch (uSceneMaxPointTexture, aNode).xyz;
25ef750e 613
fc73a202 614 vec3 aTime0 = (aNodeMin - theRay.Origin) * theInverse;
615 vec3 aTime1 = (aNodeMax - theRay.Origin) * theInverse;
25ef750e 616
fc73a202 617 vec3 aTimes = min (aTime0, aTime1);
25ef750e 618
fc73a202 619 if (max (aTimes.x, max (aTimes.y, aTimes.z)) < theHit.Time)
620 {
84c71f29 621 // fetch object transformation
8c820969 622 int aTrsfId = (aData.x - 1) * 4;
bc8c79bb 623
8c820969 624 vec4 aInvTransf0 = texelFetch (uSceneTransformTexture, aTrsfId + 0);
625 vec4 aInvTransf1 = texelFetch (uSceneTransformTexture, aTrsfId + 1);
626 vec4 aInvTransf2 = texelFetch (uSceneTransformTexture, aTrsfId + 2);
627 vec4 aInvTransf3 = texelFetch (uSceneTransformTexture, aTrsfId + 3);
84c71f29 628
bc8c79bb 629 SRay aTrsfRay = SRay (
630 MatrixColMultiplyPnt (theRay.Origin, aInvTransf0, aInvTransf1, aInvTransf2, aInvTransf3),
631 MatrixColMultiplyDir (theRay.Direct, aInvTransf0, aInvTransf1, aInvTransf2, aInvTransf3));
84c71f29 632
bc8c79bb 633 vec3 aTrsfInverse = 1.0f / max (abs (aTrsfRay.Direct), SMALL);
84c71f29 634
e2da917a 635 aTrsfInverse = mix (-aTrsfInverse, aTrsfInverse, step (ZERO, aTrsfRay.Direct));
84c71f29 636
fc73a202 637 ivec4 aTriIndex = ObjectNearestHit (
bc8c79bb 638 aData.y, aData.z, aData.w, aTrsfRay, aTrsfInverse, theHit, aHead);
fc73a202 639
640 if (aTriIndex.x != -1)
641 {
bc8c79bb 642 aHitObject = ivec4 (aTriIndex.x, // vertex 0
643 aTriIndex.y, // vertex 1
644 aTriIndex.z, // vertex 2
645 aTriIndex.w); // material
84c71f29 646
8c820969 647 theTrsfId = aTrsfId;
fc73a202 648 }
649 }
e2da917a 650
8c820969 651 toContinue = aHead >= 0;
25ef750e 652
8c820969 653 if (toContinue)
654 aNode = Stack[aHead--];
fc73a202 655 }
656 else // if inner node
657 {
bc8c79bb 658 float aTimeOut;
659 float aTimeLft;
660 float aTimeRgh;
661
fc73a202 662 vec3 aNodeMinLft = texelFetch (uSceneMinPointTexture, aData.y).xyz;
663 vec3 aNodeMaxLft = texelFetch (uSceneMaxPointTexture, aData.y).xyz;
664 vec3 aNodeMinRgh = texelFetch (uSceneMinPointTexture, aData.z).xyz;
665 vec3 aNodeMaxRgh = texelFetch (uSceneMaxPointTexture, aData.z).xyz;
666
667 vec3 aTime0 = (aNodeMinLft - theRay.Origin) * theInverse;
668 vec3 aTime1 = (aNodeMaxLft - theRay.Origin) * theInverse;
669
670 vec3 aTimeMax = max (aTime0, aTime1);
671 vec3 aTimeMin = min (aTime0, aTime1);
672
673 aTimeOut = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z));
674 aTimeLft = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));
675
dc9ef964 676 int aHitLft = int(aTimeLft <= aTimeOut) & int(aTimeOut >= 0.0f) & int(aTimeLft <= theHit.Time);
e2da917a 677
fc73a202 678 aTime0 = (aNodeMinRgh - theRay.Origin) * theInverse;
679 aTime1 = (aNodeMaxRgh - theRay.Origin) * theInverse;
680
681 aTimeMax = max (aTime0, aTime1);
682 aTimeMin = min (aTime0, aTime1);
683
684 aTimeOut = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z));
685 aTimeRgh = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));
e2da917a 686
dc9ef964 687 int aHitRgh = int(aTimeRgh <= aTimeOut) & int(aTimeOut >= 0.0f) & int(aTimeRgh <= theHit.Time);
fc73a202 688
689 if (bool(aHitLft & aHitRgh))
690 {
691 aNode = (aTimeLft < aTimeRgh) ? aData.y : aData.z;
692
693 Stack[++aHead] = (aTimeLft < aTimeRgh) ? aData.z : aData.y;
694 }
695 else
696 {
697 if (bool(aHitLft | aHitRgh))
698 {
699 aNode = bool(aHitLft) ? aData.y : aData.z;
700 }
701 else
702 {
8c820969 703 toContinue = aHead >= 0;
fc73a202 704
8c820969 705 if (toContinue)
706 aNode = Stack[aHead--];
fc73a202 707 }
708 }
709 }
710 }
e2da917a 711
fc73a202 712 return aHitObject;
713}
714
715// =======================================================================
716// function : SceneAnyHit
717// purpose : Finds intersection with any scene triangle
718// =======================================================================
719float SceneAnyHit (in SRay theRay, in vec3 theInverse, in float theDistance)
720{
721 int aHead = -1; // stack pointer
722 int aNode = 0; // node to visit
bc8c79bb 723
8c820969 724 float aFactor = 1.f;
fc73a202 725
8c820969 726 for (bool toContinue = true; toContinue;)
fc73a202 727 {
728 ivec4 aData = texelFetch (uSceneNodeInfoTexture, aNode);
729
730 if (aData.x != 0) // if leaf node
731 {
84c71f29 732 // fetch object transformation
8c820969 733 int aTrsfId = (aData.x - 1) * 4;
bc8c79bb 734
8c820969 735 vec4 aInvTransf0 = texelFetch (uSceneTransformTexture, aTrsfId + 0);
736 vec4 aInvTransf1 = texelFetch (uSceneTransformTexture, aTrsfId + 1);
737 vec4 aInvTransf2 = texelFetch (uSceneTransformTexture, aTrsfId + 2);
738 vec4 aInvTransf3 = texelFetch (uSceneTransformTexture, aTrsfId + 3);
84c71f29 739
bc8c79bb 740 SRay aTrsfRay = SRay (
741 MatrixColMultiplyPnt (theRay.Origin, aInvTransf0, aInvTransf1, aInvTransf2, aInvTransf3),
742 MatrixColMultiplyDir (theRay.Direct, aInvTransf0, aInvTransf1, aInvTransf2, aInvTransf3));
84c71f29 743
bc8c79bb 744 vec3 aTrsfInverse = 1.0f / max (abs (aTrsfRay.Direct), SMALL);
84c71f29 745
e2da917a 746 aTrsfInverse = mix (-aTrsfInverse, aTrsfInverse, step (ZERO, aTrsfRay.Direct));
84c71f29 747
bc8c79bb 748#ifdef TRANSPARENT_SHADOWS
749 aFactor *= ObjectAnyHit (
750 aData.y, aData.z, aData.w, aTrsfRay, aTrsfInverse, theDistance, aHead);
84c71f29 751
8c820969 752 toContinue = aHead >= 0 && aFactor >= 0.1f;
bc8c79bb 753#else
8c820969 754 aFactor = ObjectAnyHit (
bc8c79bb 755 aData.y, aData.z, aData.w, aTrsfRay, aTrsfInverse, theDistance, aHead);
25ef750e 756
8c820969 757 toContinue = aHead >= 0 && aFactor != 0.0f;
bc8c79bb 758#endif
25ef750e 759
8c820969 760 if (toContinue)
761 aNode = Stack[aHead--];
fc73a202 762 }
763 else // if inner node
764 {
bc8c79bb 765 float aTimeOut;
766 float aTimeLft;
767 float aTimeRgh;
768
fc73a202 769 vec3 aNodeMinLft = texelFetch (uSceneMinPointTexture, aData.y).xyz;
770 vec3 aNodeMaxLft = texelFetch (uSceneMaxPointTexture, aData.y).xyz;
771 vec3 aNodeMinRgh = texelFetch (uSceneMinPointTexture, aData.z).xyz;
772 vec3 aNodeMaxRgh = texelFetch (uSceneMaxPointTexture, aData.z).xyz;
8c820969 773
fc73a202 774 vec3 aTime0 = (aNodeMinLft - theRay.Origin) * theInverse;
775 vec3 aTime1 = (aNodeMaxLft - theRay.Origin) * theInverse;
776
777 vec3 aTimeMax = max (aTime0, aTime1);
778 vec3 aTimeMin = min (aTime0, aTime1);
779
780 aTimeOut = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z));
781 aTimeLft = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));
782
dc9ef964 783 int aHitLft = int(aTimeLft <= aTimeOut) & int(aTimeOut >= 0.0f) & int(aTimeLft <= theDistance);
8c820969 784
fc73a202 785 aTime0 = (aNodeMinRgh - theRay.Origin) * theInverse;
786 aTime1 = (aNodeMaxRgh - theRay.Origin) * theInverse;
787
788 aTimeMax = max (aTime0, aTime1);
789 aTimeMin = min (aTime0, aTime1);
790
791 aTimeOut = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z));
792 aTimeRgh = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));
8c820969 793
dc9ef964 794 int aHitRgh = int(aTimeRgh <= aTimeOut) & int(aTimeOut >= 0.0f) & int(aTimeRgh <= theDistance);
fc73a202 795
796 if (bool(aHitLft & aHitRgh))
797 {
798 aNode = (aTimeLft < aTimeRgh) ? aData.y : aData.z;
799
800 Stack[++aHead] = (aTimeLft < aTimeRgh) ? aData.z : aData.y;
801 }
802 else
803 {
804 if (bool(aHitLft | aHitRgh))
805 {
806 aNode = bool(aHitLft) ? aData.y : aData.z;
807 }
808 else
809 {
8c820969 810 toContinue = aHead >= 0;
fc73a202 811
8c820969 812 if (toContinue)
813 aNode = Stack[aHead--];
fc73a202 814 }
815 }
816 }
817 }
25ef750e 818
bc8c79bb 819 return aFactor;
fc73a202 820}
821
822#define PI 3.1415926f
823
824// =======================================================================
825// function : Latlong
826// purpose : Converts world direction to environment texture coordinates
827// =======================================================================
828vec2 Latlong (in vec3 thePoint, in float theRadius)
829{
830 float aPsi = acos (-thePoint.z / theRadius);
25ef750e 831
fc73a202 832 float aPhi = atan (thePoint.y, thePoint.x) + PI;
25ef750e 833
fc73a202 834 return vec2 (aPhi * 0.1591549f,
835 aPsi * 0.3183098f);
836}
837
838// =======================================================================
839// function : SmoothNormal
840// purpose : Interpolates normal across the triangle
841// =======================================================================
842vec3 SmoothNormal (in vec2 theUV, in ivec4 theTriangle)
843{
844 vec3 aNormal0 = texelFetch (uGeometryNormalTexture, theTriangle.x).xyz;
845 vec3 aNormal1 = texelFetch (uGeometryNormalTexture, theTriangle.y).xyz;
846 vec3 aNormal2 = texelFetch (uGeometryNormalTexture, theTriangle.z).xyz;
25ef750e 847
fc73a202 848 return normalize (aNormal1 * theUV.x +
849 aNormal2 * theUV.y +
dc9ef964 850 aNormal0 * (1.0f - theUV.x - theUV.y));
851}
852
25ef750e 853// =======================================================================
854// function : SmoothUV
855// purpose : Interpolates UV coordinates across the triangle
856// =======================================================================
857#ifdef USE_TEXTURES
858vec2 SmoothUV (in vec2 theUV, in ivec4 theTriangle)
859{
860 vec2 aTexCrd0 = texelFetch (uGeometryTexCrdTexture, theTriangle.x).st;
861 vec2 aTexCrd1 = texelFetch (uGeometryTexCrdTexture, theTriangle.y).st;
862 vec2 aTexCrd2 = texelFetch (uGeometryTexCrdTexture, theTriangle.z).st;
863
864 return aTexCrd1 * theUV.x +
865 aTexCrd2 * theUV.y +
866 aTexCrd0 * (1.0f - theUV.x - theUV.y);
867}
868#endif
869
189f85a3 870// =======================================================================
871// function : FetchEnvironment
872// purpose :
873// =======================================================================
874vec4 FetchEnvironment (in vec2 theTexCoord)
875{
876 return mix (vec4 (0.0f, 0.0f, 0.0f, 1.0f),
877 textureLod (uEnvironmentMapTexture, theTexCoord, 0.0f), float (uSphereMapEnabled));
878}
879
dc9ef964 880// =======================================================================
881// function : Refract
bc8c79bb 882// purpose : Computes refraction ray (also handles TIR)
dc9ef964 883// =======================================================================
189f85a3 884#ifndef PATH_TRACING
dc9ef964 885vec3 Refract (in vec3 theInput,
886 in vec3 theNormal,
887 in float theRefractIndex,
888 in float theInvRefractIndex)
889{
25ef750e 890 float aNdotI = dot (theInput, theNormal);
891
dc9ef964 892 float anIndex = aNdotI < 0.0f
893 ? theInvRefractIndex
894 : theRefractIndex;
25ef750e 895
dc9ef964 896 float aSquare = anIndex * anIndex * (1.0f - aNdotI * aNdotI);
25ef750e 897
dc9ef964 898 if (aSquare > 1.0f)
899 {
900 return reflect (theInput, theNormal);
901 }
25ef750e 902
dc9ef964 903 float aNdotT = sqrt (1.0f - aSquare);
25ef750e 904
dc9ef964 905 return normalize (anIndex * theInput -
bc8c79bb 906 (anIndex * aNdotI + (aNdotI < 0.0f ? aNdotT : -aNdotT)) * theNormal);
fc73a202 907}
189f85a3 908#endif
fc73a202 909
a89742cf 910#define MIN_SLOPE 0.0001f
911#define EPS_SCALE 8.0000f
912
bc8c79bb 913#define THRESHOLD vec3 (0.1f)
fc73a202 914
1804bb99 915#define INVALID_BOUNCES 1000
916
fc73a202 917#define LIGHT_POS(index) (2 * index + 1)
918#define LIGHT_PWR(index) (2 * index + 0)
919
920// =======================================================================
921// function : Radiance
25ef750e 922// purpose : Computes color along the given ray
fc73a202 923// =======================================================================
189f85a3 924#ifndef PATH_TRACING
fc73a202 925vec4 Radiance (in SRay theRay, in vec3 theInverse)
926{
dc9ef964 927 vec3 aResult = vec3 (0.0f);
928 vec4 aWeight = vec4 (1.0f);
84c71f29 929
8c820969 930 int aTrsfId;
a89742cf 931
932 float anOpenGlDepth = ComputeOpenGlDepth (theRay);
933
25ef750e 934 for (int aDepth = 0; aDepth < NB_BOUNCES; ++aDepth)
fc73a202 935 {
936 SIntersect aHit = SIntersect (MAXFLOAT, vec2 (ZERO), ZERO);
a89742cf 937
8c820969 938 ivec4 aTriIndex = SceneNearestHit (theRay, theInverse, aHit, aTrsfId);
fc73a202 939
940 if (aTriIndex.x == -1)
941 {
189f85a3 942 vec4 aColor = vec4 (0.0);
25ef750e 943
189f85a3 944 if (bool(uSphereMapForBack) || aWeight.w == 0.0f /* reflection */)
fc73a202 945 {
946 float aTime = IntersectSphere (theRay, uSceneRadius);
25ef750e 947
189f85a3 948 aColor = FetchEnvironment (Latlong (
949 theRay.Direct * aTime + theRay.Origin, uSceneRadius));
950 }
951 else
952 {
953 vec4 aGlColor = ComputeOpenGlColor();
954 aColor = vec4 (BackgroundColor().rgb * aGlColor.w + ComputeOpenGlColor().rgb, aGlColor.w);
fc73a202 955 }
25ef750e 956
8c820969 957 aResult += aWeight.xyz * aColor.xyz; aWeight.w *= aColor.w;
958
959 break; // terminate path
fc73a202 960 }
a89742cf 961
8c820969 962 vec3 aInvTransf0 = texelFetch (uSceneTransformTexture, aTrsfId + 0).xyz;
963 vec3 aInvTransf1 = texelFetch (uSceneTransformTexture, aTrsfId + 1).xyz;
964 vec3 aInvTransf2 = texelFetch (uSceneTransformTexture, aTrsfId + 2).xyz;
cf537aac 965
966 aHit.Normal = normalize (vec3 (dot (aInvTransf0, aHit.Normal),
967 dot (aInvTransf1, aHit.Normal),
968 dot (aInvTransf2, aHit.Normal)));
1804bb99 969
25ef750e 970 // For polygons that are parallel to the screen plane, the depth slope
971 // is equal to 1, resulting in small polygon offset. For polygons that
972 // that are at a large angle to the screen, the depth slope tends to 1,
973 // resulting in a larger polygon offset
1804bb99 974 float aPolygonOffset = uSceneEpsilon * EPS_SCALE /
975 max (abs (dot (theRay.Direct, aHit.Normal)), MIN_SLOPE);
25ef750e 976
1804bb99 977 if (anOpenGlDepth < aHit.Time + aPolygonOffset)
25ef750e 978 {
189f85a3 979 vec4 aGlColor = ComputeOpenGlColor();
25ef750e 980
1804bb99 981 aResult += aWeight.xyz * aGlColor.xyz;
982 aWeight *= aGlColor.w;
a89742cf 983 }
984
1804bb99 985 theRay.Origin += theRay.Direct * aHit.Time; // intersection point
986
1804bb99 987 vec3 aNormal = SmoothNormal (aHit.UV, aTriIndex);
988
989 aNormal = normalize (vec3 (dot (aInvTransf0, aNormal),
990 dot (aInvTransf1, aNormal),
991 dot (aInvTransf2, aNormal)));
25ef750e 992
dc9ef964 993 vec3 aAmbient = texelFetch (
994 uRaytraceMaterialTexture, MATERIAL_AMBN (aTriIndex.w)).rgb;
25ef750e 995 vec4 aDiffuse = texelFetch (
996 uRaytraceMaterialTexture, MATERIAL_DIFF (aTriIndex.w));
dc9ef964 997 vec4 aSpecular = texelFetch (
998 uRaytraceMaterialTexture, MATERIAL_SPEC (aTriIndex.w));
999 vec4 aOpacity = texelFetch (
1000 uRaytraceMaterialTexture, MATERIAL_TRAN (aTriIndex.w));
25ef750e 1001
1002#ifdef USE_TEXTURES
1003 if (aDiffuse.w >= 0.f)
1004 {
1005 vec4 aTexCoord = vec4 (SmoothUV (aHit.UV, aTriIndex), 0.f, 1.f);
1006
1007 vec4 aTrsfRow1 = texelFetch (
1008 uRaytraceMaterialTexture, MATERIAL_TRS1 (aTriIndex.w));
1009 vec4 aTrsfRow2 = texelFetch (
1010 uRaytraceMaterialTexture, MATERIAL_TRS2 (aTriIndex.w));
1011
1012 aTexCoord.st = vec2 (dot (aTrsfRow1, aTexCoord),
1013 dot (aTrsfRow2, aTexCoord));
1014
1015 vec3 aTexColor = textureLod (
1016 uTextureSamplers[int(aDiffuse.w)], aTexCoord.st, 0.f).rgb;
1017
1018 aDiffuse.rgb *= aTexColor;
1019 aAmbient.rgb *= aTexColor;
1020 }
1021#endif
84c71f29 1022
1804bb99 1023 vec3 aEmission = texelFetch (
1024 uRaytraceMaterialTexture, MATERIAL_EMIS (aTriIndex.w)).rgb;
84c71f29 1025
1804bb99 1026 float aGeomFactor = dot (aNormal, theRay.Direct);
1027
1028 aResult.xyz += aWeight.xyz * aOpacity.x * (
1029 uGlobalAmbient.xyz * aAmbient * max (abs (aGeomFactor), 0.5f) + aEmission);
25ef750e 1030
1804bb99 1031 vec3 aSidedNormal = mix (aNormal, -aNormal, step (0.0f, aGeomFactor));
a89742cf 1032
fc73a202 1033 for (int aLightIdx = 0; aLightIdx < uLightCount; ++aLightIdx)
1034 {
1035 vec4 aLight = texelFetch (
1036 uRaytraceLightSrcTexture, LIGHT_POS (aLightIdx));
e2da917a 1037
fc73a202 1038 float aDistance = MAXFLOAT;
e2da917a 1039
dc9ef964 1040 if (aLight.w != 0.0f) // point light source
fc73a202 1041 {
1804bb99 1042 aDistance = length (aLight.xyz -= theRay.Origin);
e2da917a 1043
dc9ef964 1044 aLight.xyz *= 1.0f / aDistance;
fc73a202 1045 }
1046
1804bb99 1047 float aLdotN = dot (aLight.xyz, aSidedNormal);
e2da917a 1048
1804bb99 1049 if (aLdotN > 0.0f) // first check if light source is important
fc73a202 1050 {
1804bb99 1051 float aVisibility = 1.0f;
25ef750e 1052
189f85a3 1053 if (bool(uShadowsEnabled))
1804bb99 1054 {
1055 SRay aShadow = SRay (theRay.Origin, aLight.xyz);
e2da917a 1056
1804bb99 1057 aShadow.Origin += uSceneEpsilon * (aLight.xyz +
1058 mix (-aHit.Normal, aHit.Normal, step (0.0f, dot (aHit.Normal, aLight.xyz))));
25ef750e 1059
1804bb99 1060 vec3 aInverse = 1.0f / max (abs (aLight.xyz), SMALL);
25ef750e 1061
1804bb99 1062 aVisibility = SceneAnyHit (
1063 aShadow, mix (-aInverse, aInverse, step (ZERO, aLight.xyz)), aDistance);
1064 }
25ef750e 1065
1804bb99 1066 if (aVisibility > 0.0f)
fc73a202 1067 {
1804bb99 1068 vec3 aIntensity = vec3 (texelFetch (
1069 uRaytraceLightSrcTexture, LIGHT_PWR (aLightIdx)));
1070
1071 float aRdotV = dot (reflect (aLight.xyz, aSidedNormal), theRay.Direct);
25ef750e 1072
bc8c79bb 1073 aResult.xyz += aWeight.xyz * (aOpacity.x * aVisibility) * aIntensity *
1804bb99 1074 (aDiffuse.xyz * aLdotN + aSpecular.xyz * pow (max (0.f, aRdotV), aSpecular.w));
fc73a202 1075 }
1076 }
1077 }
0e330c8c 1078
dc9ef964 1079 if (aOpacity.x != 1.0f)
fc73a202 1080 {
1081 aWeight *= aOpacity.y;
a89742cf 1082
bc8c79bb 1083 if (aOpacity.z != 1.0f)
1084 {
1085 theRay.Direct = Refract (theRay.Direct, aNormal, aOpacity.z, aOpacity.w);
a89742cf 1086 }
1087 else
1088 {
1089 anOpenGlDepth -= aHit.Time + uSceneEpsilon;
bc8c79bb 1090 }
fc73a202 1091 }
1092 else
1093 {
189f85a3 1094 aWeight *= bool(uReflectEnabled) ?
dc9ef964 1095 texelFetch (uRaytraceMaterialTexture, MATERIAL_REFL (aTriIndex.w)) : vec4 (0.0f);
25ef750e 1096
1804bb99 1097 vec3 aReflect = reflect (theRay.Direct, aNormal);
25ef750e 1098
1804bb99 1099 if (dot (aReflect, aHit.Normal) * dot (theRay.Direct, aHit.Normal) > 0.0f)
fc73a202 1100 {
1804bb99 1101 aReflect = reflect (theRay.Direct, aHit.Normal);
fc73a202 1102 }
1103
1804bb99 1104 theRay.Direct = aReflect;
fc73a202 1105 }
25ef750e 1106
fc73a202 1107 if (all (lessThanEqual (aWeight.xyz, THRESHOLD)))
1108 {
1804bb99 1109 aDepth = INVALID_BOUNCES;
1110 }
1111 else if (aOpacity.x == 1.0f || aOpacity.z != 1.0f) // if no simple transparency
1112 {
1113 theRay.Origin += aHit.Normal * mix (
1114 -uSceneEpsilon, uSceneEpsilon, step (0.0f, dot (aHit.Normal, theRay.Direct)));
1115
1116 theInverse = 1.0f / max (abs (theRay.Direct), SMALL);
1117
1118 theInverse = mix (-theInverse, theInverse, step (ZERO, theRay.Direct));
1119
1120 anOpenGlDepth = MAXFLOAT; // disable combining image with OpenGL output
fc73a202 1121 }
25ef750e 1122
1804bb99 1123 theRay.Origin += theRay.Direct * uSceneEpsilon;
fc73a202 1124 }
1125
1126 return vec4 (aResult.x,
1127 aResult.y,
1128 aResult.z,
1129 aWeight.w);
1130}
189f85a3 1131#endif