diff --git a/Engine/source/gfx/genericConstBuffer.cpp b/Engine/source/gfx/genericConstBuffer.cpp index 77ff398fe..185150720 100644 --- a/Engine/source/gfx/genericConstBuffer.cpp +++ b/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 ) ); } } diff --git a/Engine/source/lighting/lightManager.cpp b/Engine/source/lighting/lightManager.cpp index 82faeaf68..74b4e5cb9 100644 --- a/Engine/source/lighting/lightManager.cpp +++ b/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 diff --git a/Engine/source/materials/processedShaderMaterial.cpp b/Engine/source/materials/processedShaderMaterial.cpp index 6b2b0632a..5c911be1e 100644 --- a/Engine/source/materials/processedShaderMaterial.cpp +++ b/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 ) diff --git a/Engine/source/materials/processedShaderMaterial.h b/Engine/source/materials/processedShaderMaterial.h index 2bd0ecb4a..d64471278 100644 --- a/Engine/source/materials/processedShaderMaterial.h +++ b/Engine/source/materials/processedShaderMaterial.h @@ -40,7 +40,6 @@ class ShaderMaterialParameterHandle; class ShaderFeatureConstHandles; class CustomMaterial; - class ShaderConstHandles { public: diff --git a/Engine/source/renderInstance/renderProbeMgr.cpp b/Engine/source/renderInstance/renderProbeMgr.cpp index c8b590527..e1f2a2ac6 100644 --- a/Engine/source/renderInstance/renderProbeMgr.cpp +++ b/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, diff --git a/Engine/source/renderInstance/renderProbeMgr.h b/Engine/source/renderInstance/renderProbeMgr.h index 911e05a21..8d01b8ae8 100644 --- a/Engine/source/renderInstance/renderProbeMgr.h +++ b/Engine/source/renderInstance/renderProbeMgr.h @@ -151,9 +151,7 @@ struct ProbeShaderConstants GFXShaderConstHandle *mBRDFTextureMap; - GFXShaderConstHandle *mSkylightSpecularMap; - GFXShaderConstHandle *mSkylightIrradMap; - GFXShaderConstHandle *mHasSkylight; + GFXShaderConstHandle *mSkylightCubemapIdxSC; ProbeShaderConstants(); ~ProbeShaderConstants(); diff --git a/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp b/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp index 3da4fe5ff..8a8caf90b 100644 --- a/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp +++ b/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp @@ -2980,7 +2980,7 @@ void ReflectionProbeFeatHLSL::processPix(Vector &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 &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 &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 &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; } } diff --git a/Engine/source/shaderGen/shaderGenVars.cpp b/Engine/source/shaderGen/shaderGenVars.cpp index d09460e3c..083bd09ac 100644 --- a/Engine/source/shaderGen/shaderGenVars.cpp +++ b/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"); \ No newline at end of file +const String ShaderGenVars::matInfoFlags("$matInfoFlags"); diff --git a/Engine/source/shaderGen/shaderGenVars.h b/Engine/source/shaderGen/shaderGenVars.h index 253542fee..d5612d600 100644 --- a/Engine/source/shaderGen/shaderGenVars.h +++ b/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; diff --git a/Templates/BaseGame/game/core/rendering/shaders/lighting.hlsl b/Templates/BaseGame/game/core/rendering/shaders/lighting.hlsl index 03dd662cd..070eb4aca 100644 --- a/Templates/BaseGame/game/core/rendering/shaders/lighting.hlsl +++ b/Templates/BaseGame/game/core/rendering/shaders/lighting.hlsl @@ -88,9 +88,121 @@ void compute4Lights( float3 wsView, out float4 outDiffuse, out float4 outSpecular ) { + // 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; - outDiffuse = float4(0,0,0,0); - outSpecular = float4(0,0,0,0); + 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; } \ No newline at end of file diff --git a/Templates/BaseGame/game/data/StaticShapeTest/Shapes/materials.cs b/Templates/BaseGame/game/data/StaticShapeTest/Shapes/materials.cs index 553b67c8d..4754ef45f 100644 --- a/Templates/BaseGame/game/data/StaticShapeTest/Shapes/materials.cs +++ b/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"; }; diff --git a/Templates/BaseGame/game/tools/materialEditor/gui/materialInstancesView.ed.gui b/Templates/BaseGame/game/tools/materialEditor/gui/materialInstancesView.ed.gui new file mode 100644 index 000000000..ce5c683de --- /dev/null +++ b/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 --- diff --git a/Templates/BaseGame/game/tools/materialEditor/scripts/materialInstanceView.ed.cs b/Templates/BaseGame/game/tools/materialEditor/scripts/materialInstanceView.ed.cs new file mode 100644 index 000000000..e341374ca --- /dev/null +++ b/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); +} \ No newline at end of file diff --git a/Templates/Full/game/tools/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui b/Templates/Full/game/tools/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui index a759cc42e..8ea587cd6 100644 --- a/Templates/Full/game/tools/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui +++ b/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"; diff --git a/Templates/Full/game/tools/materialEditor/gui/materialInstancesView.ed.gui b/Templates/Full/game/tools/materialEditor/gui/materialInstancesView.ed.gui new file mode 100644 index 000000000..ce5c683de --- /dev/null +++ b/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 --- diff --git a/Templates/Full/game/tools/materialEditor/main.cs b/Templates/Full/game/tools/materialEditor/main.cs index f8d054ce7..2b1149a31 100644 --- a/Templates/Full/game/tools/materialEditor/main.cs +++ b/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 ); diff --git a/Templates/Full/game/tools/materialEditor/scripts/materialEditor.ed.cs b/Templates/Full/game/tools/materialEditor/scripts/materialEditor.ed.cs index 191e77bf6..2066d7c4e 100644 --- a/Templates/Full/game/tools/materialEditor/scripts/materialEditor.ed.cs +++ b/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 diff --git a/Templates/Full/game/tools/materialEditor/scripts/materialInstanceView.ed.cs b/Templates/Full/game/tools/materialEditor/scripts/materialInstanceView.ed.cs new file mode 100644 index 000000000..e341374ca --- /dev/null +++ b/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); +} \ No newline at end of file