|
@@ -15,6 +15,9 @@ in vec4 vsEyeDir;
|
|
uniform sampler2D deferredBuffer;
|
|
uniform sampler2D deferredBuffer;
|
|
uniform sampler2D matInfoBuffer;
|
|
uniform sampler2D matInfoBuffer;
|
|
uniform samplerCube cubeMap;
|
|
uniform samplerCube cubeMap;
|
|
|
|
+uniform samplerCube irradianceCubemap;
|
|
|
|
+uniform sampler2D BRDFTexture;
|
|
|
|
+uniform float cubeMips;
|
|
|
|
|
|
uniform vec4 rtParams0;
|
|
uniform vec4 rtParams0;
|
|
|
|
|
|
@@ -22,78 +25,135 @@ uniform vec3 probeWSPos;
|
|
uniform vec3 probeLSPos;
|
|
uniform vec3 probeLSPos;
|
|
uniform vec4 vsFarPlane;
|
|
uniform vec4 vsFarPlane;
|
|
|
|
|
|
-uniform float lightRange;
|
|
|
|
-uniform vec2 lightAttenuation;
|
|
|
|
|
|
+uniform float radius;
|
|
|
|
+uniform vec2 attenuation;
|
|
|
|
|
|
-uniform mat4 invViewMat;
|
|
|
|
|
|
+uniform mat4x4 invViewMat;
|
|
|
|
|
|
uniform vec3 eyePosWorld;
|
|
uniform vec3 eyePosWorld;
|
|
uniform vec3 bbMin;
|
|
uniform vec3 bbMin;
|
|
uniform vec3 bbMax;
|
|
uniform vec3 bbMax;
|
|
|
|
|
|
-uniform float Intensity;
|
|
|
|
-
|
|
|
|
-//SHTerms
|
|
|
|
-uniform vec4 SHTerms0;
|
|
|
|
-uniform vec4 SHTerms1;
|
|
|
|
-uniform vec4 SHTerms2;
|
|
|
|
-uniform vec4 SHTerms3;
|
|
|
|
-uniform vec4 SHTerms4;
|
|
|
|
-uniform vec4 SHTerms5;
|
|
|
|
-uniform vec4 SHTerms6;
|
|
|
|
-uniform vec4 SHTerms7;
|
|
|
|
-uniform vec4 SHTerms8;
|
|
|
|
-
|
|
|
|
-uniform float SHConsts0;
|
|
|
|
-uniform float SHConsts1;
|
|
|
|
-uniform float SHConsts2;
|
|
|
|
-uniform float SHConsts3;
|
|
|
|
-uniform float SHConsts4;
|
|
|
|
-
|
|
|
|
uniform float useSphereMode;
|
|
uniform float useSphereMode;
|
|
|
|
|
|
-vec4 decodeSH(vec3 normal)
|
|
|
|
|
|
+// Box Projected IBL Lighting
|
|
|
|
+// Based on: http://www.gamedev.net/topic/568829-box-projected-cubemap-environment-mapping/
|
|
|
|
+// and https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/
|
|
|
|
+vec3 boxProject(vec3 wsPosition, vec3 reflectDir, vec3 boxWSPos, vec3 boxMin, vec3 boxMax)
|
|
|
|
+{
|
|
|
|
+ vec3 nrdir = reflectDir;
|
|
|
|
+ vec3 offset = wsPosition;
|
|
|
|
+ vec3 plane1vec = (boxMax - offset) / nrdir;
|
|
|
|
+ vec3 plane2vec = (boxMin - offset) / nrdir;
|
|
|
|
+
|
|
|
|
+ vec3 furthestPlane = max(plane1vec, plane2vec);
|
|
|
|
+ float dist = min(min(furthestPlane.x, furthestPlane.y), furthestPlane.z);
|
|
|
|
+ vec3 posonbox = offset + nrdir * dist;
|
|
|
|
+
|
|
|
|
+ return posonbox - boxWSPos;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+vec3 iblBoxDiffuse(vec3 normal,
|
|
|
|
+ vec3 wsPos,
|
|
|
|
+ samplerCube irradianceCube,
|
|
|
|
+ vec3 boxPos,
|
|
|
|
+ vec3 boxMin,
|
|
|
|
+ vec3 boxMax)
|
|
{
|
|
{
|
|
- float x = normal.x;
|
|
|
|
- float y = normal.y;
|
|
|
|
- float z = normal.z;
|
|
|
|
|
|
+ // Irradiance (Diffuse)
|
|
|
|
+ vec3 cubeN = normalize(normal);
|
|
|
|
+ vec3 irradiance = texture(irradianceCube, cubeN).xyz;
|
|
|
|
+
|
|
|
|
+ return irradiance;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+vec3 iblBoxSpecular(vec3 normal,
|
|
|
|
+ vec3 wsPos,
|
|
|
|
+ float roughness,
|
|
|
|
+ vec3 surfToEye,
|
|
|
|
+ sampler2D brdfTexture,
|
|
|
|
+ samplerCube radianceCube,
|
|
|
|
+ vec3 boxPos,
|
|
|
|
+ vec3 boxMin,
|
|
|
|
+ vec3 boxMax)
|
|
|
|
+{
|
|
|
|
+ float ndotv = clamp(dot(normal, surfToEye), 0.0, 1.0);
|
|
|
|
+
|
|
|
|
+ // BRDF
|
|
|
|
+ vec2 brdf = texture(brdfTexture, vec2(roughness, ndotv)).xy;
|
|
|
|
+
|
|
|
|
+ // Radiance (Specular)
|
|
|
|
+ float maxmip = pow(cubeMips+1,2);
|
|
|
|
+ float lod = roughness*maxmip;
|
|
|
|
+ vec3 r = reflect(surfToEye, normal);
|
|
|
|
+ vec3 cubeR = normalize(r);
|
|
|
|
+ cubeR = boxProject(wsPos, cubeR, boxPos, boxMin, boxMax);
|
|
|
|
+
|
|
|
|
+ vec3 radiance = textureLod(radianceCube, cubeR, lod).xyz * (brdf.x + brdf.y);
|
|
|
|
+
|
|
|
|
+ return radiance;
|
|
|
|
+}
|
|
|
|
|
|
- vec3 l00 = SHTerms0.rgb;
|
|
|
|
|
|
+float defineSphereSpaceInfluence(vec3 centroidPosVS, float rad, vec2 atten, vec3 surfPosVS, vec3 norm)
|
|
|
|
+{
|
|
|
|
+ // Build light vec, get length, clip pixel if needed
|
|
|
|
+ vec3 lightVec = centroidPosVS - surfPosVS;
|
|
|
|
+ float lenLightV = length( lightVec );
|
|
|
|
+ if (( rad - lenLightV )<0)
|
|
|
|
+ return -1;
|
|
|
|
|
|
- vec3 l10 = SHTerms1.rgb;
|
|
|
|
- vec3 l11 = SHTerms2.rgb;
|
|
|
|
- vec3 l12 = SHTerms3.rgb;
|
|
|
|
|
|
+ // Get the attenuated falloff.
|
|
|
|
+ float attn = attenuate( vec4(1,1,1,1), atten, lenLightV );
|
|
|
|
+ if ((attn - 1e-6)<0)
|
|
|
|
+ return -1;
|
|
|
|
|
|
- vec3 l20 = SHTerms4.rgb;
|
|
|
|
- vec3 l21 = SHTerms5.rgb;
|
|
|
|
- vec3 l22 = SHTerms6.rgb;
|
|
|
|
- vec3 l23 = SHTerms7.rgb;
|
|
|
|
- vec3 l24 = SHTerms8.rgb;
|
|
|
|
|
|
+ // Normalize lightVec
|
|
|
|
+ lightVec = lightVec /= lenLightV;
|
|
|
|
|
|
- vec3 result = (
|
|
|
|
- l00 * SHConsts0 +
|
|
|
|
|
|
+ // If we can do dynamic branching then avoid wasting
|
|
|
|
+ // fillrate on pixels that are backfacing to the light.
|
|
|
|
+ float nDotL = abs(dot( lightVec, norm ));
|
|
|
|
|
|
- l12 * SHConsts1 * x +
|
|
|
|
- l10 * SHConsts1 * y +
|
|
|
|
- l11 * SHConsts1 * z +
|
|
|
|
|
|
+ return saturate( nDotL * attn );
|
|
|
|
+}
|
|
|
|
|
|
- l20 * SHConsts2 * x*y +
|
|
|
|
- l21 * SHConsts2 * y*z +
|
|
|
|
- l22 * SHConsts3 * (3.0*z*z - 1.0) +
|
|
|
|
- l23 * SHConsts2 * x*z +
|
|
|
|
- l24 * SHConsts4 * (x*x - y*y)
|
|
|
|
- );
|
|
|
|
|
|
+float defineBoxSpaceInfluence(vec3 surfPosWS, vec3 probePos, float rad, vec2 atten) //atten currently unused
|
|
|
|
+{
|
|
|
|
+ vec3 boxMin = probePos-(vec3(0.5,0.5,0.5)*rad);
|
|
|
|
+ vec3 boxMax = probePos+(vec3(0.5,0.5,0.5)*rad);
|
|
|
|
+ //Try to clip anything that falls outside our box as well
|
|
|
|
+ //TODO: Make it support rotated boxes as well
|
|
|
|
+ if(surfPosWS.x > boxMax.x || surfPosWS.y > boxMax.y || surfPosWS.z > boxMax.z ||
|
|
|
|
+ surfPosWS.x < boxMin.x || surfPosWS.y < boxMin.y || surfPosWS.z < boxMin.z)
|
|
|
|
+ return -1;
|
|
|
|
+
|
|
|
|
+ float blendVal = 1;
|
|
|
|
+ //vec3 atten = min(boxMax-surfPosWS,surfPosWS-boxMin);
|
|
|
|
+ //blendVal = min(min(atten.x,atten.y),atten.z);
|
|
|
|
+ return blendVal;
|
|
|
|
+}
|
|
|
|
|
|
- return vec4(result,1);
|
|
|
|
|
|
+float defineDepthInfluence(vec3 probePosWS, vec3 surfPosWS, samplerCube radianceCube)
|
|
|
|
+{
|
|
|
|
+ //TODO properly: filter out pixels projected uppon by probes behind walls by looking up the depth stored in the probes cubemap alpha
|
|
|
|
+ //and comparing legths
|
|
|
|
+ vec3 probeToSurf = probePosWS-surfPosWS;
|
|
|
|
+
|
|
|
|
+ float depthRef = texture(cubeMap, -probeToSurf,0).a*radius;
|
|
|
|
+ float dist = length( probeToSurf );
|
|
|
|
+
|
|
|
|
+ return depthRef-dist;
|
|
}
|
|
}
|
|
|
|
|
|
out vec4 OUT_col;
|
|
out vec4 OUT_col;
|
|
|
|
+out vec4 OUT_col1;
|
|
|
|
+
|
|
void main()
|
|
void main()
|
|
-{
|
|
|
|
|
|
+{
|
|
|
|
+
|
|
// Compute scene UV
|
|
// Compute scene UV
|
|
vec3 ssPos = ssPos.xyz / ssPos.w;
|
|
vec3 ssPos = ssPos.xyz / ssPos.w;
|
|
|
|
|
|
- //vec4 hardCodedRTParams0 = vec4(0,0.0277777780,1,0.972222209);
|
|
|
|
vec2 uvScene = getUVFromSSPos( ssPos, rtParams0 );
|
|
vec2 uvScene = getUVFromSSPos( ssPos, rtParams0 );
|
|
|
|
|
|
// Matinfo flags
|
|
// Matinfo flags
|
|
@@ -104,15 +164,15 @@ void main()
|
|
vec3 normal = deferredSample.rgb;
|
|
vec3 normal = deferredSample.rgb;
|
|
float depth = deferredSample.a;
|
|
float depth = deferredSample.a;
|
|
if (depth>0.9999)
|
|
if (depth>0.9999)
|
|
- OUT_col = vec4(0,0,0,0);
|
|
|
|
|
|
+ {
|
|
|
|
+ OUT_col = vec4(0.0);
|
|
|
|
+ OUT_col1 = vec4(0.0);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
|
|
// Need world-space normal.
|
|
// Need world-space normal.
|
|
vec3 wsNormal = tMul(vec4(normal, 1), invViewMat).rgb;
|
|
vec3 wsNormal = tMul(vec4(normal, 1), invViewMat).rgb;
|
|
|
|
|
|
- vec4 color = vec4(1, 1, 1, 1);
|
|
|
|
- vec4 ref = vec4(0,0,0,0);
|
|
|
|
- float alpha = 0;
|
|
|
|
-
|
|
|
|
vec3 eyeRay = getDistanceVectorToPlane( -vsFarPlane.w, vsEyeDir.xyz, vsFarPlane );
|
|
vec3 eyeRay = getDistanceVectorToPlane( -vsFarPlane.w, vsEyeDir.xyz, vsFarPlane );
|
|
vec3 viewSpacePos = eyeRay * depth;
|
|
vec3 viewSpacePos = eyeRay * depth;
|
|
|
|
|
|
@@ -120,110 +180,31 @@ void main()
|
|
|
|
|
|
// Use eye ray to get ws pos
|
|
// Use eye ray to get ws pos
|
|
vec3 worldPos = vec3(eyePosWorld + wsEyeRay * depth);
|
|
vec3 worldPos = vec3(eyePosWorld + wsEyeRay * depth);
|
|
- float smoothness = min((1.0 - matInfo.b)*11.0 + 1.0, 8.0);//bump up to 8 for finalization
|
|
|
|
-
|
|
|
|
- if(useSphereMode>0.0)
|
|
|
|
- {
|
|
|
|
- // Eye ray - Eye -> Pixel
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- // Build light vec, get length, clip pixel if needed
|
|
|
|
- vec3 lightVec = probeLSPos - viewSpacePos;
|
|
|
|
- float lenLightV = length( lightVec );
|
|
|
|
- clip( lightRange - lenLightV );
|
|
|
|
-
|
|
|
|
- // Get the attenuated falloff.
|
|
|
|
- float atten = attenuate( vec4(1,1,1,1), lightAttenuation, lenLightV );
|
|
|
|
- clip( atten - 1e-6 );
|
|
|
|
-
|
|
|
|
- // Normalize lightVec
|
|
|
|
- lightVec /= lenLightV;
|
|
|
|
-
|
|
|
|
- // If we can do dynamic branching then avoid wasting
|
|
|
|
- // fillrate on pixels that are backfacing to the light.
|
|
|
|
- float nDotL = abs(dot( lightVec, normal ));
|
|
|
|
-
|
|
|
|
- float Sat_NL_Att = saturate( nDotL * atten );
|
|
|
|
-
|
|
|
|
- vec3 reflectionVec = reflect(wsEyeDir, vec4(wsNormal,nDotL)).xyz;
|
|
|
|
-
|
|
|
|
- vec3 nrdir = normalize(reflectionVec);
|
|
|
|
- vec3 rbmax = (bbMax - worldPos.xyz) / nrdir;
|
|
|
|
- vec3 rbmin = (bbMin - worldPos.xyz) / nrdir;
|
|
|
|
-
|
|
|
|
- vec3 rbminmax = rbmin;
|
|
|
|
- if (nrdir.x > 0.0)
|
|
|
|
- rbminmax.x = rbmax.x;
|
|
|
|
- if (nrdir.y > 0.0)
|
|
|
|
- rbminmax.y = rbmax.y;
|
|
|
|
- if (nrdir.z > 0.0)
|
|
|
|
- rbminmax.z = rbmax.z;
|
|
|
|
|
|
|
|
- float fa = min(min(rbminmax.x,rbminmax.y),rbminmax.z);
|
|
|
|
- if (dot( lightVec, normal )<0.0f)
|
|
|
|
- clip(fa);
|
|
|
|
-
|
|
|
|
- vec3 posOnBox = worldPos.xyz + nrdir * fa;
|
|
|
|
- reflectionVec = posOnBox - probeWSPos;
|
|
|
|
-
|
|
|
|
- //reflectionVec = tMul(probeWSPos,reflectionVec);
|
|
|
|
-
|
|
|
|
- ref = vec4(reflectionVec, smoothness);
|
|
|
|
-
|
|
|
|
- alpha = Sat_NL_Att;
|
|
|
|
|
|
+ float blendVal = 1.0;
|
|
|
|
+
|
|
|
|
+ //clip bounds and (TODO properly: set falloff)
|
|
|
|
+ if(useSphereMode>0)
|
|
|
|
+ {
|
|
|
|
+ blendVal = defineSphereSpaceInfluence(probeLSPos, radius, attenuation, viewSpacePos, normal);
|
|
}
|
|
}
|
|
else
|
|
else
|
|
{
|
|
{
|
|
- // Build light vec, get length, clip pixel if needed
|
|
|
|
- vec3 lightVec = probeLSPos - viewSpacePos;
|
|
|
|
- float lenLightV = length(lightVec);
|
|
|
|
- //clip(lightRange - lenLightV);
|
|
|
|
-
|
|
|
|
- // Normalize lightVec
|
|
|
|
- lightVec /= lenLightV;
|
|
|
|
-
|
|
|
|
- // If we can do dynamic branching then avoid wasting
|
|
|
|
- // fillrate on pixels that are backfacing to the light.
|
|
|
|
- float nDotL = abs(dot(lightVec, normal));
|
|
|
|
-
|
|
|
|
- vec3 reflectionVec = reflect(wsEyeDir, vec4(wsNormal, nDotL)).xyz;
|
|
|
|
-
|
|
|
|
- vec3 nrdir = normalize(reflectionVec);
|
|
|
|
- vec3 rbmax = (bbMax - worldPos.xyz) / nrdir;
|
|
|
|
- vec3 rbmin = (bbMin - worldPos.xyz) / nrdir;
|
|
|
|
-
|
|
|
|
- vec3 rbminmax = rbmin;
|
|
|
|
- if (nrdir.x > 0.0)
|
|
|
|
- rbminmax.x = rbmax.x;
|
|
|
|
- if (nrdir.y > 0.0)
|
|
|
|
- rbminmax.y = rbmax.y;
|
|
|
|
- if (nrdir.z > 0.0)
|
|
|
|
- rbminmax.z = rbmax.z;
|
|
|
|
-
|
|
|
|
- float fa = min(min(rbminmax.x, rbminmax.y), rbminmax.z);
|
|
|
|
- if (dot(lightVec, normal)<0.0f)
|
|
|
|
- clip(fa);
|
|
|
|
-
|
|
|
|
- //Try to clip anything that falls outside our box as well
|
|
|
|
- //TODO: Make it support rotated boxes as well
|
|
|
|
- if(worldPos.x > bbMax.x || worldPos.y > bbMax.y || worldPos.z > bbMax.z ||
|
|
|
|
- worldPos.x < bbMin.x || worldPos.y < bbMin.y || worldPos.z < bbMin.z)
|
|
|
|
- clip(-1);
|
|
|
|
-
|
|
|
|
- vec3 posOnBox = worldPos.xyz + nrdir * fa;
|
|
|
|
- reflectionVec = posOnBox - probeWSPos;
|
|
|
|
-
|
|
|
|
- ref = vec4(reflectionVec, smoothness);
|
|
|
|
-
|
|
|
|
- alpha = 1;
|
|
|
|
|
|
+ blendVal = defineBoxSpaceInfluence(worldPos, probeWSPos, radius*2, attenuation);
|
|
}
|
|
}
|
|
-
|
|
|
|
- color = textureLod(cubeMap, vec3(ref.xyz), float(ref.w));
|
|
|
|
-
|
|
|
|
- vec4 specularColor = (color);
|
|
|
|
- vec4 indirectColor = (decodeSH(wsNormal));
|
|
|
|
-
|
|
|
|
- color.rgb = lerp(indirectColor.rgb * 1.5, specularColor.rgb * 1.5, matInfo.b);
|
|
|
|
-
|
|
|
|
- OUT_col = vec4(color.rgb, alpha);
|
|
|
|
|
|
+ if (blendVal<0)
|
|
|
|
+ {
|
|
|
|
+ OUT_col = vec4(0.0);
|
|
|
|
+ OUT_col1 = vec4(0.0);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ //flip me on to have probes filter by depth
|
|
|
|
+ //clip(defineDepthInfluence(probeWSPos, worldPos, cubeMap));
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ //render into the bound space defined above
|
|
|
|
+ vec3 surfToEye = normalize(worldPos.xyz-eyePosWorld.xyz);
|
|
|
|
+ OUT_col = vec4(iblBoxDiffuse(wsNormal, worldPos, irradianceCubemap, probeWSPos, bbMin, bbMax), blendVal);
|
|
|
|
+ OUT_col1 = vec4(iblBoxSpecular(wsNormal, worldPos, 1.0 - matInfo.b, surfToEye, BRDFTexture, cubeMap, probeWSPos, bbMin, bbMax), blendVal);
|
|
}
|
|
}
|