#ifdef USE_TEXTURES
//! Unique 64-bit handles of OpenGL textures.
- uniform sampler2D uTextureSamplers[MAX_TEX_NUMBER];
+ uniform uvec2 uTextureSamplers[MAX_TEX_NUMBER];
#endif
//! Top color of gradient background.
in vec4 m2,
in vec4 m3)
{
- return vec3 (m0[0] * v.x + m1[0] * v.y + m2[0] * v.z + m3[0],
- m0[1] * v.x + m1[1] * v.y + m2[1] * v.z + m3[1],
- m0[2] * v.x + m1[2] * v.y + m2[2] * v.z + m3[2]);
+ return vec3 (m0.x * v.x + m1.x * v.y + m2.x * v.z + m3.x,
+ m0.y * v.x + m1.y * v.y + m2.y * v.z + m3.y,
+ m0.z * v.x + m1.z * v.y + m2.z * v.z + m3.z);
}
// =======================================================================
vec3 MatrixColMultiplyDir (in vec3 v,
in vec4 m0,
in vec4 m1,
- in vec4 m2,
- in vec4 m3)
+ in vec4 m2)
{
- return vec3 (m0[0] * v.x + m1[0] * v.y + m2[0] * v.z,
- m0[1] * v.x + m1[1] * v.y + m2[1] * v.z,
- m0[2] * v.x + m1[2] * v.y + m2[2] * v.z);
+ return vec3 (m0.x * v.x + m1.x * v.y + m2.x * v.z,
+ m0.y * v.x + m1.y * v.y + m2.y * v.z,
+ m0.z * v.x + m1.z * v.y + m2.z * v.z);
}
//=======================================================================
//! Global stack shared between traversal functions.
int Stack[STACK_SIZE];
+#define MATERIAL_AMBN(index) (18 * index + 0)
+#define MATERIAL_DIFF(index) (18 * index + 1)
+#define MATERIAL_SPEC(index) (18 * index + 2)
+#define MATERIAL_EMIS(index) (18 * index + 3)
+#define MATERIAL_REFL(index) (18 * index + 4)
+#define MATERIAL_REFR(index) (18 * index + 5)
+#define MATERIAL_TRAN(index) (18 * index + 6)
+#define MATERIAL_TRS1(index) (18 * index + 7)
+#define MATERIAL_TRS2(index) (18 * index + 8)
+#define MATERIAL_TRS3(index) (18 * index + 9)
+
+struct SSubTree
+{
+ //! Transformed ray.
+ SRay TrsfRay;
+
+ //! Inversed ray direction.
+ vec3 Inverse;
+
+ //! Parameters of sub-root node.
+ ivec4 SubData;
+};
+
+#define TRS_OFFSET(treelet) treelet.SubData.x
+#define BVH_OFFSET(treelet) treelet.SubData.y
+#define VRT_OFFSET(treelet) treelet.SubData.z
+#define TRG_OFFSET(treelet) treelet.SubData.w
+
+#define EMPTY_ROOT ivec4(0)
+
// =======================================================================
-// function : ObjectNearestHit
-// purpose : Finds intersection with nearest object triangle
+// function : SceneNearestHit
+// purpose : Finds intersection with nearest scene triangle
// =======================================================================
-ivec4 ObjectNearestHit (in int theBVHOffset, in int theVrtOffset, in int theTrgOffset,
- in SRay theRay, in vec3 theInverse, inout SIntersect theHit, in int theSentinel)
+ivec4 SceneNearestHit (in SRay theRay, in vec3 theInverse, inout SIntersect theHit, out int theTrsfId)
{
- int aHead = theSentinel; // stack pointer
- int aNode = theBVHOffset; // node to visit
-
ivec4 aTriIndex = INALID_HIT;
+ int aNode = 0; // node to traverse
+ int aHead = -1; // pointer of stack
+ int aStop = -1; // BVH level switch
+
+ SSubTree aSubTree = SSubTree (theRay, theInverse, EMPTY_ROOT);
+
for (bool toContinue = true; toContinue;)
{
- ivec3 aData = texelFetch (uSceneNodeInfoTexture, aNode).xyz;
+ ivec4 aData = texelFetch (uSceneNodeInfoTexture, aNode);
if (aData.x == 0) // if inner node
{
float aTimeLft;
float aTimeRgh;
- aData.y += theBVHOffset;
- aData.z += theBVHOffset;
+ aData.y += BVH_OFFSET (aSubTree);
+ aData.z += BVH_OFFSET (aSubTree);
vec3 aNodeMinLft = texelFetch (uSceneMinPointTexture, aData.y).xyz;
vec3 aNodeMinRgh = texelFetch (uSceneMinPointTexture, aData.z).xyz;
vec3 aNodeMaxLft = texelFetch (uSceneMaxPointTexture, aData.y).xyz;
vec3 aNodeMaxRgh = texelFetch (uSceneMaxPointTexture, aData.z).xyz;
- vec3 aTime0 = (aNodeMinLft - theRay.Origin) * theInverse;
- vec3 aTime1 = (aNodeMaxLft - theRay.Origin) * theInverse;
+ vec3 aTime0 = (aNodeMinLft - aSubTree.TrsfRay.Origin) * aSubTree.Inverse;
+ vec3 aTime1 = (aNodeMaxLft - aSubTree.TrsfRay.Origin) * aSubTree.Inverse;
vec3 aTimeMax = max (aTime0, aTime1);
vec3 aTimeMin = min (aTime0, aTime1);
- aTime0 = (aNodeMinRgh - theRay.Origin) * theInverse;
- aTime1 = (aNodeMaxRgh - theRay.Origin) * theInverse;
+ aTime0 = (aNodeMinRgh - aSubTree.TrsfRay.Origin) * aSubTree.Inverse;
+ aTime1 = (aNodeMaxRgh - aSubTree.TrsfRay.Origin) * aSubTree.Inverse;
aTimeOut = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z));
aTimeLft = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));
int aHitRgh = int(aTimeRgh <= aTimeOut) & int(aTimeOut >= 0.0f) & int(aTimeRgh <= theHit.Time);
- if (bool(aHitLft & aHitRgh))
+ aNode = (aHitLft != 0) ? aData.y : aData.z;
+
+ if (aHitLft + aHitRgh == 2) // hit both children
{
aNode = (aTimeLft < aTimeRgh) ? aData.y : aData.z;
Stack[++aHead] = (aTimeLft < aTimeRgh) ? aData.z : aData.y;
}
- else
+ else if (aHitLft == aHitRgh) // no hit
{
- if (bool(aHitLft | aHitRgh))
+ toContinue = (aHead >= 0);
+
+ if (aHead == aStop) // go to top-level BVH
{
- aNode = bool(aHitLft) ? aData.y : aData.z;
+ aStop = -1; aSubTree = SSubTree (theRay, theInverse, EMPTY_ROOT);
}
- else
- {
- toContinue = (aHead != theSentinel);
- if (toContinue)
- aNode = Stack[aHead--];
- }
+ aNode = Stack[abs (aHead)]; --aHead;
}
}
- else // if leaf node
+ else if (aData.x < 0) // leaf node (containg triangles)
{
vec3 aNormal;
vec2 aParams;
for (int anIdx = aData.y; anIdx <= aData.z; ++anIdx)
{
- ivec4 aTriangle = texelFetch (uGeometryTriangTexture, anIdx + theTrgOffset);
+ ivec4 aTriangle = texelFetch (uGeometryTriangTexture, anIdx + TRG_OFFSET (aSubTree));
- vec3 aPoint0 = texelFetch (uGeometryVertexTexture, aTriangle.x += theVrtOffset).xyz;
- vec3 aPoint1 = texelFetch (uGeometryVertexTexture, aTriangle.y += theVrtOffset).xyz;
- vec3 aPoint2 = texelFetch (uGeometryVertexTexture, aTriangle.z += theVrtOffset).xyz;
+ vec3 aPoint0 = texelFetch (uGeometryVertexTexture, aTriangle.x += VRT_OFFSET (aSubTree)).xyz;
+ vec3 aPoint1 = texelFetch (uGeometryVertexTexture, aTriangle.y += VRT_OFFSET (aSubTree)).xyz;
+ vec3 aPoint2 = texelFetch (uGeometryVertexTexture, aTriangle.z += VRT_OFFSET (aSubTree)).xyz;
- float aTime = IntersectTriangle (theRay,
- aPoint0,
- aPoint1,
- aPoint2,
- aParams,
- aNormal);
+ float aTime = IntersectTriangle (aSubTree.TrsfRay,
+ aPoint0, aPoint1, aPoint2, aParams, aNormal);
if (aTime < theHit.Time)
{
aTriIndex = aTriangle;
+ theTrsfId = TRS_OFFSET (aSubTree);
+
theHit = SIntersect (aTime, aParams, aNormal);
}
}
- toContinue = (aHead != theSentinel);
+ toContinue = (aHead >= 0);
+
+ if (aHead == aStop) // go to top-level BVH
+ {
+ aStop = -1; aSubTree = SSubTree (theRay, theInverse, EMPTY_ROOT);
+ }
+
+ aNode = Stack[abs (aHead)]; --aHead;
+ }
+ else if (aData.x > 0) // switch node
+ {
+ aSubTree.SubData = ivec4 (4 * aData.x - 4, aData.yzw); // store BVH sub-root
+
+ vec4 aInvTransf0 = texelFetch (uSceneTransformTexture, TRS_OFFSET (aSubTree) + 0);
+ vec4 aInvTransf1 = texelFetch (uSceneTransformTexture, TRS_OFFSET (aSubTree) + 1);
+ vec4 aInvTransf2 = texelFetch (uSceneTransformTexture, TRS_OFFSET (aSubTree) + 2);
+ vec4 aInvTransf3 = texelFetch (uSceneTransformTexture, TRS_OFFSET (aSubTree) + 3);
+
+ aSubTree.TrsfRay.Direct = MatrixColMultiplyDir (theRay.Direct,
+ aInvTransf0,
+ aInvTransf1,
+ aInvTransf2);
+
+ aSubTree.Inverse = mix (-UNIT, UNIT, step (ZERO, aSubTree.TrsfRay.Direct)) /
+ max (abs (aSubTree.TrsfRay.Direct), SMALL);
- if (toContinue)
- aNode = Stack[aHead--];
+ aSubTree.TrsfRay.Origin = MatrixColMultiplyPnt (theRay.Origin,
+ aInvTransf0,
+ aInvTransf1,
+ aInvTransf2,
+ aInvTransf3);
+
+ aNode = BVH_OFFSET (aSubTree); // go to sub-root node
+
+ aStop = aHead; // store current stack pointer
}
}
return aTriIndex;
}
-#define MATERIAL_AMBN(index) (18 * index + 0)
-#define MATERIAL_DIFF(index) (18 * index + 1)
-#define MATERIAL_SPEC(index) (18 * index + 2)
-#define MATERIAL_EMIS(index) (18 * index + 3)
-#define MATERIAL_REFL(index) (18 * index + 4)
-#define MATERIAL_REFR(index) (18 * index + 5)
-#define MATERIAL_TRAN(index) (18 * index + 6)
-#define MATERIAL_TRS1(index) (18 * index + 7)
-#define MATERIAL_TRS2(index) (18 * index + 8)
-#define MATERIAL_TRS3(index) (18 * index + 9)
-
// =======================================================================
-// function : ObjectAnyHit
-// purpose : Finds intersection with any object triangle
+// function : SceneAnyHit
+// purpose : Finds intersection with any scene triangle
// =======================================================================
-float ObjectAnyHit (in int theBVHOffset, in int theVrtOffset, in int theTrgOffset,
- in SRay theRay, in vec3 theInverse, in float theDistance, in int theSentinel)
+float SceneAnyHit (in SRay theRay, in vec3 theInverse, in float theDistance)
{
- int aHead = theSentinel; // stack pointer
- int aNode = theBVHOffset; // node to visit
-
float aFactor = 1.f;
+ int aNode = 0; // node to traverse
+ int aHead = -1; // pointer of stack
+ int aStop = -1; // BVH level switch
+
+ SSubTree aSubTree = SSubTree (theRay, theInverse, EMPTY_ROOT);
+
for (bool toContinue = true; toContinue;)
{
ivec4 aData = texelFetch (uSceneNodeInfoTexture, aNode);
float aTimeLft;
float aTimeRgh;
- aData.y += theBVHOffset;
- aData.z += theBVHOffset;
+ aData.y += BVH_OFFSET (aSubTree);
+ aData.z += BVH_OFFSET (aSubTree);
vec3 aNodeMinLft = texelFetch (uSceneMinPointTexture, aData.y).xyz;
- vec3 aNodeMaxLft = texelFetch (uSceneMaxPointTexture, aData.y).xyz;
vec3 aNodeMinRgh = texelFetch (uSceneMinPointTexture, aData.z).xyz;
+ vec3 aNodeMaxLft = texelFetch (uSceneMaxPointTexture, aData.y).xyz;
vec3 aNodeMaxRgh = texelFetch (uSceneMaxPointTexture, aData.z).xyz;
- vec3 aTime0 = (aNodeMinLft - theRay.Origin) * theInverse;
- vec3 aTime1 = (aNodeMaxLft - theRay.Origin) * theInverse;
+ vec3 aTime0 = (aNodeMinLft - aSubTree.TrsfRay.Origin) * aSubTree.Inverse;
+ vec3 aTime1 = (aNodeMaxLft - aSubTree.TrsfRay.Origin) * aSubTree.Inverse;
vec3 aTimeMax = max (aTime0, aTime1);
vec3 aTimeMin = min (aTime0, aTime1);
- aTime0 = (aNodeMinRgh - theRay.Origin) * theInverse;
- aTime1 = (aNodeMaxRgh - theRay.Origin) * theInverse;
+ aTime0 = (aNodeMinRgh - aSubTree.TrsfRay.Origin) * aSubTree.Inverse;
+ aTime1 = (aNodeMaxRgh - aSubTree.TrsfRay.Origin) * aSubTree.Inverse;
aTimeOut = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z));
aTimeLft = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));
int aHitRgh = int(aTimeRgh <= aTimeOut) & int(aTimeOut >= 0.0f) & int(aTimeRgh <= theDistance);
- if (bool(aHitLft & aHitRgh))
+ aNode = (aHitLft != 0) ? aData.y : aData.z;
+
+ if (aHitLft + aHitRgh == 2) // hit both children
{
aNode = (aTimeLft < aTimeRgh) ? aData.y : aData.z;
Stack[++aHead] = (aTimeLft < aTimeRgh) ? aData.z : aData.y;
}
- else
+ else if (aHitLft == aHitRgh) // no hit
{
- if (bool(aHitLft | aHitRgh))
+ toContinue = (aHead >= 0);
+
+ if (aHead == aStop) // go to top-level BVH
{
- aNode = bool(aHitLft) ? aData.y : aData.z;
+ aStop = -1; aSubTree = SSubTree (theRay, theInverse, EMPTY_ROOT);
}
- else
- {
- toContinue = (aHead != theSentinel);
- if (toContinue)
- aNode = Stack[aHead--];
- }
+ aNode = Stack[abs (aHead)]; --aHead;
}
}
- else // if leaf node
+ else if (aData.x < 0) // leaf node
{
vec3 aNormal;
vec2 aParams;
for (int anIdx = aData.y; anIdx <= aData.z; ++anIdx)
{
- ivec4 aTriangle = texelFetch (uGeometryTriangTexture, anIdx + theTrgOffset);
+ ivec4 aTriangle = texelFetch (uGeometryTriangTexture, anIdx + TRG_OFFSET (aSubTree));
- vec3 aPoint0 = texelFetch (uGeometryVertexTexture, aTriangle.x + theVrtOffset).xyz;
- vec3 aPoint1 = texelFetch (uGeometryVertexTexture, aTriangle.y + theVrtOffset).xyz;
- vec3 aPoint2 = texelFetch (uGeometryVertexTexture, aTriangle.z + theVrtOffset).xyz;
+ vec3 aPoint0 = texelFetch (uGeometryVertexTexture, aTriangle.x += VRT_OFFSET (aSubTree)).xyz;
+ vec3 aPoint1 = texelFetch (uGeometryVertexTexture, aTriangle.y += VRT_OFFSET (aSubTree)).xyz;
+ vec3 aPoint2 = texelFetch (uGeometryVertexTexture, aTriangle.z += VRT_OFFSET (aSubTree)).xyz;
- float aTime = IntersectTriangle (theRay,
- aPoint0,
- aPoint1,
- aPoint2,
- aParams,
- aNormal);
+ float aTime = IntersectTriangle (aSubTree.TrsfRay,
+ aPoint0, aPoint1, aPoint2, aParams, aNormal);
#ifdef TRANSPARENT_SHADOWS
if (aTime < theDistance)
#endif
}
- toContinue = (aHead != theSentinel) && (aFactor > 0.1f);
-
- if (toContinue)
- aNode = Stack[aHead--];
- }
- }
-
- return aFactor;
-}
-
-// =======================================================================
-// function : SceneNearestHit
-// purpose : Finds intersection with nearest scene triangle
-// =======================================================================
-ivec4 SceneNearestHit (in SRay theRay, in vec3 theInverse, inout SIntersect theHit, out int theTrsfId)
-{
- int aHead = -1; // stack pointer
- int aNode = 0; // node to visit
-
- ivec4 aHitObject = INALID_HIT;
-
- for (bool toContinue = true; toContinue;)
- {
- ivec4 aData = texelFetch (uSceneNodeInfoTexture, aNode);
-
- if (aData.x != 0) // if leaf node
- {
- vec3 aNodeMin = texelFetch (uSceneMinPointTexture, aNode).xyz;
- vec3 aNodeMax = texelFetch (uSceneMaxPointTexture, aNode).xyz;
-
- vec3 aTime0 = (aNodeMin - theRay.Origin) * theInverse;
- vec3 aTime1 = (aNodeMax - theRay.Origin) * theInverse;
-
- vec3 aTimes = min (aTime0, aTime1);
+ toContinue = (aHead >= 0) && (aFactor > 0.1f);
- if (max (aTimes.x, max (aTimes.y, aTimes.z)) < theHit.Time)
+ if (aHead == aStop) // go to top-level BVH
{
- // fetch object transformation
- int aTrsfId = (aData.x - 1) * 4;
-
- vec4 aInvTransf0 = texelFetch (uSceneTransformTexture, aTrsfId + 0);
- vec4 aInvTransf1 = texelFetch (uSceneTransformTexture, aTrsfId + 1);
- vec4 aInvTransf2 = texelFetch (uSceneTransformTexture, aTrsfId + 2);
- vec4 aInvTransf3 = texelFetch (uSceneTransformTexture, aTrsfId + 3);
-
- SRay aTrsfRay = SRay (
- MatrixColMultiplyPnt (theRay.Origin, aInvTransf0, aInvTransf1, aInvTransf2, aInvTransf3),
- MatrixColMultiplyDir (theRay.Direct, aInvTransf0, aInvTransf1, aInvTransf2, aInvTransf3));
-
- vec3 aTrsfInverse = 1.0f / max (abs (aTrsfRay.Direct), SMALL);
-
- aTrsfInverse = mix (-aTrsfInverse, aTrsfInverse, step (ZERO, aTrsfRay.Direct));
-
- ivec4 aTriIndex = ObjectNearestHit (
- aData.y, aData.z, aData.w, aTrsfRay, aTrsfInverse, theHit, aHead);
-
- if (aTriIndex.x != -1)
- {
- aHitObject = ivec4 (aTriIndex.x, // vertex 0
- aTriIndex.y, // vertex 1
- aTriIndex.z, // vertex 2
- aTriIndex.w); // material
-
- theTrsfId = aTrsfId;
- }
+ aStop = -1; aSubTree = SSubTree (theRay, theInverse, EMPTY_ROOT);
}
- toContinue = aHead >= 0;
-
- if (toContinue)
- aNode = Stack[aHead--];
+ aNode = Stack[abs (aHead)]; --aHead;
}
- else // if inner node
+ else if (aData.x > 0) // switch node
{
- float aTimeOut;
- float aTimeLft;
- float aTimeRgh;
+ aSubTree.SubData = ivec4 (4 * aData.x - 4, aData.yzw); // store BVH sub-root
- vec3 aNodeMinLft = texelFetch (uSceneMinPointTexture, aData.y).xyz;
- vec3 aNodeMaxLft = texelFetch (uSceneMaxPointTexture, aData.y).xyz;
- vec3 aNodeMinRgh = texelFetch (uSceneMinPointTexture, aData.z).xyz;
- vec3 aNodeMaxRgh = texelFetch (uSceneMaxPointTexture, aData.z).xyz;
-
- vec3 aTime0 = (aNodeMinLft - theRay.Origin) * theInverse;
- vec3 aTime1 = (aNodeMaxLft - theRay.Origin) * theInverse;
-
- vec3 aTimeMax = max (aTime0, aTime1);
- vec3 aTimeMin = min (aTime0, aTime1);
-
- aTimeOut = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z));
- aTimeLft = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));
-
- int aHitLft = int(aTimeLft <= aTimeOut) & int(aTimeOut >= 0.0f) & int(aTimeLft <= theHit.Time);
-
- aTime0 = (aNodeMinRgh - theRay.Origin) * theInverse;
- aTime1 = (aNodeMaxRgh - theRay.Origin) * theInverse;
-
- aTimeMax = max (aTime0, aTime1);
- aTimeMin = min (aTime0, aTime1);
-
- aTimeOut = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z));
- aTimeRgh = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));
-
- int aHitRgh = int(aTimeRgh <= aTimeOut) & int(aTimeOut >= 0.0f) & int(aTimeRgh <= theHit.Time);
-
- if (bool(aHitLft & aHitRgh))
- {
- aNode = (aTimeLft < aTimeRgh) ? aData.y : aData.z;
-
- Stack[++aHead] = (aTimeLft < aTimeRgh) ? aData.z : aData.y;
- }
- else
- {
- if (bool(aHitLft | aHitRgh))
- {
- aNode = bool(aHitLft) ? aData.y : aData.z;
- }
- else
- {
- toContinue = aHead >= 0;
-
- if (toContinue)
- aNode = Stack[aHead--];
- }
- }
- }
- }
-
- return aHitObject;
-}
+ vec4 aInvTransf0 = texelFetch (uSceneTransformTexture, TRS_OFFSET (aSubTree) + 0);
+ vec4 aInvTransf1 = texelFetch (uSceneTransformTexture, TRS_OFFSET (aSubTree) + 1);
+ vec4 aInvTransf2 = texelFetch (uSceneTransformTexture, TRS_OFFSET (aSubTree) + 2);
+ vec4 aInvTransf3 = texelFetch (uSceneTransformTexture, TRS_OFFSET (aSubTree) + 3);
-// =======================================================================
-// function : SceneAnyHit
-// purpose : Finds intersection with any scene triangle
-// =======================================================================
-float SceneAnyHit (in SRay theRay, in vec3 theInverse, in float theDistance)
-{
- int aHead = -1; // stack pointer
- int aNode = 0; // node to visit
+ aSubTree.TrsfRay.Direct = MatrixColMultiplyDir (theRay.Direct,
+ aInvTransf0,
+ aInvTransf1,
+ aInvTransf2);
- float aFactor = 1.f;
-
- for (bool toContinue = true; toContinue;)
- {
- ivec4 aData = texelFetch (uSceneNodeInfoTexture, aNode);
+ aSubTree.TrsfRay.Origin = MatrixColMultiplyPnt (theRay.Origin,
+ aInvTransf0,
+ aInvTransf1,
+ aInvTransf2,
+ aInvTransf3);
- if (aData.x != 0) // if leaf node
- {
- // fetch object transformation
- int aTrsfId = (aData.x - 1) * 4;
+ aSubTree.Inverse = mix (-UNIT, UNIT, step (ZERO, aSubTree.TrsfRay.Direct)) / max (abs (aSubTree.TrsfRay.Direct), SMALL);
- vec4 aInvTransf0 = texelFetch (uSceneTransformTexture, aTrsfId + 0);
- vec4 aInvTransf1 = texelFetch (uSceneTransformTexture, aTrsfId + 1);
- vec4 aInvTransf2 = texelFetch (uSceneTransformTexture, aTrsfId + 2);
- vec4 aInvTransf3 = texelFetch (uSceneTransformTexture, aTrsfId + 3);
+ aNode = BVH_OFFSET (aSubTree); // go to sub-root node
- SRay aTrsfRay = SRay (
- MatrixColMultiplyPnt (theRay.Origin, aInvTransf0, aInvTransf1, aInvTransf2, aInvTransf3),
- MatrixColMultiplyDir (theRay.Direct, aInvTransf0, aInvTransf1, aInvTransf2, aInvTransf3));
-
- vec3 aTrsfInverse = 1.0f / max (abs (aTrsfRay.Direct), SMALL);
-
- aTrsfInverse = mix (-aTrsfInverse, aTrsfInverse, step (ZERO, aTrsfRay.Direct));
-
-#ifdef TRANSPARENT_SHADOWS
- aFactor *= ObjectAnyHit (
- aData.y, aData.z, aData.w, aTrsfRay, aTrsfInverse, theDistance, aHead);
-
- toContinue = aHead >= 0 && aFactor >= 0.1f;
-#else
- aFactor = ObjectAnyHit (
- aData.y, aData.z, aData.w, aTrsfRay, aTrsfInverse, theDistance, aHead);
-
- toContinue = aHead >= 0 && aFactor != 0.0f;
-#endif
-
- if (toContinue)
- aNode = Stack[aHead--];
- }
- else // if inner node
- {
- float aTimeOut;
- float aTimeLft;
- float aTimeRgh;
-
- vec3 aNodeMinLft = texelFetch (uSceneMinPointTexture, aData.y).xyz;
- vec3 aNodeMaxLft = texelFetch (uSceneMaxPointTexture, aData.y).xyz;
- vec3 aNodeMinRgh = texelFetch (uSceneMinPointTexture, aData.z).xyz;
- vec3 aNodeMaxRgh = texelFetch (uSceneMaxPointTexture, aData.z).xyz;
-
- vec3 aTime0 = (aNodeMinLft - theRay.Origin) * theInverse;
- vec3 aTime1 = (aNodeMaxLft - theRay.Origin) * theInverse;
-
- vec3 aTimeMax = max (aTime0, aTime1);
- vec3 aTimeMin = min (aTime0, aTime1);
-
- aTimeOut = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z));
- aTimeLft = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));
-
- int aHitLft = int(aTimeLft <= aTimeOut) & int(aTimeOut >= 0.0f) & int(aTimeLft <= theDistance);
-
- aTime0 = (aNodeMinRgh - theRay.Origin) * theInverse;
- aTime1 = (aNodeMaxRgh - theRay.Origin) * theInverse;
-
- aTimeMax = max (aTime0, aTime1);
- aTimeMin = min (aTime0, aTime1);
-
- aTimeOut = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z));
- aTimeRgh = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));
-
- int aHitRgh = int(aTimeRgh <= aTimeOut) & int(aTimeOut >= 0.0f) & int(aTimeRgh <= theDistance);
-
- if (bool(aHitLft & aHitRgh))
- {
- aNode = (aTimeLft < aTimeRgh) ? aData.y : aData.z;
-
- Stack[++aHead] = (aTimeLft < aTimeRgh) ? aData.z : aData.y;
- }
- else
- {
- if (bool(aHitLft | aHitRgh))
- {
- aNode = bool(aHitLft) ? aData.y : aData.z;
- }
- else
- {
- toContinue = aHead >= 0;
-
- if (toContinue)
- aNode = Stack[aHead--];
- }
- }
+ aStop = aHead; // store current stack pointer
}
}
dot (aTrsfRow2, aTexCoord));
vec3 aTexColor = textureLod (
- uTextureSamplers[int(aDiffuse.w)], aTexCoord.st, 0.f).rgb;
+ sampler2D (uTextureSamplers[int(aDiffuse.w)]), aTexCoord.st, 0.f).rgb;
aDiffuse.rgb *= aTexColor;
aAmbient.rgb *= aTexColor;