0024936: Remove unused package IncludeLibrary
[occt.git] / src / Shaders / RaytraceBase.fs
CommitLineData
fc73a202 1//! Normalized pixel coordinates.
2in vec2 vPixel;
3
4//! Origin of viewing ray in left-top corner.
5uniform vec3 uOriginLT;
6//! Origin of viewing ray in left-bottom corner.
7uniform vec3 uOriginLB;
8//! Origin of viewing ray in right-top corner.
9uniform vec3 uOriginRT;
10//! Origin of viewing ray in right-bottom corner.
11uniform vec3 uOriginRB;
12
13//! Direction of viewing ray in left-top corner.
14uniform vec3 uDirectLT;
15//! Direction of viewing ray in left-bottom corner.
16uniform vec3 uDirectLB;
17//! Direction of viewing ray in right-top corner.
18uniform vec3 uDirectRT;
19//! Direction of viewing ray in right-bottom corner.
20uniform vec3 uDirectRB;
21
22//! Texture buffer of data records of high-level BVH nodes.
23uniform isamplerBuffer uSceneNodeInfoTexture;
24//! Texture buffer of minimum points of high-level BVH nodes.
25uniform samplerBuffer uSceneMinPointTexture;
26//! Texture buffer of maximum points of high-level BVH nodes.
27uniform samplerBuffer uSceneMaxPointTexture;
84c71f29 28//! Texture buffer of transformations of high-level BVH nodes.
29uniform samplerBuffer uSceneTransformTexture;
fc73a202 30
31//! Texture buffer of data records of bottom-level BVH nodes.
32uniform isamplerBuffer uObjectNodeInfoTexture;
33//! Texture buffer of minimum points of bottom-level BVH nodes.
34uniform samplerBuffer uObjectMinPointTexture;
35//! Texture buffer of maximum points of bottom-level BVH nodes.
36uniform samplerBuffer uObjectMaxPointTexture;
37
38//! Texture buffer of vertex coords.
39uniform samplerBuffer uGeometryVertexTexture;
40//! Texture buffer of vertex normals.
41uniform samplerBuffer uGeometryNormalTexture;
42//! Texture buffer of triangle indices.
43uniform isamplerBuffer uGeometryTriangTexture;
44
45//! Texture buffer of material properties.
46uniform samplerBuffer uRaytraceMaterialTexture;
47//! Texture buffer of light source properties.
48uniform samplerBuffer uRaytraceLightSrcTexture;
49//! Environment map texture.
50uniform sampler2D uEnvironmentMapTexture;
51
52//! Total number of light sources.
53uniform int uLightCount;
54//! Intensity of global ambient light.
55uniform vec4 uGlobalAmbient;
56
57//! Enables/disables environment map.
58uniform int uEnvironmentEnable;
59//! Enables/disables computation of shadows.
60uniform int uShadowsEnable;
61//! Enables/disables computation of reflections.
62uniform int uReflectionsEnable;
63
64//! Radius of bounding sphere of the scene.
65uniform float uSceneRadius;
66//! Scene epsilon to prevent self-intersections.
67uniform float uSceneEpsilon;
68
69/////////////////////////////////////////////////////////////////////////////////////////
70// Specific data types
71
72//! Stores ray parameters.
73struct SRay
74{
75 vec3 Origin;
76
77 vec3 Direct;
78};
79
80//! Stores intersection parameters.
81struct SIntersect
82{
83 float Time;
84
85 vec2 UV;
86
87 vec3 Normal;
88};
89
90/////////////////////////////////////////////////////////////////////////////////////////
91// Some useful constants
92
93#define MAXFLOAT 1e15f
94
95#define SMALL vec3 (exp2 (-80.f))
96
97#define ZERO vec3 (0.f, 0.f, 0.f)
98#define UNIT vec3 (1.f, 1.f, 1.f)
99
100#define AXIS_X vec3 (1.f, 0.f, 0.f)
101#define AXIS_Y vec3 (0.f, 1.f, 0.f)
102#define AXIS_Z vec3 (0.f, 0.f, 1.f)
103
84c71f29 104
105// =======================================================================
106// function : MatrixRowMultiply
107// purpose : Multiplies a vector by matrix
108// =======================================================================
109vec3 MatrixRowMultiply (in vec4 v,
110 in vec4 m0,
111 in vec4 m1,
112 in vec4 m2,
113 in vec4 m3)
114{
115 return vec3 (dot (m0, v),
116 dot (m1, v),
117 dot (m2, v));
118}
119
120
121// =======================================================================
122// function : MatrixColMultiply
123// purpose : Multiplies a vector by matrix
124// =======================================================================
125vec3 MatrixColMultiply (in vec4 v,
126 in vec4 m0,
127 in vec4 m1,
128 in vec4 m2,
129 in vec4 m3)
130{
131 return vec3 (m0[0] * v.x + m1[0] * v.y + m2[0] * v.z + m3[0] * v.w,
132 m0[1] * v.x + m1[1] * v.y + m2[1] * v.z + m3[1] * v.w,
133 m0[2] * v.x + m1[2] * v.y + m2[2] * v.z + m3[2] * v.w);
134}
135
fc73a202 136/////////////////////////////////////////////////////////////////////////////////////////
137// Functions for compute ray-object intersection
138
139// =======================================================================
140// function : GenerateRay
141// purpose :
142// =======================================================================
143SRay GenerateRay (in vec2 thePixel)
144{
145 vec3 aP0 = mix (uOriginLB, uOriginRB, thePixel.x);
146 vec3 aP1 = mix (uOriginLT, uOriginRT, thePixel.x);
147
148 vec3 aD0 = mix (uDirectLB, uDirectRB, thePixel.x);
149 vec3 aD1 = mix (uDirectLT, uDirectRT, thePixel.x);
150
151 return SRay (mix (aP0, aP1, thePixel.y),
152 mix (aD0, aD1, thePixel.y));
153}
154
155// =======================================================================
156// function : IntersectSphere
157// purpose : Computes ray-sphere intersection
158// =======================================================================
159float IntersectSphere (in SRay theRay, in float theRadius)
160{
161 float aDdotD = dot (theRay.Direct, theRay.Direct);
162 float aDdotO = dot (theRay.Direct, theRay.Origin);
163 float aOdotO = dot (theRay.Origin, theRay.Origin);
164
165 float aD = aDdotO * aDdotO - aDdotD * (aOdotO - theRadius * theRadius);
166
167 if (aD > 0.f)
168 {
169 float aTime = (sqrt (aD) - aDdotO) * (1.f / aDdotD);
170
171 return aTime > 0.f ? aTime : MAXFLOAT;
172 }
173
174 return MAXFLOAT;
175}
176
177// =======================================================================
178// function : IntersectTriangle
179// purpose : Computes ray-triangle intersection (branchless version)
180// =======================================================================
181float IntersectTriangle (in SRay theRay,
182 in vec3 thePnt0,
183 in vec3 thePnt1,
184 in vec3 thePnt2,
185 out vec2 theUV,
186 out vec3 theNorm)
187{
188 vec3 aEdge0 = thePnt1 - thePnt0;
189 vec3 aEdge1 = thePnt0 - thePnt2;
190
191 theNorm = cross (aEdge1, aEdge0);
192
193 vec3 aEdge2 = (1.f / dot (theNorm, theRay.Direct)) * (thePnt0 - theRay.Origin);
194
195 float aTime = dot (theNorm, aEdge2);
196
197 vec3 theVec = cross (theRay.Direct, aEdge2);
198
199 theUV.x = dot (theVec, aEdge1);
200 theUV.y = dot (theVec, aEdge0);
201
202 return bool (int(aTime >= 0.f) &
203 int(theUV.x >= 0.f) &
204 int(theUV.y >= 0.f) &
205 int(theUV.x + theUV.y <= 1.f)) ? aTime : MAXFLOAT;
206}
207
fc73a202 208//! Identifies the absence of intersection.
209#define INALID_HIT ivec4 (-1)
210
84c71f29 211//! Global stack shared between traversal functions.
212int Stack[STACK_SIZE];
213
fc73a202 214// =======================================================================
215// function : ObjectNearestHit
216// purpose : Finds intersection with nearest object triangle
217// =======================================================================
218ivec4 ObjectNearestHit (in int theBVHOffset, in int theVrtOffset, in int theTrgOffset,
219 in SRay theRay, in vec3 theInverse, inout SIntersect theHit, in int theSentinel)
220{
221 int aHead = theSentinel; // stack pointer
222 int aNode = 0; // node to visit
223
224 ivec4 aTriIndex = INALID_HIT;
225
226 float aTimeOut;
227 float aTimeLft;
228 float aTimeRgh;
229
230 while (true)
231 {
232 ivec3 aData = texelFetch (uObjectNodeInfoTexture, aNode + theBVHOffset).xyz;
233
234 if (aData.x == 0) // if inner node
235 {
236 vec3 aNodeMinLft = texelFetch (uObjectMinPointTexture, aData.y + theBVHOffset).xyz;
237 vec3 aNodeMaxLft = texelFetch (uObjectMaxPointTexture, aData.y + theBVHOffset).xyz;
238 vec3 aNodeMinRgh = texelFetch (uObjectMinPointTexture, aData.z + theBVHOffset).xyz;
239 vec3 aNodeMaxRgh = texelFetch (uObjectMaxPointTexture, aData.z + theBVHOffset).xyz;
240
241 vec3 aTime0 = (aNodeMinLft - theRay.Origin) * theInverse;
242 vec3 aTime1 = (aNodeMaxLft - theRay.Origin) * theInverse;
243
244 vec3 aTimeMax = max (aTime0, aTime1);
245 vec3 aTimeMin = min (aTime0, aTime1);
246
247 aTime0 = (aNodeMinRgh - theRay.Origin) * theInverse;
248 aTime1 = (aNodeMaxRgh - theRay.Origin) * theInverse;
249
250 aTimeOut = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z));
251 aTimeLft = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));
252
253 int aHitLft = int(aTimeLft <= aTimeOut) & int(aTimeOut >= 0.f) & int(aTimeLft <= theHit.Time);
254
255 aTimeMax = max (aTime0, aTime1);
256 aTimeMin = min (aTime0, aTime1);
257
258 aTimeOut = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z));
259 aTimeRgh = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));
260
261 int aHitRgh = int(aTimeRgh <= aTimeOut) & int(aTimeOut >= 0.f) & int(aTimeRgh <= theHit.Time);
262
263 if (bool(aHitLft & aHitRgh))
264 {
265 aNode = (aTimeLft < aTimeRgh) ? aData.y : aData.z;
266
267 Stack[++aHead] = (aTimeLft < aTimeRgh) ? aData.z : aData.y;
268 }
269 else
270 {
271 if (bool(aHitLft | aHitRgh))
272 {
273 aNode = bool(aHitLft) ? aData.y : aData.z;
274 }
275 else
276 {
277 if (aHead == theSentinel)
278 return aTriIndex;
279
280 aNode = Stack[aHead--];
281 }
282 }
283 }
284 else // if leaf node
285 {
286 vec3 aNormal;
287 vec2 aParams;
84c71f29 288
fc73a202 289 for (int anIdx = aData.y; anIdx <= aData.z; ++anIdx)
290 {
291 ivec4 aTriangle = texelFetch (uGeometryTriangTexture, anIdx + theTrgOffset);
292
293 vec3 aPoint0 = texelFetch (uGeometryVertexTexture, aTriangle.x + theVrtOffset).xyz;
294 vec3 aPoint1 = texelFetch (uGeometryVertexTexture, aTriangle.y + theVrtOffset).xyz;
295 vec3 aPoint2 = texelFetch (uGeometryVertexTexture, aTriangle.z + theVrtOffset).xyz;
296
297 float aTime = IntersectTriangle (theRay,
298 aPoint0,
299 aPoint1,
300 aPoint2,
301 aParams,
302 aNormal);
303
304 if (aTime < theHit.Time)
305 {
306 aTriIndex = aTriangle;
307
308 theHit = SIntersect (aTime, aParams, aNormal);
309 }
310 }
311
312 if (aHead == theSentinel)
313 return aTriIndex;
314
315 aNode = Stack[aHead--];
316 }
317 }
318
319 return aTriIndex;
320}
321
322// =======================================================================
323// function : ObjectAnyHit
324// purpose : Finds intersection with any object triangle
325// =======================================================================
326float ObjectAnyHit (in int theBVHOffset, in int theVrtOffset, in int theTrgOffset,
327 in SRay theRay, in vec3 theInverse, in float theDistance, in int theSentinel)
328{
329 int aHead = theSentinel; // stack pointer
330 int aNode = 0; // node to visit
331
332 float aTimeOut;
333 float aTimeLft;
334 float aTimeRgh;
335
336 while (true)
337 {
338 ivec4 aData = texelFetch (uObjectNodeInfoTexture, aNode + theBVHOffset);
339
340 if (aData.x == 0) // if inner node
341 {
342 vec3 aNodeMinLft = texelFetch (uObjectMinPointTexture, aData.y + theBVHOffset).xyz;
343 vec3 aNodeMaxLft = texelFetch (uObjectMaxPointTexture, aData.y + theBVHOffset).xyz;
344 vec3 aNodeMinRgh = texelFetch (uObjectMinPointTexture, aData.z + theBVHOffset).xyz;
345 vec3 aNodeMaxRgh = texelFetch (uObjectMaxPointTexture, aData.z + theBVHOffset).xyz;
346
347 vec3 aTime0 = (aNodeMinLft - theRay.Origin) * theInverse;
348 vec3 aTime1 = (aNodeMaxLft - theRay.Origin) * theInverse;
349
350 vec3 aTimeMax = max (aTime0, aTime1);
351 vec3 aTimeMin = min (aTime0, aTime1);
352
353 aTime0 = (aNodeMinRgh - theRay.Origin) * theInverse;
354 aTime1 = (aNodeMaxRgh - theRay.Origin) * theInverse;
355
356 aTimeOut = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z));
357 aTimeLft = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));
358
359 int aHitLft = int(aTimeLft <= aTimeOut) & int(aTimeOut >= 0.f) & int(aTimeLft <= theDistance);
360
361 aTimeMax = max (aTime0, aTime1);
362 aTimeMin = min (aTime0, aTime1);
363
364 aTimeOut = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z));
365 aTimeRgh = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));
366
367 int aHitRgh = int(aTimeRgh <= aTimeOut) & int(aTimeOut >= 0.f) & int(aTimeRgh <= theDistance);
368
369 if (bool(aHitLft & aHitRgh))
370 {
371 aNode = (aTimeLft < aTimeRgh) ? aData.y : aData.z;
372
373 Stack[++aHead] = (aTimeLft < aTimeRgh) ? aData.z : aData.y;
374 }
375 else
376 {
377 if (bool(aHitLft | aHitRgh))
378 {
379 aNode = bool(aHitLft) ? aData.y : aData.z;
380 }
381 else
382 {
383 if (aHead == theSentinel)
384 return 1.f;
385
386 aNode = Stack[aHead--];
387 }
388 }
389 }
390 else // if leaf node
391 {
392 vec3 aNormal;
393 vec2 aParams;
394
395 for (int anIdx = aData.y; anIdx <= aData.z; ++anIdx)
396 {
397 ivec4 aTriangle = texelFetch (uGeometryTriangTexture, anIdx + theTrgOffset);
398
399 vec3 aPoint0 = texelFetch (uGeometryVertexTexture, aTriangle.x + theVrtOffset).xyz;
400 vec3 aPoint1 = texelFetch (uGeometryVertexTexture, aTriangle.y + theVrtOffset).xyz;
401 vec3 aPoint2 = texelFetch (uGeometryVertexTexture, aTriangle.z + theVrtOffset).xyz;
402
403 float aTime = IntersectTriangle (theRay,
404 aPoint0,
405 aPoint1,
406 aPoint2,
407 aParams,
408 aNormal);
409
410 if (aTime < theDistance)
411 return 0.f;
412 }
413
414 if (aHead == theSentinel)
415 return 1.f;
416
417 aNode = Stack[aHead--];
418 }
419 }
420
421 return 1.f;
422}
423
424// =======================================================================
425// function : SceneNearestHit
426// purpose : Finds intersection with nearest scene triangle
427// =======================================================================
84c71f29 428ivec4 SceneNearestHit (in SRay theRay, in vec3 theInverse, inout SIntersect theHit, out int theObjectId)
fc73a202 429{
430 int aHead = -1; // stack pointer
431 int aNode = 0; // node to visit
432
433 ivec4 aHitObject = INALID_HIT;
434
435 float aTimeOut;
436 float aTimeLft;
437 float aTimeRgh;
438
439 while (true)
440 {
441 ivec4 aData = texelFetch (uSceneNodeInfoTexture, aNode);
442
443 if (aData.x != 0) // if leaf node
444 {
445 vec3 aNodeMin = texelFetch (uSceneMinPointTexture, aNode).xyz;
446 vec3 aNodeMax = texelFetch (uSceneMaxPointTexture, aNode).xyz;
447
448 vec3 aTime0 = (aNodeMin - theRay.Origin) * theInverse;
449 vec3 aTime1 = (aNodeMax - theRay.Origin) * theInverse;
450
451 vec3 aTimes = min (aTime0, aTime1);
452
453 if (max (aTimes.x, max (aTimes.y, aTimes.z)) < theHit.Time)
454 {
84c71f29 455 // fetch object transformation
456 int anObjectId = aData.x - 1;
457 vec4 aInvTransf0 = texelFetch (uSceneTransformTexture, anObjectId * 4 + 0);
458 vec4 aInvTransf1 = texelFetch (uSceneTransformTexture, anObjectId * 4 + 1);
459 vec4 aInvTransf2 = texelFetch (uSceneTransformTexture, anObjectId * 4 + 2);
460 vec4 aInvTransf3 = texelFetch (uSceneTransformTexture, anObjectId * 4 + 3);
461
462 SRay aNewRay;
463
464 aNewRay.Origin = MatrixColMultiply (vec4 (theRay.Origin, 1.f),
465 aInvTransf0, aInvTransf1, aInvTransf2, aInvTransf3);
466
467 aNewRay.Direct = MatrixColMultiply (vec4 (theRay.Direct, 0.f),
468 aInvTransf0, aInvTransf1, aInvTransf2, aInvTransf3);
469
470 vec3 aNewInverse = 1.f / max (abs (aNewRay.Direct), SMALL);
471
472 aNewInverse.x = aNewRay.Direct.x < 0.f ? -aNewInverse.x : aNewInverse.x;
473 aNewInverse.y = aNewRay.Direct.y < 0.f ? -aNewInverse.y : aNewInverse.y;
474 aNewInverse.z = aNewRay.Direct.z < 0.f ? -aNewInverse.z : aNewInverse.z;
475
fc73a202 476 ivec4 aTriIndex = ObjectNearestHit (
84c71f29 477 aData.y, aData.z, aData.w, aNewRay, aNewInverse, theHit, aHead);
fc73a202 478
479 if (aTriIndex.x != -1)
480 {
481 aHitObject = ivec4 (aTriIndex.x + aData.z, // vertex 0
482 aTriIndex.y + aData.z, // vertex 1
483 aTriIndex.z + aData.z, // vertex 2
484 aTriIndex.w); // material
84c71f29 485
486 theObjectId = anObjectId;
fc73a202 487 }
488 }
489
490 if (aHead < 0)
491 return aHitObject;
492
493 aNode = Stack[aHead--];
494 }
495 else // if inner node
496 {
497 vec3 aNodeMinLft = texelFetch (uSceneMinPointTexture, aData.y).xyz;
498 vec3 aNodeMaxLft = texelFetch (uSceneMaxPointTexture, aData.y).xyz;
499 vec3 aNodeMinRgh = texelFetch (uSceneMinPointTexture, aData.z).xyz;
500 vec3 aNodeMaxRgh = texelFetch (uSceneMaxPointTexture, aData.z).xyz;
501
502 vec3 aTime0 = (aNodeMinLft - theRay.Origin) * theInverse;
503 vec3 aTime1 = (aNodeMaxLft - theRay.Origin) * theInverse;
504
505 vec3 aTimeMax = max (aTime0, aTime1);
506 vec3 aTimeMin = min (aTime0, aTime1);
507
508 aTimeOut = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z));
509 aTimeLft = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));
510
511 int aHitLft = int(aTimeLft <= aTimeOut) & int(aTimeOut >= 0.f) & int(aTimeLft <= theHit.Time);
512
513 aTime0 = (aNodeMinRgh - theRay.Origin) * theInverse;
514 aTime1 = (aNodeMaxRgh - theRay.Origin) * theInverse;
515
516 aTimeMax = max (aTime0, aTime1);
517 aTimeMin = min (aTime0, aTime1);
518
519 aTimeOut = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z));
520 aTimeRgh = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));
521
522 int aHitRgh = int(aTimeRgh <= aTimeOut) & int(aTimeOut >= 0.f) & int(aTimeRgh <= theHit.Time);
523
524 if (bool(aHitLft & aHitRgh))
525 {
526 aNode = (aTimeLft < aTimeRgh) ? aData.y : aData.z;
527
528 Stack[++aHead] = (aTimeLft < aTimeRgh) ? aData.z : aData.y;
529 }
530 else
531 {
532 if (bool(aHitLft | aHitRgh))
533 {
534 aNode = bool(aHitLft) ? aData.y : aData.z;
535 }
536 else
537 {
538 if (aHead < 0)
539 return aHitObject;
540
541 aNode = Stack[aHead--];
542 }
543 }
544 }
545 }
546
547 return aHitObject;
548}
549
550// =======================================================================
551// function : SceneAnyHit
552// purpose : Finds intersection with any scene triangle
553// =======================================================================
554float SceneAnyHit (in SRay theRay, in vec3 theInverse, in float theDistance)
555{
556 int aHead = -1; // stack pointer
557 int aNode = 0; // node to visit
558
559 float aTimeOut;
560 float aTimeLft;
561 float aTimeRgh;
562
563 while (true)
564 {
565 ivec4 aData = texelFetch (uSceneNodeInfoTexture, aNode);
566
567 if (aData.x != 0) // if leaf node
568 {
84c71f29 569 // fetch object transformation
570 int anObjectId = aData.x - 1;
571 vec4 aInvTransf0 = texelFetch (uSceneTransformTexture, anObjectId * 4 + 0);
572 vec4 aInvTransf1 = texelFetch (uSceneTransformTexture, anObjectId * 4 + 1);
573 vec4 aInvTransf2 = texelFetch (uSceneTransformTexture, anObjectId * 4 + 2);
574 vec4 aInvTransf3 = texelFetch (uSceneTransformTexture, anObjectId * 4 + 3);
575
576 SRay aNewRay;
577
578 aNewRay.Origin = MatrixColMultiply (vec4 (theRay.Origin, 1.f),
579 aInvTransf0, aInvTransf1, aInvTransf2, aInvTransf3);
580
581 aNewRay.Direct = MatrixColMultiply (vec4 (theRay.Direct, 0.f),
582 aInvTransf0, aInvTransf1, aInvTransf2, aInvTransf3);
583
584 vec3 aNewInverse = 1.f / max (abs (aNewRay.Direct), SMALL);
585
586 aNewInverse.x = aNewRay.Direct.x < 0.f ? -aNewInverse.x : aNewInverse.x;
587 aNewInverse.y = aNewRay.Direct.y < 0.f ? -aNewInverse.y : aNewInverse.y;
588 aNewInverse.z = aNewRay.Direct.z < 0.f ? -aNewInverse.z : aNewInverse.z;
589
fc73a202 590 bool isShadow = 0.f == ObjectAnyHit (
84c71f29 591 aData.y, aData.z, aData.w, aNewRay, aNewInverse, theDistance, aHead);
fc73a202 592
593 if (aHead < 0 || isShadow)
594 return isShadow ? 0.f : 1.f;
595
596 aNode = Stack[aHead--];
597 }
598 else // if inner node
599 {
600 vec3 aNodeMinLft = texelFetch (uSceneMinPointTexture, aData.y).xyz;
601 vec3 aNodeMaxLft = texelFetch (uSceneMaxPointTexture, aData.y).xyz;
602 vec3 aNodeMinRgh = texelFetch (uSceneMinPointTexture, aData.z).xyz;
603 vec3 aNodeMaxRgh = texelFetch (uSceneMaxPointTexture, aData.z).xyz;
604
605 vec3 aTime0 = (aNodeMinLft - theRay.Origin) * theInverse;
606 vec3 aTime1 = (aNodeMaxLft - theRay.Origin) * theInverse;
607
608 vec3 aTimeMax = max (aTime0, aTime1);
609 vec3 aTimeMin = min (aTime0, aTime1);
610
611 aTimeOut = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z));
612 aTimeLft = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));
613
614 int aHitLft = int(aTimeLft <= aTimeOut) & int(aTimeOut >= 0.f) & int(aTimeLft <= theDistance);
615
616 aTime0 = (aNodeMinRgh - theRay.Origin) * theInverse;
617 aTime1 = (aNodeMaxRgh - theRay.Origin) * theInverse;
618
619 aTimeMax = max (aTime0, aTime1);
620 aTimeMin = min (aTime0, aTime1);
621
622 aTimeOut = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z));
623 aTimeRgh = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));
624
625 int aHitRgh = int(aTimeRgh <= aTimeOut) & int(aTimeOut >= 0.f) & int(aTimeRgh <= theDistance);
626
627 if (bool(aHitLft & aHitRgh))
628 {
629 aNode = (aTimeLft < aTimeRgh) ? aData.y : aData.z;
630
631 Stack[++aHead] = (aTimeLft < aTimeRgh) ? aData.z : aData.y;
632 }
633 else
634 {
635 if (bool(aHitLft | aHitRgh))
636 {
637 aNode = bool(aHitLft) ? aData.y : aData.z;
638 }
639 else
640 {
641 if (aHead < 0)
642 return 1.f;
643
644 aNode = Stack[aHead--];
645 }
646 }
647 }
648 }
649
650 return 1.f;
651}
652
653#define PI 3.1415926f
654
655// =======================================================================
656// function : Latlong
657// purpose : Converts world direction to environment texture coordinates
658// =======================================================================
659vec2 Latlong (in vec3 thePoint, in float theRadius)
660{
661 float aPsi = acos (-thePoint.z / theRadius);
662
663 float aPhi = atan (thePoint.y, thePoint.x) + PI;
664
665 return vec2 (aPhi * 0.1591549f,
666 aPsi * 0.3183098f);
667}
668
669// =======================================================================
670// function : SmoothNormal
671// purpose : Interpolates normal across the triangle
672// =======================================================================
673vec3 SmoothNormal (in vec2 theUV, in ivec4 theTriangle)
674{
675 vec3 aNormal0 = texelFetch (uGeometryNormalTexture, theTriangle.x).xyz;
676 vec3 aNormal1 = texelFetch (uGeometryNormalTexture, theTriangle.y).xyz;
677 vec3 aNormal2 = texelFetch (uGeometryNormalTexture, theTriangle.z).xyz;
678
679 return normalize (aNormal1 * theUV.x +
680 aNormal2 * theUV.y +
681 aNormal0 * (1.f - theUV.x - theUV.y));
682}
683
684#define THRESHOLD vec3 (0.1f, 0.1f, 0.1f)
685
686#define MATERIAL_AMBN(index) (7 * index + 0)
687#define MATERIAL_DIFF(index) (7 * index + 1)
688#define MATERIAL_SPEC(index) (7 * index + 2)
689#define MATERIAL_EMIS(index) (7 * index + 3)
690#define MATERIAL_REFL(index) (7 * index + 4)
691#define MATERIAL_REFR(index) (7 * index + 5)
692#define MATERIAL_TRAN(index) (7 * index + 6)
693
694#define LIGHT_POS(index) (2 * index + 1)
695#define LIGHT_PWR(index) (2 * index + 0)
696
697// =======================================================================
698// function : Radiance
699// purpose : Computes color of specified ray
700// =======================================================================
701vec4 Radiance (in SRay theRay, in vec3 theInverse)
702{
703 vec3 aResult = vec3 (0.f);
704 vec4 aWeight = vec4 (1.f);
84c71f29 705
706 int anObjectId;
fc73a202 707
708 for (int aDepth = 0; aDepth < 5; ++aDepth)
709 {
710 SIntersect aHit = SIntersect (MAXFLOAT, vec2 (ZERO), ZERO);
711
84c71f29 712 ivec4 aTriIndex = SceneNearestHit (theRay, theInverse, aHit, anObjectId);
fc73a202 713
714 if (aTriIndex.x == -1)
715 {
716 if (aWeight.w != 0.f)
717 {
718 return vec4 (aResult.x,
719 aResult.y,
720 aResult.z,
721 aWeight.w);
722 }
723
724 if (bool(uEnvironmentEnable))
725 {
726 float aTime = IntersectSphere (theRay, uSceneRadius);
727
728 aResult.xyz += aWeight.xyz * textureLod (uEnvironmentMapTexture,
729 Latlong (theRay.Direct * aTime + theRay.Origin, uSceneRadius), 0.f).xyz;
730 }
731
732 return vec4 (aResult.x,
733 aResult.y,
734 aResult.z,
735 aWeight.w);
736 }
737
738 vec3 aPoint = theRay.Direct * aHit.Time + theRay.Origin;
739
740 vec3 aAmbient = vec3 (texelFetch (
741 uRaytraceMaterialTexture, MATERIAL_AMBN (aTriIndex.w)));
742 vec3 aDiffuse = vec3 (texelFetch (
743 uRaytraceMaterialTexture, MATERIAL_DIFF (aTriIndex.w)));
744 vec4 aSpecular = vec4 (texelFetch (
745 uRaytraceMaterialTexture, MATERIAL_SPEC (aTriIndex.w)));
746 vec2 aOpacity = vec2 (texelFetch (
747 uRaytraceMaterialTexture, MATERIAL_TRAN (aTriIndex.w)));
748
749 vec3 aNormal = SmoothNormal (aHit.UV, aTriIndex);
84c71f29 750
751 vec4 aInvTransf0 = texelFetch (uSceneTransformTexture, anObjectId * 4 + 0);
752 vec4 aInvTransf1 = texelFetch (uSceneTransformTexture, anObjectId * 4 + 1);
753 vec4 aInvTransf2 = texelFetch (uSceneTransformTexture, anObjectId * 4 + 2);
754 vec4 aInvTransf3 = texelFetch (uSceneTransformTexture, anObjectId * 4 + 3);
755
756 aNormal = MatrixRowMultiply (vec4 (aNormal, 0.f), aInvTransf0, aInvTransf1, aInvTransf2, aInvTransf3);
757 aNormal = normalize (aNormal);
fc73a202 758
759 aHit.Normal = normalize (aHit.Normal);
760
761 for (int aLightIdx = 0; aLightIdx < uLightCount; ++aLightIdx)
762 {
763 vec4 aLight = texelFetch (
764 uRaytraceLightSrcTexture, LIGHT_POS (aLightIdx));
765
766 float aDistance = MAXFLOAT;
767
768 if (aLight.w != 0.f) // point light source
769 {
770 aDistance = length (aLight.xyz -= aPoint);
771
772 aLight.xyz *= 1.f / aDistance;
773 }
774
775 SRay aShadow = SRay (aPoint + aLight.xyz * uSceneEpsilon, aLight.xyz);
776
777 aShadow.Origin += aHit.Normal * uSceneEpsilon *
778 (dot (aHit.Normal, aLight.xyz) >= 0.f ? 1.f : -1.f);
779
780 float aVisibility = 1.f;
781
782 if (bool(uShadowsEnable))
783 {
784 vec3 aInverse = 1.f / max (abs (aLight.xyz), SMALL);
785
786 aInverse.x = aLight.x < 0.f ? -aInverse.x : aInverse.x;
787 aInverse.y = aLight.y < 0.f ? -aInverse.y : aInverse.y;
788 aInverse.z = aLight.z < 0.f ? -aInverse.z : aInverse.z;
789
790 aVisibility = SceneAnyHit (aShadow, aInverse, aDistance);
791 }
792
793 if (aVisibility > 0.f)
794 {
795 vec3 aIntensity = vec3 (texelFetch (
796 uRaytraceLightSrcTexture, LIGHT_PWR (aLightIdx)));
797
798 float aLdotN = dot (aShadow.Direct, aNormal);
799
800 if (aOpacity.y > 0.f) // force two-sided lighting
801 aLdotN = abs (aLdotN); // for transparent surfaces
802
803 if (aLdotN > 0.f)
804 {
805 float aRdotV = dot (reflect (aShadow.Direct, aNormal), theRay.Direct);
806
807 aResult.xyz += aWeight.xyz * aOpacity.x * aIntensity *
808 (aDiffuse * aLdotN + aSpecular.xyz * pow (max (0.f, aRdotV), aSpecular.w));
809 }
810 }
811 }
812
813 aResult.xyz += aWeight.xyz * uGlobalAmbient.xyz *
814 aAmbient * aOpacity.x * max (abs (dot (aNormal, theRay.Direct)), 0.5f);
815
816 if (aOpacity.x != 1.f)
817 {
818 aWeight *= aOpacity.y;
819 }
820 else
821 {
822 aWeight *= bool(uReflectionsEnable) ?
823 texelFetch (uRaytraceMaterialTexture, MATERIAL_REFL (aTriIndex.w)) : vec4 (0.f);
824
825 theRay.Direct = reflect (theRay.Direct, aNormal);
826
827 if (dot (theRay.Direct, aHit.Normal) < 0.f)
828 {
829 theRay.Direct = reflect (theRay.Direct, aHit.Normal);
830 }
831
832 theInverse = 1.0 / max (abs (theRay.Direct), SMALL);
833
834 theInverse.x = theRay.Direct.x < 0.0 ? -theInverse.x : theInverse.x;
835 theInverse.y = theRay.Direct.y < 0.0 ? -theInverse.y : theInverse.y;
836 theInverse.z = theRay.Direct.z < 0.0 ? -theInverse.z : theInverse.z;
837
838 aPoint += aHit.Normal * (dot (aHit.Normal, theRay.Direct) >= 0.f ? uSceneEpsilon : -uSceneEpsilon);
839 }
840
841 if (all (lessThanEqual (aWeight.xyz, THRESHOLD)))
842 {
843 return vec4 (aResult.x,
844 aResult.y,
845 aResult.z,
846 aWeight.w);
847 }
848
849 theRay.Origin = theRay.Direct * uSceneEpsilon + aPoint;
850 }
851
852 return vec4 (aResult.x,
853 aResult.y,
854 aResult.z,
855 aWeight.w);
856}