1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036 |
- /* Copyright (c) 2002-2012 Croteam Ltd.
- This program is free software; you can redistribute it and/or modify
- it under the terms of version 2 of the GNU General Public License as published by
- the Free Software Foundation
- 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, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
- #include "stdh.h"
- #include <Engine/Brushes/Brush.h>
- #include <Engine/Brushes/BrushTransformed.h>
- #include <Engine/Rendering/Render.h>
- #include <Engine/Rendering/Render_internal.h>
- #include <Engine/Base/Console.h>
- #include <Engine/Templates/DynamicContainer.h>
- #include <Engine/Templates/DynamicContainer.cpp>
- #include <Engine/Light/LightSource.h>
- #include <Engine/Light/Gradient.h>
- #include <Engine/Base/ListIterator.inl>
- #include <Engine/World/World.h>
- #include <Engine/Entities/Entity.h>
- #include <Engine/Templates/StaticArray.cpp>
- #include <Engine/Math/Clipping.inl>
- #include <Engine/Entities/EntityClass.h>
- #include <Engine/World/WorldSettings.h>
- #include <Engine/Entities/EntityProperties.h>
- #include <Engine/Entities/FieldSettings.h>
- #include <Engine/Entities/ShadingInfo.h>
- #include <Engine/Light/LensFlares.h>
- #include <Engine/Models/ModelObject.h>
- #include <Engine/Models/RenderModel.h>
- #include <Engine/Ska/Render.h>
- #include <Engine/Terrain/Terrain.h>
- #include <Engine/Templates/BSP.h>
- #include <Engine/World/WorldEditingProfile.h>
- #include <Engine/Brushes/BrushArchive.h>
- #include <Engine/Math/Float.h>
- #include <Engine/Math/OBBox.h>
- #include <Engine/Math/Geometry.inl>
- #include <Engine/Graphics/DrawPort.h>
- #include <Engine/Graphics/GfxLibrary.h>
- #include <Engine/Graphics/Fog_internal.h>
- #include <Engine/Base/Statistics_internal.h>
- #include <Engine/Rendering/RenderProfile.h>
- #include <Engine/Templates/LinearAllocator.cpp>
- #include <Engine/Templates/DynamicArray.cpp>
- #include <Engine/Templates/StaticStackArray.cpp>
- #include <Engine/Templates/DynamicStackArray.cpp>
- extern BOOL _bSomeDarkExists;
- extern INDEX d3d_bAlternateDepthReads;
- // general coordinate stack referenced by the scene polygons
- extern CStaticStackArray<GFXVertex3> _avtxScene;
- //#pragma optimize ("gt", on)
- #pragma inline_depth(255)
- #pragma inline_recursion(on)
- #ifndef NDEBUG
- //#define ASER_EXTREME_CHECKING 1
- #endif
- // the renderer structures used in rendering
- #define MAX_RENDERERS 2
- static CRenderer _areRenderers[MAX_RENDERERS];
- static BOOL _bMirrorDrawn = FALSE;
- extern INDEX wld_bAlwaysAddAll;
- extern INDEX wld_bRenderEmptyBrushes;
- extern INDEX wld_bRenderDetailPolygons;
- extern INDEX gfx_bRenderParticles;
- extern INDEX gfx_bRenderModels;
- extern INDEX gfx_bRenderFog;
- extern INDEX gfx_bRenderPredicted;
- extern INDEX gfx_iLensFlareQuality;
- extern BOOL _bMultiPlayer;
- // variables for selection on rendering
- extern CBrushVertexSelection *_pselbvxtSelectOnRender = NULL;
- extern CStaticStackArray<PIX2D> *_pavpixSelectLasso = NULL;
- extern CEntitySelection *_pselenSelectOnRender = NULL;
- extern PIX2D _vpixSelectNearPoint = PIX2D(0,0);
- extern BOOL _bSelectAlternative = FALSE;
- extern PIX _pixDeltaAroundVertex = 10;
- // shading info for viewer of last rendered view
- FLOAT3D _vViewerLightDirection;
- COLOR _colViewerLight;
- COLOR _colViewerAmbient;
- // handy statistic helper routines
- static enum CStatForm::StatTimerIndex _stiLastStatsMode = (enum CStatForm::StatTimerIndex)-1;
- void StopStatsMode(void)
- {
- ASSERT( (INDEX)_stiLastStatsMode != -1);
- if( _stiLastStatsMode>=0) _sfStats.StopTimer(_stiLastStatsMode);
- _stiLastStatsMode = (enum CStatForm::StatTimerIndex)-1;
- }
- void StartStatsMode( enum CStatForm::StatTimerIndex sti)
- {
- ASSERT( (INDEX)sti != -1);
- ASSERT( (INDEX)_stiLastStatsMode == -1);
- if( sti>=0) _sfStats.StartTimer(sti);
- _stiLastStatsMode = sti;
- }
- void ChangeStatsMode( enum CStatForm::StatTimerIndex sti)
- {
- StopStatsMode();
- StartStatsMode(sti);
- }
- // screen edges, polygons and trapezoids used in rasterizing
- CDynamicStackArray<CAddEdge> CRenderer::re_aadeAddEdges;
- CDynamicStackArray<CScreenEdge> CRenderer::re_asedScreenEdges;
- // spans for current scan line
- CDynamicStackArray<CSpan> CRenderer::re_aspSpans;
- // vertices clipped to current clip plane
- CStaticStackArray<INDEX> CRenderer::re_aiClipBuffer;
- // buffers for edges of polygons
- CStaticStackArray<INDEX> CRenderer::re_aiEdgeVxClipSrc;
- CStaticStackArray<INDEX> CRenderer::re_aiEdgeVxClipDst;
- // add and remove lists for each scan line
- CStaticArray<CListHead> CRenderer::re_alhAddLists;
- CStaticArray<INDEX> CRenderer::re_actAddCounts; // count of edges in given add list
- CStaticArray<CScreenEdge *> CRenderer::re_apsedRemoveFirst;
- CStaticStackArray<CActiveEdge> CRenderer::re_aaceActiveEdgesTmp;
- CStaticStackArray<CActiveEdge> CRenderer::re_aaceActiveEdges;
- // container for sorting translucent polygons
- CDynamicStackArray<CTranslucentPolygon> CRenderer::re_atcTranslucentPolygons;
- // container for all light influencing current model
- struct ModelLight {
- CLightSource *ml_plsLight; // the light source
- FLOAT3D ml_vDirection; // direction from light to the model position (normalized)
- FLOAT ml_fShadowIntensity; // intensity at the model position (for shadow)
- FLOAT ml_fR, ml_fG, ml_fB; // light components at light source (0..255)
- inline void Clear(void) {};
- };
- static CDynamicStackArray<struct ModelLight> _amlLights;
- static INDEX _ctMaxAddEdges=0;
- static INDEX _ctMaxActiveEdges=0;
- void RendererInfo(void)
- {
- CPrintF("Renderer information:\n");
- SLONG slMem = 0;
- slMem += CRenderer::re_aadeAddEdges.da_Count*sizeof(CAddEdge);
- slMem += CRenderer::re_asedScreenEdges.da_Count*sizeof(CScreenEdge);
- slMem += CRenderer::re_aspSpans.da_Count*sizeof(CSpan);
- slMem += CRenderer::re_aiClipBuffer.sa_Count*sizeof(INDEX);
- slMem += CRenderer::re_aiEdgeVxClipSrc.sa_Count*sizeof(INDEX);
- slMem += CRenderer::re_aiEdgeVxClipDst.sa_Count*sizeof(INDEX);
- slMem += CRenderer::re_alhAddLists.sa_Count*sizeof(CListHead);
- slMem += CRenderer::re_actAddCounts.sa_Count*sizeof(INDEX);
- slMem += CRenderer::re_apsedRemoveFirst.sa_Count*sizeof(CScreenEdge *);
- slMem += CRenderer::re_atcTranslucentPolygons.da_Count*sizeof(CTranslucentPolygon);
- slMem += CRenderer::re_aaceActiveEdges.sa_Count*sizeof(CActiveEdge);
- slMem += CRenderer::re_aaceActiveEdgesTmp.sa_Count*sizeof(CActiveEdge);
- for (INDEX ire = 0; ire<MAX_RENDERERS; ire++) {
- CRenderer &re = _areRenderers[ire];
- slMem += re.re_aspoScreenPolygons.da_Count*sizeof(CScreenPolygon);
- slMem += re.re_admDelayedModels.da_Count*sizeof(CDelayedModel);
- slMem += re.re_cenDrawn.sa_Count*sizeof(CEntity*);
- slMem += re.re_alfiLensFlares.sa_Count*sizeof(CLensFlareInfo);
- slMem += re.re_amiMirrors.da_Count*sizeof(CMirror);
- slMem += re.re_avvxViewVertices.sa_Count*sizeof(CViewVertex);
- slMem += re.re_aiEdgeVxMain.sa_Count*sizeof(INDEX);
- }
- CPrintF("Temporary memory used: %dk\n", slMem/1024);
- }
- void ClearRenderer(void)
- {
- CRenderer::re_aadeAddEdges.Clear();
- CRenderer::re_asedScreenEdges.Clear();
- CRenderer::re_aspSpans.Clear();
- CRenderer::re_aiClipBuffer.Clear();
- CRenderer::re_aiEdgeVxClipSrc.Clear();
- CRenderer::re_aiEdgeVxClipDst.Clear();
- CRenderer::re_alhAddLists.Clear();
- CRenderer::re_actAddCounts.Clear();
- CRenderer::re_apsedRemoveFirst.Clear();
- CRenderer::re_atcTranslucentPolygons.Clear();
- CRenderer::re_aaceActiveEdges.Clear();
- CRenderer::re_aaceActiveEdgesTmp.Clear();
- for (INDEX ire = 0; ire<MAX_RENDERERS; ire++) {
- CRenderer &re = _areRenderers[ire];
- re.re_aspoScreenPolygons.Clear();
- re.re_admDelayedModels.Clear();
- re.re_cenDrawn.Clear();
- re.re_alfiLensFlares.Clear();
- re.re_amiMirrors.Clear();
- re.re_avvxViewVertices.Clear();
- re.re_aiEdgeVxMain.Clear();
- }
- CPrintF("Renderer buffers cleared.\n");
- }
- /*
- * How much to offset left, right, top and bottom clipping towards inside (in pixels).
- * This can be used to test clipping or to add an epsilon value for it.
- */
- //#define CLIPMARGIN 10.0f // used for debugging clipping
- #define CLIPMARGIN 0.0f
- #define CLIPEPSILON 0.5f
- #define CLIPMARGADD (CLIPMARGIN-CLIPEPSILON)
- #define CLIPMARGSUB (CLIPMARGIN+CLIPEPSILON)
- #define SENTINELEDGE_EPSILON 0.4f
- #include "RendMisc.cpp"
- #include "RenCache.cpp"
- #include "RendClip.cpp"
- #include "RendASER.cpp"
- #include "RenderModels.cpp"
- #include "RenderBrushes.cpp"
- #include "RenderAdding.cpp"
- extern FLOAT wld_fEdgeOffsetI;
- extern FLOAT wld_fEdgeAdjustK;
- // initialize all rendering structures
- void CRenderer::Initialize(void)
- {
- _pfRenderProfile.StartTimer(CRenderProfile::PTI_INITIALIZATION);
- // used for fixing problems with extra trapezoids generated on t-junctions
- if( !re_bRenderingShadows) {
- re_fEdgeOffsetI = wld_fEdgeOffsetI; //0.125f;
- re_fEdgeAdjustK = wld_fEdgeAdjustK; //1.0001f;
- } else {
- re_fEdgeOffsetI = 0.0f;
- re_fEdgeAdjustK = 1.0f;
- }
- // prepare the raw projection (used for rendering target lines and getting object distances)
- re_prProjection->ObjectPlacementL() = CPlacement3D(FLOAT3D(0.0f,0.0f,0.0f), ANGLE3D(0,0,0));
- re_prProjection->ObjectFaceForwardL() = FALSE;
- re_prProjection->ObjectStretchL() = FLOAT3D(1.0f, 1.0f, 1.0f);
- re_prProjection->DepthBufferNearL() = 0.0f;
- re_prProjection->DepthBufferFarL() = 0.9f;
- re_prProjection->Prepare();
- re_asedScreenEdges.PopAll();
- re_aadeAddEdges.PopAll();
- re_aspSpans.PopAll();
- re_avvxViewVertices.PopAll();
- re_aiEdgeVxMain.PopAll();
- // if more scan lines are needed than last time
- if (re_alhAddLists.Count()<re_ctScanLines) {
- re_alhAddLists.Clear();
- re_alhAddLists.New(re_ctScanLines);
- re_actAddCounts.Clear();
- re_actAddCounts.New(re_ctScanLines);
- re_apsedRemoveFirst.Clear();
- re_apsedRemoveFirst.New(re_ctScanLines);
- }
- // clear all add/remove lists
- for(INDEX iScan=0; iScan<re_ctScanLines; iScan++) {
- re_actAddCounts[iScan] = 0;
- re_apsedRemoveFirst[iScan] = NULL;
- }
- // find selection color
- re_colSelection = C_RED;
- if (_wrpWorldRenderPrefs.GetSelectionType() == CWorldRenderPrefs::ST_POLYGONS) {
- re_colSelection = C_YELLOW;
- } else if (_wrpWorldRenderPrefs.GetSelectionType() == CWorldRenderPrefs::ST_SECTORS) {
- re_colSelection = C_GREEN;
- } else if (_wrpWorldRenderPrefs.GetSelectionType() == CWorldRenderPrefs::ST_ENTITIES) {
- re_colSelection = C_BLUE;
- }
- // set up renderer for first scan line
- re_iCurrentScan = 0;
- re_pixCurrentScanJ = re_iCurrentScan + re_pixTopScanLineJ;
- re_fCurrentScanJ = FLOAT(re_pixCurrentScanJ);
- // no fog or haze initially
- re_bCurrentSectorHasHaze = FALSE;
- re_bCurrentSectorHasFog = FALSE;
- _pfRenderProfile.StopTimer(CRenderProfile::PTI_INITIALIZATION);
- }
- // add initial sectors to active lists
- void CRenderer::AddInitialSectors(void)
- {
- _pfRenderProfile.StartTimer(CRenderProfile::PTI_ADDINITIAL);
- re_bViewerInHaze = FALSE;
- re_ulVisExclude = 0;
- re_ulVisInclude = 0;
- // if showing vis tweaks
- if (_wrpWorldRenderPrefs.wrp_bShowVisTweaksOn && _pselbscVisTweaks!=NULL) {
- // add flags for selected flags
- if (_pselbscVisTweaks->Count()>0) {
- re_ulVisExclude = VISM_INCLUDEEXCLUDE;
- }
- FOREACHINDYNAMICCONTAINER(*_pselbscVisTweaks, CBrushSector, itbsc) {
- if (itbsc->bsc_ulFlags2&BSCF2_VISIBILITYINCLUDE) {
- re_ulVisInclude = itbsc->bsc_ulVisFlags&VISM_INCLUDEEXCLUDE;
- } else {
- re_ulVisExclude &= itbsc->bsc_ulVisFlags&VISM_INCLUDEEXCLUDE;
- }
- }
- }
- // check if the background is needed
- re_bBackgroundEnabled = FALSE;
- if (!re_bRenderingShadows && _wrpWorldRenderPrefs.wrp_bBackgroundTextureOn) {
- CEntity *penBackgroundViewer = re_pwoWorld->GetBackgroundViewer();
- if (penBackgroundViewer!=NULL) {
- re_bBackgroundEnabled = TRUE;
- re_penBackgroundViewer = penBackgroundViewer;
- re_prBackgroundProjection = re_prProjection;
- CPlacement3D plViewer = re_prProjection->ViewerPlacementR();
- plViewer.pl_PositionVector = FLOAT3D(0,0,0);
- CPlacement3D plBcgViewer = penBackgroundViewer->GetLerpedPlacement();
- if (re_prProjection->pr_bMirror) {
- ReflectPositionVectorByPlane(re_prProjection->pr_plMirror, plBcgViewer.pl_PositionVector);
- }
- plViewer.RelativeToAbsoluteSmooth(plBcgViewer);
- re_prBackgroundProjection->ViewerPlacementL() = plViewer;
- re_prBackgroundProjection->ObjectPlacementL() = CPlacement3D(FLOAT3D(0,0,0), ANGLE3D(0,0,0));
- re_prBackgroundProjection->FarClipDistanceL() = -1.0f;
- re_prBackgroundProjection->DepthBufferNearL() = 0.9f;
- re_prBackgroundProjection->DepthBufferFarL() = 1.0f;
- re_prBackgroundProjection->TurnOffWarpPlane(); // background never needs warp-plane clipping
- re_prBackgroundProjection->Prepare();
- }
- }
- // if a viewer entity is given
- if (re_penViewer!=NULL) {
- // add all zoning sectors near the entity
- AddZoningSectorsAroundEntity(re_penViewer, re_prProjection->ViewerPlacementR().pl_PositionVector);
- // make sure the viewer is always added (if model)
- if(re_penViewer->en_RenderType==CEntity::RT_MODEL ||
- re_penViewer->en_RenderType==CEntity::RT_EDITORMODEL) {
- AddModelEntity(re_penViewer);
- }
- // if a viewer polygons are given
- } else if (re_pcspoViewPolygons!=NULL) {
- // for each polygon
- FOREACHINDYNAMICCONTAINER(*re_pcspoViewPolygons, CScreenPolygon, itspo) {
- CBrushPolygon *pbpo = itspo->spo_pbpoBrushPolygon;
- // get the sector, sector's brush mip, brush and entity
- CBrushSector *pbsc = pbpo->bpo_pbscSector;
- CBrushMip *pbmBrushMip = pbsc->bsc_pbmBrushMip;
- CBrush3D *pbrBrush = pbmBrushMip->bm_pbrBrush;
- ASSERT(pbrBrush!=NULL);
- CEntity *penBrush = pbrBrush->br_penEntity;
- // if the brush is zoning
- if (penBrush->en_ulFlags&ENF_ZONING) {
- // add the sector that the polygon is in
- AddGivenZoningSector(pbsc);
- // if the brush is non-zoning
- } else {
- // add sectors around it
- AddZoningSectorsAroundEntity(penBrush, penBrush->GetPlacement().pl_PositionVector);
- }
- }
- // if there is no viewer entity/polygon
- } else {
- // set up viewer bounding box as box of minimum redraw range around viewer position
- if (re_bRenderingShadows) {
- // NOTE: when rendering shadows, this is set in ::RenderShadows()
- //re_boxViewer = FLOATaabbox3D(re_prProjection->ViewerPlacementR().pl_PositionVector,
- // 1.0f);
- } else {
- re_boxViewer = FLOATaabbox3D(re_prProjection->ViewerPlacementR().pl_PositionVector,
- _wrpWorldRenderPrefs.wrp_fMinimumRenderRange);
- }
- // add all zoning sectors near viewer box
- AddZoningSectorsAroundBox(re_boxViewer);
- // NOTE: this is so entities outside of world can be edited in WEd
- // if editor models should be rendered
- if (_wrpWorldRenderPrefs.IsEditorModelsOn()) {
- // add all nonzoning entities near viewer box
- AddEntitiesInBox(re_boxViewer);
- }
- }
- if( wld_bAlwaysAddAll) {
- AddAllEntities(); // used for profiling
- } else {
- // NOTE: this is so that world can be viewed from the outside in game
- // if no brush sectors have been added so far
- if (!re_bRenderingShadows && re_lhActiveSectors.IsEmpty()) {
- // add all entities in the world
- AddAllEntities();
- }
- }
- // add the background if needed
- if (re_bBackgroundEnabled) {
- AddZoningSectorsAroundEntity(re_penBackgroundViewer,
- re_penBackgroundViewer->GetPlacement().pl_PositionVector);
- }
- _pfRenderProfile.StopTimer(CRenderProfile::PTI_ADDINITIAL);
- }
- // scan through portals for other sectors
- void CRenderer::ScanForOtherSectors(void)
- {
- ChangeStatsMode(CStatForm::STI_WORLDVISIBILITY);
- // if shadows or polygons should be drawn
- if (re_bRenderingShadows
- ||_wrpWorldRenderPrefs.wrp_ftPolygons != CWorldRenderPrefs::FT_NONE) {
- // rasterize edges into spans
- ScanEdges();
- }
- // for each of models that were kept for delayed rendering
- for(INDEX iModel=0; iModel<re_admDelayedModels.Count(); iModel++) {
- // mark the entity as not active in rendering anymore
- re_admDelayedModels[iModel].dm_penModel->en_ulFlags &= ~ENF_INRENDERING;
- }
- ChangeStatsMode(CStatForm::STI_WORLDTRANSFORM);
- }
- // cleanup after scanning
- void CRenderer::CleanupScanning(void)
- {
- _pfRenderProfile.StartTimer(CRenderProfile::PTI_CLEANUP);
- // for all active sectors
- {FORDELETELIST(CBrushSector, bsc_lnInActiveSectors, re_lhActiveSectors, itbsc) {
- // remove it from list
- itbsc->bsc_lnInActiveSectors.Remove();
- // for all polygons in sector
- FOREACHINSTATICARRAY(itbsc->bsc_abpoPolygons, CBrushPolygon, itpo) {
- CBrushPolygon &bpo = *itpo;
- // clear screen polygon pointers
- bpo.bpo_pspoScreenPolygon = NULL;
- }
- }}
- ASSERT(re_lhActiveSectors.IsEmpty());
- // for all active brushes
- {FORDELETELIST(CBrush3D, br_lnInActiveBrushes, re_lhActiveBrushes, itbr) {
- // remove it from list
- itbr->br_lnInActiveBrushes.Remove();
- }}
- ASSERT(re_lhActiveBrushes.IsEmpty());
- // for all active terrains
- {FORDELETELIST(CTerrain, tr_lnInActiveTerrains, re_lhActiveTerrains, ittr) {
- // remove it from list
- ittr->tr_lnInActiveTerrains.Remove();
- }}
- ASSERT(re_lhActiveTerrains.IsEmpty());
- _pfRenderProfile.StopTimer(CRenderProfile::PTI_CLEANUP);
- }
- // Render active terrains
- void CRenderer::RenderTerrains(void)
- {
- CAnyProjection3D *papr;
- papr = &re_prProjection;
- // for all active terrains
- {FORDELETELIST(CTerrain, tr_lnInActiveTerrains, re_lhActiveTerrains, ittr) {
- // render terrain
- ittr->Render(*papr, re_pdpDrawPort);
- }}
- }
- // Render active terrains in wireframe mode
- void CRenderer::RenderWireFrameTerrains(void)
- {
- CAnyProjection3D *papr;
- papr = &re_prProjection;
- BOOL bShowEdges = _wrpWorldRenderPrefs.wrp_ftEdges != CWorldRenderPrefs::FT_NONE;
- BOOL bShowVertices = _wrpWorldRenderPrefs.wrp_ftVertices != CWorldRenderPrefs::FT_NONE;
- // BOOL bForceRegenerate = _wrpWorldRenderPrefs.wrp_ftPolygons
- COLOR colEdges = _wrpWorldRenderPrefs.wrp_colEdges;
- COLOR colVertices = 0xFF0000FF;
- // for all active terrains
- {FORDELETELIST(CTerrain, tr_lnInActiveTerrains, re_lhActiveTerrains, ittr) {
- // render terrain
- if(bShowEdges) {
- ittr->RenderWireFrame(*papr, re_pdpDrawPort,colEdges);
- }
- if(bShowVertices) {
- //ittr->RenderVertices(*papr, re_pdpDrawPort,colVertices);
- }
- }}
- }
- // draw the prepared things to screen
- void CRenderer::DrawToScreen(void)
- {
- ChangeStatsMode(CStatForm::STI_WORLDRENDERING);
-
- //------------------------------------------------- first render background
- // if polygons should be drawn
- if (!re_bRenderingShadows &&
- _wrpWorldRenderPrefs.wrp_ftPolygons != CWorldRenderPrefs::FT_NONE) {
- _pfRenderProfile.StartTimer(CRenderProfile::PTI_RENDERSCENE);
- if( re_bBackgroundEnabled) {
- // render the polygons to screen
- CPerspectiveProjection3D *pprPerspective =
- (CPerspectiveProjection3D *)(CProjection3D *)(re_prBackgroundProjection);
- pprPerspective->Prepare();
- RenderScene( re_pdpDrawPort, re_pspoFirstBackground, re_prBackgroundProjection, re_colSelection, FALSE);
- } else {
- // this is just for far sentinel
- RenderSceneBackground( re_pdpDrawPort, re_spoFarSentinel.spo_spoScenePolygon.spo_cColor);
- }
- _pfRenderProfile.StopTimer(CRenderProfile::PTI_RENDERSCENE);
- }
-
- if (re_bBackgroundEnabled) {
- // render models that were kept for delayed rendering.
- ChangeStatsMode(CStatForm::STI_MODELSETUP);
- RenderModels(TRUE); // render background models
- ChangeStatsMode(CStatForm::STI_WORLDRENDERING);
- }
-
- // if polygons should be drawn
- if (!re_bRenderingShadows &&
- re_bBackgroundEnabled
- &&_wrpWorldRenderPrefs.wrp_ftPolygons != CWorldRenderPrefs::FT_NONE) {
- // render translucent portals
- _pfRenderProfile.StartTimer(CRenderProfile::PTI_RENDERSCENE);
- CPerspectiveProjection3D *pprPerspective = (CPerspectiveProjection3D*)(CProjection3D*)(re_prBackgroundProjection);
- RenderScene( re_pdpDrawPort, SortTranslucentPolygons(re_pspoFirstBackgroundTranslucent),
- re_prBackgroundProjection, re_colSelection, TRUE);
- _pfRenderProfile.StopTimer(CRenderProfile::PTI_RENDERSCENE);
- }
-
- if( re_bBackgroundEnabled) {
- ChangeStatsMode(CStatForm::STI_PARTICLERENDERING);
- RenderParticles(TRUE); // render background particless
- ChangeStatsMode(CStatForm::STI_WORLDRENDERING);
- }
-
- //------------------------------------------------- second render non-background
- // if polygons should be drawn
- if( !re_bRenderingShadows
- && _wrpWorldRenderPrefs.wrp_ftPolygons != CWorldRenderPrefs::FT_NONE) {
- // render the spans to screen
- re_prProjection->Prepare();
- _pfRenderProfile.StartTimer(CRenderProfile::PTI_RENDERSCENE);
- CPerspectiveProjection3D *pprPerspective = (CPerspectiveProjection3D*)(CProjection3D*)re_prProjection;
- RenderScene( re_pdpDrawPort, re_pspoFirst, re_prProjection, re_colSelection, FALSE);
- _pfRenderProfile.StopTimer(CRenderProfile::PTI_RENDERSCENE);
- }
- // Render active terrains
- if( !re_bRenderingShadows
- && _wrpWorldRenderPrefs.wrp_ftPolygons != CWorldRenderPrefs::FT_NONE) {
- RenderTerrains();
- }
- // if wireframe should be drawn
- if( !re_bRenderingShadows &&
- ( _wrpWorldRenderPrefs.wrp_ftEdges != CWorldRenderPrefs::FT_NONE
- || _wrpWorldRenderPrefs.wrp_ftVertices != CWorldRenderPrefs::FT_NONE
- || _wrpWorldRenderPrefs.wrp_stSelection == CWorldRenderPrefs::ST_VERTICES
- || _wrpWorldRenderPrefs.IsFieldBrushesOn())) {
- // render in wireframe all brushes that were added (in orthographic projection!)
- re_pdpDrawPort->SetOrtho();
- RenderWireFrameBrushes();
- RenderWireFrameTerrains();
- }
- // render models that were kept for delayed rendering
- ChangeStatsMode(CStatForm::STI_MODELSETUP);
- RenderModels(FALSE); // render non-background models
- ChangeStatsMode(CStatForm::STI_PARTICLERENDERING);
- RenderParticles(FALSE); // render non-background particles
- ChangeStatsMode(CStatForm::STI_WORLDRENDERING);
-
- // if polygons should be drawn
- if (!re_bRenderingShadows
- &&_wrpWorldRenderPrefs.wrp_ftPolygons != CWorldRenderPrefs::FT_NONE) {
- // render translucent portals
- _pfRenderProfile.StartTimer(CRenderProfile::PTI_RENDERSCENE);
- CPerspectiveProjection3D *pprPerspective = (CPerspectiveProjection3D*)(CProjection3D*)re_prProjection;
- pprPerspective->Prepare();
- RenderScene( re_pdpDrawPort, SortTranslucentPolygons(re_pspoFirstTranslucent),
- re_prProjection, re_colSelection, TRUE);
- _pfRenderProfile.StopTimer(CRenderProfile::PTI_RENDERSCENE);
- }
- // render lens flares
- if( !re_bRenderingShadows) {
- ChangeStatsMode(CStatForm::STI_FLARESRENDERING);
- RenderLensFlares(); // (this also sets orthographic projection!)
- ChangeStatsMode(CStatForm::STI_WORLDRENDERING);
- }
- // if entity targets should be drawn
- if( !re_bRenderingShadows && _wrpWorldRenderPrefs.wrp_bShowTargetsOn) {
- // render entity targets
- RenderEntityTargets();
- }
- // if entity targets should be drawn
- if( !re_bRenderingShadows && _wrpWorldRenderPrefs.wrp_bShowEntityNames) {
- RenderEntityNames();
- }
- // clean all buffers after rendering
- re_aspoScreenPolygons.PopAll();
- re_admDelayedModels.PopAll();
- re_cenDrawn.PopAll();
- re_avvxViewVertices.PopAll();
- }
- // draw mirror polygons to z-buffer to enable drawing of mirror
- void CRenderer::FillMirrorDepth(CMirror &mi)
- {
- // create a list of scene polygons for mirror
- ScenePolygon *pspoFirst = NULL;
- // for each polygon
- FOREACHINDYNAMICCONTAINER(mi.mi_cspoPolygons, CScreenPolygon, itspo) {
- CScreenPolygon &spo = *itspo;
- CBrushPolygon &bpo = *spo.spo_pbpoBrushPolygon;
- // create a new screen polygon
- CScreenPolygon &spoNew = re_aspoScreenPolygons.Push();
- ScenePolygon &sppoNew = spoNew.spo_spoScenePolygon;
- // add it to mirror list
- sppoNew.spo_pspoSucc = pspoFirst;
- pspoFirst = &sppoNew;
- // use same triangles
- sppoNew.spo_iVtx0 = spo.spo_spoScenePolygon.spo_iVtx0;
- sppoNew.spo_ctVtx = spo.spo_spoScenePolygon.spo_ctVtx;
- sppoNew.spo_piElements = spo.spo_spoScenePolygon.spo_piElements;
- sppoNew.spo_ctElements = spo.spo_spoScenePolygon.spo_ctElements;
- }
- // render all those polygons just to clear z-buffer
- RenderSceneZOnly( re_pdpDrawPort, pspoFirst, re_prProjection);
- }
- // do the rendering
- void CRenderer::Render(void)
- {
- // if the world doesn't have all portal-sector links updated
- if( !re_pwoWorld->wo_bPortalLinksUpToDate) {
- // update the links
- CSetFPUPrecision FPUPrecision(FPT_53BIT);
- re_pwoWorld->wo_baBrushes.LinkPortalsAndSectors();
- re_pwoWorld->wo_bPortalLinksUpToDate = TRUE;
- }
- StartStatsMode(CStatForm::STI_WORLDTRANSFORM);
- _pfRenderProfile.IncrementAveragingCounter();
- _pfRenderProfile.StartTimer(CRenderProfile::PTI_RENDERING);
- // set FPU to single precision while rendering
- CSetFPUPrecision FPUPrecision(FPT_24BIT);
- // initialize all rendering structures
- Initialize();
- // init select-on-render functionality if not rendering shadows
- extern void InitSelectOnRender( PIX pixSizeI, PIX pixSizeJ);
- if( re_pdpDrawPort!=NULL) InitSelectOnRender( re_pdpDrawPort->GetWidth(), re_pdpDrawPort->GetHeight());
- // add initial sectors to active lists
- AddInitialSectors();
- // scan through portals for other sectors
- ScanForOtherSectors();
- // force finishing of all OpenGL pending operations, if required
- ChangeStatsMode(CStatForm::STI_SWAPBUFFERS);
- extern INDEX ogl_iFinish; ogl_iFinish = Clamp( ogl_iFinish, 0L, 3L);
- extern INDEX d3d_iFinish; d3d_iFinish = Clamp( d3d_iFinish, 0L, 3L);
- if( (ogl_iFinish==1 && _pGfx->gl_eCurrentAPI==GAT_OGL)
- #ifdef SE1_D3D
- || (d3d_iFinish==1 && _pGfx->gl_eCurrentAPI==GAT_D3D)
- #endif // SE1_D3D
- )
- gfxFinish();
- // check any eventual delayed depth points outside the mirror (if API and time allows)
- if( !re_bRenderingShadows && re_iIndex==0) {
- // OpenGL allows us to check z-buffer from previous frame - cool deal!
- // Direct3D is, of course, totally different story. :(
- if( _pGfx->gl_eCurrentAPI==GAT_OGL || d3d_bAlternateDepthReads) {
- ChangeStatsMode(CStatForm::STI_FLARESRENDERING);
- extern void CheckDelayedDepthPoints( const CDrawPort *pdp, INDEX iMirrorLevel=0);
- CheckDelayedDepthPoints(re_pdpDrawPort);
- }
- // in 1st pass - mirrors are not drawn
- _bMirrorDrawn = FALSE;
- }
- // if may render one more mirror recursion
- ChangeStatsMode(CStatForm::STI_WORLDTRANSFORM);
- if( !re_bRenderingShadows
- && re_prProjection.IsPerspective()
- && re_iIndex<MAX_RENDERERS-1
- && re_amiMirrors.Count()>0
- && !re_pdpDrawPort->IsOverlappedRendering())
- {
- // cleanup after scanning
- CleanupScanning();
- // take next renderer
- CRenderer &re = _areRenderers[re_iIndex+1];
- // for each mirror
- for( INDEX i=0; i<re_amiMirrors.Count(); i++)
- {
- // skip invalid mirrors
- CMirror &mi = re_amiMirrors[i];
- if( mi.mi_iMirrorType<0) continue;
- // calculate all needed data for the mirror
- mi.FinishAdding();
- // skip mirror that has no significant area
- if( mi.mi_fpixMaxPolygonArea<5) continue;
- // expand mirror in each direction, but keep it inside drawport
- PIX pixDPSizeI = re_pdpDrawPort->GetWidth();
- PIX pixDPSizeJ = re_pdpDrawPort->GetHeight();
- mi.mi_boxOnScreen.Expand(1);
- mi.mi_boxOnScreen &= PIXaabbox2D( PIX2D(0,0), PIX2D(pixDPSizeI,pixDPSizeJ));
- // get drawport and mirror coordinates
- PIX pixMirrorMinI = mi.mi_boxOnScreen.Min()(1);
- PIX pixMirrorMinJ = mi.mi_boxOnScreen.Min()(2);
- PIX pixMirrorMaxI = mi.mi_boxOnScreen.Max()(1);
- PIX pixMirrorMaxJ = mi.mi_boxOnScreen.Max()(2);
- // calculate mirror size
- PIX pixMirrorSizeI = pixMirrorMaxI-pixMirrorMinI;
- PIX pixMirrorSizeJ = pixMirrorMaxJ-pixMirrorMinJ;
- // clone drawport (must specify doubles here, to keep the precision)
- re_pdpDrawPort->Unlock();
- CDrawPort dpMirror( re_pdpDrawPort, pixMirrorMinI /(DOUBLE)pixDPSizeI, pixMirrorMinJ /(DOUBLE)pixDPSizeJ,
- pixMirrorSizeI/(DOUBLE)pixDPSizeI, pixMirrorSizeJ/(DOUBLE)pixDPSizeJ);
- // skip if cannot be locked
- if( !dpMirror.Lock()) {
- // lock back the original drawport
- re_pdpDrawPort->Lock();
- continue;
- }
- // recalculate mirror size to compensate for possible lost precision
- pixMirrorMinI = dpMirror.dp_MinI - re_pdpDrawPort->dp_MinI;
- pixMirrorMinJ = dpMirror.dp_MinJ - re_pdpDrawPort->dp_MinJ;
- pixMirrorMaxI = dpMirror.dp_MaxI - re_pdpDrawPort->dp_MinI +1;
- pixMirrorMaxJ = dpMirror.dp_MaxJ - re_pdpDrawPort->dp_MinJ +1;
- pixMirrorSizeI = pixMirrorMaxI-pixMirrorMinI;
- pixMirrorSizeJ = pixMirrorMaxJ-pixMirrorMinJ;
- ASSERT( pixMirrorSizeI==dpMirror.dp_Width && pixMirrorSizeJ==dpMirror.dp_Height);
- // set it up for rendering
- re.re_pwoWorld = re_pwoWorld;
- re.re_prProjection = re_prProjection;
- re.re_pdpDrawPort = &dpMirror;
- // initialize clipping rectangle around the mirror size
- re.InitClippingRectangle( 0, 0, pixMirrorSizeI, pixMirrorSizeJ);
- // setup projection to use the mirror drawport and keep same perspective as before
- re.re_prProjection->ScreenBBoxL() = FLOATaabbox2D( FLOAT2D(0,0), FLOAT2D(pixDPSizeI, pixDPSizeJ));
- ((CPerspectiveProjection3D&)(*re.re_prProjection)).ppr_boxSubScreen =
- FLOATaabbox2D( FLOAT2D(pixMirrorMinI, pixMirrorMinJ), FLOAT2D(pixMirrorMaxI, pixMirrorMaxJ));
- // warp?
- if( mi.mi_mp.mp_ulFlags&MPF_WARP) {
- // warp clip plane is parallel to view plane and contains the closest point
- re.re_penViewer = mi.mi_mp.mp_penWarpViewer;
- re.re_pcspoViewPolygons = NULL;
- re.re_prProjection->WarpPlaneL() = FLOATplane3D(FLOAT3D(0,0,-1), mi.mi_vClosest);
- // create new viewer placement
- CPlacement3D pl = re.re_prProjection->ViewerPlacementR();
- FLOATmatrix3D m;
- MakeRotationMatrixFast(m, pl.pl_OrientationAngle);
- pl.AbsoluteToRelativeSmooth(mi.mi_mp.mp_plWarpIn);
- pl.RelativeToAbsoluteSmooth(mi.mi_mp.mp_plWarpOut);
- re.re_prProjection->ViewerPlacementL() = pl;
- if (re.re_prProjection.IsPerspective() && mi.mi_mp.mp_fWarpFOV>=1 && mi.mi_mp.mp_fWarpFOV<=170) {
- ((CPerspectiveProjection3D&)*re.re_prProjection).FOVL() = mi.mi_mp.mp_fWarpFOV;
- }
- // mirror!
- } else {
- re.re_penViewer = NULL;
- re.re_pcspoViewPolygons = &mi.mi_cspoPolygons;
- re.re_prProjection->MirrorPlaneL() = mi.mi_plPlane;
- re.re_prProjection->MirrorPlaneL().Offset(0.05f); // move projection towards mirror a bit, to avoid cracks
- }
- re.re_bRenderingShadows = FALSE;
- re.re_ubLightIllumination = 0;
- // just flat-fill if mirrors are disabled
- extern INDEX wld_bRenderMirrors;
- if( !wld_bRenderMirrors) dpMirror.Fill(C_GRAY|CT_OPAQUE);
- else {
- // render the view inside mirror
- StopStatsMode();
- _pfRenderProfile.StopTimer(CRenderProfile::PTI_RENDERING);
- re.Render();
- _pfRenderProfile.StartTimer(CRenderProfile::PTI_RENDERING);
- StartStatsMode(CStatForm::STI_WORLDTRANSFORM);
- }
- // unlock mirror's and lock back the original drawport
- dpMirror.Unlock();
- re_pdpDrawPort->Lock();
- // clear entire buffer to back value
- re_pdpDrawPort->FillZBuffer(ZBUF_BACK);
- // fill depth buffer of the mirror, so that scene cannot be drawn through it
- FillMirrorDepth(mi);
- _bMirrorDrawn = TRUE;
- }
- // flush all mirrors
- re_amiMirrors.PopAll();
- // fill z-buffer only if no mirrors have been drawn, not rendering second layer in world editor and not in wireframe mode
- if( !_bMirrorDrawn
- && !re_pdpDrawPort->IsOverlappedRendering()
- && _wrpWorldRenderPrefs.wrp_ftPolygons != CWorldRenderPrefs::FT_NONE) {
- re_pdpDrawPort->FillZBuffer(ZBUF_BACK);
- }
- // draw the prepared things to screen
- DrawToScreen();
- }
- // no mirrors
- else
- {
- // if rendering a mirror
- // or not rendering second layer in world editor
- // and not in wireframe mode
- if( re_iIndex>0
- || !re_bRenderingShadows
- && !re_pdpDrawPort->IsOverlappedRendering()
- && _wrpWorldRenderPrefs.wrp_ftPolygons != CWorldRenderPrefs::FT_NONE) {
- re_pdpDrawPort->FillZBuffer(ZBUF_BACK);
- }
- // draw the prepared things to screen and finish
- DrawToScreen();
- CleanupScanning();
- }
- // disable fog/haze
- StopFog();
- StopHaze();
- // reset vertex arrays if this is the last renderer
- if( re_iIndex==0) _avtxScene.PopAll();
- // for D3D (or mirror) we have to check depth points now, because we need back (not depth!) buffer for it,
- // and D3D can't guarantee that it won't be discarded upon swapbuffers (especially if multisampling is on!) :(
- #ifdef SE1_D3D
- if( !re_bRenderingShadows && ((_pGfx->gl_eCurrentAPI==GAT_D3D && !d3d_bAlternateDepthReads) || re_iIndex>0)) {
- extern void CheckDelayedDepthPoints( const CDrawPort *pdp, INDEX iMirrorLevel=0);
- CheckDelayedDepthPoints( re_pdpDrawPort, re_iIndex);
- }
- #endif // SE1_D3D
-
- // end select-on-render functionality
- extern void EndSelectOnRender(void);
- EndSelectOnRender();
- // assure that FPU precision was low all the rendering time
- ASSERT( GetFPUPrecision()==FPT_24BIT);
- StopStatsMode();
- }
- /*
- * Constructor.
- */
- CRenderer::CRenderer(void)
- {
- // setup self index
- INDEX i = this-_areRenderers;
- ASSERT(i>=0 && i<MAX_RENDERERS);
- re_iIndex = i;
- }
- /*
- * Destructor.
- */
- CRenderer::~CRenderer(void)
- {
- }
- // initialize clipping rectangle
- void CRenderer::InitClippingRectangle(PIX pixMinI, PIX pixMinJ, PIX pixSizeI, PIX pixSizeJ)
- {
- re_pspoFirst = NULL;
- re_pspoFirstTranslucent = NULL;
- re_pspoFirstBackground = NULL;
- re_pspoFirstBackgroundTranslucent = NULL;
- re_fMinJ = (FLOAT) pixMinJ;
- re_fMaxJ = (FLOAT) pixSizeJ+pixMinJ;
- re_pixSizeI = pixSizeI;
- re_fbbClipBox =
- FLOATaabbox2D( FLOAT2D((FLOAT) pixMinI+CLIPMARGADD,
- (FLOAT) pixMinJ+CLIPMARGADD),
- FLOAT2D((FLOAT) pixMinI+pixSizeI-CLIPMARGSUB,
- (FLOAT) pixMinJ+pixSizeJ-CLIPMARGSUB));
- re_pixTopScanLineJ = PIXCoord(pixMinJ+CLIPMARGADD);
- re_ctScanLines =
- PIXCoord(pixSizeJ-CLIPMARGSUB) - PIXCoord(CLIPMARGADD)/* +1*/;
- re_pixBottomScanLineJ = re_pixTopScanLineJ+re_ctScanLines;
- }
- // render a 3D view to a drawport
- void RenderView(CWorld &woWorld, CEntity &enViewer,
- CAnyProjection3D &prProjection, CDrawPort &dpDrawport)
- {
- // let the worldbase execute its render function
- if (woWorld.wo_pecWorldBaseClass!=NULL
- &&woWorld.wo_pecWorldBaseClass->ec_pdecDLLClass!=NULL
- &&woWorld.wo_pecWorldBaseClass->ec_pdecDLLClass->dec_OnWorldRender!=NULL) {
- woWorld.wo_pecWorldBaseClass->ec_pdecDLLClass->dec_OnWorldRender(&woWorld);
- }
- if(_wrpWorldRenderPrefs.GetShadowsType() == CWorldRenderPrefs::SHT_FULL)
- {
- // calculate all non directional shadows that are not up to date
- woWorld.CalculateNonDirectionalShadows();
- }
- // take first renderer object
- CRenderer &re = _areRenderers[0];
- // set it up for rendering
- re.re_penViewer = &enViewer;
- re.re_pcspoViewPolygons = NULL;
- re.re_pwoWorld = &woWorld;
- re.re_prProjection = prProjection;
- re.re_pdpDrawPort = &dpDrawport;
- // initialize clipping rectangle around the drawport
- re.InitClippingRectangle(0, 0, dpDrawport.GetWidth(), dpDrawport.GetHeight());
- prProjection->ScreenBBoxL() = FLOATaabbox2D(
- FLOAT2D(0.0f, 0.0f),
- FLOAT2D((float)dpDrawport.GetWidth(), (float)dpDrawport.GetHeight())
- );
- re.re_bRenderingShadows = FALSE;
- re.re_ubLightIllumination = 0;
- // render the view (with eventuall t-buffer effect)
- extern void SetTBufferEffect( BOOL bEnable);
- SetTBufferEffect(TRUE);
- re.Render();
- SetTBufferEffect(FALSE);
- }
- // Render a world with some viewer, projection and drawport. (viewer may be NULL)
- // internal version used for rendering shadows
- ULONG RenderShadows(CWorld &woWorld, CEntity &enViewer,
- CAnyProjection3D &prProjection, const FLOATaabbox3D &boxViewer,
- UBYTE *pubShadowMask, SLONG slShadowWidth, SLONG slShadowHeight,
- UBYTE ubIllumination)
- {
- _pfWorldEditingProfile.StartTimer(CWorldEditingProfile::PTI_RENDERSHADOWS);
- // take a renderer object
- CRenderer &re = _areRenderers[0];
- // set it up for rendering
- re.re_penViewer = &enViewer;
- re.re_pcspoViewPolygons = NULL;
- re.re_pwoWorld = &woWorld;
- re.re_prProjection = prProjection;
- re.re_pdpDrawPort = NULL;
- re.re_boxViewer = boxViewer;
- // initialize clipping rectangle around the drawport
- const FLOATaabbox2D &box = prProjection->ScreenBBoxR();
- //re.InitClippingRectangle(box.Min()(1), box.Min()(2), box.Size()(1), box.Size()(2));
- re.InitClippingRectangle(0, 0, box.Size()(1), box.Size()(2));
- re.re_bRenderingShadows = TRUE;
- re.re_bDirectionalShadows = prProjection.IsParallel();
- re.re_bSomeLightExists = FALSE;
- re.re_bSomeDarkExists = FALSE;
- _bSomeDarkExists = FALSE;
- re.re_pubShadow = pubShadowMask;
- re.re_slShadowWidth = slShadowWidth;
- re.re_slShadowHeight = slShadowHeight;
- re.re_ubLightIllumination = ubIllumination;
- // render the view
- re.Render();
- ULONG ulFlags = 0;
- if (!re.re_bSomeLightExists) {
- ulFlags|=BSLF_ALLDARK;
- }
- if (!(re.re_bSomeDarkExists|_bSomeDarkExists)) {
- ulFlags|=BSLF_ALLLIGHT;
- }
- _pfWorldEditingProfile.StopTimer(CWorldEditingProfile::PTI_RENDERSHADOWS);
- return ulFlags;
- }
|