| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 |
- /*
- ** Command & Conquer Generals Zero Hour(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- ////////////////////////////////////////////////////////////////////////////////
- // //
- // (c) 2001-2003 Electronic Arts Inc. //
- // //
- ////////////////////////////////////////////////////////////////////////////////
- // FILE: W3DShadow.cpp ///////////////////////////////////////////////////////////
- //
- // Real time shadow representations
- //
- // Author: Mark Wilczynski, February 2002
- //
- //
- // USER INCLUDES //////////////////////////////////////////////////////////////
- #include "always.h"
- #include "GameClient/View.h"
- #include "WW3D2/Camera.h"
- #include "WW3D2/Light.h"
- #include "WW3D2/DX8Wrapper.h"
- #include "WW3D2/HLod.h"
- #include "WW3D2/mesh.h"
- #include "WW3D2/meshmdl.h"
- #include "Lib/BaseType.h"
- #include "W3DDevice/GameClient/W3DGranny.h"
- #include "W3DDevice/GameClient/Heightmap.h"
- #include "D3dx8math.h"
- #include "common/GlobalData.h"
- #include "W3DDevice/GameClient/W3DVolumetricShadow.h"
- #include "W3DDevice/GameClient/W3DProjectedShadow.h"
- #include "W3DDevice/GameClient/W3DShadow.h"
- #include "WW3D2/statistics.h"
- #include "Common/Debug.h"
- #include "Common/PerfTimer.h"
- #define SUN_DISTANCE_FROM_GROUND 10000.0f //distance of sun (our only light source).
- // Global Variables and Functions /////////////////////////////////////////////
- W3DShadowManager *TheW3DShadowManager=NULL;
- const FrustumClass *shadowCameraFrustum;
- Vector3 LightPosWorld[ MAX_SHADOW_LIGHTS ] =
- {
- Vector3( 94.0161f, 50.499f, 200.0f)
- };
- //DECLARE_PERF_TIMER(shadowsRender)
- void DoShadows(RenderInfoClass & rinfo, Bool stencilPass)
- {
- //USE_PERF_TIMER(shadowsRender)
- shadowCameraFrustum=&rinfo.Camera.Get_Frustum();
- Int projectionCount=0;
- //Projected shadows render first because they may fill the stencil buffer
- //which will be used by the shadow volumes
- if (stencilPass == FALSE && TheW3DProjectedShadowManager)
- {
- if (TheW3DShadowManager->isShadowScene())
- projectionCount=TheW3DProjectedShadowManager->renderShadows(rinfo);
- }
- if (stencilPass == TRUE && TheW3DVolumetricShadowManager)
- {
- // TheW3DShadowManager->loadTerrainShadows();
- //This function gets called many times by the W3D renderer
- //so we use this flag to make sure shadows rendered only once per frame.
- if (TheW3DShadowManager->isShadowScene())
- TheW3DVolumetricShadowManager->renderShadows(projectionCount);
- }
- if (TheW3DShadowManager && stencilPass) //reset so no more shadow processing this frame.
- TheW3DShadowManager->queueShadows(FALSE);
- }
-
- W3DShadowManager::W3DShadowManager( void )
- {
- DEBUG_ASSERTCRASH(TheW3DVolumetricShadowManager == NULL && TheW3DProjectedShadowManager == NULL,
- ("Creating new shadow managers without deleting old ones"));
- m_shadowColor = 0x7fa0a0a0;
- m_isShadowScene = FALSE;
- m_stencilShadowMask = 0; //all bits can be used for storing shadows.
- Vector3 lightRay(-TheGlobalData->m_terrainLightPos[0].x,
- -TheGlobalData->m_terrainLightPos[0].y, -TheGlobalData->m_terrainLightPos[0].z);
- lightRay.Normalize();
- LightPosWorld[0]=lightRay*SUN_DISTANCE_FROM_GROUND;
- TheW3DVolumetricShadowManager = NEW W3DVolumetricShadowManager;
- TheProjectedShadowManager = TheW3DProjectedShadowManager = NEW W3DProjectedShadowManager;
- }
- W3DShadowManager::~W3DShadowManager( void )
- {
- delete TheW3DVolumetricShadowManager;
- TheW3DVolumetricShadowManager = NULL;
- delete TheW3DProjectedShadowManager;
- TheProjectedShadowManager = TheW3DProjectedShadowManager = NULL;
- }
- /** Do one-time initilalization of shadow systems that need to be
- active for full duration of game*/
- Bool W3DShadowManager::init( void )
- {
- Bool result=TRUE;
- if (TheW3DVolumetricShadowManager && TheW3DVolumetricShadowManager->init())
- {
- if (TheW3DVolumetricShadowManager->ReAcquireResources())
- result = TRUE;
- }
- if ( TheW3DProjectedShadowManager && TheW3DProjectedShadowManager->init())
- {
- if (TheW3DProjectedShadowManager->ReAcquireResources())
- result = TRUE;
- }
- return result;
- }
- /** Do per-map reset. This frees up shadows from all objects since
- they may not exist on the next map*/
- void W3DShadowManager::Reset( void )
- {
- if (TheW3DVolumetricShadowManager)
- TheW3DVolumetricShadowManager->reset();
- if (TheW3DProjectedShadowManager)
- TheW3DProjectedShadowManager->reset();
- }
- Bool W3DShadowManager::ReAcquireResources()
- {
- Bool result = TRUE;
- if (TheW3DVolumetricShadowManager && !TheW3DVolumetricShadowManager->ReAcquireResources())
- result = FALSE;
- if (TheW3DProjectedShadowManager && !TheW3DProjectedShadowManager->ReAcquireResources())
- result = FALSE;
- return result;
- }
- void W3DShadowManager::ReleaseResources(void)
- {
- if (TheW3DVolumetricShadowManager)
- TheW3DVolumetricShadowManager->ReleaseResources();
- if (TheW3DProjectedShadowManager)
- TheW3DProjectedShadowManager->ReleaseResources();
- }
- Shadow *W3DShadowManager::addShadow( RenderObjClass *robj, Shadow::ShadowTypeInfo *shadowInfo, Drawable *draw)
- {
- ShadowType type = SHADOW_VOLUME;
- if (shadowInfo)
- type = shadowInfo->m_type;
- switch(type)
- {
- case SHADOW_VOLUME:
- if (TheW3DVolumetricShadowManager)
- return (Shadow *)TheW3DVolumetricShadowManager->addShadow(robj, shadowInfo, draw);
- break;
- case SHADOW_PROJECTION:
- case SHADOW_DECAL:
- if (TheW3DProjectedShadowManager)
- return (Shadow *)TheW3DProjectedShadowManager->addShadow(robj, shadowInfo, draw);
- break;
- default:
- return NULL;
- }
-
- return NULL;
- }
- void W3DShadowManager::removeShadow(Shadow *shadow)
- {
- shadow->release();
- }
- void W3DShadowManager::removeAllShadows(void)
- {
- if (TheW3DVolumetricShadowManager)
- TheW3DVolumetricShadowManager->removeAllShadows();
- if (TheW3DProjectedShadowManager)
- TheW3DProjectedShadowManager->removeAllShadows();
- }
- /**Force update of all shadows even when light source and object have not moved*/
- void W3DShadowManager::invalidateCachedLightPositions(void)
- {
- if (TheW3DVolumetricShadowManager)
- TheW3DVolumetricShadowManager->invalidateCachedLightPositions();
- if (TheW3DProjectedShadowManager)
- TheW3DProjectedShadowManager->invalidateCachedLightPositions();
- }
- Vector3 &W3DShadowManager::getLightPosWorld(Int lightIndex)
- {
- return LightPosWorld[lightIndex];
- }
- void W3DShadowManager::setLightPosition(Int lightIndex, Real x, Real y, Real z)
- {
- if (lightIndex != 0)
- return; ///@todo: Add support for multiple lights
- LightPosWorld[lightIndex]=Vector3(x,y,z);
- }
- void W3DShadowManager::setTimeOfDay(TimeOfDay tod)
- {
- //Ray to light source
- const GlobalData::TerrainLighting *ol=&TheGlobalData->m_terrainObjectsLighting[tod][0];
- Vector3 lightRay(-ol->lightPos.x,-ol->lightPos.y,-ol->lightPos.z);
- lightRay.Normalize();
- lightRay *= SUN_DISTANCE_FROM_GROUND;
- setLightPosition(0, lightRay.X, lightRay.Y, lightRay.Z);
- }
|