Browse Source

WIP of the rewrite of blend/projection to follow BSF's math approach.

Areloch 6 năm trước cách đây
mục cha
commit
2903aaeea0

+ 9 - 1
Engine/source/renderInstance/renderProbeMgr.cpp

@@ -655,7 +655,15 @@ void RenderProbeMgr::render( SceneRenderState *state )
 
 
          for (U32 i = 0; i < mEffectiveProbeCount; i++)
          for (U32 i = 0; i < mEffectiveProbeCount; i++)
          {
          {
-            contribColors[i] = Point4F(RandomGen.randF(0, 1), RandomGen.randF(0, 1), RandomGen.randF(0, 1),1);
+            //we're going to cheat here a little for consistent debugging behavior. The first 3 probes will always have R G and then B for their colors, every other will be random
+            if (i == 0)
+               contribColors[i] = Point4F(1, 0, 0, 1);
+            else if (i == 1)
+               contribColors[i] = Point4F(0, 1, 0, 1);
+            else if (i == 2)
+               contribColors[i] = Point4F(0, 0, 1, 1);
+            else
+               contribColors[i] = Point4F(RandomGen.randF(0, 1), RandomGen.randF(0, 1), RandomGen.randF(0, 1),1);
          }
          }
 
 
          mProbeArrayEffect->setShaderConst("$probeContribColors", contribColors);
          mProbeArrayEffect->setShaderConst("$probeContribColors", contribColors);

+ 117 - 105
Templates/Full/game/shaders/common/lighting/advanced/reflectionProbeArrayP.hlsl

@@ -33,11 +33,25 @@ uniform float4    probeConfigData[MAX_PROBES];   //r,g,b/mode,radius,atten
 uniform float4    probeContribColors[MAX_PROBES];
 uniform float4    probeContribColors[MAX_PROBES];
 #endif
 #endif
 
 
+struct ProbeData
+{
+   float3 wsPosition;
+   float radius;
+   float3 boxExtents;
+   float attenuation;
+   float4x4 worldToLocal;
+   uint cubemapIdx;
+   uint type; //box = 0, sphere = 1
+   float contribution;
+   float pad;
+};
+
 // 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 wsEyeRay, float3 reflectDir, float3 boxWSPos, float3 boxMin, float3 boxMax)
+/*float3 boxProject(float3 wsPosition, float3 wsEyeRay, float3 reflectDir, float3 boxWSPos, float3 boxMin, float3 boxMax)
 { 
 { 
+   float3 positionLS = mul(worldToObjArray[id], float4(wsEyeRay, 1.0)).xyz;
    //float3 rayLS = mul(worldToObjArray[id], float4(wsEyeRay, 1.0)).xyz;
    //float3 rayLS = mul(worldToObjArray[id], float4(wsEyeRay, 1.0)).xyz;
    //float3 reflCameraLS = mul(worldToObjArray[id], float4(reflectDir), 1.0)).xyz;
    //float3 reflCameraLS = mul(worldToObjArray[id], float4(reflectDir), 1.0)).xyz;
 
 
@@ -51,18 +65,54 @@ float3 boxProject(float3 wsPosition, float3 wsEyeRay, float3 reflectDir, float3
    float3 posonbox = offset + nrdir * dist;
    float3 posonbox = offset + nrdir * dist;
 
 
    return posonbox - boxWSPos;
    return posonbox - boxWSPos;
+}*/
+
+float3 defineSphereSpaceInfluence(Surface surface, ProbeData probe, float3 wsEyeRay, out float contribution)
+{
+   contribution = 0;
+   return float3(0, 0, 0);
+}
+
+float3 defineBoxSpaceInfluence(Surface surface, ProbeData probe, float3 wsEyeRay, out float contribution)
+{
+   float3 lsPos = mul(probe.worldToLocal, float4(surface.P, 1.0)).xyz;
+   float3 lsDir = mul(probe.worldToLocal, float4(wsEyeRay, 0)).xyz;
+
+   float3 lsInvDir = float3(1 / lsDir.x, 1 / lsDir.y, 1 / lsDir.z);
+
+   float3 intersectsMax = lsInvDir - lsPos * lsInvDir;
+   float3 intersectsMin = -lsInvDir - lsPos * lsInvDir;
+
+   float3 positiveIntersections = max(intersectsMax, intersectsMin);
+   float intersectDist = min(positiveIntersections.x, min(positiveIntersections.y, positiveIntersections.z));
+
+   float3 wsIntersectPosition = surface.P + intersectDist * wsEyeRay;
+   float3 lookupDir = wsIntersectPosition - probe.wsPosition;
+
+   float3 reducedExtents = probe.boxExtents - float3(probe.attenuation, probe.attenuation, probe.attenuation);
+
+   float distToBox = length(max(max(-reducedExtents - (lsPos * probe.boxExtents), 0), (lsPos * probe.boxExtents) - reducedExtents));
+
+   float normalizedDistance = distToBox / 50; //50 is a random BS number. was probe.attenuation
+
+   float t = saturate(3.3333 - 3.3333 * normalizedDistance);
+   contribution = t * t * (3.0 - 2.0 * t);
+
+   return lookupDir;
 }
 }
 
 
-float3 iblBoxDiffuse( Surface surface, int id)
+float4 iblBoxDiffuse( Surface surface, ProbeData probe, float3 dir)
 {
 {
-   float3 cubeN = boxProject(surface.P, surface.V, surface.R, inRefPosArray[id].xyz, bbMinArray[id].xyz, bbMaxArray[id].xyz);
-   return TORQUE_TEXCUBEARRAYLOD(irradianceCubemapAR,cubeN,id,surface.roughness*cubeMips).xyz;
+   float lod = surface.roughness*cubeMips;
+   float3 color = TORQUE_TEXCUBEARRAYLOD(irradianceCubemapAR, dir, probe.cubemapIdx, lod).xyz;
+
+   return float4(color * probe.contribution, ceil(probe.contribution));
 }
 }
 
 
-float3 iblBoxSpecular(Surface surface, TORQUE_SAMPLER2D(brdfTexture), int id)
+float4 iblBoxSpecular(Surface surface, ProbeData probe, float3 dir)
 {
 {
     // BRDF
     // BRDF
-   float2 brdf = TORQUE_TEX2DLOD(brdfTexture, float4(surface.roughness, surface.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)
 #if DEBUGVIZ_SPECCUBEMAP == 0
 #if DEBUGVIZ_SPECCUBEMAP == 0
@@ -71,27 +121,9 @@ float3 iblBoxSpecular(Surface surface, TORQUE_SAMPLER2D(brdfTexture), int id)
    float lod = 0;
    float lod = 0;
 #endif
 #endif
 
 
-   float3 cubeR = boxProject(surface.P, surface.V, surface.R, inRefPosArray[id].xyz, bbMinArray[id].xyz, bbMaxArray[id].xyz);
+   float3 color = TORQUE_TEXCUBEARRAYLOD(cubeMapAR, dir, probe.cubemapIdx, lod).xyz * (brdf.x + brdf.y);
 
 
-   float3 radiance = TORQUE_TEXCUBEARRAYLOD(cubeMapAR,cubeR,id,lod).xyz * (brdf.x + brdf.y);
-    
-   return radiance;
-}
-
-float defineBoxSpaceInfluence(Surface surface, int id)
-{
-    float3 surfPosLS = mul( worldToObjArray[id], float4(surface.P,1.0)).xyz;
-
-    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 boxInnerRange = boxOuterRange / probeConfigData[id].b;
-
-    float3 localDir = float3(abs(surfPosLS.x), abs(surfPosLS.y), abs(surfPosLS.z));
-    localDir = (localDir - boxInnerRange) / (boxOuterRange - boxInnerRange);
-
-    return max(localDir.x, max(localDir.y, localDir.z)) * -1;
+   return float4(color * probe.contribution, 1);
 }
 }
 
 
 float4 main( PFXVertToPix IN ) : SV_TARGET
 float4 main( PFXVertToPix IN ) : SV_TARGET
@@ -111,67 +143,65 @@ float4 main( PFXVertToPix IN ) : SV_TARGET
 
 
    int i = 0;
    int i = 0;
 
 
-   float blendVal[MAX_PROBES];
-   float blendFactor[MAX_PROBES];
-   float blendSum = 0;
-   float blendFacSum = 0;
-   float invBlendSum = 0;
+   float3 F = FresnelSchlickRoughness(surface.NdotV, surface.f0, surface.roughness);
 
 
-   for (i = 0; i < numProbes; i++)
-   {
-      if (probeConfigData[i].r)
-      {
-         float3 L = inProbePosArray[i].xyz - surface.P;
-         blendVal[i] = 1.0 - length(L) / probeConfigData[i].g;
-      }
-      else
-      {
-         blendVal[i] = defineBoxSpaceInfluence(surface, i);
-      }
-      blendVal[i] = saturate(blendVal[i]);
-      blendSum += blendVal[i];
-      invBlendSum += (1.0f - blendVal[i]);
-   }
+   //energy conservation
+   float3 kD = 1.0.xxx - F;
+   kD *= 1.0 - surface.metalness;
 
 
-   // 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). 
-   // respect constraint B.
-   // Weight1 = normalized inverted NDF, so we have 1 at center, 0 at boundary
-   // and respect constraint A.
+   float4 irradiance = float4(0, 0, 0, 0);
+   float4 specular = float4(0, 0, 0, 0);
 
 
-   for (i = 0; i < numProbes; i++)
-   {
-      if (numProbes>1)
-      {
-         blendFactor[i] = ((1.0f -blendVal[i] / blendSum)) / (numProbes - 1);
-         blendFactor[i] *= ((1.0f -blendVal[i]) / invBlendSum);
-         blendFacSum += blendFactor[i];
-      }
-      else
-      {
-         blendFactor[i] = blendVal[i];
-         blendFacSum = blendVal[i];
-      }
-   }
+   float contributingProbeCount = 1;
 
 
-   // Normalize blendVal
-#if DEBUGVIZ_ATTENUATION == 0 //this can likely be removed when we fix the above normalization behavior
-   if (blendFacSum == 0.0f) // Possible with custom weight
-   {
-      blendFacSum = 1.0f;
-   }
+   float contribSum = 0;
+
+#if DEBUGVIZ_CONTRIB == 1
+   float contribVal[MAX_PROBES];
 #endif
 #endif
 
 
-   float invBlendSumWeighted = 1.0f / blendFacSum;
+   //Process prooooobes
    for (i = 0; i < numProbes; ++i)
    for (i = 0; i < numProbes; ++i)
    {
    {
-      blendFactor[i] *= invBlendSumWeighted;
+      ProbeData probe;
+
+      probe.wsPosition = inProbePosArray[i].xyz;
+      probe.radius = probeConfigData[i].g;
+      probe.boxExtents = length(bbMaxArray[i].xyz - bbMinArray[i].xyz);
+      probe.attenuation = probeConfigData[i].b;
+      probe.worldToLocal = worldToObjArray[i];
+      probe.cubemapIdx = i;
+      probe.type = probeConfigData[i].r;
+      probe.contribution = 0;
+
+      if (probe.type == 0) //box
+      {
+         float3 reflDir = defineBoxSpaceInfluence(surface, probe, IN.wsEyeRay, probe.contribution);
+
+         float4 irr = iblBoxDiffuse(surface, probe, reflDir);
+
+         float3 spec = iblBoxSpecular(surface, probe, reflDir).rgb * F;
+
+         irradiance += irr;
+         specular += float4(spec,1);
+
+         contributingProbeCount += irr.a; //if we have any contribution to this pixel, our a should be at a 1, which we'll ultimately utilize to average the total
+
+         contribSum += probe.contribution;
+
+#if DEBUGVIZ_CONTRIB == 1
+         contribVal[i] = probe.contribution;
+#endif
+      }
    }
    }
 
 
-   //return float4(blendFactor[0], blendFactor[0], blendFactor[0], 1);
+   //Average these bad boys out
+   //irradiance /= contributingProbeCount;
+   //specular /= contributingProbeCount;
+
    
    
 #if DEBUGVIZ_ATTENUATION == 1
 #if DEBUGVIZ_ATTENUATION == 1
-   return float4(blendFacSum, blendFacSum, blendFacSum, 1);
+   return float4(contribSum, contribSum, contribSum, 1);
 #endif
 #endif
 
 
 #if DEBUGVIZ_CONTRIB == 1
 #if DEBUGVIZ_CONTRIB == 1
@@ -179,10 +209,10 @@ float4 main( PFXVertToPix IN ) : SV_TARGET
    float3 finalContribColor = float3(0, 0, 0);
    float3 finalContribColor = float3(0, 0, 0);
    for (i = 0; i < numProbes; ++i)
    for (i = 0; i < numProbes; ++i)
    {
    {
-      if (blendFactor[i] == 0)
+      if (contribVal[i] == 0)
          continue;
          continue;
 
 
-      finalContribColor += blendFactor[i] * probeContribColors[i].rgb;
+      finalContribColor += contribVal[i] * probeContribColors[i].rgb;
    }
    }
 
 
    return float4(finalContribColor, 1);
    return float4(finalContribColor, 1);
@@ -190,44 +220,26 @@ float4 main( PFXVertToPix IN ) : SV_TARGET
 
 
 #if DEBUGVIZ_SPECCUBEMAP == 0 && DEBUGVIZ_DIFFCUBEMAP == 0
 #if DEBUGVIZ_SPECCUBEMAP == 0 && DEBUGVIZ_DIFFCUBEMAP == 0
     
     
-   float3 irradiance = float3(0,0,0);
-   float3 specular = float3(0,0,0);
-   float3 F = FresnelSchlickRoughness(surface.NdotV, surface.f0, surface.roughness);
    
    
-   //energy conservation
-   float3 kD = 1.0.xxx - F;
-   kD *= 1.0 - surface.metalness;
-   for (i = 0; i < numProbes; ++i)
+   /*for (i = 0; i < numProbes; ++i)
    {
    {
-      if (blendFactor[i] == 0)
+      if (blendVal[i] == 0)
          continue;
          continue;
 
 
-      irradiance += blendFactor[i]*iblBoxDiffuse(surface, i);
+      irradiance += blendVal[i]*iblBoxDiffuse(surface, i);
       
       
-      specular += blendFactor[i]*F*iblBoxSpecular(surface, 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;
-	float4 finalColor = float4(diffuse + specular * surface.ao, blendFacSum);
+   float3 diffuse = kD * irradiance.rgb * surface.baseColor.rgb;
+	float4 finalColor = float4(diffuse + specular.rgb * surface.ao, contribSum);
 
 
-    return finalColor;
+   return finalColor;
 
 
 #elif DEBUGVIZ_SPECCUBEMAP == 1 && DEBUGVIZ_DIFFCUBEMAP == 0
 #elif DEBUGVIZ_SPECCUBEMAP == 1 && DEBUGVIZ_DIFFCUBEMAP == 0
-   float3 cubeColor = float3(0, 0, 0);
-   for (i = 0; i < numProbes; ++i)
-   {
-      cubeColor += blendFactor[i] * iblBoxSpecular(surface, TORQUE_SAMPLER2D_MAKEARG(BRDFTexture), i);
-   }
-
-   return float4(cubeColor,1);
+   return float4(specular.rgb, 1);
 #elif DEBUGVIZ_DIFFCUBEMAP == 1
 #elif DEBUGVIZ_DIFFCUBEMAP == 1
-   float3 cubeColor = float3(0, 0, 0);
-   for (i = 0; i < numProbes; ++i)
-   {
-      cubeColor += blendFactor[i] * iblBoxDiffuse(surface, i);
-   }
-
-   return float4(cubeColor, 1);
+   return float4(irradiance.rgb, 1);
 #endif
 #endif
 }
 }