123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899 |
- //-----------------------------------------------------------------------------
- // Copyright (c) 2012 GarageGames, LLC
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to
- // deal in the Software without restriction, including without limitation the
- // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- // sell copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- // IN THE SOFTWARE.
- //-----------------------------------------------------------------------------
- #include "platform/platform.h"
- #include "terrain/terrCellMaterial.h"
- #include "core/util/safeRelease.h"
- #include "terrain/terrData.h"
- #include "terrain/terrCell.h"
- #include "materials/materialFeatureTypes.h"
- #include "materials/materialManager.h"
- #include "terrain/terrFeatureTypes.h"
- #include "terrain/terrMaterial.h"
- #include "renderInstance/renderDeferredMgr.h"
- #include "shaderGen/shaderGen.h"
- #include "shaderGen/featureMgr.h"
- #include "scene/sceneRenderState.h"
- #include "materials/sceneData.h"
- #include "gfx/util/screenspace.h"
- #include "lighting/advanced/advancedLightBinManager.h"
- S32 sgMaxTerrainMaterialsPerPass = 32;
- AFTER_MODULE_INIT( MaterialManager )
- {
- Con::NotifyDelegate callabck( &TerrainCellMaterial::_updateDefaultAnisotropy );
- Con::addVariableNotify( "$pref::Video::defaultAnisotropy", callabck );
- }
- Vector<TerrainCellMaterial*> TerrainCellMaterial::smAllMaterials;
- Vector<String> _initSamplerNames()
- {
- Vector<String> samplerNames;
- samplerNames.push_back("$baseTexMap");
- samplerNames.push_back("$layerTex");
- samplerNames.push_back("$lightMapTex");
- samplerNames.push_back("$lightInfoBuffer");
- samplerNames.push_back("$normalMapSampler");
- samplerNames.push_back("$detailMapSampler");
- samplerNames.push_back("$macroMapSampler");
- samplerNames.push_back("$ormMapSampler");
- return samplerNames;
- }
- const Vector<String> TerrainCellMaterial::mSamplerNames = _initSamplerNames();
- TerrainCellMaterial::TerrainCellMaterial()
- : mTerrain( NULL ),
- mDeferredMat( NULL ),
- mReflectMat( NULL ),
- mShader( NULL ),
- mCurrPass( 0 ),
- mMaterials( 0 )
- {
- smAllMaterials.push_back( this );
- }
- TerrainCellMaterial::~TerrainCellMaterial()
- {
- SAFE_DELETE( mDeferredMat );
- SAFE_DELETE( mReflectMat );
- smAllMaterials.remove( this );
- T3D::for_each(mMaterialInfos.begin(), mMaterialInfos.end(), T3D::delete_pointer());
- mMaterialInfos.clear();
- }
- void TerrainCellMaterial::_updateDefaultAnisotropy()
- {
- // TODO: We need to split the stateblock initialization
- // from the shader constant lookup and pass setup in a
- // future version of terrain materials.
- //
- // For now use some custom code in a horrible loop to
- // change the anisotropy directly and fast.
- //
- const U32 maxAnisotropy = MATMGR->getDefaultAnisotropy();
- Vector<TerrainCellMaterial*>::iterator iter = smAllMaterials.begin();
- for ( ; iter != smAllMaterials.end(); iter++ )
- {
- // Start from the existing state block.
- GFXStateBlockDesc desc = (*iter)->mStateBlock->getDesc();
- if ((*iter)->mDetailTexArrayConst->isValid())
- {
- const S32 sampler = (*iter)->mDetailTexArrayConst->getSamplerRegister();
- if (maxAnisotropy > 1)
- {
- desc.samplers[sampler].minFilter = GFXTextureFilterAnisotropic;
- desc.samplers[sampler].maxAnisotropy = maxAnisotropy;
- }
- else
- desc.samplers[sampler].minFilter = GFXTextureFilterLinear;
- }
- if ((*iter)->mMacroTexArrayConst->isValid())
- {
- const S32 sampler = (*iter)->mMacroTexArrayConst->getSamplerRegister();
- if (maxAnisotropy > 1)
- {
- desc.samplers[sampler].minFilter = GFXTextureFilterAnisotropic;
- desc.samplers[sampler].maxAnisotropy = maxAnisotropy;
- }
- else
- desc.samplers[sampler].minFilter = GFXTextureFilterLinear;
- }
- if ((*iter)->mNormalTexArrayConst->isValid())
- {
- const S32 sampler = (*iter)->mNormalTexArrayConst->getSamplerRegister();
- if (maxAnisotropy > 1)
- {
- desc.samplers[sampler].minFilter = GFXTextureFilterAnisotropic;
- desc.samplers[sampler].maxAnisotropy = maxAnisotropy;
- }
- else
- desc.samplers[sampler].minFilter = GFXTextureFilterLinear;
- }
- if ((*iter)->mOrmTexArrayConst->isValid())
- {
- const S32 sampler = (*iter)->mOrmTexArrayConst->getSamplerRegister();
- if (maxAnisotropy > 1)
- {
- desc.samplers[sampler].minFilter = GFXTextureFilterAnisotropic;
- desc.samplers[sampler].maxAnisotropy = maxAnisotropy;
- }
- else
- desc.samplers[sampler].minFilter = GFXTextureFilterLinear;
- }
- // Set the updated stateblock.
- desc.setCullMode(GFXCullCCW);
- (*iter)->mStateBlock = GFX->createStateBlock(desc);
- //reflection
- desc.setCullMode(GFXCullCW);
- (*iter)->mReflectionStateBlock = GFX->createStateBlock(desc);
- // Create the wireframe state blocks.
- GFXStateBlockDesc wireframe(desc);
- wireframe.fillMode = GFXFillWireframe;
- wireframe.setCullMode(GFXCullCCW);
- (*iter)->mWireframeStateBlock = GFX->createStateBlock(wireframe);
- }
- }
- void TerrainCellMaterial::setTransformAndEye( const MatrixF &modelXfm,
- const MatrixF &viewXfm,
- const MatrixF &projectXfm,
- F32 farPlane )
- {
- PROFILE_SCOPE( TerrainCellMaterial_SetTransformAndEye );
- MatrixF modelViewProj = projectXfm * viewXfm * modelXfm;
-
- MatrixF invViewXfm( viewXfm );
- invViewXfm.inverse();
- Point3F eyePos = invViewXfm.getPosition();
-
- MatrixF invModelXfm( modelXfm );
- invModelXfm.inverse();
- Point3F objEyePos = eyePos;
- invModelXfm.mulP( objEyePos );
-
- VectorF vEye = invViewXfm.getForwardVector();
- vEye.normalize( 1.0f / farPlane );
- mConsts->setSafe(mModelViewProjConst, modelViewProj);
- if (mViewToObjConst->isValid() || mWorldViewOnlyConst->isValid())
- {
- MatrixF worldViewOnly = viewXfm * modelXfm;
- mConsts->setSafe(mWorldViewOnlyConst, worldViewOnly);
- if (mViewToObjConst->isValid())
- {
- worldViewOnly.affineInverse();
- mConsts->set(mViewToObjConst, worldViewOnly);
- }
- }
- mConsts->setSafe(mEyePosWorldConst, eyePos);
- mConsts->setSafe(mEyePosConst, objEyePos);
- mConsts->setSafe(mObjTransConst, modelXfm);
- mConsts->setSafe(mWorldToObjConst, invModelXfm);
- mConsts->setSafe(mVEyeConst, vEye);
- }
- TerrainCellMaterial* TerrainCellMaterial::getDeferredMat()
- {
- if ( !mDeferredMat )
- {
- mDeferredMat = new TerrainCellMaterial();
- mDeferredMat->init( mTerrain, mMaterials, true, false, mMaterials == 0 );
- }
- return mDeferredMat;
- }
- TerrainCellMaterial* TerrainCellMaterial::getReflectMat()
- {
- if ( !mReflectMat )
- {
- mReflectMat = new TerrainCellMaterial();
- mReflectMat->init( mTerrain, mMaterials, false, true, true );
- }
- return mReflectMat;
- }
- void TerrainCellMaterial::init( TerrainBlock *block,
- U64 activeMaterials,
- bool deferredMat,
- bool reflectMat,
- bool baseOnly )
- {
- // This isn't allowed for now.
- AssertFatal( !( deferredMat && reflectMat ), "TerrainCellMaterial::init - We shouldn't get deferred and reflection in the same material!" );
- mTerrain = block;
- mMaterials = activeMaterials;
- mMaterialInfos.clear();
- for ( U32 i = 0; i < 64; i++ )
- {
- if ( !( mMaterials & ((U64)1 << i ) ) )
- continue;
- TerrainMaterial *mat = block->getMaterial( i );
- MaterialInfo *info = new MaterialInfo();
- info->layerId = i;
- info->mat = mat;
- mMaterialInfos.push_back(info);
- }
- if (!_initShader(deferredMat,
- reflectMat,
- baseOnly))
- {
- Con::errorf("TerrainCellMaterial::init - Failed to init shader!");
- T3D::for_each(mMaterialInfos.begin(), mMaterialInfos.end(), T3D::delete_pointer());
- mMaterialInfos.clear();
- return;
- }
- // If we have attached mats then update them too.
- if ( mDeferredMat )
- mDeferredMat->init( mTerrain, mMaterials, true, false, baseOnly );
- if ( mReflectMat )
- mReflectMat->init( mTerrain, mMaterials, false, true, baseOnly );
- }
- bool TerrainCellMaterial::_initShader(bool deferredMat,
- bool reflectMat,
- bool baseOnly)
- {
- if (GFX->getPixelShaderVersion() < 3.0f)
- baseOnly = true;
- // NOTE: At maximum we only try to combine sgMaxTerrainMaterialsPerPass materials
- // into a single pass. This is sub-optimal for the simplest
- // cases, but the most common case results in much fewer
- // shader generation failures and permutations leading to
- // faster load time and less hiccups during gameplay.
- U32 matCount = getMin(sgMaxTerrainMaterialsPerPass, mMaterialInfos.size());
- Vector<GFXTexHandle> normalMaps;
- // See if we're currently running under the
- // basic lighting manager.
- //
- // TODO: This seems ugly... we should trigger
- // features like this differently in the future.
- //
- bool useBLM = String::compare(LIGHTMGR->getId(), "BLM") == 0;
- // Do we need to disable normal mapping?
- const bool disableNormalMaps = MATMGR->getExclusionFeatures().hasFeature(MFT_NormalMap) || useBLM;
- // How about parallax?
- const bool disableParallaxMaps = GFX->getPixelShaderVersion() < 3.0f ||
- MATMGR->getExclusionFeatures().hasFeature(MFT_Parallax);
- // Has advanced lightmap support been enabled for deferred.
- bool advancedLightmapSupport = false;
- if (deferredMat)
- {
- // This sucks... but it works.
- AdvancedLightBinManager* lightBin;
- if (Sim::findObject("AL_LightBinMgr", lightBin))
- advancedLightmapSupport = lightBin->MRTLightmapsDuringDeferred();
- }
- // Loop till we create a valid shader!
- while (true)
- {
- FeatureSet features;
- features.addFeature(MFT_VertTransform);
- features.addFeature(MFT_TerrainBaseMap);
- if (deferredMat)
- {
- features.addFeature(MFT_EyeSpaceDepthOut);
- features.addFeature(MFT_DeferredConditioner);
- features.addFeature(MFT_isDeferred);
- if (advancedLightmapSupport)
- features.addFeature(MFT_RenderTarget3_Zero);
- }
- else
- {
- features.addFeature(MFT_RTLighting);
- // The HDR feature is always added... it will compile out
- // if HDR is not enabled in the engine.
- features.addFeature(MFT_HDROut);
- }
- // Enable lightmaps and fogging if we're in BL.
- if (reflectMat || useBLM)
- {
- features.addFeature(MFT_Fog);
- features.addFeature(MFT_ForwardShading);
- }
- if (useBLM)
- features.addFeature(MFT_TerrainLightMap);
- normalMaps.clear();
- S32 featureIndex = 0;
- // Now add all the material layer features.
- for (U32 i = 0; i < matCount && !baseOnly; i++)
- {
- TerrainMaterial* mat = mMaterialInfos[i]->mat;
- if (mat == NULL)
- continue;
- // We only include materials that
- // have more than a base texture.
- if (mat->getDetailSize() <= 0 ||
- mat->getDetailDistance() <= 0 ||
- mat->getDetailMap() == StringTable->EmptyString())
- continue;
- // check for macro detail texture
- if (!(mat->getMacroSize() <= 0 || mat->getMacroDistance() <= 0 || mat->getMacroMap() == StringTable->EmptyString()))
- {
- if (deferredMat)
- features.addFeature(MFT_isDeferred, featureIndex);
- features.addFeature(MFT_TerrainMacroMap, featureIndex);
- }
- if (deferredMat)
- features.addFeature(MFT_isDeferred, featureIndex);
- features.addFeature(MFT_TerrainDetailMap, featureIndex);
- if (deferredMat)
- {
- if (!(mat->getORMConfigMap() == StringTable->EmptyString()))
- {
- features.addFeature(MFT_TerrainORMMap, featureIndex);
- }
- else
- {
- features.addFeature(MFT_DeferredTerrainBlankInfoMap, featureIndex);
- }
- }
-
- if (mat->getInvertRoughness())
- features.addFeature(MFT_InvertRoughness, featureIndex);
- normalMaps.increment();
- // Skip normal maps if we need to.
- if (!disableNormalMaps && mat->getNormalMap() != StringTable->EmptyString())
- {
- features.addFeature(MFT_TerrainNormalMap, featureIndex);
- normalMaps.last() = mat->getNormalMapResource();
- GFXFormat normalFmt = normalMaps.last().getFormat();
- if (normalFmt == GFXFormatBC3)
- features.addFeature(MFT_IsBC3nm, featureIndex);
- else if (normalFmt == GFXFormatBC5)
- features.addFeature(MFT_IsBC5nm, featureIndex);
- // Do we need and can we do parallax mapping?
- if (!disableParallaxMaps &&
- mat->getParallaxScale() > 0.0f &&
- !mat->useSideProjection())
- features.addFeature(MFT_TerrainParallaxMap, featureIndex);
- }
- // Is this layer got side projection?
- if (mat->useSideProjection())
- features.addFeature(MFT_TerrainSideProject, featureIndex);
- featureIndex++;
- }
- // New blending
- if (matCount > 0 && !Con::getBoolVariable("$Terrain::LerpBlend", false))
- {
- features.addFeature(MFT_TerrainHeightBlend);
- }
- MaterialFeatureData featureData;
- featureData.features = features;
- featureData.materialFeatures = features;
- // Check to see how many vertex shader output
- // registers we're gonna need.
- U32 numTex = 0;
- U32 numTexReg = 0;
- for (U32 i = 0; i < features.getCount(); i++)
- {
- S32 index;
- const FeatureType& type = features.getAt(i, &index);
- ShaderFeature* sf = FEATUREMGR->getByType(type);
- if (!sf)
- continue;
- sf->setProcessIndex(index);
- ShaderFeature::Resources res = sf->getResources(featureData);
- numTex += res.numTex;
- numTexReg += res.numTexReg;
- }
- // Can we build the shader?
- //
- // NOTE: The 10 is sort of an abitrary SM 3.0
- // limit. Its really supposed to be 11, but that
- // always fails to compile so far.
- //
- if (numTex < GFX->getNumSamplers() &&
- numTexReg <= 10)
- {
- // NOTE: We really shouldn't be getting errors building the shaders,
- // but we can generate more instructions than the ps_2_x will allow.
- //
- // There is no way to deal with this case that i know of other than
- // letting the compile fail then recovering by trying to build it
- // with fewer materials.
- //
- // We normally disable the shader error logging so that the user
- // isn't fooled into thinking there is a real bug. That is until
- // we get down to a single material. If a single material case
- // fails it means it cannot generate any passes at all!
- const bool logErrors = true;// matCount == 1;
- GFXShader::setLogging(logErrors, true);
- mShader = SHADERGEN->getShader(featureData, getGFXVertexFormat<TerrVertex>(), NULL, mSamplerNames);
- }
- // If we got a shader then we can continue.
- if (mShader)
- break;
- // If the material count is already 1 then this
- // is a real shader error... give up!
- if (matCount <= 1)
- return false;
- // If we failed we next try half the input materials
- // so that we can more quickly arrive at a valid shader.
- matCount -= matCount / 2;
- }
- // Setup the constant buffer.
- mConsts = mShader->allocConstBuffer();
- // Prepare the basic constants.
- mModelViewProjConst = mShader->getShaderConstHandle("$modelview");
- mWorldViewOnlyConst = mShader->getShaderConstHandle("$worldViewOnly");
- mViewToObjConst = mShader->getShaderConstHandle("$viewToObj");
- mEyePosWorldConst = mShader->getShaderConstHandle("$eyePosWorld");
- mEyePosConst = mShader->getShaderConstHandle("$eyePos");
- mVEyeConst = mShader->getShaderConstHandle("$vEye");
- mLayerSizeConst = mShader->getShaderConstHandle("$layerSize");
- mObjTransConst = mShader->getShaderConstHandle("$objTrans");
- mWorldToObjConst = mShader->getShaderConstHandle("$worldToObj");
- mLightInfoBufferConst = mShader->getShaderConstHandle("$lightInfoBuffer");
- mBaseTexMapConst = mShader->getShaderConstHandle("$baseTexMap");
- mLayerTexConst = mShader->getShaderConstHandle("$layerTex");
- mFogDataConst = mShader->getShaderConstHandle("$fogData");
- mFogColorConst = mShader->getShaderConstHandle("$fogColor");
- mLightMapTexConst = mShader->getShaderConstHandle("$lightMapTex");
- mOneOverTerrainSizeConst = mShader->getShaderConstHandle("$oneOverTerrainSize");
- mSquareSizeConst = mShader->getShaderConstHandle("$squareSize");
- mBlendDepthConst = mShader->getShaderConstHandle("$baseBlendDepth");
- mLightParamsConst = mShader->getShaderConstHandle("$rtParamslightInfoBuffer");
- // Now prepare the basic stateblock.
- GFXStateBlockDesc desc;
- // We write to the zbuffer if this is a deferred
- // material or if the deferred is disabled.
- desc.setZReadWrite(true, !MATMGR->getDeferredEnabled() ||
- deferredMat ||
- reflectMat);
- desc.samplersDefined = true;
- if (mBaseTexMapConst->isValid())
- desc.samplers[mBaseTexMapConst->getSamplerRegister()] = GFXSamplerStateDesc::getWrapLinear();
- if (mLayerTexConst->isValid())
- desc.samplers[mLayerTexConst->getSamplerRegister()] = GFXSamplerStateDesc::getClampPoint();
- if (mLightInfoBufferConst->isValid())
- desc.samplers[mLightInfoBufferConst->getSamplerRegister()] = GFXSamplerStateDesc::getClampPoint();
- if (mLightMapTexConst->isValid())
- desc.samplers[mLightMapTexConst->getSamplerRegister()] = GFXSamplerStateDesc::getWrapLinear();
- const U32 maxAnisotropy = MATMGR->getDefaultAnisotropy();
- mDetailInfoVArrayConst = mShader->getShaderConstHandle("$detailScaleAndFade");
- mDetailInfoPArrayConst = mShader->getShaderConstHandle("$detailIdStrengthParallax");
- mMacroInfoVArrayConst = mShader->getShaderConstHandle("$macroIdStrengthParallax");
- mMacroInfoPArrayConst = mShader->getShaderConstHandle("$macroIdStrengthParallax");
- mDetailTexArrayConst = mShader->getShaderConstHandle("$detailMapSampler");
- if (mDetailTexArrayConst->isValid())
- {
- const S32 sampler = mDetailTexArrayConst->getSamplerRegister();
- desc.samplers[sampler] = GFXSamplerStateDesc::getWrapLinear();
- desc.samplers[sampler].magFilter = GFXTextureFilterLinear;
- desc.samplers[sampler].mipFilter = GFXTextureFilterLinear;
- if (maxAnisotropy > 1)
- {
- desc.samplers[sampler].minFilter = GFXTextureFilterAnisotropic;
- desc.samplers[sampler].maxAnisotropy = maxAnisotropy;
- }
- else
- desc.samplers[sampler].minFilter = GFXTextureFilterLinear;
- }
- mMacroTexArrayConst = mShader->getShaderConstHandle("$macroMapSampler");
- if (mMacroTexArrayConst->isValid())
- {
- const S32 sampler = mMacroTexArrayConst->getSamplerRegister();
- desc.samplers[sampler] = GFXSamplerStateDesc::getWrapLinear();
- desc.samplers[sampler].magFilter = GFXTextureFilterLinear;
- desc.samplers[sampler].mipFilter = GFXTextureFilterLinear;
- if (maxAnisotropy > 1)
- {
- desc.samplers[sampler].minFilter = GFXTextureFilterAnisotropic;
- desc.samplers[sampler].maxAnisotropy = maxAnisotropy;
- }
- else
- desc.samplers[sampler].minFilter = GFXTextureFilterLinear;
- }
- mNormalTexArrayConst = mShader->getShaderConstHandle("$normalMapSampler");
- if (mNormalTexArrayConst->isValid())
- {
- const S32 sampler = mNormalTexArrayConst->getSamplerRegister();
- desc.samplers[sampler] = GFXSamplerStateDesc::getWrapLinear();
- desc.samplers[sampler].magFilter = GFXTextureFilterLinear;
- desc.samplers[sampler].mipFilter = GFXTextureFilterLinear;
- if (maxAnisotropy > 1)
- {
- desc.samplers[sampler].minFilter = GFXTextureFilterAnisotropic;
- desc.samplers[sampler].maxAnisotropy = maxAnisotropy;
- }
- else
- desc.samplers[sampler].minFilter = GFXTextureFilterLinear;
- }
- mOrmTexArrayConst = mShader->getShaderConstHandle("$ormMapSampler");
- if (mOrmTexArrayConst->isValid())
- {
- const S32 sampler = mOrmTexArrayConst->getSamplerRegister();
- desc.samplers[sampler] = GFXSamplerStateDesc::getWrapLinear();
- desc.samplers[sampler].magFilter = GFXTextureFilterLinear;
- desc.samplers[sampler].mipFilter = GFXTextureFilterLinear;
- if (maxAnisotropy > 1)
- {
- desc.samplers[sampler].minFilter = GFXTextureFilterAnisotropic;
- desc.samplers[sampler].maxAnisotropy = maxAnisotropy;
- }
- else
- desc.samplers[sampler].minFilter = GFXTextureFilterLinear;
- }
- for (U32 i = 0; i < matCount && !baseOnly; i++)
- {
- TerrainMaterial* mat = mMaterialInfos[i]->mat;
- if (mat == NULL)
- continue;
- // We only include materials that
- // have more than a base texture.
- if (mat->getDetailSize() <= 0 ||
- mat->getDetailDistance() <= 0 ||
- mat->getDetailMap() == StringTable->EmptyString())
- continue;
- mMaterialInfos[i]->mBlendDepthConst = mShader->getShaderConstHandle(avar("$blendDepth%d", i));
- mMaterialInfos[i]->mBlendContrastConst = mShader->getShaderConstHandle(avar("$blendContrast%d", i));
- }
- // If we're doing deferred it requires some
- // special stencil settings for it to work.
- if ( deferredMat )
- desc.addDesc( RenderDeferredMgr::getOpaqueStenciWriteDesc( false ) );
- desc.setCullMode( GFXCullCCW );
- mStateBlock = GFX->createStateBlock(desc);
- //reflection stateblock
- desc.setCullMode( GFXCullCW );
- mReflectionStateBlock = GFX->createStateBlock(desc);
- // Create the wireframe state blocks.
- GFXStateBlockDesc wireframe( desc );
- wireframe.fillMode = GFXFillWireframe;
- wireframe.setCullMode( GFXCullCCW );
- mWireframeStateBlock = GFX->createStateBlock( wireframe );
- return true;
- }
- void TerrainCellMaterial::_updateMaterialConsts( )
- {
- PROFILE_SCOPE( TerrainCellMaterial_UpdateMaterialConsts );
- int detailMatCount = 0;
- for (MaterialInfo* materialInfo : mMaterialInfos)
- {
- if (materialInfo == NULL)
- continue;
- TerrainMaterial* mat = materialInfo->mat;
- if (mat == NULL)
- continue;
- // We only include materials that
- // have more than a base texture.
- if (mat->getDetailSize() <= 0 ||
- mat->getDetailDistance() <= 0 ||
- mat->getDetailMap() == StringTable->EmptyString())
- continue;
- detailMatCount++;
- }
- if (detailMatCount == 0)
- {
- return;
- }
- AlignedArray<Point4F> detailInfoArray(detailMatCount, sizeof(Point4F));
- AlignedArray<Point4F> detailScaleAndFadeArray(detailMatCount, sizeof(Point4F));
- int detailIndex = 0;
- for (MaterialInfo* matInfo : mMaterialInfos)
- {
- if (matInfo == NULL)
- continue;
- TerrainMaterial* mat = matInfo->mat;
- if (mat == NULL)
- continue;
- // We only include materials that
- // have more than a base texture.
- if (mat->getDetailSize() <= 0 ||
- mat->getDetailDistance() <= 0 ||
- mat->getDetailMap() == StringTable->EmptyString())
- continue;
- F32 detailSize = matInfo->mat->getDetailSize();
- F32 detailScale = 1.0f;
- if ( !mIsZero( detailSize ) )
- detailScale = mTerrain->getWorldBlockSize() / detailSize;
- // Scale the distance by the global scalar.
- const F32 distance = mTerrain->smDetailScale * matInfo->mat->getDetailDistance();
- // NOTE: The negation of the y scale is to make up for
- // my mistake early in development and passing the wrong
- // y texture coord into the system.
- //
- // This negation fixes detail, normal, and parallax mapping
- // without harming the layer id blending code.
- //
- // Eventually we should rework this to correct this little
- // mistake, but there isn't really a hurry to.
- //
- Point4F detailScaleAndFade( detailScale,
- -detailScale,
- distance,
- 0 );
- if ( !mIsZero( distance ) )
- detailScaleAndFade.w = 1.0f / distance;
- Point4F detailIdStrengthParallax( matInfo->layerId,
- matInfo->mat->getDetailStrength(),
- matInfo->mat->getParallaxScale(), 0 );
- detailScaleAndFadeArray[detailIndex] = detailScaleAndFade;
- detailInfoArray[detailIndex] = detailIdStrengthParallax;
- if (matInfo->mBlendDepthConst != NULL)
- {
- mConsts->setSafe(matInfo->mBlendDepthConst, matInfo->mat->getBlendDepth());
- }
- if (matInfo->mBlendContrastConst != NULL)
- {
- mConsts->setSafe(matInfo->mBlendContrastConst, matInfo->mat->getBlendContrast());
- }
- detailIndex++;
- }
- mConsts->setSafe(mDetailInfoVArrayConst, detailScaleAndFadeArray);
- mConsts->setSafe(mDetailInfoPArrayConst, detailInfoArray);
- }
- bool TerrainCellMaterial::setupPass( const SceneRenderState *state,
- const SceneData &sceneData )
- {
- PROFILE_SCOPE( TerrainCellMaterial_SetupPass );
- if (mCurrPass > 0)
- {
- mCurrPass = 0;
- return false;
- }
- mCurrPass++;
- _updateMaterialConsts();
- if ( mBaseTexMapConst->isValid() )
- GFX->setTexture( mBaseTexMapConst->getSamplerRegister(), mTerrain->mBaseTex.getPointer() );
- if ( mLayerTexConst->isValid() )
- GFX->setTexture( mLayerTexConst->getSamplerRegister(), mTerrain->mLayerTex.getPointer() );
- if ( mLightMapTexConst->isValid() )
- GFX->setTexture( mLightMapTexConst->getSamplerRegister(), mTerrain->getLightMapTex() );
- if ( sceneData.wireframe )
- GFX->setStateBlock( mWireframeStateBlock );
- else if ( state->isReflectPass( ))
- GFX->setStateBlock( mReflectionStateBlock );
- else
- GFX->setStateBlock( mStateBlock );
- GFX->setShader( mShader );
- GFX->setShaderConstBuffer( mConsts );
- // Let the light manager prepare any light stuff it needs.
- LIGHTMGR->setLightInfo( NULL,
- NULL,
- sceneData,
- state,
- 0,
- mConsts );
- if (mDetailTexArrayConst->isValid() && mTerrain->getDetailTextureArray().isValid())
- GFX->setTextureArray(mDetailTexArrayConst->getSamplerRegister(), mTerrain->getDetailTextureArray());
- if (mMacroTexArrayConst->isValid() && mTerrain->getMacroTextureArray().isValid())
- GFX->setTextureArray(mMacroTexArrayConst->getSamplerRegister(), mTerrain->getMacroTextureArray());
- if (mNormalTexArrayConst->isValid() && mTerrain->getNormalTextureArray().isValid())
- GFX->setTextureArray(mNormalTexArrayConst->getSamplerRegister(), mTerrain->getNormalTextureArray());
- if (mOrmTexArrayConst->isValid() && mTerrain->getOrmTextureArray().isValid())
- GFX->setTextureArray(mOrmTexArrayConst->getSamplerRegister(), mTerrain->getOrmTextureArray());
- mConsts->setSafe( mLayerSizeConst, (F32)mTerrain->mLayerTex.getWidth() );
- if ( mOneOverTerrainSizeConst->isValid() )
- {
- F32 oneOverTerrainSize = 1.0f / mTerrain->getWorldBlockSize();
- mConsts->set( mOneOverTerrainSizeConst, oneOverTerrainSize );
- }
- mConsts->setSafe( mSquareSizeConst, mTerrain->getSquareSize() );
- if ( mFogDataConst->isValid() )
- {
- Point3F fogData;
- fogData.x = sceneData.fogDensity;
- fogData.y = sceneData.fogDensityOffset;
- fogData.z = sceneData.fogHeightFalloff;
- mConsts->set( mFogDataConst, fogData );
- }
- if (String::isEmpty(Con::getVariable("$Terrain::BlendDepth")))
- {
- mConsts->setSafe(mBlendDepthConst, 0.2f);
- }
- else
- {
- mConsts->setSafe(mBlendDepthConst, Con::getFloatVariable("$Terrain::BlendDepth"));
- }
- mConsts->setSafe( mFogColorConst, sceneData.fogColor );
- if ( mLightInfoBufferConst->isValid() &&
- mLightParamsConst->isValid() )
- {
- if ( !mLightInfoTarget )
- mLightInfoTarget = NamedTexTarget::find( "diffuseLighting" );
- GFXTextureObject *texObject = mLightInfoTarget->getTexture();
-
- // TODO: Sometimes during reset of the light manager we get a
- // NULL texture here. This is corrected on the next frame, but
- // we should still investigate why that happens.
-
- if ( texObject )
- {
- GFX->setTexture( mLightInfoBufferConst->getSamplerRegister(), texObject );
- const Point3I &targetSz = texObject->getSize();
- const RectI &targetVp = mLightInfoTarget->getViewport();
- Point4F rtParams;
- ScreenSpace::RenderTargetParameters(targetSz, targetVp, rtParams);
- mConsts->setSafe( mLightParamsConst, rtParams );
- }
- }
- return true;
- }
- BaseMatInstance* TerrainCellMaterial::getShadowMat()
- {
- // Find our material which has some settings
- // defined on it in script.
- Material *mat = MATMGR->getMaterialDefinitionByName( "AL_DefaultShadowMaterial" );
- // Create the material instance adding the feature which
- // handles rendering terrain cut outs.
- FeatureSet features = MATMGR->getDefaultFeatures();
- BaseMatInstance *matInst = mat->createMatInstance();
- if ( !matInst->init( features, getGFXVertexFormat<TerrVertex>() ) )
- {
- delete matInst;
- matInst = NULL;
- }
- return matInst;
- }
|