diff --git a/Engine/source/gfx/D3D9/gfxD3D9Shader.cpp b/Engine/source/gfx/D3D9/gfxD3D9Shader.cpp index a7ff68a78..2af7a9abd 100644 --- a/Engine/source/gfx/D3D9/gfxD3D9Shader.cpp +++ b/Engine/source/gfx/D3D9/gfxD3D9Shader.cpp @@ -1101,11 +1101,13 @@ void GFXD3D9Shader::_getShaderConstants( ID3DXConstantTable *table, desc.constType = GFXSCT_Sampler; desc.arraySize = constantDesc.RegisterIndex; samplerDescriptions.push_back( desc ); + mShaderConsts.push_back(desc); break; case D3DXPT_SAMPLERCUBE : desc.constType = GFXSCT_SamplerCube; desc.arraySize = constantDesc.RegisterIndex; samplerDescriptions.push_back( desc ); + mShaderConsts.push_back(desc); break; } } @@ -1371,7 +1373,7 @@ GFXShaderConstBufferRef GFXD3D9Shader::allocConstBuffer() } } -/// Returns a shader constant handle for name, if the variable doesn't exist NULL is returned. +/// Returns a shader constant handle for name GFXShaderConstHandle* GFXD3D9Shader::getShaderConstHandle(const String& name) { HandleMap::Iterator i = mHandles.find(name); @@ -1390,6 +1392,20 @@ GFXShaderConstHandle* GFXD3D9Shader::getShaderConstHandle(const String& name) } } +/// Returns a shader constant handle for name, if the variable doesn't exist NULL is returned. +GFXShaderConstHandle* GFXD3D9Shader::findShaderConstHandle(const String& name) +{ + HandleMap::Iterator i = mHandles.find(name); + if ( i != mHandles.end() ) + { + return i->value; + } + else + { + return NULL; + } +} + const Vector& GFXD3D9Shader::getShaderConstDesc() const { return mShaderConsts; diff --git a/Engine/source/gfx/D3D9/gfxD3D9Shader.h b/Engine/source/gfx/D3D9/gfxD3D9Shader.h index 1db493cf7..ccc3af282 100644 --- a/Engine/source/gfx/D3D9/gfxD3D9Shader.h +++ b/Engine/source/gfx/D3D9/gfxD3D9Shader.h @@ -205,6 +205,7 @@ public: virtual GFXShaderConstBufferRef allocConstBuffer(); virtual const Vector& getShaderConstDesc() const; virtual GFXShaderConstHandle* getShaderConstHandle(const String& name); + virtual GFXShaderConstHandle* findShaderConstHandle(const String& name); virtual U32 getAlignmentValue(const GFXShaderConstType constType) const; virtual bool getDisassembly( String &outStr ) const; diff --git a/Engine/source/gfx/gfxDevice.h b/Engine/source/gfx/gfxDevice.h index a46ddbd98..2fa414cdd 100644 --- a/Engine/source/gfx/gfxDevice.h +++ b/Engine/source/gfx/gfxDevice.h @@ -1117,4 +1117,10 @@ inline void GFXDevice::setVertexFormat( const GFXVertexFormat *vertexFormat ) } +#if defined(TORQUE_DEBUG) && defined(TORQUE_DEBUG_GFX) +#define GFXAssertFatal(x, error) AssertFatal(x, error) +#else +#define GFXAssertFatal(x, error) +#endif + #endif // _GFXDEVICE_H_ diff --git a/Engine/source/gfx/gfxShader.h b/Engine/source/gfx/gfxShader.h index 4b2c10f46..318ab5ec0 100644 --- a/Engine/source/gfx/gfxShader.h +++ b/Engine/source/gfx/gfxShader.h @@ -332,6 +332,9 @@ public: /// if the constant doesn't exist at this time. virtual GFXShaderConstHandle* getShaderConstHandle( const String& name ) = 0; + /// Returns a shader constant handle for the name constant, if the variable doesn't exist NULL is returned. + virtual GFXShaderConstHandle* findShaderConstHandle( const String& name ) = 0; + /// Returns the alignment value for constType virtual U32 getAlignmentValue(const GFXShaderConstType constType) const = 0; diff --git a/Engine/source/lighting/advanced/hlsl/advancedLightingFeaturesHLSL.cpp b/Engine/source/lighting/advanced/hlsl/advancedLightingFeaturesHLSL.cpp index 9e04f3f76..661530bf3 100644 --- a/Engine/source/lighting/advanced/hlsl/advancedLightingFeaturesHLSL.cpp +++ b/Engine/source/lighting/advanced/hlsl/advancedLightingFeaturesHLSL.cpp @@ -98,7 +98,7 @@ void DeferredRTLightingFeatHLSL::processPix( Vector &component uvScene->setName( "uvScene" ); LangElement *uvSceneDecl = new DecOp( uvScene ); - String rtParamName = String::ToString( "rtParams%d", mLastTexIndex ); + String rtParamName = String::ToString( "rtParams%s", "lightInfoBuffer" ); Var *rtParams = (Var*) LangElement::find( rtParamName ); if( !rtParams ) { @@ -207,6 +207,7 @@ void DeferredRTLightingFeatHLSL::setTexData( Material::StageData &stageDat, mLastTexIndex = texIndex; passData.mTexType[ texIndex ] = Material::TexTarget; + passData.mSamplerNames[ texIndex ]= "lightInfoBuffer"; passData.mTexSlot[ texIndex++ ].texTarget = texTarget; } } @@ -402,12 +403,14 @@ void DeferredBumpFeatHLSL::setTexData( Material::StageData &stageDat, fd.features[MFT_PixSpecular] ) ) { passData.mTexType[ texIndex ] = Material::Bump; + passData.mSamplerNames[ texIndex ] = "bumpMap"; passData.mTexSlot[ texIndex++ ].texObject = stageDat.getTex( MFT_NormalMap ); if ( fd.features[MFT_PrePassConditioner] && fd.features.hasFeature( MFT_DetailNormalMap ) ) { passData.mTexType[ texIndex ] = Material::DetailBump; + passData.mSamplerNames[ texIndex ] = "detailBumpMap"; passData.mTexSlot[ texIndex++ ].texObject = stageDat.getTex( MFT_DetailNormalMap ); } } diff --git a/Engine/source/materials/customMaterialDefinition.cpp b/Engine/source/materials/customMaterialDefinition.cpp index c61a10a34..bda6a9afe 100644 --- a/Engine/source/materials/customMaterialDefinition.cpp +++ b/Engine/source/materials/customMaterialDefinition.cpp @@ -138,9 +138,25 @@ bool CustomMaterial::onAdd() return false; } - mSamplerNames[i] = entry->slotName + dStrlen(samplerDecl); - mSamplerNames[i].insert(0, '$'); - mTexFilename[i] = entry->value; + // Assert sampler names are defined on ShaderData + S32 pos = -1; + String samplerName = entry->slotName + dStrlen(samplerDecl); + samplerName.insert(0, '$'); + mShaderData->hasSamplerDef(samplerName, pos); + + if(pos == -1) + { + const char *error = (avar("CustomMaterial(%s) bind sampler[%s] and is not present on ShaderData(%s)", + getName(), samplerName.c_str(), mShaderDataName.c_str() )); + Con::errorf(error); + +#if TORQUE_OPENGL + GFXAssertFatal(0, error); + continue; +#endif + } + mSamplerNames[pos] = samplerName; + mTexFilename[pos] = entry->value; ++i; } } diff --git a/Engine/source/materials/processedCustomMaterial.cpp b/Engine/source/materials/processedCustomMaterial.cpp index 2c26b14da..7c225362f 100644 --- a/Engine/source/materials/processedCustomMaterial.cpp +++ b/Engine/source/materials/processedCustomMaterial.cpp @@ -79,6 +79,7 @@ void ProcessedCustomMaterial::_setStageData() if(filename.equal(String("$dynamiclight"), String::NoCase)) { rpd->mTexType[i] = Material::DynamicLight; + rpd->mSamplerNames[i] = mCustomMaterial->mSamplerNames[i]; mMaxTex = i+1; continue; } @@ -86,6 +87,7 @@ void ProcessedCustomMaterial::_setStageData() if(filename.equal(String("$dynamiclightmask"), String::NoCase)) { rpd->mTexType[i] = Material::DynamicLightMask; + rpd->mSamplerNames[i] = mCustomMaterial->mSamplerNames[i]; mMaxTex = i+1; continue; } @@ -93,6 +95,7 @@ void ProcessedCustomMaterial::_setStageData() if(filename.equal(String("$lightmap"), String::NoCase)) { rpd->mTexType[i] = Material::Lightmap; + rpd->mSamplerNames[i] = mCustomMaterial->mSamplerNames[i]; mMaxTex = i+1; continue; } @@ -102,6 +105,7 @@ void ProcessedCustomMaterial::_setStageData() if( mCustomMaterial->mCubemapData ) { rpd->mTexType[i] = Material::Cube; + rpd->mSamplerNames[i] = mCustomMaterial->mSamplerNames[i]; mMaxTex = i+1; } else @@ -114,6 +118,7 @@ void ProcessedCustomMaterial::_setStageData() if(filename.equal(String("$dynamicCubemap"), String::NoCase)) { rpd->mTexType[i] = Material::SGCube; + rpd->mSamplerNames[i] = mCustomMaterial->mSamplerNames[i]; mMaxTex = i+1; continue; } @@ -121,6 +126,7 @@ void ProcessedCustomMaterial::_setStageData() if(filename.equal(String("$backbuff"), String::NoCase)) { rpd->mTexType[i] = Material::BackBuff; + rpd->mSamplerNames[i] = mCustomMaterial->mSamplerNames[i]; mMaxTex = i+1; continue; } @@ -128,6 +134,7 @@ void ProcessedCustomMaterial::_setStageData() if(filename.equal(String("$reflectbuff"), String::NoCase)) { rpd->mTexType[i] = Material::ReflectBuff; + rpd->mSamplerNames[i] = mCustomMaterial->mSamplerNames[i]; mMaxTex = i+1; continue; } @@ -135,6 +142,7 @@ void ProcessedCustomMaterial::_setStageData() if(filename.equal(String("$miscbuff"), String::NoCase)) { rpd->mTexType[i] = Material::Misc; + rpd->mSamplerNames[i] = mCustomMaterial->mSamplerNames[i]; mMaxTex = i+1; continue; } @@ -151,6 +159,7 @@ void ProcessedCustomMaterial::_setStageData() texTarget->getShaderMacros( &mConditionerMacros ); rpd->mTexType[i] = Material::TexTarget; + rpd->mSamplerNames[i] = mCustomMaterial->mSamplerNames[i]; mMaxTex = i+1; continue; } @@ -162,6 +171,7 @@ void ProcessedCustomMaterial::_setStageData() continue; } rpd->mTexType[i] = Material::Standard; + rpd->mSamplerNames[i] = mCustomMaterial->mSamplerNames[i]; mMaxTex = i+1; } @@ -232,6 +242,20 @@ bool ProcessedCustomMaterial::init( const FeatureSet &features, setMaterialParameters( mDefaultParameters, 0 ); mStateHint.init( this ); + for(int i = 0; i < mMaxTex; i++) + { + ShaderConstHandles *handles = _getShaderConstHandles( mPasses.size()-1 ); + AssertFatal(handles,""); + + if(rpd->mSamplerNames[i].isEmpty()) + continue; + + String samplerName = rpd->mSamplerNames[i].startsWith("$") ? rpd->mSamplerNames[i] : String("$") + rpd->mSamplerNames[i]; + GFXShaderConstHandle *handle = rpd->shader->getShaderConstHandle( samplerName ); + AssertFatal(handle,""); + handles->mTexHandlesSC[i] = handle; + } + return true; } @@ -384,14 +408,14 @@ void ProcessedCustomMaterial::setTextureStages( SceneRenderState *state, const S if ( !texObject ) texObject = GFXTexHandle::ZERO; - if ( handles->mRTParamsSC[samplerRegister]->isValid() && texObject ) + if ( handles->mRTParamsSC[i]->isValid() && texObject ) { const Point3I &targetSz = texObject->getSize(); const RectI &targetVp = texTarget->getViewport(); Point4F rtParams; ScreenSpace::RenderTargetParameters(targetSz, targetVp, rtParams); - shaderConsts->set(handles->mRTParamsSC[samplerRegister], rtParams); + shaderConsts->set(handles->mRTParamsSC[i], rtParams); } GFX->setTexture( samplerRegister, texObject ); diff --git a/Engine/source/materials/processedShaderMaterial.cpp b/Engine/source/materials/processedShaderMaterial.cpp index 03b8172d1..723129404 100644 --- a/Engine/source/materials/processedShaderMaterial.cpp +++ b/Engine/source/materials/processedShaderMaterial.cpp @@ -221,6 +221,7 @@ bool ProcessedShaderMaterial::init( const FeatureSet &features, { rpd->mTexSlot[0].texTarget = texTarget; rpd->mTexType[0] = Material::TexTarget; + rpd->mSamplerNames[0] = "diffuseMap"; } } @@ -516,8 +517,23 @@ bool ProcessedShaderMaterial::_createPasses( MaterialFeatureData &stageFeatures, passData.mNumTexReg += numTexReg; passData.mFeatureData.features.addFeature( *info.type ); + +#if defined(TORQUE_DEBUG) && defined( TORQUE_OPENGL) + U32 oldTexNumber = texIndex; +#endif + info.feature->setTexData( mStages[stageNum], stageFeatures, passData, texIndex ); +#if defined(TORQUE_DEBUG) && defined( TORQUE_OPENGL) + if(oldTexNumber != texIndex) + { + for(int i = oldTexNumber; i < texIndex; i++) + { + AssertFatal(passData.mSamplerNames[ oldTexNumber ].isNotEmpty(), avar( "ERROR: ShaderGen feature %s don't set used sampler name", info.feature->getName().c_str()) ); + } + } +#endif + // Add pass if tex units are maxed out if( texIndex > GFX->getNumSamplers() ) { @@ -527,6 +543,13 @@ bool ProcessedShaderMaterial::_createPasses( MaterialFeatureData &stageFeatures, } } +#if defined(TORQUE_DEBUG) && defined( TORQUE_OPENGL) + for(int i = 0; i < texIndex; i++) + { + AssertFatal(passData.mSamplerNames[ i ].isNotEmpty(),""); + } +#endif + const FeatureSet &passFeatures = passData.mFeatureData.codify(); if ( passFeatures.isNotEmpty() ) { @@ -587,9 +610,16 @@ bool ProcessedShaderMaterial::_addPass( ShaderRenderPassData &rpd, // Copy over features rpd.mFeatureData.materialFeatures = fd.features; + Vector samplers; + samplers.setSize(Material::MAX_TEX_PER_PASS); + for(int i = 0; i < Material::MAX_TEX_PER_PASS; ++i) + { + samplers[i] = (rpd.mSamplerNames[i].isEmpty() || rpd.mSamplerNames[i][0] == '$') ? rpd.mSamplerNames[i] : "$" + rpd.mSamplerNames[i]; + } + // Generate shader GFXShader::setLogging( true, true ); - rpd.shader = SHADERGEN->getShader( rpd.mFeatureData, mVertexFormat, &mUserMacros ); + rpd.shader = SHADERGEN->getShader( rpd.mFeatureData, mVertexFormat, &mUserMacros, samplers ); if( !rpd.shader ) return false; rpd.shaderHandles.init( rpd.shader ); @@ -601,6 +631,30 @@ bool ProcessedShaderMaterial::_addPass( ShaderRenderPassData &rpd, ShaderRenderPassData *newPass = new ShaderRenderPassData( rpd ); mPasses.push_back( newPass ); + //initSamplerHandles + ShaderConstHandles *handles = _getShaderConstHandles( mPasses.size()-1 ); + AssertFatal(handles,""); + for(int i = 0; i < rpd.mNumTex; i++) + { + if(rpd.mSamplerNames[i].isEmpty()) + { + handles->mTexHandlesSC[i] = newPass->shader->getShaderConstHandle( String::EmptyString ); + handles->mRTParamsSC[i] = newPass->shader->getShaderConstHandle( String::EmptyString ); + continue; + } + + String samplerName = rpd.mSamplerNames[i]; + if( !samplerName.startsWith("$")) + samplerName.insert(0, "$"); + + GFXShaderConstHandle *handle = newPass->shader->getShaderConstHandle( samplerName ); + + handles->mTexHandlesSC[i] = handle; + handles->mRTParamsSC[i] = newPass->shader->getShaderConstHandle( String::ToString( "$rtParams%s", samplerName.c_str()+1 ) ); + + AssertFatal( handle,""); + } + // Give each active feature a chance to create specialized shader consts. for( U32 i=0; i < FEATUREMGR->getFeatureCount(); i++ ) { @@ -705,6 +759,7 @@ void ProcessedShaderMaterial::setTextureStages( SceneRenderState *state, const S PROFILE_SCOPE( ProcessedShaderMaterial_SetTextureStages ); ShaderConstHandles *handles = _getShaderConstHandles(pass); + AssertFatal(handles,""); // Set all of the textures we need to render the give pass. #ifdef TORQUE_DEBUG diff --git a/Engine/source/materials/shaderData.cpp b/Engine/source/materials/shaderData.cpp index d0c526383..36e0a3994 100644 --- a/Engine/source/materials/shaderData.cpp +++ b/Engine/source/materials/shaderData.cpp @@ -64,6 +64,9 @@ ShaderData::ShaderData() mUseDevicePixVersion = false; mPixVersion = 1.0; + + for( int i = 0; i < NumTextures; ++i) + mRTParams[i] = false; } void ShaderData::initPersistFields() @@ -115,6 +118,14 @@ void ShaderData::initPersistFields() "@endtsexample\n\n" ); + addField("samplerNames", TypeRealString, Offset(mSamplerNames, ShaderData), NumTextures, + "@brief Indicates names of samplers present in shader. Order is important.\n\n" + "Order of sampler names are used to assert correct sampler register/location" + "Other objects (GFXStateBlockData, PostEffect...) use index number to link samplers." + ); + + addField("rtParams", TypeBool, Offset(mRTParams, ShaderData), NumTextures, ""); + Parent::initPersistFields(); // Make sure we get activation signals. @@ -133,6 +144,12 @@ bool ShaderData::onAdd() // NOTE: We initialize the shader on request. + for(int i = 0; i < NumTextures; ++i) + { + if( mSamplerNames[i].isNotEmpty() && !mSamplerNames[i].startsWith("$") ) + mSamplerNames[i].insert(0, "$"); + } + return true; } @@ -190,6 +207,8 @@ GFXShader* ShaderData::getShader( const Vector ¯os ) if ( !shader ) return NULL; + _checkDefinition(shader); + // Store the shader in the cache and return it. mShaders.insertUnique( cacheKey, shader ); return shader; @@ -207,6 +226,11 @@ GFXShader* ShaderData::_createShader( const Vector ¯os ) GFXShader *shader = GFX->createShader(); bool success = false; + Vector samplers; + samplers.setSize(ShaderData::NumTextures); + for(int i = 0; i < ShaderData::NumTextures; ++i) + samplers[i] = mSamplerNames[i][0] == '$' ? mSamplerNames[i] : "$"+mSamplerNames[i]; + // Initialize the right shader type. switch( GFX->getAdapterType() ) { @@ -216,7 +240,8 @@ GFXShader* ShaderData::_createShader( const Vector ¯os ) success = shader->init( mDXVertexShaderName, mDXPixelShaderName, pixver, - macros ); + macros, + samplers); break; } @@ -225,7 +250,8 @@ GFXShader* ShaderData::_createShader( const Vector ¯os ) success = shader->init( mOGLVertexShaderName, mOGLPixelShaderName, pixver, - macros ); + macros, + samplers); break; } @@ -235,6 +261,29 @@ GFXShader* ShaderData::_createShader( const Vector ¯os ) break; } +#if defined(TORQUE_DEBUG) + //Assert Sampler registers + const Vector& descs = shader->getShaderConstDesc(); + for(int i = 0; i < descs.size(); ++i) + { + if(descs[i].constType != GFXSCT_Sampler && descs[i].constType != GFXSCT_SamplerCube) + continue; + + GFXShaderConstHandle *handle = shader->findShaderConstHandle(descs[i].name); + if(!handle || !handle->isValid()) + continue; + + int reg = handle->getSamplerRegister(); + if( descs[i].name != samplers[reg] ) + { + const char *err = avar("ShaderData(%s): samplerNames[%d] = \"%s\" are diferent to sampler in shader: %s : register(S%d)" + ,getName(), reg, samplers[reg].c_str(), handle->getName().c_str(), reg); + Con::printf(err); + GFXAssertFatal(0, err); + } + } +#endif + // If we failed to load the shader then // cleanup and return NULL. if ( !success ) @@ -270,6 +319,69 @@ void ShaderData::_onLMActivate( const char *lm, bool activate ) reloadAllShaders(); } +bool ShaderData::hasSamplerDef(const String &_samplerName, int &pos) const +{ + String samplerName = _samplerName.startsWith("$") ? _samplerName : "$"+_samplerName; + for(int i = 0; i < NumTextures; ++i) + { + if( mSamplerNames[i].equal(samplerName, String::NoCase ) ) + { + pos = i; + return true; + } + } + + pos = -1; + return false; +} + +bool ShaderData::_checkDefinition(GFXShader *shader) +{ + bool error = false; + Vector samplers; + samplers.reserve(NumTextures); + bool rtParams[NumTextures]; + for(int i = 0; i < NumTextures; ++i) + rtParams[i] = false; + + const Vector &shaderConstDesc = shader->getShaderConstDesc(); + + for(int i = 0; i < shaderConstDesc.size(); ++i) + { + const GFXShaderConstDesc &desc = shaderConstDesc[i]; + if(desc.constType == GFXSCT_Sampler) + { + samplers.push_back(desc.name ); + } + } + + for(int i = 0; i < samplers.size(); ++i) + { + int pos; + bool find = hasSamplerDef(samplers[i], pos); + + if(find && pos >= 0 && mRTParams[pos]) + { + if( !shader->findShaderConstHandle( String::ToString("$rtParams%d", pos)) ) + { + String error = String::ToString("ShaderData(%s) sampler[%d] used but rtParams%d not used in shader compilation. Possible error", getName(), pos, pos); + Con::errorf( error ); + error = true; + } + } + + if(!find) + { + String error = String::ToString("ShaderData(%s) sampler %s not defined", getName(), samplers[i].c_str()); + Con::errorf(error ); + GFXAssertFatal(0, error ); + error = true; + } + } + + return !error; +} + DefineEngineMethod( ShaderData, reload, void, (),, "@brief Rebuilds all the vertex and pixel shader instances created from this ShaderData.\n\n" diff --git a/Engine/source/materials/shaderData.h b/Engine/source/materials/shaderData.h index cc896e23f..cce62f324 100644 --- a/Engine/source/materials/shaderData.h +++ b/Engine/source/materials/shaderData.h @@ -91,8 +91,23 @@ protected: /// @see LightManager::smActivateSignal static void _onLMActivate( const char *lm, bool activate ); + enum + { + NumTextures = 8 + }; + + String mSamplerNames[NumTextures]; + bool mRTParams[NumTextures]; + + bool _checkDefinition(GFXShader *shader); + public: + void setSamplerName(const String &name, int idx) { mSamplerNames[idx] = name; } + String getSamplerName(int idx) const { return mSamplerNames[idx]; } + + bool hasSamplerDef(const String &samplerName, int &pos) const; + bool hasRTParamsDef(const int pos) const { return mRTParams[pos]; } ShaderData(); diff --git a/Engine/source/shaderGen/HLSL/bumpHLSL.cpp b/Engine/source/shaderGen/HLSL/bumpHLSL.cpp index 2d6dc8464..c54f9a7f3 100644 --- a/Engine/source/shaderGen/HLSL/bumpHLSL.cpp +++ b/Engine/source/shaderGen/HLSL/bumpHLSL.cpp @@ -222,12 +222,14 @@ void BumpFeatHLSL::setTexData( Material::StageData &stageDat, if ( fd.features[MFT_NormalMap] ) { passData.mTexType[ texIndex ] = Material::Bump; + passData.mSamplerNames[ texIndex ] = "bumpMap"; passData.mTexSlot[ texIndex++ ].texObject = stageDat.getTex( MFT_NormalMap ); } if ( fd.features[ MFT_DetailNormalMap ] ) { passData.mTexType[ texIndex ] = Material::DetailBump; + passData.mSamplerNames[ texIndex ] = "detailBumpMap"; passData.mTexSlot[ texIndex++ ].texObject = stageDat.getTex( MFT_DetailNormalMap ); } } @@ -382,6 +384,7 @@ void ParallaxFeatHLSL::setTexData( Material::StageData &stageDat, GFXTextureObject *tex = stageDat.getTex( MFT_NormalMap ); if ( tex ) { + passData.mSamplerNames[ texIndex ] = "bumpMap"; passData.mTexType[ texIndex ] = Material::Bump; passData.mTexSlot[ texIndex++ ].texObject = tex; } diff --git a/Engine/source/shaderGen/HLSL/pixSpecularHLSL.cpp b/Engine/source/shaderGen/HLSL/pixSpecularHLSL.cpp index 930e702c8..97485dbd6 100644 --- a/Engine/source/shaderGen/HLSL/pixSpecularHLSL.cpp +++ b/Engine/source/shaderGen/HLSL/pixSpecularHLSL.cpp @@ -147,6 +147,7 @@ void SpecularMapHLSL::setTexData( Material::StageData &stageDat, if ( tex ) { passData.mTexType[ texIndex ] = Material::Standard; + passData.mSamplerNames[ texIndex ] = "specularMap"; passData.mTexSlot[ texIndex++ ].texObject = tex; } } \ No newline at end of file diff --git a/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp b/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp index 586978eec..b0fb3ad0f 100644 --- a/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp +++ b/Engine/source/shaderGen/HLSL/shaderFeatureHLSL.cpp @@ -985,7 +985,10 @@ void DiffuseMapFeatHLSL::setTexData( Material::StageData &stageDat, { GFXTextureObject *tex = stageDat.getTex( MFT_DiffuseMap ); if ( tex ) + { + passData.mSamplerNames[ texIndex ] = "diffuseMap"; passData.mTexSlot[ texIndex++ ].texObject = tex; + } } @@ -1069,7 +1072,10 @@ void OverlayTexFeatHLSL::setTexData( Material::StageData &stageDat, { GFXTextureObject *tex = stageDat.getTex( MFT_OverlayMap ); if ( tex ) + { + passData.mSamplerNames[texIndex] = "overlayMap"; passData.mTexSlot[ texIndex++ ].texObject = tex; + } } @@ -1257,6 +1263,7 @@ void LightmapFeatHLSL::setTexData( Material::StageData &stageDat, U32 &texIndex ) { GFXTextureObject *tex = stageDat.getTex( MFT_LightMap ); + passData.mSamplerNames[ texIndex ] = "lightMap"; if ( tex ) passData.mTexSlot[ texIndex++ ].texObject = tex; else @@ -1386,6 +1393,7 @@ void TonemapFeatHLSL::setTexData( Material::StageData &stageDat, if ( tex ) { passData.mTexType[ texIndex ] = Material::ToneMapTex; + passData.mSamplerNames[ texIndex ] = "toneMap"; passData.mTexSlot[ texIndex++ ].texObject = tex; } } @@ -1576,7 +1584,10 @@ void DetailFeatHLSL::setTexData( Material::StageData &stageDat, { GFXTextureObject *tex = stageDat.getTex( MFT_DetailMap ); if ( tex ) + { + passData.mSamplerNames[texIndex] = "detailMap"; passData.mTexSlot[ texIndex++ ].texObject = tex; + } } @@ -1846,22 +1857,27 @@ void ReflectCubeFeatHLSL::setTexData( Material::StageData &stageDat, !passData.mFeatureData.features[MFT_NormalMap] ) { GFXTextureObject *tex = stageDat.getTex( MFT_DetailMap ); - if ( tex && - stageFeatures.features[MFT_DiffuseMap] ) + if ( tex && stageFeatures.features[MFT_DiffuseMap] ) + { + passData.mSamplerNames[ texIndex ] = "diffuseMap"; passData.mTexSlot[ texIndex++ ].texObject = tex; + } else { tex = stageDat.getTex( MFT_NormalMap ); - if ( tex && - stageFeatures.features[ MFT_NormalMap ] ) + if ( tex && stageFeatures.features[ MFT_NormalMap ] ) + { + passData.mSamplerNames[ texIndex ] = "bumpMap"; passData.mTexSlot[ texIndex++ ].texObject = tex; } } + } if( stageDat.getCubemap() ) { passData.mCubeMap = stageDat.getCubemap(); + passData.mSamplerNames[texIndex] = "cubeMap"; passData.mTexType[texIndex++] = Material::Cube; } else @@ -1869,6 +1885,7 @@ void ReflectCubeFeatHLSL::setTexData( Material::StageData &stageDat, if( stageFeatures.features[MFT_CubeMap] ) { // assuming here that it is a scenegraph cubemap + passData.mSamplerNames[texIndex] = "cubeMap"; passData.mTexType[texIndex++] = Material::SGCube; } } diff --git a/Engine/source/shaderGen/shaderGen.cpp b/Engine/source/shaderGen/shaderGen.cpp index 5cd18f10c..ada454296 100644 --- a/Engine/source/shaderGen/shaderGen.cpp +++ b/Engine/source/shaderGen/shaderGen.cpp @@ -443,7 +443,7 @@ void ShaderGen::_printPixShader( Stream &stream ) mPrinter->printPixelShaderCloser(stream); } -GFXShader* ShaderGen::getShader( const MaterialFeatureData &featureData, const GFXVertexFormat *vertexFormat, const Vector *macros ) +GFXShader* ShaderGen::getShader( const MaterialFeatureData &featureData, const GFXVertexFormat *vertexFormat, const Vector *macros, const Vector &samplers ) { PROFILE_SCOPE( ShaderGen_GetShader ); @@ -488,7 +488,7 @@ GFXShader* ShaderGen::getShader( const MaterialFeatureData &featureData, const G GFXShader *shader = GFX->createShader(); shader->mInstancingFormat.copy( mInstancingFormat ); // TODO: Move to init() below! - if ( !shader->init( vertFile, pixFile, pixVersion, shaderMacros ) ) + if ( !shader->init( vertFile, pixFile, pixVersion, shaderMacros, samplers ) ) { delete shader; return NULL; diff --git a/Engine/source/shaderGen/shaderGen.h b/Engine/source/shaderGen/shaderGen.h index dab3a29e2..016159559 100644 --- a/Engine/source/shaderGen/shaderGen.h +++ b/Engine/source/shaderGen/shaderGen.h @@ -155,7 +155,7 @@ public: Vector ¯os ); // Returns a shader that implements the features listed by dat. - GFXShader* getShader( const MaterialFeatureData &dat, const GFXVertexFormat *vertexFormat, const Vector *macros ); + GFXShader* getShader( const MaterialFeatureData &dat, const GFXVertexFormat *vertexFormat, const Vector *macros, const Vector &samplers ); // This will delete all of the procedural shaders that we have. Used to regenerate shaders when // the ShaderFeatures have changed (due to lighting system change, or new plugin) diff --git a/Engine/source/terrain/terrCellMaterial.cpp b/Engine/source/terrain/terrCellMaterial.cpp index 63f03a188..dadb6d4a8 100644 --- a/Engine/source/terrain/terrCellMaterial.cpp +++ b/Engine/source/terrain/terrCellMaterial.cpp @@ -46,6 +46,27 @@ AFTER_MODULE_INIT( MaterialManager ) Vector TerrainCellMaterial::smAllMaterials; +Vector _initSamplerNames() +{ + Vector samplerNames; + samplerNames.push_back("$baseTexMap"); + samplerNames.push_back("$layerTex"); + samplerNames.push_back("$macrolayerTex"); + samplerNames.push_back("$lightMapTex"); + samplerNames.push_back("$lightInfoBuffer"); + for(int i = 0; i < 3; ++i) + { + samplerNames.push_back(avar("$normalMap%d",i)); + samplerNames.push_back(avar("$detailMap%d",i)); + samplerNames.push_back(avar("$macroMap%d",i)); + } + + return samplerNames; +} + + +const Vector TerrainCellMaterial::mSamplerNames = _initSamplerNames(); + TerrainCellMaterial::TerrainCellMaterial() : mCurrPass( 0 ), mTerrain( NULL ), @@ -460,7 +481,7 @@ bool TerrainCellMaterial::_createPass( Vector *materials, const bool logErrors = matCount == 1; GFXShader::setLogging( logErrors, true ); - pass->shader = SHADERGEN->getShader( featureData, getGFXVertexFormat(), NULL ); + pass->shader = SHADERGEN->getShader( featureData, getGFXVertexFormat(), NULL, mSamplerNames ); } // If we got a shader then we can continue. @@ -499,14 +520,7 @@ bool TerrainCellMaterial::_createPass( Vector *materials, pass->oneOverTerrainSize = pass->shader->getShaderConstHandle( "$oneOverTerrainSize" ); pass->squareSize = pass->shader->getShaderConstHandle( "$squareSize" ); - // NOTE: We're assuming rtParams0 here as we know its the only - // render target we currently get in a terrain material and the - // DeferredRTLightingFeatHLSL will always use 0. - // - // This could change in the future and we would need to fix - // the ShaderFeature API to allow us to do this right. - // - pass->lightParamsConst = pass->shader->getShaderConstHandle( "$rtParams0" ); + pass->lightParamsConst = pass->shader->getShaderConstHandle( "$rtParamslightInfoBuffer" ); // Now prepare the basic stateblock. GFXStateBlockDesc desc; diff --git a/Engine/source/terrain/terrCellMaterial.h b/Engine/source/terrain/terrCellMaterial.h index b7acaf16e..0784bc192 100644 --- a/Engine/source/terrain/terrCellMaterial.h +++ b/Engine/source/terrain/terrCellMaterial.h @@ -144,6 +144,8 @@ protected: U32 mCurrPass; + static const Vector mSamplerNames; + GFXTexHandle mBaseMapTexture; GFXTexHandle mLayerMapTexture;