Render.cpp 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036
  1. /* Copyright (c) 2002-2012 Croteam Ltd.
  2. This program is free software; you can redistribute it and/or modify
  3. it under the terms of version 2 of the GNU General Public License as published by
  4. the Free Software Foundation
  5. This program is distributed in the hope that it will be useful,
  6. but WITHOUT ANY WARRANTY; without even the implied warranty of
  7. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  8. GNU General Public License for more details.
  9. You should have received a copy of the GNU General Public License along
  10. with this program; if not, write to the Free Software Foundation, Inc.,
  11. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
  12. #include "stdh.h"
  13. #include <Engine/Brushes/Brush.h>
  14. #include <Engine/Brushes/BrushTransformed.h>
  15. #include <Engine/Rendering/Render.h>
  16. #include <Engine/Rendering/Render_internal.h>
  17. #include <Engine/Base/Console.h>
  18. #include <Engine/Templates/DynamicContainer.h>
  19. #include <Engine/Templates/DynamicContainer.cpp>
  20. #include <Engine/Light/LightSource.h>
  21. #include <Engine/Light/Gradient.h>
  22. #include <Engine/Base/ListIterator.inl>
  23. #include <Engine/World/World.h>
  24. #include <Engine/Entities/Entity.h>
  25. #include <Engine/Templates/StaticArray.cpp>
  26. #include <Engine/Math/Clipping.inl>
  27. #include <Engine/Entities/EntityClass.h>
  28. #include <Engine/World/WorldSettings.h>
  29. #include <Engine/Entities/EntityProperties.h>
  30. #include <Engine/Entities/FieldSettings.h>
  31. #include <Engine/Entities/ShadingInfo.h>
  32. #include <Engine/Light/LensFlares.h>
  33. #include <Engine/Models/ModelObject.h>
  34. #include <Engine/Models/RenderModel.h>
  35. #include <Engine/Ska/Render.h>
  36. #include <Engine/Terrain/Terrain.h>
  37. #include <Engine/Templates/BSP.h>
  38. #include <Engine/World/WorldEditingProfile.h>
  39. #include <Engine/Brushes/BrushArchive.h>
  40. #include <Engine/Math/Float.h>
  41. #include <Engine/Math/OBBox.h>
  42. #include <Engine/Math/Geometry.inl>
  43. #include <Engine/Graphics/DrawPort.h>
  44. #include <Engine/Graphics/GfxLibrary.h>
  45. #include <Engine/Graphics/Fog_internal.h>
  46. #include <Engine/Base/Statistics_internal.h>
  47. #include <Engine/Rendering/RenderProfile.h>
  48. #include <Engine/Templates/LinearAllocator.cpp>
  49. #include <Engine/Templates/DynamicArray.cpp>
  50. #include <Engine/Templates/StaticStackArray.cpp>
  51. #include <Engine/Templates/DynamicStackArray.cpp>
  52. extern BOOL _bSomeDarkExists;
  53. extern INDEX d3d_bAlternateDepthReads;
  54. // general coordinate stack referenced by the scene polygons
  55. extern CStaticStackArray<GFXVertex3> _avtxScene;
  56. //#pragma optimize ("gt", on)
  57. #pragma inline_depth(255)
  58. #pragma inline_recursion(on)
  59. #ifndef NDEBUG
  60. //#define ASER_EXTREME_CHECKING 1
  61. #endif
  62. // the renderer structures used in rendering
  63. #define MAX_RENDERERS 2
  64. static CRenderer _areRenderers[MAX_RENDERERS];
  65. static BOOL _bMirrorDrawn = FALSE;
  66. extern INDEX wld_bAlwaysAddAll;
  67. extern INDEX wld_bRenderEmptyBrushes;
  68. extern INDEX wld_bRenderDetailPolygons;
  69. extern INDEX gfx_bRenderParticles;
  70. extern INDEX gfx_bRenderModels;
  71. extern INDEX gfx_bRenderFog;
  72. extern INDEX gfx_bRenderPredicted;
  73. extern INDEX gfx_iLensFlareQuality;
  74. extern BOOL _bMultiPlayer;
  75. // variables for selection on rendering
  76. extern CBrushVertexSelection *_pselbvxtSelectOnRender = NULL;
  77. extern CStaticStackArray<PIX2D> *_pavpixSelectLasso = NULL;
  78. extern CEntitySelection *_pselenSelectOnRender = NULL;
  79. extern PIX2D _vpixSelectNearPoint = PIX2D(0,0);
  80. extern BOOL _bSelectAlternative = FALSE;
  81. extern PIX _pixDeltaAroundVertex = 10;
  82. // shading info for viewer of last rendered view
  83. FLOAT3D _vViewerLightDirection;
  84. COLOR _colViewerLight;
  85. COLOR _colViewerAmbient;
  86. // handy statistic helper routines
  87. static enum CStatForm::StatTimerIndex _stiLastStatsMode = (enum CStatForm::StatTimerIndex)-1;
  88. void StopStatsMode(void)
  89. {
  90. ASSERT( (INDEX)_stiLastStatsMode != -1);
  91. if( _stiLastStatsMode>=0) _sfStats.StopTimer(_stiLastStatsMode);
  92. _stiLastStatsMode = (enum CStatForm::StatTimerIndex)-1;
  93. }
  94. void StartStatsMode( enum CStatForm::StatTimerIndex sti)
  95. {
  96. ASSERT( (INDEX)sti != -1);
  97. ASSERT( (INDEX)_stiLastStatsMode == -1);
  98. if( sti>=0) _sfStats.StartTimer(sti);
  99. _stiLastStatsMode = sti;
  100. }
  101. void ChangeStatsMode( enum CStatForm::StatTimerIndex sti)
  102. {
  103. StopStatsMode();
  104. StartStatsMode(sti);
  105. }
  106. // screen edges, polygons and trapezoids used in rasterizing
  107. CDynamicStackArray<CAddEdge> CRenderer::re_aadeAddEdges;
  108. CDynamicStackArray<CScreenEdge> CRenderer::re_asedScreenEdges;
  109. // spans for current scan line
  110. CDynamicStackArray<CSpan> CRenderer::re_aspSpans;
  111. // vertices clipped to current clip plane
  112. CStaticStackArray<INDEX> CRenderer::re_aiClipBuffer;
  113. // buffers for edges of polygons
  114. CStaticStackArray<INDEX> CRenderer::re_aiEdgeVxClipSrc;
  115. CStaticStackArray<INDEX> CRenderer::re_aiEdgeVxClipDst;
  116. // add and remove lists for each scan line
  117. CStaticArray<CListHead> CRenderer::re_alhAddLists;
  118. CStaticArray<INDEX> CRenderer::re_actAddCounts; // count of edges in given add list
  119. CStaticArray<CScreenEdge *> CRenderer::re_apsedRemoveFirst;
  120. CStaticStackArray<CActiveEdge> CRenderer::re_aaceActiveEdgesTmp;
  121. CStaticStackArray<CActiveEdge> CRenderer::re_aaceActiveEdges;
  122. // container for sorting translucent polygons
  123. CDynamicStackArray<CTranslucentPolygon> CRenderer::re_atcTranslucentPolygons;
  124. // container for all light influencing current model
  125. struct ModelLight {
  126. CLightSource *ml_plsLight; // the light source
  127. FLOAT3D ml_vDirection; // direction from light to the model position (normalized)
  128. FLOAT ml_fShadowIntensity; // intensity at the model position (for shadow)
  129. FLOAT ml_fR, ml_fG, ml_fB; // light components at light source (0..255)
  130. inline void Clear(void) {};
  131. };
  132. static CDynamicStackArray<struct ModelLight> _amlLights;
  133. static INDEX _ctMaxAddEdges=0;
  134. static INDEX _ctMaxActiveEdges=0;
  135. void RendererInfo(void)
  136. {
  137. CPrintF("Renderer information:\n");
  138. SLONG slMem = 0;
  139. slMem += CRenderer::re_aadeAddEdges.da_Count*sizeof(CAddEdge);
  140. slMem += CRenderer::re_asedScreenEdges.da_Count*sizeof(CScreenEdge);
  141. slMem += CRenderer::re_aspSpans.da_Count*sizeof(CSpan);
  142. slMem += CRenderer::re_aiClipBuffer.sa_Count*sizeof(INDEX);
  143. slMem += CRenderer::re_aiEdgeVxClipSrc.sa_Count*sizeof(INDEX);
  144. slMem += CRenderer::re_aiEdgeVxClipDst.sa_Count*sizeof(INDEX);
  145. slMem += CRenderer::re_alhAddLists.sa_Count*sizeof(CListHead);
  146. slMem += CRenderer::re_actAddCounts.sa_Count*sizeof(INDEX);
  147. slMem += CRenderer::re_apsedRemoveFirst.sa_Count*sizeof(CScreenEdge *);
  148. slMem += CRenderer::re_atcTranslucentPolygons.da_Count*sizeof(CTranslucentPolygon);
  149. slMem += CRenderer::re_aaceActiveEdges.sa_Count*sizeof(CActiveEdge);
  150. slMem += CRenderer::re_aaceActiveEdgesTmp.sa_Count*sizeof(CActiveEdge);
  151. for (INDEX ire = 0; ire<MAX_RENDERERS; ire++) {
  152. CRenderer &re = _areRenderers[ire];
  153. slMem += re.re_aspoScreenPolygons.da_Count*sizeof(CScreenPolygon);
  154. slMem += re.re_admDelayedModels.da_Count*sizeof(CDelayedModel);
  155. slMem += re.re_cenDrawn.sa_Count*sizeof(CEntity*);
  156. slMem += re.re_alfiLensFlares.sa_Count*sizeof(CLensFlareInfo);
  157. slMem += re.re_amiMirrors.da_Count*sizeof(CMirror);
  158. slMem += re.re_avvxViewVertices.sa_Count*sizeof(CViewVertex);
  159. slMem += re.re_aiEdgeVxMain.sa_Count*sizeof(INDEX);
  160. }
  161. CPrintF("Temporary memory used: %dk\n", slMem/1024);
  162. }
  163. void ClearRenderer(void)
  164. {
  165. CRenderer::re_aadeAddEdges.Clear();
  166. CRenderer::re_asedScreenEdges.Clear();
  167. CRenderer::re_aspSpans.Clear();
  168. CRenderer::re_aiClipBuffer.Clear();
  169. CRenderer::re_aiEdgeVxClipSrc.Clear();
  170. CRenderer::re_aiEdgeVxClipDst.Clear();
  171. CRenderer::re_alhAddLists.Clear();
  172. CRenderer::re_actAddCounts.Clear();
  173. CRenderer::re_apsedRemoveFirst.Clear();
  174. CRenderer::re_atcTranslucentPolygons.Clear();
  175. CRenderer::re_aaceActiveEdges.Clear();
  176. CRenderer::re_aaceActiveEdgesTmp.Clear();
  177. for (INDEX ire = 0; ire<MAX_RENDERERS; ire++) {
  178. CRenderer &re = _areRenderers[ire];
  179. re.re_aspoScreenPolygons.Clear();
  180. re.re_admDelayedModels.Clear();
  181. re.re_cenDrawn.Clear();
  182. re.re_alfiLensFlares.Clear();
  183. re.re_amiMirrors.Clear();
  184. re.re_avvxViewVertices.Clear();
  185. re.re_aiEdgeVxMain.Clear();
  186. }
  187. CPrintF("Renderer buffers cleared.\n");
  188. }
  189. /*
  190. * How much to offset left, right, top and bottom clipping towards inside (in pixels).
  191. * This can be used to test clipping or to add an epsilon value for it.
  192. */
  193. //#define CLIPMARGIN 10.0f // used for debugging clipping
  194. #define CLIPMARGIN 0.0f
  195. #define CLIPEPSILON 0.5f
  196. #define CLIPMARGADD (CLIPMARGIN-CLIPEPSILON)
  197. #define CLIPMARGSUB (CLIPMARGIN+CLIPEPSILON)
  198. #define SENTINELEDGE_EPSILON 0.4f
  199. #include "RendMisc.cpp"
  200. #include "RenCache.cpp"
  201. #include "RendClip.cpp"
  202. #include "RendASER.cpp"
  203. #include "RenderModels.cpp"
  204. #include "RenderBrushes.cpp"
  205. #include "RenderAdding.cpp"
  206. extern FLOAT wld_fEdgeOffsetI;
  207. extern FLOAT wld_fEdgeAdjustK;
  208. // initialize all rendering structures
  209. void CRenderer::Initialize(void)
  210. {
  211. _pfRenderProfile.StartTimer(CRenderProfile::PTI_INITIALIZATION);
  212. // used for fixing problems with extra trapezoids generated on t-junctions
  213. if( !re_bRenderingShadows) {
  214. re_fEdgeOffsetI = wld_fEdgeOffsetI; //0.125f;
  215. re_fEdgeAdjustK = wld_fEdgeAdjustK; //1.0001f;
  216. } else {
  217. re_fEdgeOffsetI = 0.0f;
  218. re_fEdgeAdjustK = 1.0f;
  219. }
  220. // prepare the raw projection (used for rendering target lines and getting object distances)
  221. re_prProjection->ObjectPlacementL() = CPlacement3D(FLOAT3D(0.0f,0.0f,0.0f), ANGLE3D(0,0,0));
  222. re_prProjection->ObjectFaceForwardL() = FALSE;
  223. re_prProjection->ObjectStretchL() = FLOAT3D(1.0f, 1.0f, 1.0f);
  224. re_prProjection->DepthBufferNearL() = 0.0f;
  225. re_prProjection->DepthBufferFarL() = 0.9f;
  226. re_prProjection->Prepare();
  227. re_asedScreenEdges.PopAll();
  228. re_aadeAddEdges.PopAll();
  229. re_aspSpans.PopAll();
  230. re_avvxViewVertices.PopAll();
  231. re_aiEdgeVxMain.PopAll();
  232. // if more scan lines are needed than last time
  233. if (re_alhAddLists.Count()<re_ctScanLines) {
  234. re_alhAddLists.Clear();
  235. re_alhAddLists.New(re_ctScanLines);
  236. re_actAddCounts.Clear();
  237. re_actAddCounts.New(re_ctScanLines);
  238. re_apsedRemoveFirst.Clear();
  239. re_apsedRemoveFirst.New(re_ctScanLines);
  240. }
  241. // clear all add/remove lists
  242. for(INDEX iScan=0; iScan<re_ctScanLines; iScan++) {
  243. re_actAddCounts[iScan] = 0;
  244. re_apsedRemoveFirst[iScan] = NULL;
  245. }
  246. // find selection color
  247. re_colSelection = C_RED;
  248. if (_wrpWorldRenderPrefs.GetSelectionType() == CWorldRenderPrefs::ST_POLYGONS) {
  249. re_colSelection = C_YELLOW;
  250. } else if (_wrpWorldRenderPrefs.GetSelectionType() == CWorldRenderPrefs::ST_SECTORS) {
  251. re_colSelection = C_GREEN;
  252. } else if (_wrpWorldRenderPrefs.GetSelectionType() == CWorldRenderPrefs::ST_ENTITIES) {
  253. re_colSelection = C_BLUE;
  254. }
  255. // set up renderer for first scan line
  256. re_iCurrentScan = 0;
  257. re_pixCurrentScanJ = re_iCurrentScan + re_pixTopScanLineJ;
  258. re_fCurrentScanJ = FLOAT(re_pixCurrentScanJ);
  259. // no fog or haze initially
  260. re_bCurrentSectorHasHaze = FALSE;
  261. re_bCurrentSectorHasFog = FALSE;
  262. _pfRenderProfile.StopTimer(CRenderProfile::PTI_INITIALIZATION);
  263. }
  264. // add initial sectors to active lists
  265. void CRenderer::AddInitialSectors(void)
  266. {
  267. _pfRenderProfile.StartTimer(CRenderProfile::PTI_ADDINITIAL);
  268. re_bViewerInHaze = FALSE;
  269. re_ulVisExclude = 0;
  270. re_ulVisInclude = 0;
  271. // if showing vis tweaks
  272. if (_wrpWorldRenderPrefs.wrp_bShowVisTweaksOn && _pselbscVisTweaks!=NULL) {
  273. // add flags for selected flags
  274. if (_pselbscVisTweaks->Count()>0) {
  275. re_ulVisExclude = VISM_INCLUDEEXCLUDE;
  276. }
  277. FOREACHINDYNAMICCONTAINER(*_pselbscVisTweaks, CBrushSector, itbsc) {
  278. if (itbsc->bsc_ulFlags2&BSCF2_VISIBILITYINCLUDE) {
  279. re_ulVisInclude = itbsc->bsc_ulVisFlags&VISM_INCLUDEEXCLUDE;
  280. } else {
  281. re_ulVisExclude &= itbsc->bsc_ulVisFlags&VISM_INCLUDEEXCLUDE;
  282. }
  283. }
  284. }
  285. // check if the background is needed
  286. re_bBackgroundEnabled = FALSE;
  287. if (!re_bRenderingShadows && _wrpWorldRenderPrefs.wrp_bBackgroundTextureOn) {
  288. CEntity *penBackgroundViewer = re_pwoWorld->GetBackgroundViewer();
  289. if (penBackgroundViewer!=NULL) {
  290. re_bBackgroundEnabled = TRUE;
  291. re_penBackgroundViewer = penBackgroundViewer;
  292. re_prBackgroundProjection = re_prProjection;
  293. CPlacement3D plViewer = re_prProjection->ViewerPlacementR();
  294. plViewer.pl_PositionVector = FLOAT3D(0,0,0);
  295. CPlacement3D plBcgViewer = penBackgroundViewer->GetLerpedPlacement();
  296. if (re_prProjection->pr_bMirror) {
  297. ReflectPositionVectorByPlane(re_prProjection->pr_plMirror, plBcgViewer.pl_PositionVector);
  298. }
  299. plViewer.RelativeToAbsoluteSmooth(plBcgViewer);
  300. re_prBackgroundProjection->ViewerPlacementL() = plViewer;
  301. re_prBackgroundProjection->ObjectPlacementL() = CPlacement3D(FLOAT3D(0,0,0), ANGLE3D(0,0,0));
  302. re_prBackgroundProjection->FarClipDistanceL() = -1.0f;
  303. re_prBackgroundProjection->DepthBufferNearL() = 0.9f;
  304. re_prBackgroundProjection->DepthBufferFarL() = 1.0f;
  305. re_prBackgroundProjection->TurnOffWarpPlane(); // background never needs warp-plane clipping
  306. re_prBackgroundProjection->Prepare();
  307. }
  308. }
  309. // if a viewer entity is given
  310. if (re_penViewer!=NULL) {
  311. // add all zoning sectors near the entity
  312. AddZoningSectorsAroundEntity(re_penViewer, re_prProjection->ViewerPlacementR().pl_PositionVector);
  313. // make sure the viewer is always added (if model)
  314. if(re_penViewer->en_RenderType==CEntity::RT_MODEL ||
  315. re_penViewer->en_RenderType==CEntity::RT_EDITORMODEL) {
  316. AddModelEntity(re_penViewer);
  317. }
  318. // if a viewer polygons are given
  319. } else if (re_pcspoViewPolygons!=NULL) {
  320. // for each polygon
  321. FOREACHINDYNAMICCONTAINER(*re_pcspoViewPolygons, CScreenPolygon, itspo) {
  322. CBrushPolygon *pbpo = itspo->spo_pbpoBrushPolygon;
  323. // get the sector, sector's brush mip, brush and entity
  324. CBrushSector *pbsc = pbpo->bpo_pbscSector;
  325. CBrushMip *pbmBrushMip = pbsc->bsc_pbmBrushMip;
  326. CBrush3D *pbrBrush = pbmBrushMip->bm_pbrBrush;
  327. ASSERT(pbrBrush!=NULL);
  328. CEntity *penBrush = pbrBrush->br_penEntity;
  329. // if the brush is zoning
  330. if (penBrush->en_ulFlags&ENF_ZONING) {
  331. // add the sector that the polygon is in
  332. AddGivenZoningSector(pbsc);
  333. // if the brush is non-zoning
  334. } else {
  335. // add sectors around it
  336. AddZoningSectorsAroundEntity(penBrush, penBrush->GetPlacement().pl_PositionVector);
  337. }
  338. }
  339. // if there is no viewer entity/polygon
  340. } else {
  341. // set up viewer bounding box as box of minimum redraw range around viewer position
  342. if (re_bRenderingShadows) {
  343. // NOTE: when rendering shadows, this is set in ::RenderShadows()
  344. //re_boxViewer = FLOATaabbox3D(re_prProjection->ViewerPlacementR().pl_PositionVector,
  345. // 1.0f);
  346. } else {
  347. re_boxViewer = FLOATaabbox3D(re_prProjection->ViewerPlacementR().pl_PositionVector,
  348. _wrpWorldRenderPrefs.wrp_fMinimumRenderRange);
  349. }
  350. // add all zoning sectors near viewer box
  351. AddZoningSectorsAroundBox(re_boxViewer);
  352. // NOTE: this is so entities outside of world can be edited in WEd
  353. // if editor models should be rendered
  354. if (_wrpWorldRenderPrefs.IsEditorModelsOn()) {
  355. // add all nonzoning entities near viewer box
  356. AddEntitiesInBox(re_boxViewer);
  357. }
  358. }
  359. if( wld_bAlwaysAddAll) {
  360. AddAllEntities(); // used for profiling
  361. } else {
  362. // NOTE: this is so that world can be viewed from the outside in game
  363. // if no brush sectors have been added so far
  364. if (!re_bRenderingShadows && re_lhActiveSectors.IsEmpty()) {
  365. // add all entities in the world
  366. AddAllEntities();
  367. }
  368. }
  369. // add the background if needed
  370. if (re_bBackgroundEnabled) {
  371. AddZoningSectorsAroundEntity(re_penBackgroundViewer,
  372. re_penBackgroundViewer->GetPlacement().pl_PositionVector);
  373. }
  374. _pfRenderProfile.StopTimer(CRenderProfile::PTI_ADDINITIAL);
  375. }
  376. // scan through portals for other sectors
  377. void CRenderer::ScanForOtherSectors(void)
  378. {
  379. ChangeStatsMode(CStatForm::STI_WORLDVISIBILITY);
  380. // if shadows or polygons should be drawn
  381. if (re_bRenderingShadows
  382. ||_wrpWorldRenderPrefs.wrp_ftPolygons != CWorldRenderPrefs::FT_NONE) {
  383. // rasterize edges into spans
  384. ScanEdges();
  385. }
  386. // for each of models that were kept for delayed rendering
  387. for(INDEX iModel=0; iModel<re_admDelayedModels.Count(); iModel++) {
  388. // mark the entity as not active in rendering anymore
  389. re_admDelayedModels[iModel].dm_penModel->en_ulFlags &= ~ENF_INRENDERING;
  390. }
  391. ChangeStatsMode(CStatForm::STI_WORLDTRANSFORM);
  392. }
  393. // cleanup after scanning
  394. void CRenderer::CleanupScanning(void)
  395. {
  396. _pfRenderProfile.StartTimer(CRenderProfile::PTI_CLEANUP);
  397. // for all active sectors
  398. {FORDELETELIST(CBrushSector, bsc_lnInActiveSectors, re_lhActiveSectors, itbsc) {
  399. // remove it from list
  400. itbsc->bsc_lnInActiveSectors.Remove();
  401. // for all polygons in sector
  402. FOREACHINSTATICARRAY(itbsc->bsc_abpoPolygons, CBrushPolygon, itpo) {
  403. CBrushPolygon &bpo = *itpo;
  404. // clear screen polygon pointers
  405. bpo.bpo_pspoScreenPolygon = NULL;
  406. }
  407. }}
  408. ASSERT(re_lhActiveSectors.IsEmpty());
  409. // for all active brushes
  410. {FORDELETELIST(CBrush3D, br_lnInActiveBrushes, re_lhActiveBrushes, itbr) {
  411. // remove it from list
  412. itbr->br_lnInActiveBrushes.Remove();
  413. }}
  414. ASSERT(re_lhActiveBrushes.IsEmpty());
  415. // for all active terrains
  416. {FORDELETELIST(CTerrain, tr_lnInActiveTerrains, re_lhActiveTerrains, ittr) {
  417. // remove it from list
  418. ittr->tr_lnInActiveTerrains.Remove();
  419. }}
  420. ASSERT(re_lhActiveTerrains.IsEmpty());
  421. _pfRenderProfile.StopTimer(CRenderProfile::PTI_CLEANUP);
  422. }
  423. // Render active terrains
  424. void CRenderer::RenderTerrains(void)
  425. {
  426. CAnyProjection3D *papr;
  427. papr = &re_prProjection;
  428. // for all active terrains
  429. {FORDELETELIST(CTerrain, tr_lnInActiveTerrains, re_lhActiveTerrains, ittr) {
  430. // render terrain
  431. ittr->Render(*papr, re_pdpDrawPort);
  432. }}
  433. }
  434. // Render active terrains in wireframe mode
  435. void CRenderer::RenderWireFrameTerrains(void)
  436. {
  437. CAnyProjection3D *papr;
  438. papr = &re_prProjection;
  439. BOOL bShowEdges = _wrpWorldRenderPrefs.wrp_ftEdges != CWorldRenderPrefs::FT_NONE;
  440. BOOL bShowVertices = _wrpWorldRenderPrefs.wrp_ftVertices != CWorldRenderPrefs::FT_NONE;
  441. // BOOL bForceRegenerate = _wrpWorldRenderPrefs.wrp_ftPolygons
  442. COLOR colEdges = _wrpWorldRenderPrefs.wrp_colEdges;
  443. COLOR colVertices = 0xFF0000FF;
  444. // for all active terrains
  445. {FORDELETELIST(CTerrain, tr_lnInActiveTerrains, re_lhActiveTerrains, ittr) {
  446. // render terrain
  447. if(bShowEdges) {
  448. ittr->RenderWireFrame(*papr, re_pdpDrawPort,colEdges);
  449. }
  450. if(bShowVertices) {
  451. //ittr->RenderVertices(*papr, re_pdpDrawPort,colVertices);
  452. }
  453. }}
  454. }
  455. // draw the prepared things to screen
  456. void CRenderer::DrawToScreen(void)
  457. {
  458. ChangeStatsMode(CStatForm::STI_WORLDRENDERING);
  459. //------------------------------------------------- first render background
  460. // if polygons should be drawn
  461. if (!re_bRenderingShadows &&
  462. _wrpWorldRenderPrefs.wrp_ftPolygons != CWorldRenderPrefs::FT_NONE) {
  463. _pfRenderProfile.StartTimer(CRenderProfile::PTI_RENDERSCENE);
  464. if( re_bBackgroundEnabled) {
  465. // render the polygons to screen
  466. CPerspectiveProjection3D *pprPerspective =
  467. (CPerspectiveProjection3D *)(CProjection3D *)(re_prBackgroundProjection);
  468. pprPerspective->Prepare();
  469. RenderScene( re_pdpDrawPort, re_pspoFirstBackground, re_prBackgroundProjection, re_colSelection, FALSE);
  470. } else {
  471. // this is just for far sentinel
  472. RenderSceneBackground( re_pdpDrawPort, re_spoFarSentinel.spo_spoScenePolygon.spo_cColor);
  473. }
  474. _pfRenderProfile.StopTimer(CRenderProfile::PTI_RENDERSCENE);
  475. }
  476. if (re_bBackgroundEnabled) {
  477. // render models that were kept for delayed rendering.
  478. ChangeStatsMode(CStatForm::STI_MODELSETUP);
  479. RenderModels(TRUE); // render background models
  480. ChangeStatsMode(CStatForm::STI_WORLDRENDERING);
  481. }
  482. // if polygons should be drawn
  483. if (!re_bRenderingShadows &&
  484. re_bBackgroundEnabled
  485. &&_wrpWorldRenderPrefs.wrp_ftPolygons != CWorldRenderPrefs::FT_NONE) {
  486. // render translucent portals
  487. _pfRenderProfile.StartTimer(CRenderProfile::PTI_RENDERSCENE);
  488. CPerspectiveProjection3D *pprPerspective = (CPerspectiveProjection3D*)(CProjection3D*)(re_prBackgroundProjection);
  489. RenderScene( re_pdpDrawPort, SortTranslucentPolygons(re_pspoFirstBackgroundTranslucent),
  490. re_prBackgroundProjection, re_colSelection, TRUE);
  491. _pfRenderProfile.StopTimer(CRenderProfile::PTI_RENDERSCENE);
  492. }
  493. if( re_bBackgroundEnabled) {
  494. ChangeStatsMode(CStatForm::STI_PARTICLERENDERING);
  495. RenderParticles(TRUE); // render background particless
  496. ChangeStatsMode(CStatForm::STI_WORLDRENDERING);
  497. }
  498. //------------------------------------------------- second render non-background
  499. // if polygons should be drawn
  500. if( !re_bRenderingShadows
  501. && _wrpWorldRenderPrefs.wrp_ftPolygons != CWorldRenderPrefs::FT_NONE) {
  502. // render the spans to screen
  503. re_prProjection->Prepare();
  504. _pfRenderProfile.StartTimer(CRenderProfile::PTI_RENDERSCENE);
  505. CPerspectiveProjection3D *pprPerspective = (CPerspectiveProjection3D*)(CProjection3D*)re_prProjection;
  506. RenderScene( re_pdpDrawPort, re_pspoFirst, re_prProjection, re_colSelection, FALSE);
  507. _pfRenderProfile.StopTimer(CRenderProfile::PTI_RENDERSCENE);
  508. }
  509. // Render active terrains
  510. if( !re_bRenderingShadows
  511. && _wrpWorldRenderPrefs.wrp_ftPolygons != CWorldRenderPrefs::FT_NONE) {
  512. RenderTerrains();
  513. }
  514. // if wireframe should be drawn
  515. if( !re_bRenderingShadows &&
  516. ( _wrpWorldRenderPrefs.wrp_ftEdges != CWorldRenderPrefs::FT_NONE
  517. || _wrpWorldRenderPrefs.wrp_ftVertices != CWorldRenderPrefs::FT_NONE
  518. || _wrpWorldRenderPrefs.wrp_stSelection == CWorldRenderPrefs::ST_VERTICES
  519. || _wrpWorldRenderPrefs.IsFieldBrushesOn())) {
  520. // render in wireframe all brushes that were added (in orthographic projection!)
  521. re_pdpDrawPort->SetOrtho();
  522. RenderWireFrameBrushes();
  523. RenderWireFrameTerrains();
  524. }
  525. // render models that were kept for delayed rendering
  526. ChangeStatsMode(CStatForm::STI_MODELSETUP);
  527. RenderModels(FALSE); // render non-background models
  528. ChangeStatsMode(CStatForm::STI_PARTICLERENDERING);
  529. RenderParticles(FALSE); // render non-background particles
  530. ChangeStatsMode(CStatForm::STI_WORLDRENDERING);
  531. // if polygons should be drawn
  532. if (!re_bRenderingShadows
  533. &&_wrpWorldRenderPrefs.wrp_ftPolygons != CWorldRenderPrefs::FT_NONE) {
  534. // render translucent portals
  535. _pfRenderProfile.StartTimer(CRenderProfile::PTI_RENDERSCENE);
  536. CPerspectiveProjection3D *pprPerspective = (CPerspectiveProjection3D*)(CProjection3D*)re_prProjection;
  537. pprPerspective->Prepare();
  538. RenderScene( re_pdpDrawPort, SortTranslucentPolygons(re_pspoFirstTranslucent),
  539. re_prProjection, re_colSelection, TRUE);
  540. _pfRenderProfile.StopTimer(CRenderProfile::PTI_RENDERSCENE);
  541. }
  542. // render lens flares
  543. if( !re_bRenderingShadows) {
  544. ChangeStatsMode(CStatForm::STI_FLARESRENDERING);
  545. RenderLensFlares(); // (this also sets orthographic projection!)
  546. ChangeStatsMode(CStatForm::STI_WORLDRENDERING);
  547. }
  548. // if entity targets should be drawn
  549. if( !re_bRenderingShadows && _wrpWorldRenderPrefs.wrp_bShowTargetsOn) {
  550. // render entity targets
  551. RenderEntityTargets();
  552. }
  553. // if entity targets should be drawn
  554. if( !re_bRenderingShadows && _wrpWorldRenderPrefs.wrp_bShowEntityNames) {
  555. RenderEntityNames();
  556. }
  557. // clean all buffers after rendering
  558. re_aspoScreenPolygons.PopAll();
  559. re_admDelayedModels.PopAll();
  560. re_cenDrawn.PopAll();
  561. re_avvxViewVertices.PopAll();
  562. }
  563. // draw mirror polygons to z-buffer to enable drawing of mirror
  564. void CRenderer::FillMirrorDepth(CMirror &mi)
  565. {
  566. // create a list of scene polygons for mirror
  567. ScenePolygon *pspoFirst = NULL;
  568. // for each polygon
  569. FOREACHINDYNAMICCONTAINER(mi.mi_cspoPolygons, CScreenPolygon, itspo) {
  570. CScreenPolygon &spo = *itspo;
  571. CBrushPolygon &bpo = *spo.spo_pbpoBrushPolygon;
  572. // create a new screen polygon
  573. CScreenPolygon &spoNew = re_aspoScreenPolygons.Push();
  574. ScenePolygon &sppoNew = spoNew.spo_spoScenePolygon;
  575. // add it to mirror list
  576. sppoNew.spo_pspoSucc = pspoFirst;
  577. pspoFirst = &sppoNew;
  578. // use same triangles
  579. sppoNew.spo_iVtx0 = spo.spo_spoScenePolygon.spo_iVtx0;
  580. sppoNew.spo_ctVtx = spo.spo_spoScenePolygon.spo_ctVtx;
  581. sppoNew.spo_piElements = spo.spo_spoScenePolygon.spo_piElements;
  582. sppoNew.spo_ctElements = spo.spo_spoScenePolygon.spo_ctElements;
  583. }
  584. // render all those polygons just to clear z-buffer
  585. RenderSceneZOnly( re_pdpDrawPort, pspoFirst, re_prProjection);
  586. }
  587. // do the rendering
  588. void CRenderer::Render(void)
  589. {
  590. // if the world doesn't have all portal-sector links updated
  591. if( !re_pwoWorld->wo_bPortalLinksUpToDate) {
  592. // update the links
  593. CSetFPUPrecision FPUPrecision(FPT_53BIT);
  594. re_pwoWorld->wo_baBrushes.LinkPortalsAndSectors();
  595. re_pwoWorld->wo_bPortalLinksUpToDate = TRUE;
  596. }
  597. StartStatsMode(CStatForm::STI_WORLDTRANSFORM);
  598. _pfRenderProfile.IncrementAveragingCounter();
  599. _pfRenderProfile.StartTimer(CRenderProfile::PTI_RENDERING);
  600. // set FPU to single precision while rendering
  601. CSetFPUPrecision FPUPrecision(FPT_24BIT);
  602. // initialize all rendering structures
  603. Initialize();
  604. // init select-on-render functionality if not rendering shadows
  605. extern void InitSelectOnRender( PIX pixSizeI, PIX pixSizeJ);
  606. if( re_pdpDrawPort!=NULL) InitSelectOnRender( re_pdpDrawPort->GetWidth(), re_pdpDrawPort->GetHeight());
  607. // add initial sectors to active lists
  608. AddInitialSectors();
  609. // scan through portals for other sectors
  610. ScanForOtherSectors();
  611. // force finishing of all OpenGL pending operations, if required
  612. ChangeStatsMode(CStatForm::STI_SWAPBUFFERS);
  613. extern INDEX ogl_iFinish; ogl_iFinish = Clamp( ogl_iFinish, 0L, 3L);
  614. extern INDEX d3d_iFinish; d3d_iFinish = Clamp( d3d_iFinish, 0L, 3L);
  615. if( (ogl_iFinish==1 && _pGfx->gl_eCurrentAPI==GAT_OGL)
  616. #ifdef SE1_D3D
  617. || (d3d_iFinish==1 && _pGfx->gl_eCurrentAPI==GAT_D3D)
  618. #endif // SE1_D3D
  619. )
  620. gfxFinish();
  621. // check any eventual delayed depth points outside the mirror (if API and time allows)
  622. if( !re_bRenderingShadows && re_iIndex==0) {
  623. // OpenGL allows us to check z-buffer from previous frame - cool deal!
  624. // Direct3D is, of course, totally different story. :(
  625. if( _pGfx->gl_eCurrentAPI==GAT_OGL || d3d_bAlternateDepthReads) {
  626. ChangeStatsMode(CStatForm::STI_FLARESRENDERING);
  627. extern void CheckDelayedDepthPoints( const CDrawPort *pdp, INDEX iMirrorLevel=0);
  628. CheckDelayedDepthPoints(re_pdpDrawPort);
  629. }
  630. // in 1st pass - mirrors are not drawn
  631. _bMirrorDrawn = FALSE;
  632. }
  633. // if may render one more mirror recursion
  634. ChangeStatsMode(CStatForm::STI_WORLDTRANSFORM);
  635. if( !re_bRenderingShadows
  636. && re_prProjection.IsPerspective()
  637. && re_iIndex<MAX_RENDERERS-1
  638. && re_amiMirrors.Count()>0
  639. && !re_pdpDrawPort->IsOverlappedRendering())
  640. {
  641. // cleanup after scanning
  642. CleanupScanning();
  643. // take next renderer
  644. CRenderer &re = _areRenderers[re_iIndex+1];
  645. // for each mirror
  646. for( INDEX i=0; i<re_amiMirrors.Count(); i++)
  647. {
  648. // skip invalid mirrors
  649. CMirror &mi = re_amiMirrors[i];
  650. if( mi.mi_iMirrorType<0) continue;
  651. // calculate all needed data for the mirror
  652. mi.FinishAdding();
  653. // skip mirror that has no significant area
  654. if( mi.mi_fpixMaxPolygonArea<5) continue;
  655. // expand mirror in each direction, but keep it inside drawport
  656. PIX pixDPSizeI = re_pdpDrawPort->GetWidth();
  657. PIX pixDPSizeJ = re_pdpDrawPort->GetHeight();
  658. mi.mi_boxOnScreen.Expand(1);
  659. mi.mi_boxOnScreen &= PIXaabbox2D( PIX2D(0,0), PIX2D(pixDPSizeI,pixDPSizeJ));
  660. // get drawport and mirror coordinates
  661. PIX pixMirrorMinI = mi.mi_boxOnScreen.Min()(1);
  662. PIX pixMirrorMinJ = mi.mi_boxOnScreen.Min()(2);
  663. PIX pixMirrorMaxI = mi.mi_boxOnScreen.Max()(1);
  664. PIX pixMirrorMaxJ = mi.mi_boxOnScreen.Max()(2);
  665. // calculate mirror size
  666. PIX pixMirrorSizeI = pixMirrorMaxI-pixMirrorMinI;
  667. PIX pixMirrorSizeJ = pixMirrorMaxJ-pixMirrorMinJ;
  668. // clone drawport (must specify doubles here, to keep the precision)
  669. re_pdpDrawPort->Unlock();
  670. CDrawPort dpMirror( re_pdpDrawPort, pixMirrorMinI /(DOUBLE)pixDPSizeI, pixMirrorMinJ /(DOUBLE)pixDPSizeJ,
  671. pixMirrorSizeI/(DOUBLE)pixDPSizeI, pixMirrorSizeJ/(DOUBLE)pixDPSizeJ);
  672. // skip if cannot be locked
  673. if( !dpMirror.Lock()) {
  674. // lock back the original drawport
  675. re_pdpDrawPort->Lock();
  676. continue;
  677. }
  678. // recalculate mirror size to compensate for possible lost precision
  679. pixMirrorMinI = dpMirror.dp_MinI - re_pdpDrawPort->dp_MinI;
  680. pixMirrorMinJ = dpMirror.dp_MinJ - re_pdpDrawPort->dp_MinJ;
  681. pixMirrorMaxI = dpMirror.dp_MaxI - re_pdpDrawPort->dp_MinI +1;
  682. pixMirrorMaxJ = dpMirror.dp_MaxJ - re_pdpDrawPort->dp_MinJ +1;
  683. pixMirrorSizeI = pixMirrorMaxI-pixMirrorMinI;
  684. pixMirrorSizeJ = pixMirrorMaxJ-pixMirrorMinJ;
  685. ASSERT( pixMirrorSizeI==dpMirror.dp_Width && pixMirrorSizeJ==dpMirror.dp_Height);
  686. // set it up for rendering
  687. re.re_pwoWorld = re_pwoWorld;
  688. re.re_prProjection = re_prProjection;
  689. re.re_pdpDrawPort = &dpMirror;
  690. // initialize clipping rectangle around the mirror size
  691. re.InitClippingRectangle( 0, 0, pixMirrorSizeI, pixMirrorSizeJ);
  692. // setup projection to use the mirror drawport and keep same perspective as before
  693. re.re_prProjection->ScreenBBoxL() = FLOATaabbox2D( FLOAT2D(0,0), FLOAT2D(pixDPSizeI, pixDPSizeJ));
  694. ((CPerspectiveProjection3D&)(*re.re_prProjection)).ppr_boxSubScreen =
  695. FLOATaabbox2D( FLOAT2D(pixMirrorMinI, pixMirrorMinJ), FLOAT2D(pixMirrorMaxI, pixMirrorMaxJ));
  696. // warp?
  697. if( mi.mi_mp.mp_ulFlags&MPF_WARP) {
  698. // warp clip plane is parallel to view plane and contains the closest point
  699. re.re_penViewer = mi.mi_mp.mp_penWarpViewer;
  700. re.re_pcspoViewPolygons = NULL;
  701. re.re_prProjection->WarpPlaneL() = FLOATplane3D(FLOAT3D(0,0,-1), mi.mi_vClosest);
  702. // create new viewer placement
  703. CPlacement3D pl = re.re_prProjection->ViewerPlacementR();
  704. FLOATmatrix3D m;
  705. MakeRotationMatrixFast(m, pl.pl_OrientationAngle);
  706. pl.AbsoluteToRelativeSmooth(mi.mi_mp.mp_plWarpIn);
  707. pl.RelativeToAbsoluteSmooth(mi.mi_mp.mp_plWarpOut);
  708. re.re_prProjection->ViewerPlacementL() = pl;
  709. if (re.re_prProjection.IsPerspective() && mi.mi_mp.mp_fWarpFOV>=1 && mi.mi_mp.mp_fWarpFOV<=170) {
  710. ((CPerspectiveProjection3D&)*re.re_prProjection).FOVL() = mi.mi_mp.mp_fWarpFOV;
  711. }
  712. // mirror!
  713. } else {
  714. re.re_penViewer = NULL;
  715. re.re_pcspoViewPolygons = &mi.mi_cspoPolygons;
  716. re.re_prProjection->MirrorPlaneL() = mi.mi_plPlane;
  717. re.re_prProjection->MirrorPlaneL().Offset(0.05f); // move projection towards mirror a bit, to avoid cracks
  718. }
  719. re.re_bRenderingShadows = FALSE;
  720. re.re_ubLightIllumination = 0;
  721. // just flat-fill if mirrors are disabled
  722. extern INDEX wld_bRenderMirrors;
  723. if( !wld_bRenderMirrors) dpMirror.Fill(C_GRAY|CT_OPAQUE);
  724. else {
  725. // render the view inside mirror
  726. StopStatsMode();
  727. _pfRenderProfile.StopTimer(CRenderProfile::PTI_RENDERING);
  728. re.Render();
  729. _pfRenderProfile.StartTimer(CRenderProfile::PTI_RENDERING);
  730. StartStatsMode(CStatForm::STI_WORLDTRANSFORM);
  731. }
  732. // unlock mirror's and lock back the original drawport
  733. dpMirror.Unlock();
  734. re_pdpDrawPort->Lock();
  735. // clear entire buffer to back value
  736. re_pdpDrawPort->FillZBuffer(ZBUF_BACK);
  737. // fill depth buffer of the mirror, so that scene cannot be drawn through it
  738. FillMirrorDepth(mi);
  739. _bMirrorDrawn = TRUE;
  740. }
  741. // flush all mirrors
  742. re_amiMirrors.PopAll();
  743. // fill z-buffer only if no mirrors have been drawn, not rendering second layer in world editor and not in wireframe mode
  744. if( !_bMirrorDrawn
  745. && !re_pdpDrawPort->IsOverlappedRendering()
  746. && _wrpWorldRenderPrefs.wrp_ftPolygons != CWorldRenderPrefs::FT_NONE) {
  747. re_pdpDrawPort->FillZBuffer(ZBUF_BACK);
  748. }
  749. // draw the prepared things to screen
  750. DrawToScreen();
  751. }
  752. // no mirrors
  753. else
  754. {
  755. // if rendering a mirror
  756. // or not rendering second layer in world editor
  757. // and not in wireframe mode
  758. if( re_iIndex>0
  759. || !re_bRenderingShadows
  760. && !re_pdpDrawPort->IsOverlappedRendering()
  761. && _wrpWorldRenderPrefs.wrp_ftPolygons != CWorldRenderPrefs::FT_NONE) {
  762. re_pdpDrawPort->FillZBuffer(ZBUF_BACK);
  763. }
  764. // draw the prepared things to screen and finish
  765. DrawToScreen();
  766. CleanupScanning();
  767. }
  768. // disable fog/haze
  769. StopFog();
  770. StopHaze();
  771. // reset vertex arrays if this is the last renderer
  772. if( re_iIndex==0) _avtxScene.PopAll();
  773. // for D3D (or mirror) we have to check depth points now, because we need back (not depth!) buffer for it,
  774. // and D3D can't guarantee that it won't be discarded upon swapbuffers (especially if multisampling is on!) :(
  775. #ifdef SE1_D3D
  776. if( !re_bRenderingShadows && ((_pGfx->gl_eCurrentAPI==GAT_D3D && !d3d_bAlternateDepthReads) || re_iIndex>0)) {
  777. extern void CheckDelayedDepthPoints( const CDrawPort *pdp, INDEX iMirrorLevel=0);
  778. CheckDelayedDepthPoints( re_pdpDrawPort, re_iIndex);
  779. }
  780. #endif // SE1_D3D
  781. // end select-on-render functionality
  782. extern void EndSelectOnRender(void);
  783. EndSelectOnRender();
  784. // assure that FPU precision was low all the rendering time
  785. ASSERT( GetFPUPrecision()==FPT_24BIT);
  786. StopStatsMode();
  787. }
  788. /*
  789. * Constructor.
  790. */
  791. CRenderer::CRenderer(void)
  792. {
  793. // setup self index
  794. INDEX i = this-_areRenderers;
  795. ASSERT(i>=0 && i<MAX_RENDERERS);
  796. re_iIndex = i;
  797. }
  798. /*
  799. * Destructor.
  800. */
  801. CRenderer::~CRenderer(void)
  802. {
  803. }
  804. // initialize clipping rectangle
  805. void CRenderer::InitClippingRectangle(PIX pixMinI, PIX pixMinJ, PIX pixSizeI, PIX pixSizeJ)
  806. {
  807. re_pspoFirst = NULL;
  808. re_pspoFirstTranslucent = NULL;
  809. re_pspoFirstBackground = NULL;
  810. re_pspoFirstBackgroundTranslucent = NULL;
  811. re_fMinJ = (FLOAT) pixMinJ;
  812. re_fMaxJ = (FLOAT) pixSizeJ+pixMinJ;
  813. re_pixSizeI = pixSizeI;
  814. re_fbbClipBox =
  815. FLOATaabbox2D( FLOAT2D((FLOAT) pixMinI+CLIPMARGADD,
  816. (FLOAT) pixMinJ+CLIPMARGADD),
  817. FLOAT2D((FLOAT) pixMinI+pixSizeI-CLIPMARGSUB,
  818. (FLOAT) pixMinJ+pixSizeJ-CLIPMARGSUB));
  819. re_pixTopScanLineJ = PIXCoord(pixMinJ+CLIPMARGADD);
  820. re_ctScanLines =
  821. PIXCoord(pixSizeJ-CLIPMARGSUB) - PIXCoord(CLIPMARGADD)/* +1*/;
  822. re_pixBottomScanLineJ = re_pixTopScanLineJ+re_ctScanLines;
  823. }
  824. // render a 3D view to a drawport
  825. void RenderView(CWorld &woWorld, CEntity &enViewer,
  826. CAnyProjection3D &prProjection, CDrawPort &dpDrawport)
  827. {
  828. // let the worldbase execute its render function
  829. if (woWorld.wo_pecWorldBaseClass!=NULL
  830. &&woWorld.wo_pecWorldBaseClass->ec_pdecDLLClass!=NULL
  831. &&woWorld.wo_pecWorldBaseClass->ec_pdecDLLClass->dec_OnWorldRender!=NULL) {
  832. woWorld.wo_pecWorldBaseClass->ec_pdecDLLClass->dec_OnWorldRender(&woWorld);
  833. }
  834. if(_wrpWorldRenderPrefs.GetShadowsType() == CWorldRenderPrefs::SHT_FULL)
  835. {
  836. // calculate all non directional shadows that are not up to date
  837. woWorld.CalculateNonDirectionalShadows();
  838. }
  839. // take first renderer object
  840. CRenderer &re = _areRenderers[0];
  841. // set it up for rendering
  842. re.re_penViewer = &enViewer;
  843. re.re_pcspoViewPolygons = NULL;
  844. re.re_pwoWorld = &woWorld;
  845. re.re_prProjection = prProjection;
  846. re.re_pdpDrawPort = &dpDrawport;
  847. // initialize clipping rectangle around the drawport
  848. re.InitClippingRectangle(0, 0, dpDrawport.GetWidth(), dpDrawport.GetHeight());
  849. prProjection->ScreenBBoxL() = FLOATaabbox2D(
  850. FLOAT2D(0.0f, 0.0f),
  851. FLOAT2D((float)dpDrawport.GetWidth(), (float)dpDrawport.GetHeight())
  852. );
  853. re.re_bRenderingShadows = FALSE;
  854. re.re_ubLightIllumination = 0;
  855. // render the view (with eventuall t-buffer effect)
  856. extern void SetTBufferEffect( BOOL bEnable);
  857. SetTBufferEffect(TRUE);
  858. re.Render();
  859. SetTBufferEffect(FALSE);
  860. }
  861. // Render a world with some viewer, projection and drawport. (viewer may be NULL)
  862. // internal version used for rendering shadows
  863. ULONG RenderShadows(CWorld &woWorld, CEntity &enViewer,
  864. CAnyProjection3D &prProjection, const FLOATaabbox3D &boxViewer,
  865. UBYTE *pubShadowMask, SLONG slShadowWidth, SLONG slShadowHeight,
  866. UBYTE ubIllumination)
  867. {
  868. _pfWorldEditingProfile.StartTimer(CWorldEditingProfile::PTI_RENDERSHADOWS);
  869. // take a renderer object
  870. CRenderer &re = _areRenderers[0];
  871. // set it up for rendering
  872. re.re_penViewer = &enViewer;
  873. re.re_pcspoViewPolygons = NULL;
  874. re.re_pwoWorld = &woWorld;
  875. re.re_prProjection = prProjection;
  876. re.re_pdpDrawPort = NULL;
  877. re.re_boxViewer = boxViewer;
  878. // initialize clipping rectangle around the drawport
  879. const FLOATaabbox2D &box = prProjection->ScreenBBoxR();
  880. //re.InitClippingRectangle(box.Min()(1), box.Min()(2), box.Size()(1), box.Size()(2));
  881. re.InitClippingRectangle(0, 0, box.Size()(1), box.Size()(2));
  882. re.re_bRenderingShadows = TRUE;
  883. re.re_bDirectionalShadows = prProjection.IsParallel();
  884. re.re_bSomeLightExists = FALSE;
  885. re.re_bSomeDarkExists = FALSE;
  886. _bSomeDarkExists = FALSE;
  887. re.re_pubShadow = pubShadowMask;
  888. re.re_slShadowWidth = slShadowWidth;
  889. re.re_slShadowHeight = slShadowHeight;
  890. re.re_ubLightIllumination = ubIllumination;
  891. // render the view
  892. re.Render();
  893. ULONG ulFlags = 0;
  894. if (!re.re_bSomeLightExists) {
  895. ulFlags|=BSLF_ALLDARK;
  896. }
  897. if (!(re.re_bSomeDarkExists|_bSomeDarkExists)) {
  898. ulFlags|=BSLF_ALLLIGHT;
  899. }
  900. _pfWorldEditingProfile.StopTimer(CWorldEditingProfile::PTI_RENDERSHADOWS);
  901. return ulFlags;
  902. }