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