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