|
@@ -26,15 +26,20 @@ uniform float4 inProbePosArray[MAX_PROBES];
|
|
uniform float4x4 worldToObjArray[MAX_PROBES];
|
|
uniform float4x4 worldToObjArray[MAX_PROBES];
|
|
uniform float4 bbMinArray[MAX_PROBES];
|
|
uniform float4 bbMinArray[MAX_PROBES];
|
|
uniform float4 bbMaxArray[MAX_PROBES];
|
|
uniform float4 bbMaxArray[MAX_PROBES];
|
|
-uniform float4 useSphereMode[MAX_PROBES];
|
|
|
|
-uniform float4 radius[MAX_PROBES];
|
|
|
|
-uniform float4 attenuation[MAX_PROBES];
|
|
|
|
|
|
+uniform float4 probeConfigData[MAX_PROBES]; //r,g,b/mode,radius,atten
|
|
|
|
+
|
|
|
|
+#if DEBUGVIZ_CONTRIB
|
|
|
|
+uniform float4 probeContribColors[MAX_PROBES];
|
|
|
|
+#endif
|
|
|
|
|
|
// Box Projected IBL Lighting
|
|
// Box Projected IBL Lighting
|
|
// Based on: http://www.gamedev.net/topic/568829-box-projected-cubemap-environment-mapping/
|
|
// 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/
|
|
// and https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/
|
|
-float3 boxProject(float3 wsPosition, float3 reflectDir, float3 boxWSPos, float3 boxMin, float3 boxMax)
|
|
|
|
|
|
+float3 boxProject(float3 wsPosition, float3 wsEyeRay, float3 reflectDir, float3 boxWSPos, float3 boxMin, float3 boxMax)
|
|
{
|
|
{
|
|
|
|
+ //float3 rayLS = mul(worldToObjArray[id], float4(wsEyeRay, 1.0)).xyz;
|
|
|
|
+ //float3 reflCameraLS = mul(worldToObjArray[id], float4(reflectDir), 1.0)).xyz;
|
|
|
|
+
|
|
float3 nrdir = reflectDir;
|
|
float3 nrdir = reflectDir;
|
|
float3 offset = wsPosition;
|
|
float3 offset = wsPosition;
|
|
float3 plane1vec = (boxMax - offset) / nrdir;
|
|
float3 plane1vec = (boxMax - offset) / nrdir;
|
|
@@ -49,23 +54,19 @@ float3 boxProject(float3 wsPosition, float3 reflectDir, float3 boxWSPos, float3
|
|
|
|
|
|
float3 iblBoxDiffuse( Surface surface, int id)
|
|
float3 iblBoxDiffuse( Surface surface, int id)
|
|
{
|
|
{
|
|
- float3 cubeN = boxProject(surface.P, surface.N, inProbePosArray[id].xyz, bbMinArray[id].xyz, bbMaxArray[id].xyz);
|
|
|
|
|
|
+ float3 cubeN = boxProject(surface.P, surface.V, surface.R, inProbePosArray[id].xyz, bbMinArray[id].xyz, bbMaxArray[id].xyz);
|
|
cubeN.z *=-1;
|
|
cubeN.z *=-1;
|
|
return TORQUE_TEXCUBEARRAYLOD(irradianceCubemapAR,cubeN,id,0).xyz;
|
|
return TORQUE_TEXCUBEARRAYLOD(irradianceCubemapAR,cubeN,id,0).xyz;
|
|
}
|
|
}
|
|
|
|
|
|
-float3 iblBoxSpecular(Surface surface, float3 surfToEye, TORQUE_SAMPLER2D(brdfTexture), int id)
|
|
|
|
|
|
+float3 iblBoxSpecular(Surface surface, TORQUE_SAMPLER2D(brdfTexture), int id)
|
|
{
|
|
{
|
|
- float ndotv = clamp(dot(surface.N, surfToEye), 0.0, 1.0);
|
|
|
|
-
|
|
|
|
// BRDF
|
|
// BRDF
|
|
- float2 brdf = TORQUE_TEX2DLOD(brdfTexture, float4(surface.roughness, ndotv,0.0,0.0)).xy;
|
|
|
|
|
|
+ float2 brdf = TORQUE_TEX2DLOD(brdfTexture, float4(surface.roughness, surface.NdotV,0.0,0.0)).xy;
|
|
|
|
|
|
// Radiance (Specular)
|
|
// Radiance (Specular)
|
|
float lod = surface.roughness*cubeMips;
|
|
float lod = surface.roughness*cubeMips;
|
|
- float3 r = reflect(surfToEye, surface.N);
|
|
|
|
- float3 cubeR = normalize(r);
|
|
|
|
- cubeR = boxProject(surface.P, surface.N, inProbePosArray[id].xyz, bbMinArray[id].xyz, bbMaxArray[id].xyz);
|
|
|
|
|
|
+ float3 cubeR = boxProject(surface.P, surface.V, surface.R, inProbePosArray[id].xyz, bbMinArray[id].xyz, bbMaxArray[id].xyz);
|
|
|
|
|
|
float3 radiance = TORQUE_TEXCUBEARRAYLOD(cubeMapAR,cubeR,id,lod).xyz * (brdf.x + brdf.y);
|
|
float3 radiance = TORQUE_TEXCUBEARRAYLOD(cubeMapAR,cubeR,id,lod).xyz * (brdf.x + brdf.y);
|
|
|
|
|
|
@@ -74,14 +75,13 @@ float3 iblBoxSpecular(Surface surface, float3 surfToEye, TORQUE_SAMPLER2D(brdfTe
|
|
|
|
|
|
float defineBoxSpaceInfluence(Surface surface, int id)
|
|
float defineBoxSpaceInfluence(Surface surface, int id)
|
|
{
|
|
{
|
|
- float tempAttenVal = 3.5; //replace with per probe atten
|
|
|
|
float3 surfPosLS = mul( worldToObjArray[id], float4(surface.P,1.0)).xyz;
|
|
float3 surfPosLS = mul( worldToObjArray[id], float4(surface.P,1.0)).xyz;
|
|
|
|
|
|
- float3 boxMinLS = inProbePosArray[id].xyz-(float3(1,1,1)*radius[id].x);
|
|
|
|
- float3 boxMaxLS = inProbePosArray[id].xyz+(float3(1,1,1)*radius[id].x);
|
|
|
|
|
|
+ float3 boxMinLS = inProbePosArray[id].xyz-(float3(1,1,1)*probeConfigData[id].g);
|
|
|
|
+ float3 boxMaxLS = inProbePosArray[id].xyz+(float3(1,1,1)*probeConfigData[id].g);
|
|
|
|
|
|
float boxOuterRange = length(boxMaxLS - boxMinLS);
|
|
float boxOuterRange = length(boxMaxLS - boxMinLS);
|
|
- float boxInnerRange = boxOuterRange / tempAttenVal;
|
|
|
|
|
|
+ float boxInnerRange = boxOuterRange / probeConfigData[id].b;
|
|
|
|
|
|
float3 localDir = float3(abs(surfPosLS.x), abs(surfPosLS.y), abs(surfPosLS.z));
|
|
float3 localDir = float3(abs(surfPosLS.x), abs(surfPosLS.y), abs(surfPosLS.z));
|
|
localDir = (localDir - boxInnerRange) / (boxOuterRange - boxInnerRange);
|
|
localDir = (localDir - boxInnerRange) / (boxOuterRange - boxInnerRange);
|
|
@@ -102,52 +102,47 @@ float4 main( PFXVertToPix IN ) : SV_TARGET
|
|
if (getFlag(surface.matFlag, 0))
|
|
if (getFlag(surface.matFlag, 0))
|
|
{
|
|
{
|
|
discard;
|
|
discard;
|
|
- }
|
|
|
|
-
|
|
|
|
- float blendVal[MAX_PROBES];
|
|
|
|
- float3 surfToEye = normalize(surface.P - eyePosWorld);
|
|
|
|
|
|
+ }
|
|
|
|
|
|
int i = 0;
|
|
int i = 0;
|
|
|
|
+
|
|
|
|
+ float blendVal[MAX_PROBES];
|
|
float blendSum = 0;
|
|
float blendSum = 0;
|
|
float invBlendSum = 0;
|
|
float invBlendSum = 0;
|
|
-
|
|
|
|
- for(i=0; i < numProbes; i++)
|
|
|
|
- {
|
|
|
|
- if(useSphereMode[i].r)
|
|
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < numProbes; i++)
|
|
|
|
+ {
|
|
|
|
+ if (probeConfigData[i].r)
|
|
{
|
|
{
|
|
- float3 L = inProbePosArray[i].xyz - surface.P;
|
|
|
|
- blendVal[i] = 1.0-length(L)/radius[i].r;
|
|
|
|
- blendVal[i] = max(0,blendVal[i]);
|
|
|
|
|
|
+ float3 L = inProbePosArray[i].xyz - surface.P;
|
|
|
|
+ blendVal[i] = 1.0 - length(L) / probeConfigData[i].g;
|
|
|
|
+ blendVal[i] = max(0, blendVal[i]);
|
|
}
|
|
}
|
|
else
|
|
else
|
|
{
|
|
{
|
|
- blendVal[i] = defineBoxSpaceInfluence(surface, i);
|
|
|
|
- blendVal[i] = max(0,blendVal[i]);
|
|
|
|
|
|
+ blendVal[i] = defineBoxSpaceInfluence(surface, i);
|
|
|
|
+ blendVal[i] = max(0, blendVal[i]);
|
|
}
|
|
}
|
|
- blendSum += blendVal[i];
|
|
|
|
- invBlendSum +=(1.0f - blendVal[i]);
|
|
|
|
|
|
+ blendSum += blendVal[i];
|
|
|
|
+ invBlendSum += (1.0f - blendVal[i]);
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
// Weight0 = normalized NDF, inverted to have 1 at center, 0 at boundary.
|
|
// Weight0 = normalized NDF, inverted to have 1 at center, 0 at boundary.
|
|
// And as we invert, we need to divide by Num-1 to stay normalized (else sum is > 1).
|
|
// And as we invert, we need to divide by Num-1 to stay normalized (else sum is > 1).
|
|
// respect constraint B.
|
|
// respect constraint B.
|
|
// Weight1 = normalized inverted NDF, so we have 1 at center, 0 at boundary
|
|
// Weight1 = normalized inverted NDF, so we have 1 at center, 0 at boundary
|
|
// and respect constraint A.
|
|
// and respect constraint A.
|
|
- for(i=0; i < numProbes; i++)
|
|
|
|
|
|
+
|
|
|
|
+ //This is what's cross-contaminating between probe's influence areas.
|
|
|
|
+ //Need to review this logic before we utilize it again
|
|
|
|
+ /*for (i = 0; i < numProbes; i++)
|
|
{
|
|
{
|
|
- blendVal[i] = (1.0f - ( blendVal[i] / blendSum)) / (numProbes - 1);
|
|
|
|
|
|
+ blendVal[i] = (1.0f - (blendVal[i] / blendSum)) / (numProbes - 1);
|
|
blendVal[i] *= ((1.0f - blendVal[i]) / invBlendSum);
|
|
blendVal[i] *= ((1.0f - blendVal[i]) / invBlendSum);
|
|
blendSum += blendVal[i];
|
|
blendSum += blendVal[i];
|
|
- }
|
|
|
|
|
|
+ }*/
|
|
|
|
|
|
- float finalSum = blendSum;
|
|
|
|
-
|
|
|
|
- //return TORQUE_TEX2D(colorBuffer, IN.uv0.xy);
|
|
|
|
- //return float4(surface.N,1);
|
|
|
|
- //return float4(1,1,1, 1);
|
|
|
|
- //return float4(finalSum,finalSum,finalSum, 1);
|
|
|
|
-
|
|
|
|
- // Normalize blendVal
|
|
|
|
|
|
+ // Normalize blendVal
|
|
if (blendSum == 0.0f) // Possible with custom weight
|
|
if (blendSum == 0.0f) // Possible with custom weight
|
|
{
|
|
{
|
|
blendSum = 1.0f;
|
|
blendSum = 1.0f;
|
|
@@ -158,6 +153,28 @@ float4 main( PFXVertToPix IN ) : SV_TARGET
|
|
{
|
|
{
|
|
blendVal[i] *= invBlendSumWeighted;
|
|
blendVal[i] *= invBlendSumWeighted;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ //return float4(blendVal[0], blendVal[0], blendVal[0], 1);
|
|
|
|
+
|
|
|
|
+#if DEBUGVIZ_ATTENUATION == 1
|
|
|
|
+ return float4(blendSum, blendSum, blendSum, 1);
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+#if DEBUGVIZ_CONTRIB == 1
|
|
|
|
+
|
|
|
|
+ float3 finalContribColor = float3(0, 0, 0);
|
|
|
|
+ for (i = 0; i < numProbes; ++i)
|
|
|
|
+ {
|
|
|
|
+ if (blendVal[i] == 0)
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ finalContribColor += blendSum * probeContribColors[i].rgb;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return float4(finalContribColor, 1);
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+#if DEBUGVIZ_SPECCUBEMAP == 0 && DEBUGVIZ_DIFFCUBEMAP == 0
|
|
|
|
|
|
float3 irradiance = float3(0,0,0);
|
|
float3 irradiance = float3(0,0,0);
|
|
float3 specular = float3(0,0,0);
|
|
float3 specular = float3(0,0,0);
|
|
@@ -168,13 +185,35 @@ float4 main( PFXVertToPix IN ) : SV_TARGET
|
|
kD *= 1.0 - surface.metalness;
|
|
kD *= 1.0 - surface.metalness;
|
|
for (i = 0; i < numProbes; ++i)
|
|
for (i = 0; i < numProbes; ++i)
|
|
{
|
|
{
|
|
- irradiance += blendVal[i]*iblBoxDiffuse(surface,i);
|
|
|
|
|
|
+ if (blendVal[i] == 0)
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ irradiance += blendVal[i]*iblBoxDiffuse(surface, i);
|
|
|
|
|
|
- specular += blendVal[i]*F*iblBoxSpecular(surface, surfToEye, TORQUE_SAMPLER2D_MAKEARG(BRDFTexture),i);
|
|
|
|
|
|
+ specular += blendVal[i]*F*iblBoxSpecular(surface, TORQUE_SAMPLER2D_MAKEARG(BRDFTexture),i);
|
|
}
|
|
}
|
|
|
|
+
|
|
//final diffuse color
|
|
//final diffuse color
|
|
float3 diffuse = kD * irradiance * surface.baseColor.rgb;
|
|
float3 diffuse = kD * irradiance * surface.baseColor.rgb;
|
|
float4 finalColor = float4(diffuse + specular * surface.ao, blendSum);
|
|
float4 finalColor = float4(diffuse + specular * surface.ao, blendSum);
|
|
|
|
|
|
return finalColor;
|
|
return finalColor;
|
|
|
|
+
|
|
|
|
+#elif DEBUGVIZ_SPECCUBEMAP == 1 && DEBUGVIZ_DIFFCUBEMAP == 0
|
|
|
|
+ float3 cubeColor = float3(0, 0, 0);
|
|
|
|
+ for (i = 0; i < numProbes; ++i)
|
|
|
|
+ {
|
|
|
|
+ cubeColor += blendVal[i] * iblBoxSpecular(surface, TORQUE_SAMPLER2D_MAKEARG(BRDFTexture), i);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return float4(cubeColor,1);
|
|
|
|
+#elif DEBUGVIZ_DIFFCUBEMAP == 1
|
|
|
|
+ float3 cubeColor = float3(0, 0, 0);
|
|
|
|
+ for (i = 0; i < numProbes; ++i)
|
|
|
|
+ {
|
|
|
|
+ cubeColor += blendVal[i] * iblBoxDiffuse(surface, i);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return float4(cubeColor, 1);
|
|
|
|
+#endif
|
|
}
|
|
}
|