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