Browse Source

Majority of forward work. Some state/register count issues and further testing required.
Also requires proper binding of forward probe values, as well as scoring probes for forward selection.

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

+ 65 - 62
Engine/source/renderInstance/renderProbeMgr.cpp

@@ -164,7 +164,7 @@ void ProbeShaderConstants::init(GFXShader* shader)
    mProbeIrradianceCubemapSC = shader->getShaderConstHandle(ShaderGenVars::irradianceCubemapAR);
    mProbeIrradianceCubemapSC = shader->getShaderConstHandle(ShaderGenVars::irradianceCubemapAR);
    mProbeCountSC = shader->getShaderConstHandle(ShaderGenVars::probeCount);
    mProbeCountSC = shader->getShaderConstHandle(ShaderGenVars::probeCount);
 
 
-   mSkylightPrefilterMap = shader->getShaderConstHandle(ShaderGenVars::skylightPrefilterMap);
+   mSkylightSpecularMap = shader->getShaderConstHandle(ShaderGenVars::skylightPrefilterMap);
    mSkylightIrradMap = shader->getShaderConstHandle(ShaderGenVars::skylightIrradMap);
    mSkylightIrradMap = shader->getShaderConstHandle(ShaderGenVars::skylightIrradMap);
    mHasSkylight = shader->getShaderConstHandle(ShaderGenVars::hasSkylight);
    mHasSkylight = shader->getShaderConstHandle(ShaderGenVars::hasSkylight);
 
 
@@ -568,29 +568,29 @@ void RenderProbeMgr::_update4ProbeConsts(const SceneData &sgData,
    {
    {
       PROFILE_SCOPE(ProbeManager_Update4ProbeConsts_setProbes);
       PROFILE_SCOPE(ProbeManager_Update4ProbeConsts_setProbes);
 
 
-      static AlignedArray<Point3F> probePositions(4, sizeof(Point3F));
-      static AlignedArray<F32> probeRadius(4, sizeof(F32));
-      static AlignedArray<Point3F> probeBoxMins(4, sizeof(Point3F));
-      static AlignedArray<Point3F> probeBoxMaxs(4, sizeof(Point3F));
-      static AlignedArray<Point3F> probeLocalPositions(4, sizeof(Point3F));
-      static AlignedArray<F32> probeIsSphere(4, sizeof(F32));
+      const U32 MAX_FORWARD_PROBES = 4;
+
+      static AlignedArray<Point4F> probePositionArray(MAX_FORWARD_PROBES, sizeof(Point4F));
+      static AlignedArray<Point4F> probeBoxMinArray(MAX_FORWARD_PROBES, sizeof(Point4F));
+      static AlignedArray<Point4F> probeBoxMaxArray(MAX_FORWARD_PROBES, sizeof(Point4F));
+      static AlignedArray<Point4F> probeRefPositionArray(MAX_FORWARD_PROBES, sizeof(Point4F));
+      static AlignedArray<Point4F> probeConfigArray(MAX_FORWARD_PROBES, sizeof(Point4F));
+
+      Vector<MatrixF> probeWorldToObjArray;
+      probeWorldToObjArray.setSize(MAX_FORWARD_PROBES);
       //static AlignedArray<CubemapData> probeCubemap(4, sizeof(CubemapData));
       //static AlignedArray<CubemapData> probeCubemap(4, sizeof(CubemapData));
       //F32 range;
       //F32 range;
 
 
       // Need to clear the buffers so that we don't leak
       // Need to clear the buffers so that we don't leak
       // lights from previous passes or have NaNs.
       // lights from previous passes or have NaNs.
-      dMemset(probePositions.getBuffer(), 0, probePositions.getBufferSize());
-      dMemset(probeRadius.getBuffer(), 0, probeRadius.getBufferSize());
-      dMemset(probeBoxMins.getBuffer(), 0, probeBoxMins.getBufferSize());
-      dMemset(probeBoxMaxs.getBuffer(), 0, probeBoxMaxs.getBufferSize());
-      dMemset(probeLocalPositions.getBuffer(), 0, probeLocalPositions.getBufferSize());
-      dMemset(probeIsSphere.getBuffer(), 0, probeRadius.getBufferSize());
-      //dMemset(probeCubemap.getBuffer(), 0, probeCubemap.getBufferSize());
+      dMemset(probePositionArray.getBuffer(), 0, probePositionArray.getBufferSize());
+      dMemset(probeBoxMinArray.getBuffer(), 0, probeBoxMinArray.getBufferSize());
+      dMemset(probeBoxMaxArray.getBuffer(), 0, probeBoxMaxArray.getBufferSize());
+      dMemset(probeRefPositionArray.getBuffer(), 0, probeRefPositionArray.getBufferSize());
+      dMemset(probeConfigArray.getBuffer(), 0, probeConfigArray.getBufferSize());
 
 
       matSet.restoreSceneViewProjection();
       matSet.restoreSceneViewProjection();
 
 
-      //const MatrixF &worldToCameraXfm = matSet.getWorldToCamera();
-
       // Gather the data for the first 4 probes.
       // Gather the data for the first 4 probes.
       /*const ProbeRenderInst *probe;
       /*const ProbeRenderInst *probe;
       for (U32 i = 0; i < 4; i++)
       for (U32 i = 0; i < 4; i++)
@@ -649,26 +649,21 @@ void RenderProbeMgr::_update4ProbeConsts(const SceneData &sgData,
       mEffectiveProbeCount = 0;
       mEffectiveProbeCount = 0;
       mMipCount = 0;
       mMipCount = 0;
 
 
-      if (probePositionsData.size() != MAXPROBECOUNT)
+      /*if (probePositionArray.size() != MAX_FORWARD_PROBES)
       {
       {
-         probePositionsData.setSize(MAXPROBECOUNT);
-         probeRefPositionsData.setSize(MAXPROBECOUNT);
-         probeWorldToObjData.setSize(MAXPROBECOUNT);
-         probeBBMinData.setSize(MAXPROBECOUNT);
-         probeBBMaxData.setSize(MAXPROBECOUNT);
-         probeConfigData.setSize(MAXPROBECOUNT);
-      }
-
-      probePositionsData.fill(Point4F::Zero);
-      probeRefPositionsData.fill(Point4F::Zero);
-      probeWorldToObjData.fill(MatrixF::Identity);
-      probeBBMinData.fill(Point4F::Zero);
-      probeBBMaxData.fill(Point4F::Zero);
-      probeConfigData.fill(Point4F::Zero);
+         probePositionArray.setSize(MAX_FORWARD_PROBES);
+         probeBoxMinArray.setSize(MAX_FORWARD_PROBES);
+         probeBoxMaxArray.setSize(MAX_FORWARD_PROBES);
+         probeBoxMaxArray.setSize(MAX_FORWARD_PROBES);
+         probeRefPositionArray.setSize(MAX_FORWARD_PROBES);
+         probeConfigArray.setSize(MAX_FORWARD_PROBES);
+
+         probeWorldToObjArray.setSize(MAX_FORWARD_PROBES);
+      }*/
 
 
-      cubeMaps.clear();
-      irradMaps.clear();
-      Vector<U32> cubemapIdxes;
+      //cubeMaps.clear();
+      //irradMaps.clear();
+      //Vector<U32> cubemapIdxes;
 
 
       U32 effectiveProbeCount = 0;
       U32 effectiveProbeCount = 0;
       bool hasSkylight = false;
       bool hasSkylight = false;
@@ -683,41 +678,51 @@ void RenderProbeMgr::_update4ProbeConsts(const SceneData &sgData,
 
 
          if (curEntry.mIsSkylight)
          if (curEntry.mIsSkylight)
          {
          {
-            GFX->setCubeTexture(probeShaderConsts->mSkylightPrefilterMap->getSamplerRegister(), curEntry.mPrefilterCubemap);
-            GFX->setCubeTexture(probeShaderConsts->mSkylightIrradMap->getSamplerRegister(), curEntry.mIrradianceCubemap);
-
-            shaderConsts->setSafe(probeShaderConsts->mHasSkylight, true);
-            hasSkylight = true;
-            continue;
+            if (curEntry.mPrefilterCubemap.isValid() && curEntry.mPrefilterCubemap.isValid())
+            {
+               U32 specSample = probeShaderConsts->mSkylightSpecularMap->getSamplerRegister();
+               U32 irradSample = probeShaderConsts->mSkylightIrradMap->getSamplerRegister();
+
+               GFX->setCubeTexture(probeShaderConsts->mSkylightSpecularMap->getSamplerRegister(), curEntry.mPrefilterCubemap);
+               GFX->setCubeTexture(probeShaderConsts->mSkylightIrradMap->getSamplerRegister(), curEntry.mIrradianceCubemap);
+
+               shaderConsts->setSafe(probeShaderConsts->mHasSkylight, 1.0f);
+               hasSkylight = true;
+               continue;
+            }
+         }
+         else
+         {
+            /*probePositions[effectiveProbeCount] = curEntry.getPosition();
+            probeRefPositions[effectiveProbeCount] = curEntry.mProbeRefOffset;
+            probeWorldToObj[effectiveProbeCount] = curEntry.getTransform();
+            probeBBMin[effectiveProbeCount] = curEntry.mBounds.minExtents;
+            probeBBMax[effectiveProbeCount] = curEntry.mBounds.maxExtents;
+            probeConfig[effectiveProbeCount] = Point4F(curEntry.mProbeShapeType,
+               curEntry.mRadius,
+               curEntry.mAtten,
+               curEntry.mCubemapIndex);*/
          }
          }
 
 
-         //Setup
-         /*Point3F probePos = curEntry.getPosition();
-         Point3F refPos = curEntry.getPosition() + curEntry.mProbeRefOffset;
-         probePositionsData[mEffectiveProbeCount] = Point4F(probePos.x, probePos.y, probePos.z, 0);
-         probeRefPositionsData[mEffectiveProbeCount] = Point4F(refPos.x, refPos.y, refPos.z, 0);
+         effectiveProbeCount++;
+      }
 
 
-         probeWorldToObjData[mEffectiveProbeCount] = curEntry.getTransform();
-         Point3F bbMin = refPos - curEntry.mProbeRefScale / 2 * curEntry.getTransform().getScale();
-         Point3F bbMax = refPos + curEntry.mProbeRefScale / 2 * curEntry.getTransform().getScale();
-         probeBBMinData[mEffectiveProbeCount] = Point4F(bbMin.x, bbMin.y, bbMin.z, 0);
-         probeBBMaxData[mEffectiveProbeCount] = Point4F(bbMax.x, bbMax.y, bbMax.z, 0);
+      shaderConsts->setSafe(probeShaderConsts->mProbeCountSC, (float)effectiveProbeCount);
 
 
-         probeConfigData[mEffectiveProbeCount] = Point4F(curEntry.mProbeShapeType,
-            curEntry.mRadius,
-            curEntry.mAtten,
-            curEntry.mCubemapIndex);
+      shaderConsts->setSafe(probeShaderConsts->mProbePositionSC, probePositionArray);
+      shaderConsts->setSafe(probeShaderConsts->mProbeRefPosSC, probeRefPositionArray);
 
 
-         cubeMaps.push_back(curEntry.mPrefilterCubemap);
-         irradMaps.push_back(curEntry.mIrradianceCubemap);
+      shaderConsts->set(probeShaderConsts->mWorldToObjArraySC, probeWorldToObjArray.address(), effectiveProbeCount, GFXSCT_Float4x4);
 
 
-         cubemapIdxes.push_back(i);*/
+      shaderConsts->setSafe(probeShaderConsts->mProbeBoxMinSC, probeBoxMinArray);
+      shaderConsts->setSafe(probeShaderConsts->mProbeBoxMaxSC, probeBoxMaxArray);
+      shaderConsts->setSafe(probeShaderConsts->mProbeConfigDataSC, probeConfigArray);
 
 
-         effectiveProbeCount++;
-      }
+      GFX->setCubeArrayTexture(probeShaderConsts->mProbeSpecularCubemapSC->getSamplerRegister(), mPrefilterArray);
+      GFX->setCubeArrayTexture(probeShaderConsts->mProbeIrradianceCubemapSC->getSamplerRegister(), mIrradianceArray);
 
 
       if (!hasSkylight)
       if (!hasSkylight)
-         shaderConsts->setSafe(probeShaderConsts->mHasSkylight, false);
+         shaderConsts->setSafe(probeShaderConsts->mHasSkylight, 0.0f);
    }
    }
    /*else
    /*else
    {
    {
@@ -863,8 +868,6 @@ void RenderProbeMgr::bakeProbe(ReflectionProbe *probe)
 {
 {
    GFXDEBUGEVENT_SCOPE(RenderProbeMgr_Bake, ColorI::WHITE);
    GFXDEBUGEVENT_SCOPE(RenderProbeMgr_Bake, ColorI::WHITE);
 
 
-   bool serverObj = probe->isServerObject();
-
    Con::warnf("RenderProbeMgr::bakeProbe() - Beginning bake!");
    Con::warnf("RenderProbeMgr::bakeProbe() - Beginning bake!");
    U32 startMSTime = Platform::getRealMilliseconds();
    U32 startMSTime = Platform::getRealMilliseconds();
 
 

+ 1 - 1
Engine/source/renderInstance/renderProbeMgr.h

@@ -145,7 +145,7 @@ struct ProbeShaderConstants
    GFXShaderConstHandle *mProbeIrradianceCubemapSC;
    GFXShaderConstHandle *mProbeIrradianceCubemapSC;
    GFXShaderConstHandle *mProbeCountSC;
    GFXShaderConstHandle *mProbeCountSC;
 
 
-   GFXShaderConstHandle *mSkylightPrefilterMap;
+   GFXShaderConstHandle *mSkylightSpecularMap;
    GFXShaderConstHandle *mSkylightIrradMap;
    GFXShaderConstHandle *mSkylightIrradMap;
    GFXShaderConstHandle *mHasSkylight;
    GFXShaderConstHandle *mHasSkylight;
 
 

+ 111 - 47
Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp

@@ -2966,7 +2966,7 @@ void ReflectionProbeFeatHLSL::processPix(Vector<ShaderComponent*> &componentList
    MultiLine *meta = new MultiLine;
    MultiLine *meta = new MultiLine;
 
 
    // Look for a wsNormal or grab it from the connector.
    // Look for a wsNormal or grab it from the connector.
-   Var *wsNormal = (Var*)LangElement::find("wsNormal");
+   /*Var *wsNormal = (Var*)LangElement::find("wsNormal");
    if (!wsNormal)
    if (!wsNormal)
    {
    {
       wsNormal = connectComp->getElement(RT_TEXCOORD);
       wsNormal = connectComp->getElement(RT_TEXCOORD);
@@ -2983,63 +2983,69 @@ void ReflectionProbeFeatHLSL::processPix(Vector<ShaderComponent*> &componentList
       // on older Geforce cards.
       // on older Geforce cards.
       //
       //
       meta->addStatement(new GenOp("   @ = normalize( half3( @ ) );\r\n", wsNormal, wsNormal));
       meta->addStatement(new GenOp("   @ = normalize( half3( @ ) );\r\n", wsNormal, wsNormal));
-   }
+   }*/
 
 
    // Now the wsPosition and wsView.
    // Now the wsPosition and wsView.
    Var *wsPosition = getInWsPosition(componentList);
    Var *wsPosition = getInWsPosition(componentList);
    Var *wsView = getWsView(wsPosition, meta);
    Var *wsView = getWsView(wsPosition, meta);
    
    
-   Var *metalness = (Var*)LangElement::find("metalness");
-   Var *smoothness = (Var*)LangElement::find("smoothness");
-   if (!fd.features[MFT_SpecularMap])
-   {
-      if (!metalness)
-      {
-         metalness = new Var("metalness", "float");
-         metalness->uniform = true;
-         metalness->constSortPos = cspPotentialPrimitive;
-      }
-	  if (!smoothness)
-	  {
-		  smoothness = new Var("smoothness", "float");
-		  smoothness->uniform = true;
-		  smoothness->constSortPos = cspPotentialPrimitive;
-	  }
-   }
-
    Var *albedo = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::DefaultTarget));
    Var *albedo = (Var*)LangElement::find(getOutputTargetVarName(ShaderFeature::DefaultTarget));
 
 
    //Reflection Probe WIP
    //Reflection Probe WIP
-   Var *inProbePos = new Var("inProbePosArray", "float4");
-   inProbePos->arraySize = 4;
-   inProbePos->uniform = true;
-   inProbePos->constSortPos = cspPotentialPrimitive;
-
-   Var *inProbeRadius = new Var("inRefPosArray", "float4");
-   inProbeRadius->arraySize = 4;
-   inProbeRadius->uniform = true;
-   inProbeRadius->constSortPos = cspPotentialPrimitive;
-
-   Var *inProbeBoxMin = new Var("inProbeBoxMin", "float4");
-   inProbeBoxMin->arraySize = 4;
-   inProbeBoxMin->uniform = true;
-   inProbeBoxMin->constSortPos = cspPotentialPrimitive;
-
-   Var *inProbeBoxMax = new Var("inProbeBoxMax", "float4");
-   inProbeBoxMax->arraySize = 4;
-   inProbeBoxMax->uniform = true;
-   inProbeBoxMax->constSortPos = cspPotentialPrimitive;
-
-   Var *inProbeIsSphere = new Var("probeConfigData", "float4");
-   inProbeIsSphere->arraySize = 4;
-   inProbeIsSphere->uniform = true;
-   inProbeIsSphere->constSortPos = cspPotentialPrimitive;
+   U32 MAX_FORWARD_PROBES = 4;
+
+   Var *numProbes = new Var("numProbes", "float");
+   numProbes->uniform = true;
+   numProbes->constSortPos = cspPotentialPrimitive;
+
+   Var *cubeMips = new Var("cubeMips", "float");
+   cubeMips->uniform = true;
+   cubeMips->constSortPos = cspPotentialPrimitive;
+
+   Var *hasSkylight = new Var("hasSkylight", "float");
+   hasSkylight->uniform = true;
+   hasSkylight->constSortPos = cspPotentialPrimitive;
+
+   Var *inProbePosArray = new Var("inProbePosArray", "float4");
+   inProbePosArray->arraySize = MAX_FORWARD_PROBES;
+   inProbePosArray->uniform = true;
+   inProbePosArray->constSortPos = cspPotentialPrimitive;
+
+   Var *inRefPosArray = new Var("inRefPosArray", "float4");
+   inRefPosArray->arraySize = MAX_FORWARD_PROBES;
+   inRefPosArray->uniform = true;
+   inRefPosArray->constSortPos = cspPotentialPrimitive;
+
+   Var *bbMinArray = new Var("inProbeBoxMin", "float4");
+   bbMinArray->arraySize = MAX_FORWARD_PROBES;
+   bbMinArray->uniform = true;
+   bbMinArray->constSortPos = cspPotentialPrimitive;
+
+   Var *bbMaxArray = new Var("inProbeBoxMax", "float4");
+   bbMaxArray->arraySize = MAX_FORWARD_PROBES;
+   bbMaxArray->uniform = true;
+   bbMaxArray->constSortPos = cspPotentialPrimitive;
+
+   Var *probeConfigData = new Var("probeConfigData", "float4");
+   probeConfigData->arraySize = MAX_FORWARD_PROBES;
+   probeConfigData->uniform = true;
+   probeConfigData->constSortPos = cspPotentialPrimitive;
 
 
    Var *worldToObjArray = new Var("worldToObjArray", "float4x4");
    Var *worldToObjArray = new Var("worldToObjArray", "float4x4");
-   worldToObjArray->arraySize = 4;
+   worldToObjArray->arraySize = MAX_FORWARD_PROBES;
    worldToObjArray->uniform = true;
    worldToObjArray->uniform = true;
    worldToObjArray->constSortPos = cspPotentialPrimitive;
    worldToObjArray->constSortPos = cspPotentialPrimitive;
 
 
+   Var *BRDFTexture = new Var("BRDFTexture", "SamplerState");
+   BRDFTexture->uniform = true;
+   BRDFTexture->sampler = true;
+   BRDFTexture->constNum = Var::getTexUnitNum();     // used as texture unit num here
+
+   Var *BRDFTextureTex = new Var("BRDFTextureTex", "Texture2D");
+   BRDFTextureTex->uniform = true;
+   BRDFTextureTex->texture = true;
+   BRDFTextureTex->constNum = BRDFTexture->constNum;
+
    Var *specularCubemapAR = new Var("specularCubemapAR", "SamplerState");
    Var *specularCubemapAR = new Var("specularCubemapAR", "SamplerState");
    specularCubemapAR->uniform = true;
    specularCubemapAR->uniform = true;
    specularCubemapAR->sampler = true;
    specularCubemapAR->sampler = true;
@@ -3058,7 +3064,27 @@ void ReflectionProbeFeatHLSL::processPix(Vector<ShaderComponent*> &componentList
    Var *irradianceCubemapARTex = new Var("irradianceCubemapARTex", "TextureCubeArray");
    Var *irradianceCubemapARTex = new Var("irradianceCubemapARTex", "TextureCubeArray");
    irradianceCubemapARTex->uniform = true;
    irradianceCubemapARTex->uniform = true;
    irradianceCubemapARTex->texture = true;
    irradianceCubemapARTex->texture = true;
-   irradianceCubemapARTex->constNum = specularCubemapAR->constNum;
+   irradianceCubemapARTex->constNum = irradianceCubemapAR->constNum;
+
+   Var *skylightSpecularMap = new Var("skylightSpecularMap", "SamplerState");
+   skylightSpecularMap->uniform = true;
+   skylightSpecularMap->sampler = true;
+   skylightSpecularMap->constNum = Var::getTexUnitNum();     // used as texture unit num here
+
+   Var *skylightSpecularMapTex = new Var("skylightSpecularMapTex", "TextureCube");
+   skylightSpecularMapTex->uniform = true;
+   skylightSpecularMapTex->texture = true;
+   skylightSpecularMapTex->constNum = skylightSpecularMap->constNum;
+
+   Var *skylightIrradMap = new Var("skylightIrradMap", "SamplerState");
+   skylightIrradMap->uniform = true;
+   skylightIrradMap->sampler = true;
+   skylightIrradMap->constNum = Var::getTexUnitNum();     // used as texture unit num here
+
+   Var *skylightIrradMapTex = new Var("skylightIrradMapTex", "TextureCube");
+   skylightIrradMapTex->uniform = true;
+   skylightIrradMapTex->texture = true;
+   skylightIrradMapTex->constNum = skylightIrradMap->constNum;
 
 
    /*Var *probeVec = new Var("probeVec", "float3");
    /*Var *probeVec = new Var("probeVec", "float3");
    meta->addStatement(new GenOp("   @ = @[0] - @;\r\n", new DecOp(probeVec), inProbePos, wsPosition));
    meta->addStatement(new GenOp("   @ = @[0] - @;\r\n", new DecOp(probeVec), inProbePos, wsPosition));
@@ -3137,7 +3163,45 @@ void ReflectionProbeFeatHLSL::processPix(Vector<ShaderComponent*> &componentList
       meta->addStatement(new GenOp("   @.rgb  = simpleFresnel(@.rgb, @, 0, @, @, @));\r\n", albedo, albedo, probeColor, angle, FRESNEL_BIAS, FRESNEL_POWER));
       meta->addStatement(new GenOp("   @.rgb  = simpleFresnel(@.rgb, @, 0, @, @, @));\r\n", albedo, albedo, probeColor, angle, FRESNEL_BIAS, FRESNEL_POWER));
    }*/
    }*/
 
 
-   meta->addStatement(new GenOp("   @.rgb = float3(1,1,1);\r\n", albedo));
+   Var *inTex = getInTexCoord("texCoord", "float2", componentList);
+   if (!inTex)
+      return;
+
+   Var *diffuseColor = (Var*)LangElement::find("diffuseColor");
+   if (!diffuseColor)
+      return;
+
+   Var *specularColor = (Var*)LangElement::find("specularColor");
+   if (!specularColor)
+      return;
+
+   Var *bumpNormal = (Var*)LangElement::find("bumpNormal");
+   if (!bumpNormal)
+      return;
+
+   Var *wsEyePos = (Var*)LangElement::find("eyePosWorld");
+
+   Var *worldToCamera = (Var*)LangElement::find("worldToCamera");
+   if (!worldToCamera)
+   {
+      worldToCamera = new Var;
+      worldToCamera->setType("float4x4");
+      worldToCamera->setName("worldToCamera");
+      worldToCamera->uniform = true;
+      worldToCamera->constSortPos = cspPass;
+   }
+
+   //Reflection vec
+   Var *surface = new Var("surface", "Surface");
+   meta->addStatement(new GenOp("  @ = createForwardSurface(@,@,@,@,@,@,@,@);\r\n\n", new DecOp(surface), diffuseColor, bumpNormal, specularColor,
+                     inTex, wsPosition, wsEyePos, wsView, worldToCamera));
+
+   meta->addStatement(new GenOp("   @.rgb = computeForwardProbes(@,@,@,@,@,@,@,@,@,\r\n\t\t@,@,@,@,@,\r\n\t\t@,@,@,@,@,@).rgb;\r\n", albedo,
+      surface, cubeMips, numProbes, worldToObjArray, probeConfigData, inProbePosArray, bbMinArray, bbMaxArray, inRefPosArray,
+      hasSkylight, skylightIrradMap, skylightIrradMapTex, skylightSpecularMap, skylightSpecularMapTex,
+      BRDFTexture, BRDFTextureTex, irradianceCubemapAR, irradianceCubemapARTex, specularCubemapAR, specularCubemapARTex));
+
+   //meta->addStatement(new GenOp("   @.rgb = @.roughness.xxx;\r\n", albedo, surface));
 
 
    output = meta;
    output = meta;
 }
 }

+ 1 - 1
Engine/source/shaderGen/shaderGenVars.cpp

@@ -81,7 +81,7 @@ const String ShaderGenVars::irradianceCubemapAR("$irradianceCubemapAR");
 const String ShaderGenVars::probeCount("$numProbes");
 const String ShaderGenVars::probeCount("$numProbes");
 
 
 //Skylight
 //Skylight
-const String ShaderGenVars::skylightPrefilterMap("$skylightPrefilterMap");
+const String ShaderGenVars::skylightPrefilterMap("$skylightSpecularMap");
 const String ShaderGenVars::skylightIrradMap("$skylightIrradMap");
 const String ShaderGenVars::skylightIrradMap("$skylightIrradMap");
 const String ShaderGenVars::hasSkylight("$hasSkylight");
 const String ShaderGenVars::hasSkylight("$hasSkylight");
 
 

+ 142 - 8
Templates/Full/game/shaders/common/lighting.hlsl

@@ -45,6 +45,9 @@ uniform float4 albedo;
 
 
 #endif // !TORQUE_SHADERGEN
 #endif // !TORQUE_SHADERGEN
 
 
+#define MAX_PROBES 50
+#define MAX_FORWARD_PROBES 4
+
 inline float3 getDistanceVectorToPlane( float3 origin, float3 direction, float4 plane )
 inline float3 getDistanceVectorToPlane( float3 origin, float3 direction, float4 plane )
 {
 {
    float denum = dot( plane.xyz, direction.xyz );
    float denum = dot( plane.xyz, direction.xyz );
@@ -145,6 +148,26 @@ inline Surface createSurface(float4 gbuffer0, TORQUE_SAMPLER2D(gbufferTex1), TOR
 	return surface;
 	return surface;
 }
 }
 
 
+inline Surface createForwardSurface(float4 baseColor, float4 normal, float4 pbrProperties, in float2 uv, in float3 wsPosition, in float3 wsEyePos, in float3 wsEyeRay, in float4x4 invView)
+{
+	Surface surface = (Surface)0;
+
+  surface.depth = 0;
+	surface.P = wsPosition;
+	surface.N = mul(invView, float4(normal.xyz,0)).xyz; //TODO move t3d to use WS normals
+	surface.V = normalize(wsEyePos - surface.P);
+	surface.baseColor = baseColor;
+  const float minRoughness=1e-4;
+	surface.roughness = clamp(1.0 - pbrProperties.b, minRoughness, 1.0); //t3d uses smoothness, so we convert to roughness.
+	surface.roughness_brdf = surface.roughness * surface.roughness;
+	surface.metalness = pbrProperties.a;
+  surface.ao = pbrProperties.g;
+  surface.matFlag = pbrProperties.r;
+
+	surface.Update();
+	return surface;
+}
+
 struct SurfaceToLight
 struct SurfaceToLight
 {
 {
 	float3 L;				// surface to light vector
 	float3 L;				// surface to light vector
@@ -237,9 +260,9 @@ inline float3 getPunctualLight(in Surface surface, in SurfaceToLight surfaceToLi
 }
 }
 
 
 //Probe IBL stuff
 //Probe IBL stuff
-float defineSphereSpaceInfluence(Surface surface, float3 wsProbePosition, float radius)
+float defineSphereSpaceInfluence(float3 wsPosition, float3 wsProbePosition, float radius)
 {
 {
-   float3 L = wsProbePosition.xyz - surface.P;
+   float3 L = wsProbePosition.xyz - wsPosition;
    float contribution = 1.0 - length(L) / radius;
    float contribution = 1.0 - length(L) / radius;
    return contribution;
    return contribution;
 }
 }
@@ -250,9 +273,9 @@ float getDistBoxToPoint(float3 pt, float3 extents)
    return max(max(d.x, d.y), d.z);
    return max(max(d.x, d.y), d.z);
 }
 }
 
 
-float defineBoxSpaceInfluence(Surface surface, float4x4 worldToObj, float attenuation)
+float defineBoxSpaceInfluence(float3 wsPosition, float4x4 worldToObj, float attenuation)
 {
 {
-   float3 surfPosLS = mul(worldToObj, float4(surface.P, 1.0)).xyz;
+   float3 surfPosLS = mul(worldToObj, float4(wsPosition, 1.0)).xyz;
    float atten = 1.0 - attenuation;
    float atten = 1.0 - attenuation;
    float baseVal = 0.25;
    float baseVal = 0.25;
    float dist = getDistBoxToPoint(surfPosLS, float3(baseVal, baseVal, baseVal));
    float dist = getDistBoxToPoint(surfPosLS, float3(baseVal, baseVal, baseVal));
@@ -262,17 +285,128 @@ float defineBoxSpaceInfluence(Surface surface, float4x4 worldToObj, float attenu
 // 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(Surface surface, float4x4 worldToObj, float3 bbMin, float3 bbMax, float3 refPosition)
+float3 boxProject(float3 wsPosition, float3 wsReflectVec, float4x4 worldToObj, float3 bbMin, float3 bbMax, float3 refPosition)
 {
 {
-   float3 RayLS = mul(worldToObj, float4(surface.R, 0.0)).xyz;
-   float3 PositionLS = mul(worldToObj, float4(surface.P, 1.0)).xyz;
+   float3 RayLS = mul(worldToObj, float4(wsReflectVec, 0.0)).xyz;
+   float3 PositionLS = mul(worldToObj, float4(wsPosition, 1.0)).xyz;
 
 
    float3 unit = bbMax.xyz - bbMin.xyz;
    float3 unit = bbMax.xyz - bbMin.xyz;
    float3 plane1vec = (unit / 2 - PositionLS) / RayLS;
    float3 plane1vec = (unit / 2 - PositionLS) / RayLS;
    float3 plane2vec = (-unit / 2 - PositionLS) / RayLS;
    float3 plane2vec = (-unit / 2 - PositionLS) / RayLS;
    float3 furthestPlane = max(plane1vec, plane2vec);
    float3 furthestPlane = max(plane1vec, plane2vec);
    float dist = min(min(furthestPlane.x, furthestPlane.y), furthestPlane.z);
    float dist = min(min(furthestPlane.x, furthestPlane.y), furthestPlane.z);
-   float3 posonbox = surface.P + surface.R * dist;
+   float3 posonbox = wsPosition + wsReflectVec * dist;
 
 
    return posonbox - refPosition.xyz;
    return posonbox - refPosition.xyz;
 }
 }
+
+float4 computeForwardProbes(Surface surface,
+    float cubeMips, float numProbes, float4x4 worldToObjArray[MAX_FORWARD_PROBES], float4 probeConfigData[MAX_FORWARD_PROBES], 
+    float4 inProbePosArray[MAX_FORWARD_PROBES], float4 bbMinArray[MAX_FORWARD_PROBES], float4 bbMaxArray[MAX_FORWARD_PROBES], float4 inRefPosArray[MAX_FORWARD_PROBES],
+    float hasSkylight, SamplerState skylightIrradMap, TextureCube skylightIrradMapTex, SamplerState skylightSpecularMap, TextureCube skylightSpecularMapTex,
+    SamplerState BRDFTexture, Texture2D BRDFTextureTex, SamplerState irradianceCubemapAR, TextureCubeArray irradianceCubemapARTex,
+    SamplerState specularCubemapAR, TextureCubeArray specularCubemapARTex)
+{
+  int i = 0;
+   float blendFactor[MAX_FORWARD_PROBES];
+   float blendSum = 0;
+   float blendFacSum = 0;
+   float invBlendSum = 0;
+   float probehits = 0;
+   //Set up our struct data
+   float contribution[MAX_FORWARD_PROBES];
+  for (i = 0; i < numProbes; ++i)
+  {
+      contribution[i] = 0;
+
+      if (probeConfigData[i].r == 0) //box
+      {
+         contribution[i] = defineBoxSpaceInfluence(surface.P, worldToObjArray[i], probeConfigData[i].b);
+         if (contribution[i] > 0.0)
+            probehits++;
+      }
+      else if (probeConfigData[i].r == 1) //sphere
+      {
+         contribution[i] = defineSphereSpaceInfluence(surface.P, inProbePosArray[i].xyz, probeConfigData[i].g);
+         if (contribution[i] > 0.0)
+            probehits++;
+      }
+
+      contribution[i] = max(contribution[i], 0);
+
+      blendSum += contribution[i];
+      invBlendSum += (1.0f - contribution[i]);
+   }
+
+   if (probehits > 1.0)
+   {
+      for (i = 0; i < numProbes; i++)
+      {
+         blendFactor[i] = ((contribution[i] / blendSum)) / probehits;
+         blendFactor[i] *= ((contribution[i]) / invBlendSum);
+         blendFactor[i] = saturate(blendFactor[i]);
+         blendFacSum += blendFactor[i];
+      }
+
+      // Normalize blendVal
+      if (blendFacSum == 0.0f) // Possible with custom weight
+      {
+         blendFacSum = 1.0f;
+      }
+
+      float invBlendSumWeighted = 1.0f / blendFacSum;
+      for (i = 0; i < numProbes; ++i)
+      {
+         blendFactor[i] *= invBlendSumWeighted;
+         contribution[i] *= blendFactor[i];
+         //alpha -= contribution[i];
+      }
+   }
+   //else
+   //   alpha -= blendSum;
+
+   float3 irradiance = float3(0, 0, 0);
+   float3 specular = float3(0, 0, 0);
+
+   // Radiance (Specular)
+   float lod = surface.roughness*cubeMips;
+
+   float alpha = 1;
+   for (i = 0; i < numProbes; ++i)
+   {
+      float contrib = contribution[i];
+      if (contrib != 0)
+      {
+         int cubemapIdx = probeConfigData[i].a;
+         float3 dir = boxProject(surface.P, surface.R, worldToObjArray[i], bbMinArray[i].xyz, bbMaxArray[i].xyz, inRefPosArray[i].xyz);
+
+         irradiance += irradianceCubemapARTex.SampleLevel(irradianceCubemapAR,float4(dir,cubemapIdx),0).xyz * contrib;
+         specular += specularCubemapARTex.SampleLevel(specularCubemapAR,float4(dir,cubemapIdx),lod).xyz * contrib;
+         alpha -= contrib;
+      }
+   }
+
+   if (hasSkylight && alpha > 0.001)
+   {
+      irradiance += skylightIrradMapTex.SampleLevel(skylightIrradMap,surface.R,0).xyz * alpha;
+      specular += skylightSpecularMapTex.SampleLevel(skylightSpecularMap,surface.R,lod).xyz * alpha;
+   }
+
+   float3 F = FresnelSchlickRoughness(surface.NdotV, surface.f0, surface.roughness);
+
+   //energy conservation
+   float3 kD = 1.0.xxx - F;
+   kD *= 1.0 - surface.metalness;
+
+   //apply brdf
+   //Do it once to save on texture samples
+   float2 brdf = BRDFTextureTex.SampleLevel(BRDFTexture,float2(surface.roughness, surface.NdotV),0).xy;
+   specular *= brdf.x * F + brdf.y;
+
+   //final diffuse color
+   float3 diffuse = kD * irradiance * surface.baseColor.rgb;
+   float4 finalColor = float4(diffuse + specular * surface.ao, 1.0);
+
+   finalColor = float4(irradiance.rgb,1);
+   return finalColor;
+}

+ 27 - 28
Templates/Full/game/shaders/common/lighting/advanced/reflectionProbeArrayP.hlsl

@@ -15,7 +15,6 @@ uniform float3 eyePosWorld;
 
 
 //cubemap arrays require all the same size. so shared mips# value
 //cubemap arrays require all the same size. so shared mips# value
 uniform float cubeMips;
 uniform float cubeMips;
-#define MAX_PROBES 50
 
 
 uniform float numProbes;
 uniform float numProbes;
 TORQUE_UNIFORM_SAMPLERCUBEARRAY(specularCubemapAR, 4);
 TORQUE_UNIFORM_SAMPLERCUBEARRAY(specularCubemapAR, 4);
@@ -32,7 +31,7 @@ uniform float4    probeConfigData[MAX_PROBES];   //r,g,b/mode,radius,atten
 uniform float4    probeContribColors[MAX_PROBES];
 uniform float4    probeContribColors[MAX_PROBES];
 #endif
 #endif
 
 
-TORQUE_UNIFORM_SAMPLERCUBE(skylightPrefilterMap, 6);
+TORQUE_UNIFORM_SAMPLERCUBE(skylightSpecularMap, 6);
 TORQUE_UNIFORM_SAMPLERCUBE(skylightIrradMap, 7);
 TORQUE_UNIFORM_SAMPLERCUBE(skylightIrradMap, 7);
 uniform float hasSkylight;
 uniform float hasSkylight;
 
 
@@ -70,13 +69,13 @@ float4 main(PFXVertToPix IN) : SV_TARGET
 
 
          if (probeConfigData[i].r == 0) //box
          if (probeConfigData[i].r == 0) //box
          {
          {
-            contribution[i] = defineBoxSpaceInfluence(surface, worldToObjArray[i], probeConfigData[i].b);
+            contribution[i] = defineBoxSpaceInfluence(surface.P, worldToObjArray[i], probeConfigData[i].b);
             if (contribution[i]>0.0)
             if (contribution[i]>0.0)
                probehits++;
                probehits++;
          }
          }
          else if (probeConfigData[i].r == 1) //sphere
          else if (probeConfigData[i].r == 1) //sphere
          {
          {
-            contribution[i] = defineSphereSpaceInfluence(surface, inProbePosArray[i].xyz, probeConfigData[i].g);
+            contribution[i] = defineSphereSpaceInfluence(surface.P, inProbePosArray[i].xyz, probeConfigData[i].g);
             if (contribution[i]>0.0)
             if (contribution[i]>0.0)
                probehits++;
                probehits++;
          }
          }
@@ -93,33 +92,33 @@ float4 main(PFXVertToPix IN) : SV_TARGET
 	   // and respect constraint A.
 	   // and respect constraint A.
       
       
       if (probehits>1.0)
       if (probehits>1.0)
-	   {
-         for (i = 0; i < numProbes; i++)
-         {
-            blendFactor[i] = ((contribution[i] / blendSum)) / probehits;
-	         blendFactor[i] *= ((contribution[i]) / invBlendSum);
-            blendFactor[i] = saturate(blendFactor[i]);
-	         blendFacSum += blendFactor[i];
-	      }
+	{
+            for (i = 0; i < numProbes; i++)
+            {
+                  blendFactor[i] = ((contribution[i] / blendSum)) / probehits;
+                  blendFactor[i] *= ((contribution[i]) / invBlendSum);
+                  blendFactor[i] = saturate(blendFactor[i]);
+                  blendFacSum += blendFactor[i];
+            }
 
 
       // Normalize blendVal
       // Normalize blendVal
 #if DEBUGVIZ_ATTENUATION == 0 //this can likely be removed when we fix the above normalization behavior
 #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;
-      }
+            if (blendFacSum == 0.0f) // Possible with custom weight
+            {
+                  blendFacSum = 1.0f;
+            }
 #endif
 #endif
 
 
-		  float invBlendSumWeighted = 1.0f / blendFacSum;
-		  for (i = 0; i < numProbes; ++i)
-		  {
-		     blendFactor[i] *= invBlendSumWeighted;
-		     contribution[i] *= blendFactor[i];
-           alpha -= contribution[i];
-		  }
-   }
-   else
-      alpha -= blendSum;
+            float invBlendSumWeighted = 1.0f / blendFacSum;
+            for (i = 0; i < numProbes; ++i)
+            {
+                  blendFactor[i] *= invBlendSumWeighted;
+                  contribution[i] *= blendFactor[i];
+                  alpha -= contribution[i];
+            }
+      }
+      else
+            alpha -= blendSum;
       
       
 #if DEBUGVIZ_ATTENUATION == 1
 #if DEBUGVIZ_ATTENUATION == 1
       float contribAlpha = 1;
       float contribAlpha = 1;
@@ -164,7 +163,7 @@ float4 main(PFXVertToPix IN) : SV_TARGET
       if (contrib != 0)
       if (contrib != 0)
       {
       {
          int cubemapIdx = probeConfigData[i].a;
          int cubemapIdx = probeConfigData[i].a;
-         float3 dir = boxProject(surface, worldToObjArray[i], bbMinArray[i].xyz, bbMaxArray[i].xyz, inRefPosArray[i].xyz);
+         float3 dir = boxProject(surface.P, surface.R, worldToObjArray[i], bbMinArray[i].xyz, bbMaxArray[i].xyz, inRefPosArray[i].xyz);
 
 
          irradiance += TORQUE_TEXCUBEARRAYLOD(irradianceCubemapAR, dir, cubemapIdx, 0).xyz * contrib;
          irradiance += TORQUE_TEXCUBEARRAYLOD(irradianceCubemapAR, dir, cubemapIdx, 0).xyz * contrib;
          specular += TORQUE_TEXCUBEARRAYLOD(specularCubemapAR, dir, cubemapIdx, lod).xyz * contrib;
          specular += TORQUE_TEXCUBEARRAYLOD(specularCubemapAR, dir, cubemapIdx, lod).xyz * contrib;
@@ -175,7 +174,7 @@ float4 main(PFXVertToPix IN) : SV_TARGET
    if (hasSkylight && alpha > 0.001)
    if (hasSkylight && alpha > 0.001)
    {
    {
       irradiance += TORQUE_TEXCUBELOD(skylightIrradMap, float4(surface.R, 0)).xyz * alpha;
       irradiance += TORQUE_TEXCUBELOD(skylightIrradMap, float4(surface.R, 0)).xyz * alpha;
-      specular += TORQUE_TEXCUBELOD(skylightPrefilterMap, float4(surface.R, lod)).xyz * alpha;
+      specular += TORQUE_TEXCUBELOD(skylightSpecularMap, float4(surface.R, lod)).xyz * alpha;
    }
    }
 
 
 #if DEBUGVIZ_SPECCUBEMAP == 1 && DEBUGVIZ_DIFFCUBEMAP == 0
 #if DEBUGVIZ_SPECCUBEMAP == 1 && DEBUGVIZ_DIFFCUBEMAP == 0