فهرست منبع

Merge branch 'Preview4_0' of https://github.com/Areloch/Torque3D into Preview4_0

AzaezelX 6 سال پیش
والد
کامیت
261bcd9a45

+ 2 - 2
Engine/source/gfx/genericConstBuffer.cpp

@@ -281,8 +281,8 @@ void GenericConstBuffer::assertUnassignedConstants( const char *shaderName )
       mLayout->getDesc( i, pd );
 
       // Assert on the unassigned constant.
-      AssertFatal( false, avar( "The '%s' shader constant in shader '%s' was unassigned!",
-         pd.name.c_str(), shaderName ) );
+      //AssertFatal( false, avar( "The '%s' shader constant in shader '%s' was unassigned!",
+      //   pd.name.c_str(), shaderName ) );
    }
 }
 

+ 3 - 5
Engine/source/lighting/lightManager.cpp

@@ -380,11 +380,9 @@ void LightManager::_update4LightConsts(   const SceneData &sgData,
       shaderConsts->setSafe( lightDiffuseSC, lightColors );
       shaderConsts->setSafe( lightInvRadiusSqSC, lightInvRadiusSq );
 
-         shaderConsts->setSafe( lightSpotDirSC, lightSpotDirs );
-         shaderConsts->setSafe( lightSpotAngleSC, lightSpotAngle );
-       shaderConsts->setSafe( lightSpotFalloffSC, lightSpotFalloff );
-
-      
+      shaderConsts->setSafe( lightSpotDirSC, lightSpotDirs );
+      shaderConsts->setSafe( lightSpotAngleSC, lightSpotAngle );
+      shaderConsts->setSafe( lightSpotFalloffSC, lightSpotFalloff );
    }
 
    // Setup the ambient lighting from the first 

+ 1 - 1
Engine/source/materials/processedShaderMaterial.cpp

@@ -1360,7 +1360,7 @@ void ProcessedShaderMaterial::setSceneInfo(SceneRenderState * state, const Scene
 
    LIGHTMGR->setLightInfo(this, mMaterial, sgData, state, pass, shaderConsts);
 
-   //PROBEMGR->setProbeInfo(this, mMaterial, sgData, state, pass, shaderConsts);
+   PROBEMGR->setProbeInfo(this, mMaterial, sgData, state, pass, shaderConsts);
 }
 
 void ProcessedShaderMaterial::setBuffers( GFXVertexBufferHandleBase *vertBuffer, GFXPrimitiveBufferHandle *primBuffer )

+ 0 - 1
Engine/source/materials/processedShaderMaterial.h

@@ -40,7 +40,6 @@ class ShaderMaterialParameterHandle;
 class ShaderFeatureConstHandles;
 class CustomMaterial;
 
-
 class ShaderConstHandles
 {
 public:

+ 22 - 54
Engine/source/renderInstance/renderProbeMgr.cpp

@@ -131,9 +131,7 @@ ProbeShaderConstants::ProbeShaderConstants()
    mProbeIrradianceCubemapSC(NULL),
    mProbeCountSC(NULL),
    mBRDFTextureMap(NULL),
-   mSkylightSpecularMap(NULL),
-   mSkylightIrradMap(NULL),
-   mHasSkylight(NULL),
+   mSkylightCubemapIdxSC(NULL),
    mWorldToObjArraySC(NULL)
 {
 }
@@ -171,9 +169,7 @@ void ProbeShaderConstants::init(GFXShader* shader)
 
    mBRDFTextureMap = shader->getShaderConstHandle(ShaderGenVars::BRDFTextureMap);
 
-   mSkylightSpecularMap = shader->getShaderConstHandle(ShaderGenVars::skylightPrefilterMap);
-   mSkylightIrradMap = shader->getShaderConstHandle(ShaderGenVars::skylightIrradMap);
-   mHasSkylight = shader->getShaderConstHandle(ShaderGenVars::hasSkylight);
+   mSkylightCubemapIdxSC = shader->getShaderConstHandle(ShaderGenVars::skylightCubemapIdx);
 
    mInit = true;
 }
@@ -519,7 +515,7 @@ ProbeShaderConstants* RenderProbeMgr::getProbeShaderConstants(GFXShaderConstBuff
 
    // Check to see if this is the same shader, we'll get hit repeatedly by
    // the same one due to the render bin loops.
-   if (mLastShader.getPointer() != shader)
+   /*if (mLastShader.getPointer() != shader)
    {
       ProbeConstantMap::Iterator iter = mConstantLookup.find(shader);
       if (iter != mConstantLookup.end())
@@ -536,7 +532,12 @@ ProbeShaderConstants* RenderProbeMgr::getProbeShaderConstants(GFXShaderConstBuff
 
       // Set our new shader
       mLastShader = shader;
-   }
+   }*/
+
+   ProbeShaderConstants* psc = new ProbeShaderConstants();
+   mConstantLookup[shader] = psc;
+
+   mLastConstants = psc;
 
    // Make sure that our current lighting constants are initialized
    if (mLastConstants && !mLastConstants->mInit)
@@ -550,11 +551,10 @@ void RenderProbeMgr::_update4ProbeConsts(const SceneData &sgData,
    ProbeShaderConstants *probeShaderConsts,
    GFXShaderConstBuffer *shaderConsts)
 {
-   return;
    PROFILE_SCOPE(ProbeManager_Update4ProbeConsts);
 
    // Skip over gathering lights if we don't have to!
-   if (probeShaderConsts->isValid())
+   //if (probeShaderConsts->isValid())
    {
       PROFILE_SCOPE(ProbeManager_Update4ProbeConsts_setProbes);
 
@@ -586,6 +586,8 @@ void RenderProbeMgr::_update4ProbeConsts(const SceneData &sgData,
 
       S8 bestPickProbes[4] = { -1,-1,-1,-1 };
 
+      S32 skyLightIdx = -1;
+
       U32 effectiveProbeCount = 0;
       for (U32 i = 0; i < probeCount; i++)
       {
@@ -612,6 +614,10 @@ void RenderProbeMgr::_update4ProbeConsts(const SceneData &sgData,
             else if (bestPickProbes[3] == -1 || (Point3F(sgData.objTrans->getPosition() - mRegisteredProbes[bestPickProbes[3]].mPosition).len() > dist))
                bestPickProbes[3] = i;
          }
+         else
+         {
+            skyLightIdx = curEntry.mCubemapIndex;
+         }
       }
 
       //Grab our best probe picks
@@ -626,7 +632,6 @@ void RenderProbeMgr::_update4ProbeConsts(const SceneData &sgData,
          probeRefPositionArray[effectiveProbeCount] = curEntry.mProbeRefOffset;
          probeWorldToObjArray[effectiveProbeCount] = curEntry.getTransform();
 
-         probeWorldToObjData[mEffectiveProbeCount] = curEntry.getTransform();
          /*
          Point3F refPos = curEntry.getPosition() + curEntry.mProbeRefOffset;
          Point3F bbMin = refPos - curEntry.mProbeRefScale / 2 * curEntry.getTransform().getScale();
@@ -644,65 +649,28 @@ void RenderProbeMgr::_update4ProbeConsts(const SceneData &sgData,
          effectiveProbeCount++;
       }
 
-      shaderConsts->setSafe(probeShaderConsts->mProbeCountSC, (float)effectiveProbeCount);
+      shaderConsts->setSafe(probeShaderConsts->mProbeCountSC, (S32)effectiveProbeCount);
 
       shaderConsts->setSafe(probeShaderConsts->mProbePositionSC, probePositionArray);
       shaderConsts->setSafe(probeShaderConsts->mProbeRefPosSC, probeRefPositionArray);
 
-      shaderConsts->set(probeShaderConsts->mWorldToObjArraySC, probeWorldToObjArray.address(), effectiveProbeCount, GFXSCT_Float4x4);
+      if(probeShaderConsts->isValid())
+         shaderConsts->set(probeShaderConsts->mWorldToObjArraySC, probeWorldToObjArray.address(), effectiveProbeCount, GFXSCT_Float4x4);
 
       shaderConsts->setSafe(probeShaderConsts->mProbeBoxMinSC, probeBoxMinArray);
       shaderConsts->setSafe(probeShaderConsts->mProbeBoxMaxSC, probeBoxMaxArray);
       shaderConsts->setSafe(probeShaderConsts->mProbeConfigDataSC, probeConfigArray);
 
+      shaderConsts->setSafe(probeShaderConsts->mSkylightCubemapIdxSC, (float)skyLightIdx);
+
       if (mBRDFTexture.isValid())
-         GFX->setTexture(3, mBRDFTexture);
+         GFX->setTexture(2, mBRDFTexture);
 
       if(probeShaderConsts->mProbeSpecularCubemapSC->getSamplerRegister() != -1)
          GFX->setCubeArrayTexture(probeShaderConsts->mProbeSpecularCubemapSC->getSamplerRegister(), mPrefilterArray);
       if(probeShaderConsts->mProbeIrradianceCubemapSC->getSamplerRegister() != -1)
          GFX->setCubeArrayTexture(probeShaderConsts->mProbeIrradianceCubemapSC->getSamplerRegister(), mIrradianceArray);
    }
-
-   //check for skylight action
-   if (probeShaderConsts->mSkylightIrradMap->isValid()
-      && probeShaderConsts->mSkylightSpecularMap->isValid())
-   {
-      //Array rendering
-      U32 probeCount = mRegisteredProbes.size();
-
-      bool hasSkylight = false;
-      for (U32 i = 0; i < probeCount; i++)
-      {
-         const ProbeRenderInst& curEntry = mRegisteredProbes[i];
-         if (!curEntry.mIsEnabled)
-            continue;
-
-         if (curEntry.mIsSkylight)
-         {
-            if (curEntry.mPrefilterCubemap->isInitialized() && curEntry.mIrradianceCubemap->isInitialized())
-            {
-               GFX->setCubeTexture(probeShaderConsts->mSkylightSpecularMap->getSamplerRegister(), curEntry.mPrefilterCubemap);
-               GFX->setCubeTexture(probeShaderConsts->mSkylightIrradMap->getSamplerRegister(), curEntry.mIrradianceCubemap);
-
-               shaderConsts->setSafe(probeShaderConsts->mHasSkylight, 1.0f);
-               hasSkylight = true;
-               break;
-            }
-         }
-      }
-
-      if (!hasSkylight)
-         shaderConsts->setSafe(probeShaderConsts->mHasSkylight, 0.0f);
-   }
-   /*else
-   {
-      if (probeCubemapSC->isValid())
-      {
-         for (U32 i = 0; i < 4; ++i)
-            GFX->setCubeTexture(probeCubemapSC->getSamplerRegister() + i, NULL);
-      }
-   }*/
 }
 
 void RenderProbeMgr::setProbeInfo(ProcessedMaterial *pmat,

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

@@ -151,9 +151,7 @@ struct ProbeShaderConstants
 
    GFXShaderConstHandle *mBRDFTextureMap;
 
-   GFXShaderConstHandle *mSkylightSpecularMap;
-   GFXShaderConstHandle *mSkylightIrradMap;
-   GFXShaderConstHandle *mHasSkylight;
+   GFXShaderConstHandle *mSkylightCubemapIdxSC;
 
    ProbeShaderConstants();
    ~ProbeShaderConstants();

+ 7 - 33
Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp

@@ -2980,7 +2980,7 @@ void ReflectionProbeFeatHLSL::processPix(Vector<ShaderComponent*> &componentList
    //Reflection Probe WIP
    U32 MAX_FORWARD_PROBES = 4;
 
-   Var *numProbes = new Var("numProbes", "float");
+   Var *numProbes = new Var("numProbes", "int");
    numProbes->uniform = true;
    numProbes->constSortPos = cspPotentialPrimitive;
 
@@ -2988,9 +2988,9 @@ void ReflectionProbeFeatHLSL::processPix(Vector<ShaderComponent*> &componentList
    cubeMips->uniform = true;
    cubeMips->constSortPos = cspPotentialPrimitive;
 
-   Var *hasSkylight = new Var("hasSkylight", "float");
-   hasSkylight->uniform = true;
-   hasSkylight->constSortPos = cspPotentialPrimitive;
+   Var * skylightCubemapIdx = new Var("skylightCubemapIdx", "float");
+   skylightCubemapIdx->uniform = true;
+   skylightCubemapIdx->constSortPos = cspPotentialPrimitive;
 
    Var *inProbePosArray = new Var("inProbePosArray", "float4");
    inProbePosArray->arraySize = MAX_FORWARD_PROBES;
@@ -3051,26 +3051,6 @@ void ReflectionProbeFeatHLSL::processPix(Vector<ShaderComponent*> &componentList
    irradianceCubemapARTex->uniform = true;
    irradianceCubemapARTex->texture = true;
    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("texture_skylightSpecularMap", "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("texture_skylightIrradMap", "TextureCube");
-   skylightIrradMapTex->uniform = true;
-   skylightIrradMapTex->texture = true;
-   skylightIrradMapTex->constNum = skylightIrradMap->constNum;
    
    Var *inTex = getInTexCoord("texCoord", "float2", componentList);
    if (!inTex)
@@ -3130,12 +3110,10 @@ void ReflectionProbeFeatHLSL::processPix(Vector<ShaderComponent*> &componentList
       inTex, wsPosition, wsEyePos, wsView));
    String computeForwardProbes = String::String("   @.rgb = computeForwardProbes(@,@,@,@,@,@,@,@,@,\r\n\t\t");
    computeForwardProbes += String::String("@,TORQUE_SAMPLER2D_MAKEARG(@),\r\n\t\t"); 
-   computeForwardProbes += String::String("TORQUE_SAMPLERCUBE_MAKEARG(@), TORQUE_SAMPLERCUBE_MAKEARG(@), \r\n\t\t");
    computeForwardProbes += String::String("TORQUE_SAMPLERCUBEARRAY_MAKEARG(@),TORQUE_SAMPLERCUBEARRAY_MAKEARG(@)).rgb; \r\n");
       
    meta->addStatement(new GenOp(computeForwardProbes.c_str(), diffuseColor, surface, cubeMips, numProbes, worldToObjArray, probeConfigData, inProbePosArray, bbMinArray, bbMaxArray, inRefPosArray,
-      hasSkylight, BRDFTexture, 
-      skylightIrradMap, skylightSpecularMap,
+      skylightCubemapIdx, BRDFTexture,
       irradianceCubemapAR, specularCubemapAR));
 
    //meta->addStatement(new GenOp("   @.rgb = @.roughness.xxx;\r\n", albedo, surface));
@@ -3147,8 +3125,8 @@ ShaderFeature::Resources ReflectionProbeFeatHLSL::getResources(const MaterialFea
 {
    Resources res;
 
-   res.numTex = 5;
-   res.numTexReg = 5;
+   res.numTex = 3;
+   res.numTexReg = 3;
 
    return res;
 }
@@ -3167,9 +3145,5 @@ void ReflectionProbeFeatHLSL::setTexData(Material::StageData &stageDat,
       passData.mTexType[texIndex++] = Material::SGCube;
       passData.mSamplerNames[texIndex] = "irradianceCubemapAR";
       passData.mTexType[texIndex++] = Material::SGCube;
-      passData.mSamplerNames[texIndex] = "skylightSpecularMap";
-      passData.mTexType[texIndex++] = Material::SGCube;
-      passData.mSamplerNames[texIndex] = "skylightIrradMap";
-      passData.mTexType[texIndex++] = Material::SGCube;
    }
 }

+ 2 - 4
Engine/source/shaderGen/shaderGenVars.cpp

@@ -83,9 +83,7 @@ const String ShaderGenVars::probeCount("$numProbes");
 const String ShaderGenVars::BRDFTextureMap("$BRDFTexture");
 
 //Skylight
-const String ShaderGenVars::skylightPrefilterMap("$skylightSpecularMap");
-const String ShaderGenVars::skylightIrradMap("$skylightIrradMap");
-const String ShaderGenVars::hasSkylight("$hasSkylight");
+const String ShaderGenVars::skylightCubemapIdx("$skylightCubemapIdx");
 
 // These are ignored by the D3D layers.
 const String ShaderGenVars::fogMap("$fogMap");
@@ -103,4 +101,4 @@ const String ShaderGenVars::dLightMask("$dlightMask");
 const String ShaderGenVars::toneMap("$toneMap");
 
 // Deferred shading
-const String ShaderGenVars::matInfoFlags("$matInfoFlags");
+const String ShaderGenVars::matInfoFlags("$matInfoFlags");

+ 1 - 3
Engine/source/shaderGen/shaderGenVars.h

@@ -96,9 +96,7 @@ struct ShaderGenVars
    const static String BRDFTextureMap;
 
    //Skylight
-   const static String skylightPrefilterMap;
-   const static String skylightIrradMap;
-   const static String hasSkylight;
+   const static String skylightCubemapIdx;
    
    // Textures
    const static String fogMap;

+ 163 - 15
Templates/BaseGame/game/core/rendering/shaders/lighting.hlsl

@@ -88,9 +88,121 @@ void compute4Lights( float3 wsView,
                      out float4 outDiffuse,
                      out float4 outSpecular )
 {
-
-   outDiffuse = float4(0,0,0,0);
-   outSpecular = float4(0,0,0,0);
+   // NOTE: The light positions and spotlight directions
+   // are stored in SoA order, so inLightPos[0] is the
+   // x coord for all 4 lights... inLightPos[1] is y... etc.
+   //
+   // This is the key to fully utilizing the vector units and
+   // saving a huge amount of instructions.
+   //
+   // For example this change saved more than 10 instructions 
+   // over a simple for loop for each light.
+   
+   int i;
+
+   float4 lightVectors[3];
+   for ( i = 0; i < 3; i++ )
+      lightVectors[i] = wsPosition[i] - inLightPos[i];
+
+   float4 squareDists = 0;
+   for ( i = 0; i < 3; i++ )
+      squareDists += lightVectors[i] * lightVectors[i];
+
+   // Accumulate the dot product between the light 
+   // vector and the normal.
+   //
+   // The normal is negated because it faces away from
+   // the surface and the light faces towards the
+   // surface... this keeps us from needing to flip
+   // the light vector direction which complicates
+   // the spot light calculations.
+   //
+   // We normalize the result a little later.
+   //
+   float4 nDotL = 0;
+   for ( i = 0; i < 3; i++ )
+      nDotL += lightVectors[i] * -wsNormal[i];
+
+   float4 rDotL = 0;
+   #ifndef TORQUE_BL_NOSPECULAR
+
+      // We're using the Phong specular reflection model
+      // here where traditionally Torque has used Blinn-Phong
+      // which has proven to be more accurate to real materials.
+      //
+      // We do so because its cheaper as do not need to 
+      // calculate the half angle for all 4 lights.
+      //   
+      // Advanced Lighting still uses Blinn-Phong, but the
+      // specular reconstruction it does looks fairly similar
+      // to this.
+      //
+      float3 R = reflect( wsView, -wsNormal );
+
+      for ( i = 0; i < 3; i++ )
+         rDotL += lightVectors[i] * R[i];
+
+   #endif
+ 
+   // Normalize the dots.
+   //
+   // Notice we're using the half type here to get a
+   // much faster sqrt via the rsq_pp instruction at 
+   // the loss of some precision.
+   //
+   // Unless we have some extremely large point lights
+   // i don't believe the precision loss will matter.
+   //
+   half4 correction = (half4)rsqrt( squareDists );
+   nDotL = saturate( nDotL * correction );
+   rDotL = clamp( rDotL * correction, 0.00001, 1.0 );
+
+   // First calculate a simple point light linear 
+   // attenuation factor.
+   //
+   // If this is a directional light the inverse
+   // radius should be greater than the distance
+   // causing the attenuation to have no affect.
+   //
+   float4 atten = saturate( 1.0 - ( squareDists * inLightInvRadiusSq ) );
+
+   #ifndef TORQUE_BL_NOSPOTLIGHT
+
+      // The spotlight attenuation factor.  This is really
+      // fast for what it does... 6 instructions for 4 spots.
+
+      float4 spotAtten = 0;
+      for ( i = 0; i < 3; i++ )
+         spotAtten += lightVectors[i] * inLightSpotDir[i];
+
+      float4 cosAngle = ( spotAtten * correction ) - inLightSpotAngle;
+      atten *= saturate( cosAngle * inLightSpotFalloff );
+
+   #endif
+
+   // Finally apply the shadow masking on the attenuation.
+   atten *= shadowMask;
+
+   // Get the final light intensity.
+   float4 intensity = nDotL * atten;
+
+   // Combine the light colors for output.
+   outDiffuse = 0;
+   for ( i = 0; i < 4; i++ )
+      outDiffuse += intensity[i] * inLightColor[i];
+
+   // Output the specular power.
+   float4 specularIntensity = pow( rDotL, float4(1,1,1,1) ) * atten;
+   
+   // Apply the per-light specular attenuation.
+   float4 specular = float4(0,0,0,1);
+   for ( i = 0; i < 4; i++ )
+      specular += float4( inLightColor[i].rgb * inLightColor[i].a * specularIntensity[i], 1 );
+
+   // Add the final specular intensity values together
+   // using a single dot product operation then get the
+   // final specular lighting color.
+   outSpecular = float4(1,1,1,1) * specular;
 }
 
 struct Surface
@@ -159,7 +271,7 @@ inline Surface createForwardSurface(float4 baseColor, float3 normal, float4 pbrP
 	surface.V = normalize(wsEyePos - surface.P);
 	surface.baseColor = baseColor;
   const float minRoughness=1e-4;
-	surface.roughness = clamp(1.0 - pbrProperties.b, minRoughness, 1); //t3d uses smoothness, so we convert to roughness.
+	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;
@@ -302,13 +414,13 @@ float3 boxProject(float3 wsPosition, float3 wsReflectVec, float4x4 worldToObj, f
 }
 
 float4 computeForwardProbes(Surface surface,
-    float cubeMips, float numProbes, float4x4 worldToObjArray[MAX_FORWARD_PROBES], float4 probeConfigData[MAX_FORWARD_PROBES], 
+    float cubeMips, int 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, TORQUE_SAMPLER2D(BRDFTexture), 
-	TORQUE_SAMPLERCUBE(skylightIrradMap), TORQUE_SAMPLERCUBE(skylightSpecularMap),
-	TORQUE_SAMPLERCUBEARRAY(irradianceCubemapAR), TORQUE_SAMPLERCUBEARRAY(specularCubemapAR))
+    float skylightCubemapIdx, TORQUE_SAMPLER2D(BRDFTexture), 
+	 TORQUE_SAMPLERCUBEARRAY(irradianceCubemapAR), TORQUE_SAMPLERCUBEARRAY(specularCubemapAR))
 {
-  int i = 0;
+   int i = 0;
+   float alpha = 1;
    float blendFactor[MAX_FORWARD_PROBES];
    float blendSum = 0;
    float blendFacSum = 0;
@@ -332,6 +444,8 @@ float4 computeForwardProbes(Surface surface,
          if (contribution[i] > 0.0)
             probehits++;
       }
+      else
+         continue;
 
       contribution[i] = max(contribution[i], 0);
 
@@ -360,8 +474,43 @@ float4 computeForwardProbes(Surface surface,
       {
          blendFactor[i] *= invBlendSumWeighted;
          contribution[i] *= blendFactor[i];
+         alpha -= contribution[i];
       }
    }
+   else
+      alpha -= blendSum;
+
+#if DEBUGVIZ_ATTENUATION == 1
+      float contribAlpha = 1;
+      for (i = 0; i < numProbes; ++i)
+      {
+         contribAlpha -= contribution[i];
+      }
+
+      return float4(1 - contribAlpha, 1 - contribAlpha, 1 - contribAlpha, 1);
+#endif
+
+#if DEBUGVIZ_CONTRIB == 1
+   float3 probeContribColors[4];
+   probeContribColors[0] = float3(1,0,0);
+   probeContribColors[1] = float3(0,1,0);
+   probeContribColors[2] = float3(0,0,1);
+   probeContribColors[3] = float3(1,1,0);
+
+   float3 finalContribColor = float3(0, 0, 0);
+   float contribAlpha = 1;
+   for (i = 0; i < numProbes; ++i)
+   {
+      finalContribColor += contribution[i] *probeContribColors[i].rgb;
+      contribAlpha -= contribution[i];
+   }
+
+   //Skylight coloration for anything not covered by probes above
+   if(skylightCubemapIdx != -1)
+      finalContribColor += float3(0.3, 0.3, 0.3) * contribAlpha;
+
+   return float4(finalContribColor, 1);
+#endif
 
    float3 irradiance = float3(0, 0, 0);
    float3 specular = float3(0, 0, 0);
@@ -369,7 +518,6 @@ float4 computeForwardProbes(Surface surface,
    // Radiance (Specular)
    float lod = surface.roughness*cubeMips;
 
-   float alpha = 1;
    for (i = 0; i < numProbes; ++i)
    {
       float contrib = contribution[i];
@@ -384,10 +532,10 @@ float4 computeForwardProbes(Surface surface,
       }
    }
 
-   if (hasSkylight && alpha > 0.001)
+   if(skylightCubemapIdx != -1 && alpha >= 0.001)
    {
-      irradiance += TORQUE_TEXCUBELOD(skylightIrradMap, float4(surface.R, 0)).xyz;
-      specular = TORQUE_TEXCUBELOD(skylightSpecularMap, float4(surface.R, lod)).xyz;
+      irradiance += TORQUE_TEXCUBEARRAYLOD(irradianceCubemapAR, surface.R, skylightCubemapIdx, 0).xyz * alpha;
+      specular += TORQUE_TEXCUBEARRAYLOD(specularCubemapAR, surface.R, skylightCubemapIdx, lod).xyz * alpha;
    }
 
    float3 F = FresnelSchlickRoughness(surface.NdotV, surface.f0, surface.roughness);
@@ -403,7 +551,7 @@ float4 computeForwardProbes(Surface surface,
 
    //final diffuse color
    float3 diffuse = kD * irradiance * surface.baseColor.rgb;
-   float4 finalColor = float4(diffuse + specular, 1); 
-//finalColor.rgb += abs(surface.N);
+   float4 finalColor = float4(diffuse + specular * surface.ao, 1.0);
+
    return finalColor;
 }

+ 1 - 4
Templates/BaseGame/game/data/StaticShapeTest/Shapes/materials.cs

@@ -14,11 +14,8 @@ singleton Material(Grid_512_Orange)
    specularStrength0 = "25";
    specular0 = "0.8 0.8 0.8 1";
    specularPower0 = "0.25";
-   emissive[0] = "1";
+   emissive[0] = "0";
    translucent = "1";
    normalMap[0] = "data/pbr/images/FloorEbony_normal.png";
    invertSmoothness[0] = "1";
-   roughMap[0] = "data/pbr/images/FloorEbony_rough.png";
-   aoMap[0] = "data/pbr/images/FloorEbony_ao.png";
-   metalMap[0] = "data/pbr/images/FloorEbony_metal.png";
 };

+ 170 - 0
Templates/BaseGame/game/tools/materialEditor/gui/materialInstancesView.ed.gui

@@ -0,0 +1,170 @@
+//--- OBJECT WRITE BEGIN ---
+%guiContent = new GuiControl(MaterialInstanceViewCtrl) {
+   position = "0 0";
+   extent = "1024 768";
+   minExtent = "8 2";
+   horizSizing = "right";
+   vertSizing = "bottom";
+   profile = "GuiDefaultProfile";
+   visible = "1";
+   active = "1";
+   tooltipProfile = "GuiToolTipProfile";
+   hovertime = "1000";
+   isContainer = "1";
+   canSave = "1";
+   canSaveDynamicFields = "1";
+
+   new GuiWindowCtrl(MaterialInstanceViewWindow) {
+      text = "Material Instances Viewer";
+      resizeWidth = "1";
+      resizeHeight = "1";
+      canMove = "1";
+      canClose = "1";
+      canMinimize = "1";
+      canMaximize = "1";
+      canCollapse = "0";
+      closeCommand = "Canvas.popDialog(MaterialInstanceViewCtrl);";
+      edgeSnap = "1";
+      margin = "0 0 0 0";
+      padding = "0 0 0 0";
+      anchorTop = "1";
+      anchorBottom = "0";
+      anchorLeft = "1";
+      anchorRight = "0";
+      position = "429 123";
+      extent = "550 550";
+      minExtent = "8 2";
+      horizSizing = "right";
+      vertSizing = "bottom";
+      profile = "ToolsGuiWindowProfile";
+      visible = "1";
+      active = "1";
+      tooltipProfile = "GuiToolTipProfile";
+      hovertime = "1000";
+      isContainer = "1";
+      canSave = "1";
+      canSaveDynamicFields = "0";
+
+      new GuiTextEditCtrl(MaterialInstanceFilter) {
+         historySize = "0";
+         tabComplete = "0";
+         sinkAllKeyEvents = "0";
+         password = "0";
+         passwordMask = "*";
+         text = "\c2Filter...";
+         maxLength = "1024";
+         margin = "0 0 0 0";
+         padding = "0 0 0 0";
+         anchorTop = "1";
+         anchorBottom = "0";
+         anchorLeft = "1";
+         anchorRight = "0";
+         position = "11 21";
+         extent = "516 18";
+         minExtent = "8 2";
+         horizSizing = "width";
+         vertSizing = "bottom";
+         profile = "ToolsGuiTextEditProfile";
+         visible = "1";
+         active = "1";
+         tooltipProfile = "GuiToolTipProfile";
+         hovertime = "1000";
+         isContainer = "1";
+         class = "AssetBrowserSearchFilterText";
+         canSave = "1";
+         canSaveDynamicFields = "0";
+      };
+      new GuiBitmapButtonCtrl(MaterialInstanceFilterBtn) {
+         bitmap = "tools/gui/images/delete";
+         bitmapMode = "Stretched";
+         autoFitExtents = "0";
+         useModifiers = "0";
+         useStates = "1";
+         masked = "0";
+         groupNum = "-1";
+         buttonType = "PushButton";
+         useMouseEvents = "0";
+         position = "529 22";
+         extent = "15 15";
+         minExtent = "8 2";
+         horizSizing = "left";
+         vertSizing = "bottom";
+         profile = "ToolsGuiDefaultProfile";
+         visible = "1";
+         active = "1";
+         tooltipProfile = "GuiToolTipProfile";
+         tooltip = "Delete Asset";
+         hovertime = "1000";
+         isContainer = "0";
+         canSave = "1";
+         canSaveDynamicFields = "0";
+      };
+      new GuiScrollCtrl() {
+         willFirstRespond = "1";
+         hScrollBar = "dynamic";
+         vScrollBar = "dynamic";
+         lockHorizScroll = "0";
+         lockVertScroll = "0";
+         constantThumbHeight = "0";
+         childMargin = "0 0";
+         mouseWheelScrollSpeed = "-1";
+         margin = "0 0 0 0";
+         padding = "0 0 0 0";
+         anchorTop = "1";
+         anchorBottom = "0";
+         anchorLeft = "1";
+         anchorRight = "0";
+         position = "0 38";
+         extent = "550 510";
+         minExtent = "8 2";
+         horizSizing = "width";
+         vertSizing = "height";
+         profile = "ToolsGuiScrollProfile";
+         visible = "1";
+         active = "1";
+         tooltipProfile = "GuiToolTipProfile";
+         hovertime = "1000";
+         isContainer = "1";
+         canSave = "1";
+         canSaveDynamicFields = "0";
+
+         new GuiTreeViewCtrl(MaterialInstanceViewTree) {
+            tabSize = "16";
+            textOffset = "2";
+            fullRowSelect = "0";
+            itemHeight = "21";
+            destroyTreeOnSleep = "1";
+            mouseDragging = "1";
+            multipleSelections = "1";
+            deleteObjectAllowed = "1";
+            dragToItemAllowed = "1";
+            clearAllOnSingleSelection = "1";
+            showRoot = "1";
+            useInspectorTooltips = "0";
+            tooltipOnWidthOnly = "0";
+            showObjectIds = "1";
+            showClassNames = "1";
+            showObjectNames = "1";
+            showInternalNames = "1";
+            showClassNameForUnnamedObjects = "0";
+            compareToObjectID = "1";
+            canRenameObjects = "1";
+            renameInternal = "0";
+            position = "1 1";
+            extent = "550 510";
+            minExtent = "8 2";
+            horizSizing = "width";
+            vertSizing = "height";
+            profile = "ToolsGuiTreeViewProfile";
+            visible = "1";
+            active = "1";
+            tooltipProfile = "GuiToolTipProfile";
+            hovertime = "1000";
+            isContainer = "1";
+            canSave = "1";
+            canSaveDynamicFields = "0";
+         };
+      };
+   };
+};
+//--- OBJECT WRITE END ---

+ 27 - 0
Templates/BaseGame/game/tools/materialEditor/scripts/materialInstanceView.ed.cs

@@ -0,0 +1,27 @@
+function MaterialInstanceFilter::onGainFirstResponder( %this )
+{
+   %this.selectAllText();
+}
+
+function MaterialInstanceFilter::onReturn( %this )
+{
+   %text = %this.getText();
+   if( %text $= "" )
+   {
+      %this.reset();
+      MaterialInstanceViewTree.clearFilterText();
+   }
+   else
+   {
+      MaterialInstanceViewTree.setFilterText(%text);
+   }
+   
+   MaterialInstanceViewTree.buildVisibleTree(true);
+}
+
+function MaterialInstanceFilterBtn::onClick(%this)
+{
+   MaterialInstanceFilter.reset();
+   MaterialInstanceViewTree.clearFilterText();
+   MaterialInstanceViewTree.buildVisibleTree(true);
+}

+ 24 - 3
Templates/Full/game/tools/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui

@@ -4476,7 +4476,7 @@
             isContainer = "0";
             HorizSizing = "left";
             VertSizing = "bottom";
-            position = "86 1";
+            position = "66 1";
             Extent = "16 16";
             MinExtent = "8 2";
             canSave = "1";
@@ -4497,7 +4497,7 @@
             Profile = "ToolsGuiDefaultProfile";
             HorizSizing = "left";
             VertSizing = "bottom";
-            position = "106 1";
+            position = "86 1";
             Extent = "16 16";
             MinExtent = "8 2";
             canSave = "1";
@@ -4519,7 +4519,7 @@
             Profile = "ToolsGuiDefaultProfile";
             HorizSizing = "left";
             VertSizing = "bottom";
-            position = "123 1";
+            position = "106 1";
             Extent = "16 16";
             MinExtent = "8 2";
             canSave = "1";
@@ -4533,6 +4533,27 @@
             useMouseEvents = "0";
             bitmap = "tools/gui/images/save-icon";
          };
+         new GuiBitmapButtonCtrl() {
+            canSaveDynamicFields = "0";
+            Enabled = "1";
+            isContainer = "0";
+            Profile = "ToolsGuiDefaultProfile";
+            HorizSizing = "left";
+            VertSizing = "bottom";
+            position = "126 1";
+            Extent = "16 16";
+            MinExtent = "8 2";
+            canSave = "1";
+            Visible = "1";
+            Command = "MaterialEditorGui.lookupMaterialInstances();";
+            hovertime = "1000";
+            groupNum = "-1";
+            text ="";
+            tooltip = "Lookup Material Instances";
+            buttonType = "PushButton";
+            useMouseEvents = "0";
+            bitmap = "tools/gui/images/visible";
+         };
          new GuiBitmapCtrl(){
             position = "147 1";
             Extent = "2 16";

+ 170 - 0
Templates/Full/game/tools/materialEditor/gui/materialInstancesView.ed.gui

@@ -0,0 +1,170 @@
+//--- OBJECT WRITE BEGIN ---
+%guiContent = new GuiControl(MaterialInstanceViewCtrl) {
+   position = "0 0";
+   extent = "1024 768";
+   minExtent = "8 2";
+   horizSizing = "right";
+   vertSizing = "bottom";
+   profile = "GuiDefaultProfile";
+   visible = "1";
+   active = "1";
+   tooltipProfile = "GuiToolTipProfile";
+   hovertime = "1000";
+   isContainer = "1";
+   canSave = "1";
+   canSaveDynamicFields = "1";
+
+   new GuiWindowCtrl(MaterialInstanceViewWindow) {
+      text = "Material Instances Viewer";
+      resizeWidth = "1";
+      resizeHeight = "1";
+      canMove = "1";
+      canClose = "1";
+      canMinimize = "1";
+      canMaximize = "1";
+      canCollapse = "0";
+      closeCommand = "Canvas.popDialog(MaterialInstanceViewCtrl);";
+      edgeSnap = "1";
+      margin = "0 0 0 0";
+      padding = "0 0 0 0";
+      anchorTop = "1";
+      anchorBottom = "0";
+      anchorLeft = "1";
+      anchorRight = "0";
+      position = "429 123";
+      extent = "550 550";
+      minExtent = "8 2";
+      horizSizing = "right";
+      vertSizing = "bottom";
+      profile = "ToolsGuiWindowProfile";
+      visible = "1";
+      active = "1";
+      tooltipProfile = "GuiToolTipProfile";
+      hovertime = "1000";
+      isContainer = "1";
+      canSave = "1";
+      canSaveDynamicFields = "0";
+
+      new GuiTextEditCtrl(MaterialInstanceFilter) {
+         historySize = "0";
+         tabComplete = "0";
+         sinkAllKeyEvents = "0";
+         password = "0";
+         passwordMask = "*";
+         text = "\c2Filter...";
+         maxLength = "1024";
+         margin = "0 0 0 0";
+         padding = "0 0 0 0";
+         anchorTop = "1";
+         anchorBottom = "0";
+         anchorLeft = "1";
+         anchorRight = "0";
+         position = "11 21";
+         extent = "516 18";
+         minExtent = "8 2";
+         horizSizing = "width";
+         vertSizing = "bottom";
+         profile = "ToolsGuiTextEditProfile";
+         visible = "1";
+         active = "1";
+         tooltipProfile = "GuiToolTipProfile";
+         hovertime = "1000";
+         isContainer = "1";
+         class = "AssetBrowserSearchFilterText";
+         canSave = "1";
+         canSaveDynamicFields = "0";
+      };
+      new GuiBitmapButtonCtrl(MaterialInstanceFilterBtn) {
+         bitmap = "tools/gui/images/delete";
+         bitmapMode = "Stretched";
+         autoFitExtents = "0";
+         useModifiers = "0";
+         useStates = "1";
+         masked = "0";
+         groupNum = "-1";
+         buttonType = "PushButton";
+         useMouseEvents = "0";
+         position = "529 22";
+         extent = "15 15";
+         minExtent = "8 2";
+         horizSizing = "left";
+         vertSizing = "bottom";
+         profile = "ToolsGuiDefaultProfile";
+         visible = "1";
+         active = "1";
+         tooltipProfile = "GuiToolTipProfile";
+         tooltip = "Delete Asset";
+         hovertime = "1000";
+         isContainer = "0";
+         canSave = "1";
+         canSaveDynamicFields = "0";
+      };
+      new GuiScrollCtrl() {
+         willFirstRespond = "1";
+         hScrollBar = "dynamic";
+         vScrollBar = "dynamic";
+         lockHorizScroll = "0";
+         lockVertScroll = "0";
+         constantThumbHeight = "0";
+         childMargin = "0 0";
+         mouseWheelScrollSpeed = "-1";
+         margin = "0 0 0 0";
+         padding = "0 0 0 0";
+         anchorTop = "1";
+         anchorBottom = "0";
+         anchorLeft = "1";
+         anchorRight = "0";
+         position = "0 38";
+         extent = "550 510";
+         minExtent = "8 2";
+         horizSizing = "width";
+         vertSizing = "height";
+         profile = "ToolsGuiScrollProfile";
+         visible = "1";
+         active = "1";
+         tooltipProfile = "GuiToolTipProfile";
+         hovertime = "1000";
+         isContainer = "1";
+         canSave = "1";
+         canSaveDynamicFields = "0";
+
+         new GuiTreeViewCtrl(MaterialInstanceViewTree) {
+            tabSize = "16";
+            textOffset = "2";
+            fullRowSelect = "0";
+            itemHeight = "21";
+            destroyTreeOnSleep = "1";
+            mouseDragging = "1";
+            multipleSelections = "1";
+            deleteObjectAllowed = "1";
+            dragToItemAllowed = "1";
+            clearAllOnSingleSelection = "1";
+            showRoot = "1";
+            useInspectorTooltips = "0";
+            tooltipOnWidthOnly = "0";
+            showObjectIds = "1";
+            showClassNames = "1";
+            showObjectNames = "1";
+            showInternalNames = "1";
+            showClassNameForUnnamedObjects = "0";
+            compareToObjectID = "1";
+            canRenameObjects = "1";
+            renameInternal = "0";
+            position = "1 1";
+            extent = "550 510";
+            minExtent = "8 2";
+            horizSizing = "width";
+            vertSizing = "height";
+            profile = "ToolsGuiTreeViewProfile";
+            visible = "1";
+            active = "1";
+            tooltipProfile = "GuiToolTipProfile";
+            hovertime = "1000";
+            isContainer = "1";
+            canSave = "1";
+            canSaveDynamicFields = "0";
+         };
+      };
+   };
+};
+//--- OBJECT WRITE END ---

+ 4 - 0
Templates/Full/game/tools/materialEditor/main.cs

@@ -32,9 +32,13 @@ function initializeMaterialEditor()
    // Load Properties Window
    exec("~/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui");
    
+   //Material Instance viewer
+   exec("~/materialEditor/gui/materialInstancesView.ed.gui");
+   
    // Load Client Scripts.
    exec("./scripts/materialEditor.ed.cs");
    exec("./scripts/materialEditorUndo.ed.cs");
+   exec("./scripts/materialInstanceView.ed.cs");
    //exec("./gui/profiles.ed.cs");
    
    MaterialEditorPreviewWindow.setVisible( false );

+ 26 - 0
Templates/Full/game/tools/materialEditor/scripts/materialEditor.ed.cs

@@ -2278,6 +2278,32 @@ function MaterialEditorGui::refreshMaterial(%this)
    MaterialEditorGui.setMaterialNotDirty();
 }
 
+//==============================================================================
+// Looking up material instances/getting mat info 
+function MaterialEditorGui::lookupMaterialInstances( %this )
+{
+   if( MaterialEditorGui.currentMaterial.getName() $= "" )
+   {
+      MessageBoxOK("Cannot perform operation", "Unable to look up a material with a blank name" );
+      return;   
+   }
+   
+   MaterialInstanceViewTree.clear();
+   MaterialInstanceViewTree.setFilterChildren(false);
+   MaterialInstanceViewTree.setItemFilterException(1, true);
+   
+   MaterialEditorGui.currentMaterial.getMaterialInstances(MaterialInstanceViewTree);
+   
+   if(MaterialInstanceFilter.Text !$= "\c2Filter...")
+   {
+      MaterialInstanceViewTree.setFilterText(MaterialInstanceFilter.Text);
+   }
+   
+   MaterialInstanceViewTree.buildVisibleTree(true);
+   
+   Canvas.pushDialog(MaterialInstanceViewCtrl);
+}
+
 //==============================================================================
 // Switching and Changing Materials
 

+ 27 - 0
Templates/Full/game/tools/materialEditor/scripts/materialInstanceView.ed.cs

@@ -0,0 +1,27 @@
+function MaterialInstanceFilter::onGainFirstResponder( %this )
+{
+   %this.selectAllText();
+}
+
+function MaterialInstanceFilter::onReturn( %this )
+{
+   %text = %this.getText();
+   if( %text $= "" )
+   {
+      %this.reset();
+      MaterialInstanceViewTree.clearFilterText();
+   }
+   else
+   {
+      MaterialInstanceViewTree.setFilterText(%text);
+   }
+   
+   MaterialInstanceViewTree.buildVisibleTree(true);
+}
+
+function MaterialInstanceFilterBtn::onClick(%this)
+{
+   MaterialInstanceFilter.reset();
+   MaterialInstanceViewTree.clearFilterText();
+   MaterialInstanceViewTree.buildVisibleTree(true);
+}