1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-04 13:13:25 +03:00

0024739: TKOpenGl - port ray-tracing from OpenCL to GLSL for better integration and portability

RayTracing - disable reflections by default
Fix possible compilation issue on Mac OS X.
This commit is contained in:
dbp
2014-04-04 14:14:02 +04:00
committed by apn
parent 54e37688ef
commit fc73a20256
39 changed files with 2399 additions and 2676 deletions

768
src/Shaders/RaytraceBase.fs Normal file
View File

@@ -0,0 +1,768 @@
//! Normalized pixel coordinates.
in vec2 vPixel;
//! Origin of viewing ray in left-top corner.
uniform vec3 uOriginLT;
//! Origin of viewing ray in left-bottom corner.
uniform vec3 uOriginLB;
//! Origin of viewing ray in right-top corner.
uniform vec3 uOriginRT;
//! Origin of viewing ray in right-bottom corner.
uniform vec3 uOriginRB;
//! Direction of viewing ray in left-top corner.
uniform vec3 uDirectLT;
//! Direction of viewing ray in left-bottom corner.
uniform vec3 uDirectLB;
//! Direction of viewing ray in right-top corner.
uniform vec3 uDirectRT;
//! Direction of viewing ray in right-bottom corner.
uniform vec3 uDirectRB;
//! Texture buffer of data records of high-level BVH nodes.
uniform isamplerBuffer uSceneNodeInfoTexture;
//! Texture buffer of minimum points of high-level BVH nodes.
uniform samplerBuffer uSceneMinPointTexture;
//! Texture buffer of maximum points of high-level BVH nodes.
uniform samplerBuffer uSceneMaxPointTexture;
//! Texture buffer of data records of bottom-level BVH nodes.
uniform isamplerBuffer uObjectNodeInfoTexture;
//! Texture buffer of minimum points of bottom-level BVH nodes.
uniform samplerBuffer uObjectMinPointTexture;
//! Texture buffer of maximum points of bottom-level BVH nodes.
uniform samplerBuffer uObjectMaxPointTexture;
//! Texture buffer of vertex coords.
uniform samplerBuffer uGeometryVertexTexture;
//! Texture buffer of vertex normals.
uniform samplerBuffer uGeometryNormalTexture;
//! Texture buffer of triangle indices.
uniform isamplerBuffer uGeometryTriangTexture;
//! Texture buffer of material properties.
uniform samplerBuffer uRaytraceMaterialTexture;
//! Texture buffer of light source properties.
uniform samplerBuffer uRaytraceLightSrcTexture;
//! Environment map texture.
uniform sampler2D uEnvironmentMapTexture;
//! Total number of light sources.
uniform int uLightCount;
//! Intensity of global ambient light.
uniform vec4 uGlobalAmbient;
//! Enables/disables environment map.
uniform int uEnvironmentEnable;
//! Enables/disables computation of shadows.
uniform int uShadowsEnable;
//! Enables/disables computation of reflections.
uniform int uReflectionsEnable;
//! Radius of bounding sphere of the scene.
uniform float uSceneRadius;
//! Scene epsilon to prevent self-intersections.
uniform float uSceneEpsilon;
/////////////////////////////////////////////////////////////////////////////////////////
// Specific data types
//! Stores ray parameters.
struct SRay
{
vec3 Origin;
vec3 Direct;
};
//! Stores intersection parameters.
struct SIntersect
{
float Time;
vec2 UV;
vec3 Normal;
};
/////////////////////////////////////////////////////////////////////////////////////////
// Some useful constants
#define MAXFLOAT 1e15f
#define SMALL vec3 (exp2 (-80.f))
#define ZERO vec3 (0.f, 0.f, 0.f)
#define UNIT vec3 (1.f, 1.f, 1.f)
#define AXIS_X vec3 (1.f, 0.f, 0.f)
#define AXIS_Y vec3 (0.f, 1.f, 0.f)
#define AXIS_Z vec3 (0.f, 0.f, 1.f)
/////////////////////////////////////////////////////////////////////////////////////////
// Functions for compute ray-object intersection
// =======================================================================
// function : GenerateRay
// purpose :
// =======================================================================
SRay GenerateRay (in vec2 thePixel)
{
vec3 aP0 = mix (uOriginLB, uOriginRB, thePixel.x);
vec3 aP1 = mix (uOriginLT, uOriginRT, thePixel.x);
vec3 aD0 = mix (uDirectLB, uDirectRB, thePixel.x);
vec3 aD1 = mix (uDirectLT, uDirectRT, thePixel.x);
return SRay (mix (aP0, aP1, thePixel.y),
mix (aD0, aD1, thePixel.y));
}
// =======================================================================
// function : IntersectSphere
// purpose : Computes ray-sphere intersection
// =======================================================================
float IntersectSphere (in SRay theRay, in float theRadius)
{
float aDdotD = dot (theRay.Direct, theRay.Direct);
float aDdotO = dot (theRay.Direct, theRay.Origin);
float aOdotO = dot (theRay.Origin, theRay.Origin);
float aD = aDdotO * aDdotO - aDdotD * (aOdotO - theRadius * theRadius);
if (aD > 0.f)
{
float aTime = (sqrt (aD) - aDdotO) * (1.f / aDdotD);
return aTime > 0.f ? aTime : MAXFLOAT;
}
return MAXFLOAT;
}
// =======================================================================
// function : IntersectTriangle
// purpose : Computes ray-triangle intersection (branchless version)
// =======================================================================
float IntersectTriangle (in SRay theRay,
in vec3 thePnt0,
in vec3 thePnt1,
in vec3 thePnt2,
out vec2 theUV,
out vec3 theNorm)
{
vec3 aEdge0 = thePnt1 - thePnt0;
vec3 aEdge1 = thePnt0 - thePnt2;
theNorm = cross (aEdge1, aEdge0);
vec3 aEdge2 = (1.f / dot (theNorm, theRay.Direct)) * (thePnt0 - theRay.Origin);
float aTime = dot (theNorm, aEdge2);
vec3 theVec = cross (theRay.Direct, aEdge2);
theUV.x = dot (theVec, aEdge1);
theUV.y = dot (theVec, aEdge0);
return bool (int(aTime >= 0.f) &
int(theUV.x >= 0.f) &
int(theUV.y >= 0.f) &
int(theUV.x + theUV.y <= 1.f)) ? aTime : MAXFLOAT;
}
//! Global stack shared between traversal functions.
int Stack[STACK_SIZE];
//! Identifies the absence of intersection.
#define INALID_HIT ivec4 (-1)
// =======================================================================
// function : ObjectNearestHit
// purpose : Finds intersection with nearest object triangle
// =======================================================================
ivec4 ObjectNearestHit (in int theBVHOffset, in int theVrtOffset, in int theTrgOffset,
in SRay theRay, in vec3 theInverse, inout SIntersect theHit, in int theSentinel)
{
int aHead = theSentinel; // stack pointer
int aNode = 0; // node to visit
ivec4 aTriIndex = INALID_HIT;
float aTimeOut;
float aTimeLft;
float aTimeRgh;
while (true)
{
ivec3 aData = texelFetch (uObjectNodeInfoTexture, aNode + theBVHOffset).xyz;
if (aData.x == 0) // if inner node
{
vec3 aNodeMinLft = texelFetch (uObjectMinPointTexture, aData.y + theBVHOffset).xyz;
vec3 aNodeMaxLft = texelFetch (uObjectMaxPointTexture, aData.y + theBVHOffset).xyz;
vec3 aNodeMinRgh = texelFetch (uObjectMinPointTexture, aData.z + theBVHOffset).xyz;
vec3 aNodeMaxRgh = texelFetch (uObjectMaxPointTexture, aData.z + theBVHOffset).xyz;
vec3 aTime0 = (aNodeMinLft - theRay.Origin) * theInverse;
vec3 aTime1 = (aNodeMaxLft - theRay.Origin) * theInverse;
vec3 aTimeMax = max (aTime0, aTime1);
vec3 aTimeMin = min (aTime0, aTime1);
aTime0 = (aNodeMinRgh - theRay.Origin) * theInverse;
aTime1 = (aNodeMaxRgh - theRay.Origin) * theInverse;
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.f) & int(aTimeLft <= theHit.Time);
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.f) & 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
{
if (aHead == theSentinel)
return aTriIndex;
aNode = Stack[aHead--];
}
}
}
else // if leaf node
{
vec3 aNormal;
vec2 aParams;
for (int anIdx = aData.y; anIdx <= aData.z; ++anIdx)
{
ivec4 aTriangle = texelFetch (uGeometryTriangTexture, anIdx + theTrgOffset);
vec3 aPoint0 = texelFetch (uGeometryVertexTexture, aTriangle.x + theVrtOffset).xyz;
vec3 aPoint1 = texelFetch (uGeometryVertexTexture, aTriangle.y + theVrtOffset).xyz;
vec3 aPoint2 = texelFetch (uGeometryVertexTexture, aTriangle.z + theVrtOffset).xyz;
float aTime = IntersectTriangle (theRay,
aPoint0,
aPoint1,
aPoint2,
aParams,
aNormal);
if (aTime < theHit.Time)
{
aTriIndex = aTriangle;
theHit = SIntersect (aTime, aParams, aNormal);
}
}
if (aHead == theSentinel)
return aTriIndex;
aNode = Stack[aHead--];
}
}
return aTriIndex;
}
// =======================================================================
// function : ObjectAnyHit
// purpose : Finds intersection with any object triangle
// =======================================================================
float ObjectAnyHit (in int theBVHOffset, in int theVrtOffset, in int theTrgOffset,
in SRay theRay, in vec3 theInverse, in float theDistance, in int theSentinel)
{
int aHead = theSentinel; // stack pointer
int aNode = 0; // node to visit
float aTimeOut;
float aTimeLft;
float aTimeRgh;
while (true)
{
ivec4 aData = texelFetch (uObjectNodeInfoTexture, aNode + theBVHOffset);
if (aData.x == 0) // if inner node
{
vec3 aNodeMinLft = texelFetch (uObjectMinPointTexture, aData.y + theBVHOffset).xyz;
vec3 aNodeMaxLft = texelFetch (uObjectMaxPointTexture, aData.y + theBVHOffset).xyz;
vec3 aNodeMinRgh = texelFetch (uObjectMinPointTexture, aData.z + theBVHOffset).xyz;
vec3 aNodeMaxRgh = texelFetch (uObjectMaxPointTexture, aData.z + theBVHOffset).xyz;
vec3 aTime0 = (aNodeMinLft - theRay.Origin) * theInverse;
vec3 aTime1 = (aNodeMaxLft - theRay.Origin) * theInverse;
vec3 aTimeMax = max (aTime0, aTime1);
vec3 aTimeMin = min (aTime0, aTime1);
aTime0 = (aNodeMinRgh - theRay.Origin) * theInverse;
aTime1 = (aNodeMaxRgh - theRay.Origin) * theInverse;
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.f) & int(aTimeLft <= theDistance);
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.f) & 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
{
if (aHead == theSentinel)
return 1.f;
aNode = Stack[aHead--];
}
}
}
else // if leaf node
{
vec3 aNormal;
vec2 aParams;
for (int anIdx = aData.y; anIdx <= aData.z; ++anIdx)
{
ivec4 aTriangle = texelFetch (uGeometryTriangTexture, anIdx + theTrgOffset);
vec3 aPoint0 = texelFetch (uGeometryVertexTexture, aTriangle.x + theVrtOffset).xyz;
vec3 aPoint1 = texelFetch (uGeometryVertexTexture, aTriangle.y + theVrtOffset).xyz;
vec3 aPoint2 = texelFetch (uGeometryVertexTexture, aTriangle.z + theVrtOffset).xyz;
float aTime = IntersectTriangle (theRay,
aPoint0,
aPoint1,
aPoint2,
aParams,
aNormal);
if (aTime < theDistance)
return 0.f;
}
if (aHead == theSentinel)
return 1.f;
aNode = Stack[aHead--];
}
}
return 1.f;
}
// =======================================================================
// function : SceneNearestHit
// purpose : Finds intersection with nearest scene triangle
// =======================================================================
ivec4 SceneNearestHit (in SRay theRay, in vec3 theInverse, inout SIntersect theHit)
{
int aHead = -1; // stack pointer
int aNode = 0; // node to visit
ivec4 aHitObject = INALID_HIT;
float aTimeOut;
float aTimeLft;
float aTimeRgh;
while (true)
{
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);
if (max (aTimes.x, max (aTimes.y, aTimes.z)) < theHit.Time)
{
ivec4 aTriIndex = ObjectNearestHit (
aData.y, aData.z, aData.w, theRay, theInverse, theHit, aHead);
if (aTriIndex.x != -1)
{
aHitObject = ivec4 (aTriIndex.x + aData.z, // vertex 0
aTriIndex.y + aData.z, // vertex 1
aTriIndex.z + aData.z, // vertex 2
aTriIndex.w); // material
}
}
if (aHead < 0)
return aHitObject;
aNode = Stack[aHead--];
}
else // if inner node
{
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.f) & 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.f) & 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
{
if (aHead < 0)
return aHitObject;
aNode = Stack[aHead--];
}
}
}
}
return aHitObject;
}
// =======================================================================
// 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
float aTimeOut;
float aTimeLft;
float aTimeRgh;
while (true)
{
ivec4 aData = texelFetch (uSceneNodeInfoTexture, aNode);
if (aData.x != 0) // if leaf node
{
bool isShadow = 0.f == ObjectAnyHit (
aData.y, aData.z, aData.w, theRay, theInverse, theDistance, aHead);
if (aHead < 0 || isShadow)
return isShadow ? 0.f : 1.f;
aNode = Stack[aHead--];
}
else // if inner node
{
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.f) & 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.f) & 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
{
if (aHead < 0)
return 1.f;
aNode = Stack[aHead--];
}
}
}
}
return 1.f;
}
#define PI 3.1415926f
// =======================================================================
// function : Latlong
// purpose : Converts world direction to environment texture coordinates
// =======================================================================
vec2 Latlong (in vec3 thePoint, in float theRadius)
{
float aPsi = acos (-thePoint.z / theRadius);
float aPhi = atan (thePoint.y, thePoint.x) + PI;
return vec2 (aPhi * 0.1591549f,
aPsi * 0.3183098f);
}
// =======================================================================
// function : SmoothNormal
// purpose : Interpolates normal across the triangle
// =======================================================================
vec3 SmoothNormal (in vec2 theUV, in ivec4 theTriangle)
{
vec3 aNormal0 = texelFetch (uGeometryNormalTexture, theTriangle.x).xyz;
vec3 aNormal1 = texelFetch (uGeometryNormalTexture, theTriangle.y).xyz;
vec3 aNormal2 = texelFetch (uGeometryNormalTexture, theTriangle.z).xyz;
return normalize (aNormal1 * theUV.x +
aNormal2 * theUV.y +
aNormal0 * (1.f - theUV.x - theUV.y));
}
#define THRESHOLD vec3 (0.1f, 0.1f, 0.1f)
#define MATERIAL_AMBN(index) (7 * index + 0)
#define MATERIAL_DIFF(index) (7 * index + 1)
#define MATERIAL_SPEC(index) (7 * index + 2)
#define MATERIAL_EMIS(index) (7 * index + 3)
#define MATERIAL_REFL(index) (7 * index + 4)
#define MATERIAL_REFR(index) (7 * index + 5)
#define MATERIAL_TRAN(index) (7 * index + 6)
#define LIGHT_POS(index) (2 * index + 1)
#define LIGHT_PWR(index) (2 * index + 0)
// =======================================================================
// function : Radiance
// purpose : Computes color of specified ray
// =======================================================================
vec4 Radiance (in SRay theRay, in vec3 theInverse)
{
vec3 aResult = vec3 (0.f);
vec4 aWeight = vec4 (1.f);
for (int aDepth = 0; aDepth < 5; ++aDepth)
{
SIntersect aHit = SIntersect (MAXFLOAT, vec2 (ZERO), ZERO);
ivec4 aTriIndex = SceneNearestHit (theRay, theInverse, aHit);
if (aTriIndex.x == -1)
{
if (aWeight.w != 0.f)
{
return vec4 (aResult.x,
aResult.y,
aResult.z,
aWeight.w);
}
if (bool(uEnvironmentEnable))
{
float aTime = IntersectSphere (theRay, uSceneRadius);
aResult.xyz += aWeight.xyz * textureLod (uEnvironmentMapTexture,
Latlong (theRay.Direct * aTime + theRay.Origin, uSceneRadius), 0.f).xyz;
}
return vec4 (aResult.x,
aResult.y,
aResult.z,
aWeight.w);
}
vec3 aPoint = theRay.Direct * aHit.Time + theRay.Origin;
vec3 aAmbient = vec3 (texelFetch (
uRaytraceMaterialTexture, MATERIAL_AMBN (aTriIndex.w)));
vec3 aDiffuse = vec3 (texelFetch (
uRaytraceMaterialTexture, MATERIAL_DIFF (aTriIndex.w)));
vec4 aSpecular = vec4 (texelFetch (
uRaytraceMaterialTexture, MATERIAL_SPEC (aTriIndex.w)));
vec2 aOpacity = vec2 (texelFetch (
uRaytraceMaterialTexture, MATERIAL_TRAN (aTriIndex.w)));
vec3 aNormal = SmoothNormal (aHit.UV, aTriIndex);
aHit.Normal = normalize (aHit.Normal);
for (int aLightIdx = 0; aLightIdx < uLightCount; ++aLightIdx)
{
vec4 aLight = texelFetch (
uRaytraceLightSrcTexture, LIGHT_POS (aLightIdx));
float aDistance = MAXFLOAT;
if (aLight.w != 0.f) // point light source
{
aDistance = length (aLight.xyz -= aPoint);
aLight.xyz *= 1.f / aDistance;
}
SRay aShadow = SRay (aPoint + aLight.xyz * uSceneEpsilon, aLight.xyz);
aShadow.Origin += aHit.Normal * uSceneEpsilon *
(dot (aHit.Normal, aLight.xyz) >= 0.f ? 1.f : -1.f);
float aVisibility = 1.f;
if (bool(uShadowsEnable))
{
vec3 aInverse = 1.f / max (abs (aLight.xyz), SMALL);
aInverse.x = aLight.x < 0.f ? -aInverse.x : aInverse.x;
aInverse.y = aLight.y < 0.f ? -aInverse.y : aInverse.y;
aInverse.z = aLight.z < 0.f ? -aInverse.z : aInverse.z;
aVisibility = SceneAnyHit (aShadow, aInverse, aDistance);
}
if (aVisibility > 0.f)
{
vec3 aIntensity = vec3 (texelFetch (
uRaytraceLightSrcTexture, LIGHT_PWR (aLightIdx)));
float aLdotN = dot (aShadow.Direct, aNormal);
if (aOpacity.y > 0.f) // force two-sided lighting
aLdotN = abs (aLdotN); // for transparent surfaces
if (aLdotN > 0.f)
{
float aRdotV = dot (reflect (aShadow.Direct, aNormal), theRay.Direct);
aResult.xyz += aWeight.xyz * aOpacity.x * aIntensity *
(aDiffuse * aLdotN + aSpecular.xyz * pow (max (0.f, aRdotV), aSpecular.w));
}
}
}
aResult.xyz += aWeight.xyz * uGlobalAmbient.xyz *
aAmbient * aOpacity.x * max (abs (dot (aNormal, theRay.Direct)), 0.5f);
if (aOpacity.x != 1.f)
{
aWeight *= aOpacity.y;
}
else
{
aWeight *= bool(uReflectionsEnable) ?
texelFetch (uRaytraceMaterialTexture, MATERIAL_REFL (aTriIndex.w)) : vec4 (0.f);
theRay.Direct = reflect (theRay.Direct, aNormal);
if (dot (theRay.Direct, aHit.Normal) < 0.f)
{
theRay.Direct = reflect (theRay.Direct, aHit.Normal);
}
theInverse = 1.0 / max (abs (theRay.Direct), SMALL);
theInverse.x = theRay.Direct.x < 0.0 ? -theInverse.x : theInverse.x;
theInverse.y = theRay.Direct.y < 0.0 ? -theInverse.y : theInverse.y;
theInverse.z = theRay.Direct.z < 0.0 ? -theInverse.z : theInverse.z;
aPoint += aHit.Normal * (dot (aHit.Normal, theRay.Direct) >= 0.f ? uSceneEpsilon : -uSceneEpsilon);
}
if (all (lessThanEqual (aWeight.xyz, THRESHOLD)))
{
return vec4 (aResult.x,
aResult.y,
aResult.z,
aWeight.w);
}
theRay.Origin = theRay.Direct * uSceneEpsilon + aPoint;
}
return vec4 (aResult.x,
aResult.y,
aResult.z,
aWeight.w);
}

View File

@@ -0,0 +1,12 @@
in vec4 aPosition;
//! Normalized pixel coordinates.
out vec2 vPixel;
void main (void)
{
vPixel = vec2 ((aPosition.x + 1.f) * 0.5f,
(aPosition.y + 1.f) * 0.5f);
gl_Position = aPosition;
}

View File

@@ -0,0 +1,18 @@
out vec4 OutColor;
// =======================================================================
// function : main
// purpose :
// =======================================================================
void main (void)
{
SRay aRay = GenerateRay (vPixel);
vec3 aInvDirect = 1.f / max (abs (aRay.Direct), SMALL);
aInvDirect = vec3 (aRay.Direct.x < 0.f ? -aInvDirect.x : aInvDirect.x,
aRay.Direct.y < 0.f ? -aInvDirect.y : aInvDirect.y,
aRay.Direct.z < 0.f ? -aInvDirect.z : aInvDirect.z);
OutColor = clamp (Radiance (aRay, aInvDirect), 0.f, 1.f);
}

View File

@@ -0,0 +1,79 @@
//! Input ray-traced image.
uniform sampler2D uFSAAInputTexture;
//! Number of accumulated FSAA samples.
uniform int uSamples;
//! Sub-pixel offset in X direction for FSAA.
uniform float uOffsetX;
//! Sub-pixel offset in Y direction for FSAA.
uniform float uOffsetY;
//! Output pixel color.
out vec4 OutColor;
#define LUM_DIFFERENCE 0.085f
#define LUMA vec3 (0.2126f, 0.7152f, 0.0722f)
// =======================================================================
// function : main
// purpose :
// =======================================================================
void main (void)
{
int aPixelX = int (gl_FragCoord.x);
int aPixelY = int (gl_FragCoord.y);
vec4 aClr0 = texelFetch (uFSAAInputTexture, ivec2 (aPixelX + 0, aPixelY + 0), 0);
vec4 aClr1 = texelFetch (uFSAAInputTexture, ivec2 (aPixelX + 0, aPixelY - 1), 0);
vec4 aClr2 = texelFetch (uFSAAInputTexture, ivec2 (aPixelX + 0, aPixelY + 1), 0);
vec4 aClr3 = texelFetch (uFSAAInputTexture, ivec2 (aPixelX + 1, aPixelY + 0), 0);
vec4 aClr4 = texelFetch (uFSAAInputTexture, ivec2 (aPixelX + 1, aPixelY - 1), 0);
vec4 aClr5 = texelFetch (uFSAAInputTexture, ivec2 (aPixelX + 1, aPixelY + 1), 0);
vec4 aClr6 = texelFetch (uFSAAInputTexture, ivec2 (aPixelX - 1, aPixelY + 0), 0);
vec4 aClr7 = texelFetch (uFSAAInputTexture, ivec2 (aPixelX - 1, aPixelY - 1), 0);
vec4 aClr8 = texelFetch (uFSAAInputTexture, ivec2 (aPixelX - 1, aPixelY + 1), 0);
float aLum = dot (LUMA, aClr0.xyz);
bool aRender = abs (aClr1.w - aClr0.w) > LUM_DIFFERENCE ||
abs (aClr2.w - aClr0.w) > LUM_DIFFERENCE ||
abs (aClr3.w - aClr0.w) > LUM_DIFFERENCE ||
abs (aClr4.w - aClr0.w) > LUM_DIFFERENCE ||
abs (aClr5.w - aClr0.w) > LUM_DIFFERENCE ||
abs (aClr6.w - aClr0.w) > LUM_DIFFERENCE ||
abs (aClr7.w - aClr0.w) > LUM_DIFFERENCE ||
abs (aClr8.w - aClr0.w) > LUM_DIFFERENCE;
if (!aRender)
{
aRender = abs (dot (LUMA, aClr1.xyz) - aLum) > LUM_DIFFERENCE ||
abs (dot (LUMA, aClr2.xyz) - aLum) > LUM_DIFFERENCE ||
abs (dot (LUMA, aClr3.xyz) - aLum) > LUM_DIFFERENCE ||
abs (dot (LUMA, aClr4.xyz) - aLum) > LUM_DIFFERENCE ||
abs (dot (LUMA, aClr5.xyz) - aLum) > LUM_DIFFERENCE ||
abs (dot (LUMA, aClr6.xyz) - aLum) > LUM_DIFFERENCE ||
abs (dot (LUMA, aClr7.xyz) - aLum) > LUM_DIFFERENCE ||
abs (dot (LUMA, aClr8.xyz) - aLum) > LUM_DIFFERENCE;
}
vec4 aColor = aClr0;
if (aRender)
{
SRay aRay = GenerateRay (vPixel + vec2 (uOffsetX, uOffsetY));
vec3 aInvDirect = 1.f / max (abs (aRay.Direct), SMALL);
aInvDirect = vec3 (aRay.Direct.x < 0.f ? -aInvDirect.x : aInvDirect.x,
aRay.Direct.y < 0.f ? -aInvDirect.y : aInvDirect.y,
aRay.Direct.z < 0.f ? -aInvDirect.z : aInvDirect.z);
aColor = mix (aClr0, clamp (Radiance (aRay, aInvDirect), 0.f, 1.f), 1.f / uSamples);
}
OutColor = aColor;
}