123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739 |
- //-----------------------------------------------------------------------------
- // 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 "lighting/shadowMap/lightShadowMap.h"
- #include "lighting/shadowMap/shadowMapManager.h"
- #include "lighting/shadowMap/shadowMatHook.h"
- #include "gfx/gfxDevice.h"
- #include "gfx/gfxTextureManager.h"
- #include "gfx/gfxOcclusionQuery.h"
- #include "gfx/gfxCardProfile.h"
- #include "gfx/sim/debugDraw.h"
- #include "materials/materialDefinition.h"
- #include "materials/baseMatInstance.h"
- #include "scene/sceneManager.h"
- #include "scene/sceneRenderState.h"
- #include "scene/zones/sceneZoneSpace.h"
- #include "lighting/lightManager.h"
- #include "math/mathUtils.h"
- #include "shaderGen/shaderGenVars.h"
- #include "core/util/safeDelete.h"
- #include "core/stream/bitStream.h"
- #include "math/mathIO.h"
- #include "materials/shaderData.h"
- #include "core/module.h"
- // Used for creation in ShadowMapParams::getOrCreateShadowMap()
- #include "lighting/shadowMap/singleLightShadowMap.h"
- #include "lighting/shadowMap/pssmLightShadowMap.h"
- #include "lighting/shadowMap/cubeLightShadowMap.h"
- #include "lighting/shadowMap/dualParaboloidLightShadowMap.h"
- // Remove this when the shader constants are reworked better
- #include "lighting/advanced/advancedLightManager.h"
- #include "lighting/advanced/advancedLightBinManager.h"
- // TODO: Some cards (Justin's GeForce 7x series) barf on the integer format causing
- // filtering artifacts. These can (sometimes) be resolved by switching the format
- // to FP16 instead of Int16.
- const GFXFormat LightShadowMap::ShadowMapFormat = GFXFormatR32F; // GFXFormatR8G8B8A8;
- bool LightShadowMap::smDebugRenderFrustums;
- F32 LightShadowMap::smShadowTexScalar = 1.0f;
- Vector<LightShadowMap*> LightShadowMap::smUsedShadowMaps;
- Vector<LightShadowMap*> LightShadowMap::smShadowMaps;
- GFX_ImplementTextureProfile( ShadowMapProfile,
- GFXTextureProfile::DiffuseMap,
- GFXTextureProfile::PreserveSize |
- GFXTextureProfile::RenderTarget |
- GFXTextureProfile::Pooled,
- GFXTextureProfile::NONE );
- GFX_ImplementTextureProfile( ShadowMapZProfile,
- GFXTextureProfile::DiffuseMap,
- GFXTextureProfile::PreserveSize |
- GFXTextureProfile::NoMipmap |
- GFXTextureProfile::ZTarget |
- GFXTextureProfile::Pooled,
- GFXTextureProfile::NONE );
- LightShadowMap::LightShadowMap( LightInfo *light )
- : mWorldToLightProj( true ),
- mTexSize( 0 ),
- mLight( light ),
- mLastShader( NULL ),
- mIsViewDependent( false ),
- mLastCull( 0 ),
- mLastScreenSize( 0.0f ),
- mLastPriority( 0.0f )
- {
- GFXTextureManager::addEventDelegate( this, &LightShadowMap::_onTextureEvent );
- mTarget = GFX->allocRenderToTextureTarget();
- smShadowMaps.push_back( this );
- }
- LightShadowMap::~LightShadowMap()
- {
- mTarget = NULL;
- releaseTextures();
- smShadowMaps.remove( this );
- smUsedShadowMaps.remove( this );
- GFXTextureManager::removeEventDelegate( this, &LightShadowMap::_onTextureEvent );
- }
- void LightShadowMap::releaseAllTextures()
- {
- PROFILE_SCOPE( LightShadowMap_ReleaseAllTextures );
- for ( U32 i=0; i < smShadowMaps.size(); i++ )
- smShadowMaps[i]->releaseTextures();
- }
- U32 LightShadowMap::releaseUnusedTextures()
- {
- PROFILE_SCOPE( LightShadowMap_ReleaseUnusedTextures );
- const U32 currTime = Sim::getCurrentTime();
- const U32 purgeTime = 1000;
- for ( U32 i=0; i < smUsedShadowMaps.size(); )
- {
- LightShadowMap *lsm = smUsedShadowMaps[i];
- // If the shadow has not been culled in a while then
- // release its textures for other shadows to use.
- if ( currTime > ( lsm->mLastCull + purgeTime ) )
- {
- // Internally this will remove the map from the used
- // list, so don't increment the loop.
- lsm->releaseTextures();
- continue;
- }
- i++;
- }
- return smUsedShadowMaps.size();
- }
- void LightShadowMap::_onTextureEvent( GFXTexCallbackCode code )
- {
- if ( code == GFXZombify )
- releaseTextures();
- // We don't initialize here as we want the textures
- // to be reallocated when the shadow becomes visible.
- }
- void LightShadowMap::calcLightMatrices( MatrixF &outLightMatrix, const Frustum &viewFrustum )
- {
- // Create light matrix, set projection
- switch ( mLight->getType() )
- {
- case LightInfo::Vector :
- {
- const ShadowMapParams *p = mLight->getExtended<ShadowMapParams>();
- // Calculate the bonding box of the shadowed area
- // we're interested in... this is the shadow box
- // transformed by the frustum transform.
- Box3F viewBB( -p->shadowDistance, -p->shadowDistance, -p->shadowDistance,
- p->shadowDistance, p->shadowDistance, p->shadowDistance );
- viewFrustum.getTransform().mul( viewBB );
- // Calculate a light "projection" matrix.
- MatrixF lightMatrix = MathUtils::createOrientFromDir(mLight->getDirection());
- outLightMatrix = lightMatrix;
- static MatrixF rotMat(EulerF( (M_PI_F / 2.0f), 0.0f, 0.0f));
- lightMatrix.mul( rotMat );
- // This is the box in lightspace
- Box3F lightViewBB(viewBB);
- lightMatrix.mul(lightViewBB);
- // Now, let's position our light based on the lightViewBB
- Point3F newLightPos(viewBB.getCenter());
- F32 sceneDepth = lightViewBB.maxExtents.z - lightViewBB.minExtents.z;
- newLightPos += mLight->getDirection() * ((-sceneDepth / 2.0f)-1.0f); // -1 for the nearplane
- outLightMatrix.setPosition(newLightPos);
- // Update light info
- mLight->setRange( sceneDepth );
- mLight->setPosition( newLightPos );
- // Set our ortho projection
- F32 width = (lightViewBB.maxExtents.x - lightViewBB.minExtents.x) / 2.0f;
- F32 height = (lightViewBB.maxExtents.y - lightViewBB.minExtents.y) / 2.0f;
- width = getMax(width, height);
- GFX->setOrtho(-width, width, -width, width, 1.0f, sceneDepth, true);
- // TODO: Width * 2... really isn't that pixels being used as
- // meters? Is a real physical metric of scene depth better?
- //SceneManager::setVisibleDistance(width * 2.0f);
- #if 0
- DebugDrawer::get()->drawFrustum(viewFrustum, LinearColorF(1.0f, 0.0f, 0.0f));
- DebugDrawer::get()->drawBox(viewBB.minExtents, viewBB.maxExtents, LinearColorF(0.0f, 1.0f, 0.0f));
- DebugDrawer::get()->drawBox(lightViewBB.minExtents, lightViewBB.maxExtents, LinearColorF(0.0f, 0.0f, 1.0f));
- DebugDrawer::get()->drawBox(newLightPos - Point3F(1,1,1), newLightPos + Point3F(1,1,1), LinearColorF(1,1,0));
- DebugDrawer::get()->drawLine(newLightPos, newLightPos + mLight.mDirection*3.0f, LinearColorF(0,1,1));
- Point3F a(newLightPos);
- Point3F b(newLightPos);
- Point3F offset(width, height,0.0f);
- a -= offset;
- b += offset;
- DebugDrawer::get()->drawBox(a, b, LinearColorF(0.5f, 0.5f, 0.5f));
- #endif
- }
- break;
- case LightInfo::Spot :
- {
- outLightMatrix = mLight->getTransform();
- F32 fov = mDegToRad( mLight->getOuterConeAngle() );
- F32 farDist = mLight->getRange().x;
- F32 nearDist = farDist * 0.01f;
- F32 left, right, top, bottom;
- MathUtils::makeFrustum( &left, &right, &top, &bottom, fov, 1.0f, nearDist );
- GFX->setFrustum( left, right, bottom, top, nearDist, farDist );
- }
- break;
- default:
- AssertFatal(false, "Unsupported light type!");
- }
- }
- void LightShadowMap::releaseTextures()
- {
- mShadowMapTex = NULL;
- mDebugTarget.setTexture( NULL );
- smUsedShadowMaps.remove( this );
- }
- void LightShadowMap::setDebugTarget( const String &name )
- {
- mDebugTarget.registerWithName( name );
- mDebugTarget.setTexture( mShadowMapTex );
- }
- GFXTextureObject* LightShadowMap::_getDepthTarget( U32 width, U32 height )
- {
- // Get a depth texture target from the pooled profile
- // which is returned as a temporary.
- GFXTexHandle depthTex( width, height, GFXFormatD24S8, &ShadowMapZProfile,
- "LightShadowMap::_getDepthTarget()" );
- return depthTex;
- }
- bool LightShadowMap::setTextureStage( U32 currTexFlag, LightingShaderConstants* lsc )
- {
- if ( currTexFlag == Material::DynamicLight )
- {
- S32 reg = lsc->mShadowMapSC->getSamplerRegister();
- if ( reg != -1 )
- GFX->setTexture( reg, mShadowMapTex);
- return true;
- } else if ( currTexFlag == Material::DynamicLightMask )
- {
- S32 reg = lsc->mCookieMapSC->getSamplerRegister();
- if ( reg != -1 )
- {
- ShadowMapParams *p = mLight->getExtended<ShadowMapParams>();
- if ( lsc->mCookieMapSC->getType() == GFXSCT_SamplerCube )
- GFX->setCubeTexture( reg, p->getCookieCubeTex() );
- else
- GFX->setTexture( reg, p->getCookieTex() );
- }
- return true;
- }
- return false;
- }
- void LightShadowMap::render(RenderPassManager* renderPass, const SceneRenderState *diffuseState)
- {
- mDebugTarget.setTexture( NULL );
- _render( renderPass, diffuseState );
- mDebugTarget.setTexture( mShadowMapTex );
- // Add it to the used list unless we're been updated.
- //AssertFatal( !smUsedShadowMaps.contains( this ), "LightShadowMap::render - Used shadow map inserted twice!" );
- if(!smUsedShadowMaps.contains(this))
- smUsedShadowMaps.push_back( this );
- }
- BaseMatInstance* LightShadowMap::getShadowMaterial( BaseMatInstance *inMat ) const
- {
- // See if we have an existing material hook.
- ShadowMaterialHook *hook = static_cast<ShadowMaterialHook*>( inMat->getHook( ShadowMaterialHook::Type ) );
- if ( !hook )
- {
- // Create a hook and initialize it using the incoming material.
- hook = new ShadowMaterialHook;
- hook->init( inMat );
- inMat->addHook( hook );
- }
- return hook->getShadowMat( getShadowType() );
- }
- U32 LightShadowMap::getBestTexSize( U32 scale ) const
- {
- const ShadowMapParams *params = mLight->getExtended<ShadowMapParams>();
-
- // The view dependent shadows don't scale by screen size.
- U32 texSize;
- if ( isViewDependent() )
- texSize = params->texSize;
- else
- texSize = params->texSize * getMin( 1.0f, mLastScreenSize );
- // Apply the shadow texture scale and make
- // sure this is a power of 2.
- texSize = getNextPow2( texSize * smShadowTexScalar );
- // Get the max texture size this card supports and
- // scale it down... ensuring the final texSize can
- // be scaled up that many times and not go over
- // the card maximum.
- U32 maxTexSize = GFX->getCardProfiler()->queryProfile( "maxTextureSize", 2048 );
- if ( scale > 1 )
- maxTexSize >>= ( scale - 1 );
- // Never let the shadow texture get smaller than 16x16 as
- // it just makes the pool bigger and the fillrate savings
- // are less and leass as we get smaller.
- texSize = mClamp( texSize, (U32)16, maxTexSize );
- // Return it.
- return texSize;
- }
- void LightShadowMap::updatePriority( const SceneRenderState *state, U32 currTimeMs )
- {
- PROFILE_SCOPE( LightShadowMap_updatePriority );
- mLastCull = currTimeMs;
- if ( isViewDependent() )
- {
- mLastScreenSize = 1.0f;
- mLastPriority = F32_MAX;
- return;
- }
- const Point3F &camPt = state->getCameraPosition();
- F32 range = mLight->getRange().x;
- F32 dist;
- if ( mLight->getType() == LightInfo::Spot )
- {
- // We treat the cone as a cylinder to get the
- // approximate projection distance.
- Point3F endPt = mLight->getPosition() + ( mLight->getDirection() * range );
- Point3F nearPt = MathUtils::mClosestPointOnSegment( mLight->getPosition(), endPt, camPt );
- dist = ( camPt - nearPt ).len();
- F32 radius = range * mSin( mDegToRad( mLight->getOuterConeAngle() * 0.5f ) );
- dist -= radius;
- }
- else
- dist = SphereF( mLight->getPosition(), range ).distanceTo( camPt );
- // Get the approximate screen size of the light.
- mLastScreenSize = state->projectRadius( dist, range );
- mLastScreenSize /= state->getViewport().extent.y;
- // Update the priority.
- mLastPriority = mPow( mLastScreenSize * 50.0f, 2.0f );
- mLastPriority *= mLight->getPriority();
- }
- S32 QSORT_CALLBACK LightShadowMap::cmpPriority( LightShadowMap *const *lsm1, LightShadowMap *const *lsm2 )
- {
- F32 diff = (*lsm1)->getLastPriority() - (*lsm2)->getLastPriority();
- return diff > 0.0f ? -1 : ( diff < 0.0f ? 1 : 0 );
- }
- void LightShadowMap::_debugRender( SceneRenderState* shadowRenderState )
- {
- #ifdef TORQUE_DEBUG
- // Skip if light does not have debug rendering enabled.
- if( !getLightInfo()->isDebugRenderingEnabled() )
- return;
- DebugDrawer* drawer = DebugDrawer::get();
- if( !drawer )
- return;
- if( smDebugRenderFrustums )
- shadowRenderState->getCullingState().debugRenderCullingVolumes();
- #endif
- }
- LightingShaderConstants::LightingShaderConstants()
- : mInit( false ),
- mShader( NULL ),
- mLightParamsSC(NULL),
- mLightSpotParamsSC(NULL),
- mLightPositionSC(NULL),
- mLightDiffuseSC(NULL),
- mLightAmbientSC(NULL),
- mLightConfigDataSC(NULL),
- mLightSpotDirSC(NULL),
- mHasVectorLightSC(NULL),
- mVectorLightDirectionSC(NULL),
- mVectorLightColorSC(NULL),
- mVectorLightBrightnessSC(NULL),
- mShadowMapSC(NULL),
- mShadowMapSizeSC(NULL),
- mCookieMapSC(NULL),
- mRandomDirsConst(NULL),
- mShadowSoftnessConst(NULL),
- mAtlasXOffsetSC(NULL),
- mAtlasYOffsetSC(NULL),
- mAtlasScaleSC(NULL),
- mFadeStartLength(NULL),
- mOverDarkFactorPSSM(NULL),
- mTapRotationTexSC(NULL),
- mWorldToLightProjSC(NULL),
- mViewToLightProjSC(NULL),
- mScaleXSC(NULL),
- mScaleYSC(NULL),
- mOffsetXSC(NULL),
- mOffsetYSC(NULL),
- mFarPlaneScalePSSM(NULL)
- {
- }
- LightingShaderConstants::~LightingShaderConstants()
- {
- if (mShader.isValid())
- {
- mShader->getReloadSignal().remove( this, &LightingShaderConstants::_onShaderReload );
- mShader = NULL;
- }
- }
- void LightingShaderConstants::init(GFXShader* shader)
- {
- if (mShader.getPointer() != shader)
- {
- if (mShader.isValid())
- mShader->getReloadSignal().remove( this, &LightingShaderConstants::_onShaderReload );
- mShader = shader;
- mShader->getReloadSignal().notify( this, &LightingShaderConstants::_onShaderReload );
- }
- mLightParamsSC = shader->getShaderConstHandle("$lightParams");
- // NOTE: These are the shader constants used for doing lighting
- // during the forward pass. Do not confuse these for the deferred
- // lighting constants which are used from AdvancedLightBinManager.
- mLightPositionSC = shader->getShaderConstHandle( ShaderGenVars::lightPosition );
- mLightDiffuseSC = shader->getShaderConstHandle( ShaderGenVars::lightDiffuse );
- mLightAmbientSC = shader->getShaderConstHandle( ShaderGenVars::lightAmbient );
- mLightConfigDataSC = shader->getShaderConstHandle( ShaderGenVars::lightConfigData);
- mLightSpotDirSC = shader->getShaderConstHandle( ShaderGenVars::lightSpotDir );
- mLightSpotParamsSC = shader->getShaderConstHandle(ShaderGenVars::lightSpotParams);
- mHasVectorLightSC = shader->getShaderConstHandle(ShaderGenVars::hasVectorLight);
- mVectorLightDirectionSC = shader->getShaderConstHandle(ShaderGenVars::vectorLightDirection);
- mVectorLightColorSC = shader->getShaderConstHandle(ShaderGenVars::vectorLightColor);
- mVectorLightBrightnessSC = shader->getShaderConstHandle(ShaderGenVars::vectorLightBrightness);
- mShadowMapSC = shader->getShaderConstHandle("$shadowMap");
- mShadowMapSizeSC = shader->getShaderConstHandle("$shadowMapSize");
- mCookieMapSC = shader->getShaderConstHandle("$cookieMap");
- mShadowSoftnessConst = shader->getShaderConstHandle("$shadowSoftness");
- mAtlasXOffsetSC = shader->getShaderConstHandle("$atlasXOffset");
- mAtlasYOffsetSC = shader->getShaderConstHandle("$atlasYOffset");
- mAtlasScaleSC = shader->getShaderConstHandle("$atlasScale");
- mFadeStartLength = shader->getShaderConstHandle("$fadeStartLength");
- mOverDarkFactorPSSM = shader->getShaderConstHandle("$overDarkPSSM");
- mTapRotationTexSC = shader->getShaderConstHandle( "$gTapRotationTex" );
- mWorldToLightProjSC = shader->getShaderConstHandle("$worldToLightProj");
- mViewToLightProjSC = shader->getShaderConstHandle("$viewToLightProj");
- mScaleXSC = shader->getShaderConstHandle("$scaleX");
- mScaleYSC = shader->getShaderConstHandle("$scaleY");
- mOffsetXSC = shader->getShaderConstHandle("$offsetX");
- mOffsetYSC = shader->getShaderConstHandle("$offsetY");
- mFarPlaneScalePSSM = shader->getShaderConstHandle("$farPlaneScalePSSM");
- mInit = true;
- }
- void LightingShaderConstants::_onShaderReload()
- {
- if (mShader.isValid())
- init( mShader );
- }
- MODULE_BEGIN( ShadowMapParams )
- MODULE_INIT_BEFORE( LightMapParams )
- MODULE_INIT
- {
- ShadowMapParams::Type = "ShadowMapParams" ;
- }
- MODULE_END;
- LightInfoExType ShadowMapParams::Type( "" );
- ShadowMapParams::ShadowMapParams( LightInfo *light )
- : mShadowMap( NULL ),
- mLight( light )
- {
- attenuationRatio.set( 0.0f, 1.0f, 1.0f );
- shadowType = ShadowType_Spot;
- overDarkFactor.set(2000.0f, 1000.0f, 500.0f, 100.0f);
- numSplits = 4;
- logWeight = 0.91f;
- texSize = 1024;
- shadowDistance = 100.0f;
- shadowSoftness = 0.2f;
- fadeStartDist = 75.0f;
- lastSplitTerrainOnly = false;
- mQuery = GFX->createOcclusionQuery();
- cookie = StringTable->EmptyString();;
- _validate();
- }
- ShadowMapParams::~ShadowMapParams()
- {
- SAFE_DELETE( mQuery );
- SAFE_DELETE( mShadowMap );
- }
- void ShadowMapParams::_validate()
- {
- switch ( mLight->getType() )
- {
- case LightInfo::Spot:
- shadowType = ShadowType_Spot;
- break;
- case LightInfo::Vector:
- shadowType = ShadowType_PSSM;
- break;
- case LightInfo::Point:
- if ( shadowType < ShadowType_Paraboloid )
- shadowType = ShadowType_DualParaboloidSinglePass;
- break;
-
- default:
- break;
- }
- // The texture sizes for shadows should always
- // be power of 2 in size.
- texSize = getNextPow2( texSize );
- // The maximum shadow texture size setting we're
- // gonna allow... this doesn't use your hardware
- // settings as you may be on a lower end system
- // than your target machine.
- //
- // We apply the hardware specific limits during
- // shadow rendering.
- //
- U32 maxTexSize = 8192;
- if ( mLight->getType() == LightInfo::Vector )
- {
- numSplits = mClamp( numSplits, 1, 4 );
-
- // Adjust the shadow texture size for the PSSM
- // based on the split count to keep the total
- // shadow texture size within 4096.
- if ( numSplits == 2 || numSplits == 4 )
- maxTexSize = 8192;
- if ( numSplits == 3 )
- maxTexSize = 4096;
- }
- else
- numSplits = 1;
- // Keep it in a valid range... less than 32 is dumb.
- texSize = mClamp( texSize, 32, maxTexSize );
- shadowDistance = mClamp(shadowDistance, 25.0f, 10000.0f);
- }
- LightShadowMap* ShadowMapParams::getOrCreateShadowMap()
- {
- if (mShadowMap)
- return mShadowMap;
- if ( !mLight->getCastShadows() )
- return NULL;
- LightShadowMap* newShadowMap = NULL;
- switch ( mLight->getType() )
- {
- case LightInfo::Spot:
- newShadowMap = new SingleLightShadowMap( mLight );
- break;
- case LightInfo::Vector:
- newShadowMap = new PSSMLightShadowMap( mLight );
- break;
- case LightInfo::Point:
- if ( shadowType == ShadowType_CubeMap )
- newShadowMap = new CubeLightShadowMap( mLight );
- else if ( shadowType == ShadowType_Paraboloid )
- newShadowMap = new ParaboloidLightShadowMap( mLight );
- else
- newShadowMap = new DualParaboloidLightShadowMap( mLight );
- break;
-
- default:
- break;
- }
- mShadowMap = newShadowMap;
- return mShadowMap;
- }
- GFXTextureObject* ShadowMapParams::getCookieTex()
- {
- if ( hasCookieTex() &&
- ( mCookieTex.isNull() ||
- cookie != StringTable->insert(mCookieTex->getPath().c_str()) ) )
- {
- mCookieTex.set( cookie,
- &GFXStaticTextureSRGBProfile,
- "ShadowMapParams::getCookieTex()" );
- }
- else if (!hasCookieTex())
- mCookieTex = NULL;
- return mCookieTex.getPointer();
- }
- GFXCubemap* ShadowMapParams::getCookieCubeTex()
- {
- if ( hasCookieTex() &&
- ( mCookieCubeTex.isNull() ||
- cookie != StringTable->insert(mCookieTex->getPath().c_str())) )
- {
- mCookieCubeTex.set( cookie );
- }
- else if (!hasCookieTex())
- mCookieCubeTex = NULL;
- return mCookieCubeTex.getPointer();
- }
- void ShadowMapParams::set( const LightInfoEx *ex )
- {
- // TODO: Do we even need this?
- }
- void ShadowMapParams::packUpdate( BitStream *stream ) const
- {
- // HACK: We need to work out proper parameter
- // validation when any field changes on the light.
- ((ShadowMapParams*)this)->_validate();
- stream->writeInt( shadowType, 8 );
-
- mathWrite( *stream, attenuationRatio );
-
- stream->write( texSize );
- stream->writeString( cookie );
- stream->write( numSplits );
- stream->write( logWeight );
- mathWrite(*stream, overDarkFactor);
- stream->write( fadeStartDist );
- stream->writeFlag( lastSplitTerrainOnly );
- stream->write( shadowDistance );
- stream->write( shadowSoftness );
- }
- void ShadowMapParams::unpackUpdate( BitStream *stream )
- {
- ShadowType newType = (ShadowType)stream->readInt( 8 );
- if ( shadowType != newType )
- {
- // If the shadow type changes delete the shadow
- // map so it can be reallocated on the next render.
- shadowType = newType;
- SAFE_DELETE( mShadowMap );
- }
- mathRead( *stream, &attenuationRatio );
- stream->read( &texSize );
- cookie = stream->readSTString();
- stream->read( &numSplits );
- stream->read( &logWeight );
- mathRead(*stream, &overDarkFactor);
- stream->read( &fadeStartDist );
- lastSplitTerrainOnly = stream->readFlag();
- stream->read( &shadowDistance );
- stream->read( &shadowSoftness );
- }
|