1 //**************************************************************************
2 //**
3 //** ## ## ## ## ## #### #### ### ###
4 //** ## ## ## ## ## ## ## ## ## ## #### ####
5 //** ## ## ## ## ## ## ## ## ## ## ## ## ## ##
6 //** ## ## ######## ## ## ## ## ## ## ## ### ##
7 //** ### ## ## ### ## ## ## ## ## ##
8 //** # ## ## # #### #### ## ##
9 //**
10 //** $Id: r_main.cpp 4355 2010-12-24 01:29:15Z firebrand_kh $
11 //**
12 //** Copyright (C) 1999-2006 Jānis Legzdiņš
13 //**
14 //** This program is free software; you can redistribute it and/or
15 //** modify it under the terms of the GNU General Public License
16 //** as published by the Free Software Foundation; either version 2
17 //** of the License, or (at your option) any later version.
18 //**
19 //** This program is distributed in the hope that it will be useful,
20 //** but WITHOUT ANY WARRANTY; without even the implied warranty of
21 //** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 //** GNU General Public License for more details.
23 //**
24 //**************************************************************************
25 //**
26 //** Rendering main loop and setup functions, utility functions (BSP,
27 //** geometry, trigonometry). See tables.c, too.
28 //**
29 //**************************************************************************
30
31 // HEADER FILES ------------------------------------------------------------
32
33 #include "gamedefs.h"
34 #include "r_local.h"
35
36 // MACROS ------------------------------------------------------------------
37
38 // TYPES -------------------------------------------------------------------
39
40 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
41
42 void R_FreeSkyboxData();
43
44 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
45
46 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
47
48 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
49
50 // PUBLIC DATA DEFINITIONS -------------------------------------------------
51
52 int screenblocks = 0;
53
54 TVec vieworg;
55 TVec viewforward;
56 TVec viewright;
57 TVec viewup;
58 TAVec viewangles;
59
60 TClipPlane view_clipplanes[5];
61
62 int r_visframecount;
63
64 VCvarI r_fog("r_fog", "0");
65 VCvarI r_fog_test("r_fog_test", "0");
66 VCvarF r_fog_r("r_fog_r", "0.5");
67 VCvarF r_fog_g("r_fog_g", "0.5");
68 VCvarF r_fog_b("r_fog_b", "0.5");
69 VCvarF r_fog_start("r_fog_start", "1.0");
70 VCvarF r_fog_end("r_fog_end", "2048.0");
71 VCvarF r_fog_density("r_fog_density", "0.5");
72
73 VCvarI aspect_ratio("r_aspect_ratio", "1", CVAR_Archive);
74 VCvarI r_interpolate_frames("r_interpolate_frames", "1", CVAR_Archive);
75 VCvarI r_vsync("r_vsync", "1", CVAR_Archive);
76 VCvarI r_fade_light("r_fade_light", "0", CVAR_Archive);
77 VCvarF r_fade_factor("r_fade_factor", "4.0", CVAR_Archive);
78 VCvarF r_sky_bright_factor("r_sky_bright_factor", "1.0", CVAR_Archive);
79
80 VDrawer *Drawer;
81
82 refdef_t refdef;
83
84 float PixelAspect;
85
86 bool MirrorFlip;
87 bool MirrorClip;
88
89 // PRIVATE DATA DEFINITIONS ------------------------------------------------
90
91 static FDrawerDesc *DrawerList[DRAWER_MAX];
92
93 VCvarI screen_size("screen_size", "10", CVAR_Archive);
94 bool set_resolutioon_needed = true;
95
96 // Angles in the SCREENWIDTH wide window.
97 VCvarF fov("fov", "90");
98
99 TVec clip_base[4];
100
101 //
102 // Translation tables
103 //
104 VTextureTranslation* PlayerTranslations[MAXPLAYERS + 1];
105 static TArray<VTextureTranslation*> CachedTranslations;
106
107 // if true, load all graphics at start
108 VCvarI precache("precache", "1", CVAR_Archive);
109
110 static VCvarI _driver("_driver", "0", CVAR_Rom);
111
112 static VCvarI r_level_renderer("r_level_renderer", "0", CVAR_Archive);
113
114 // CODE --------------------------------------------------------------------
115
116 //==========================================================================
117 //
118 // FDrawerDesc::FDrawerDesc
119 //
120 //==========================================================================
121
FDrawerDesc(int Type,const char * AName,const char * ADescription,const char * ACmdLineArg,VDrawer * (* ACreator)())122 FDrawerDesc::FDrawerDesc(int Type, const char* AName, const char* ADescription,
123 const char* ACmdLineArg, VDrawer* (*ACreator)())
124 : Name(AName)
125 , Description(ADescription)
126 , CmdLineArg(ACmdLineArg)
127 , Creator(ACreator)
128 {
129 guard(FDrawerDesc::FDrawerDesc);
130 DrawerList[Type] = this;
131 unguard
132 }
133
134 //==========================================================================
135 //
136 // R_Init
137 //
138 //==========================================================================
139
R_Init()140 void R_Init()
141 {
142 guard(R_Init);
143 R_InitSkyBoxes();
144 R_InitModels();
145
146 for (int i = 0; i < 256; i++)
147 {
148 light_remap[i] = byte(i * i / 255);
149 }
150 unguard;
151 }
152
153 //==========================================================================
154 //
155 // R_Start
156 //
157 //==========================================================================
158
R_Start(VLevel * ALevel)159 void R_Start(VLevel* ALevel)
160 {
161 guard(R_Start);
162 switch (r_level_renderer)
163 {
164 case 1:
165 ALevel->RenderData = new VRenderLevel(ALevel);
166 break;
167
168 case 2:
169 ALevel->RenderData = new VAdvancedRenderLevel(ALevel);
170 break;
171
172 default:
173 if (Drawer->SupportsAdvancedRendering())
174 {
175 ALevel->RenderData = new VAdvancedRenderLevel(ALevel);
176 }
177 else
178 {
179 ALevel->RenderData = new VRenderLevel(ALevel);
180 }
181 break;
182 }
183 unguard;
184 }
185
186 //==========================================================================
187 //
188 // VRenderLevelShared::VRenderLevelShared
189 //
190 //==========================================================================
191
VRenderLevelShared(VLevel * ALevel)192 VRenderLevelShared::VRenderLevelShared(VLevel* ALevel)
193 : Level(ALevel)
194 , ViewEnt(NULL)
195 , MirrorLevel(0)
196 , PortalLevel(0)
197 , VisSize(0)
198 , BspVis(NULL)
199 , r_viewleaf(NULL)
200 , r_oldviewleaf(NULL)
201 , old_fov(90.0)
202 , prev_aspect_ratio(0)
203 , ExtraLight(0)
204 , FixedLight(0)
205 , Particles(0)
206 , ActiveParticles(0)
207 , FreeParticles(0)
208 , CurrentSky1Texture(-1)
209 , CurrentSky2Texture(-1)
210 , CurrentDoubleSky(false)
211 , CurrentLightning(false)
212 , trans_sprites(MainTransSprites)
213 , free_wsurfs(NULL)
214 , AllocatedWSurfBlocks(NULL)
215 , AllocatedSubRegions(NULL)
216 , AllocatedDrawSegs(NULL)
217 , AllocatedSegParts(NULL)
218 , cacheframecount(0)
219 {
220 guard(VRenderLevelShared::VRenderLevelShared);
221 memset(MainTransSprites, 0, sizeof(MainTransSprites));
222
223 memset(light_block, 0, sizeof(light_block));
224 memset(block_changed, 0, sizeof(block_changed));
225 memset(light_chain, 0, sizeof(light_chain));
226 memset(add_block, 0, sizeof(add_block));
227 memset(add_changed, 0, sizeof(add_changed));
228 memset(add_chain, 0, sizeof(add_chain));
229 SimpleSurfsHead = NULL;
230 SimpleSurfsTail = NULL;
231 SkyPortalsHead = NULL;
232 SkyPortalsTail = NULL;
233 HorizonPortalsHead = NULL;
234 HorizonPortalsTail = NULL;
235 PortalDepth = 0;
236
237 VisSize = (Level->NumSubsectors + 7) >> 3;
238 BspVis = new vuint8[VisSize];
239
240 InitParticles();
241 ClearParticles();
242
243 screenblocks = 0;
244
245 // preload graphics
246 if (precache)
247 {
248 PrecacheLevel();
249 }
250 unguard;
251 }
252
253 //==========================================================================
254 //
255 // VRenderLevel::VRenderLevel
256 //
257 //==========================================================================
258
VRenderLevel(VLevel * ALevel)259 VRenderLevel::VRenderLevel(VLevel* ALevel)
260 : VRenderLevelShared(ALevel)
261 , c_subdivides(0)
262 , c_seg_div(0)
263 , freeblocks(NULL)
264 {
265 guard(VRenderLevel::VRenderLevel);
266 NeedsInfiniteFarClip = false;
267
268 memset(cacheblocks, 0, sizeof(cacheblocks));
269 memset(blockbuf, 0, sizeof(blockbuf));
270
271 FlushCaches();
272
273 memset(DLights, 0, sizeof(DLights));
274 unguard;
275 }
276
277 //==========================================================================
278 //
279 // VAdvancedRenderLevel::VAdvancedRenderLevel
280 //
281 //==========================================================================
282
VAdvancedRenderLevel(VLevel * ALevel)283 VAdvancedRenderLevel::VAdvancedRenderLevel(VLevel* ALevel)
284 : VRenderLevelShared(ALevel)
285 , LightVis(NULL)
286 {
287 guard(VAdvancedRenderLevel::VAdvancedRenderLevel);
288 NeedsInfiniteFarClip = true;
289
290 memset(DLights, 0, sizeof(DLights));
291
292 LightVis = new vuint8[VisSize];
293 LightBspVis = new vuint8[VisSize];
294 unguard;
295 }
296
297 //==========================================================================
298 //
299 // VRenderLevelShared::~VRenderLevelShared
300 //
301 //==========================================================================
302
~VRenderLevelShared()303 VRenderLevelShared::~VRenderLevelShared()
304 {
305 guard(VRenderLevelShared::~VRenderLevelShared);
306 // Free fake floor data.
307 for (int i = 0; i < Level->NumSectors; i++)
308 {
309 if (Level->Sectors[i].fakefloors)
310 {
311 delete Level->Sectors[i].fakefloors;
312 Level->Sectors[i].fakefloors = NULL;
313 }
314 }
315
316 for (int i = 0; i < Level->NumSubsectors; i++)
317 {
318 for (subregion_t* r = Level->Subsectors[i].regions; r; r = r->next)
319 {
320 FreeSurfaces(r->floor->surfs);
321 delete r->floor;
322 r->floor = NULL;
323 FreeSurfaces(r->ceil->surfs);
324 delete r->ceil;
325 r->ceil = NULL;
326 }
327 }
328
329 // Free seg parts.
330 for (int i = 0; i < Level->NumSegs; i++)
331 {
332 for (drawseg_t* ds = Level->Segs[i].drawsegs; ds; ds = ds->next)
333 {
334 FreeSegParts(ds->top);
335 FreeSegParts(ds->mid);
336 FreeSegParts(ds->bot);
337 FreeSegParts(ds->topsky);
338 FreeSegParts(ds->extra);
339 if (ds->HorizonTop)
340 {
341 Z_Free(ds->HorizonTop);
342 }
343 if (ds->HorizonBot)
344 {
345 Z_Free(ds->HorizonBot);
346 }
347 }
348 }
349 // Free allocated wall surface blocks.
350 for (void* Block = AllocatedWSurfBlocks; Block;)
351 {
352 void* Next = *(void**)Block;
353 Z_Free(Block);
354 Block = Next;
355 }
356 AllocatedWSurfBlocks = NULL;
357
358 // Free big blocks.
359 delete[] AllocatedSubRegions;
360 AllocatedSubRegions = NULL;
361 delete[] AllocatedDrawSegs;
362 AllocatedDrawSegs = NULL;
363 delete[] AllocatedSegParts;
364 AllocatedSegParts = NULL;
365
366 delete[] Particles;
367 Particles = NULL;
368 delete[] BspVis;
369 BspVis = NULL;
370
371 for (int i = 0; i < SideSkies.Num(); i++)
372 {
373 delete SideSkies[i];
374 SideSkies[i] = NULL;
375 }
376 unguard;
377 }
378
379 //==========================================================================
380 //
381 // VAdvancedRenderLevel::~VAdvancedRenderLevel
382 //
383 //==========================================================================
384
~VAdvancedRenderLevel()385 VAdvancedRenderLevel::~VAdvancedRenderLevel()
386 {
387 guard(VAdvancedRenderLevel::~VAdvancedRenderLevel);
388 delete[] LightVis;
389 LightVis = NULL;
390 delete[] LightBspVis;
391 LightBspVis = NULL;
392 unguard;
393 }
394
395 //==========================================================================
396 //
397 // R_SetViewSize
398 //
399 // Do not really change anything here, because it might be in the middle
400 // of a refresh. The change will take effect next refresh.
401 //
402 //==========================================================================
403
R_SetViewSize(int blocks)404 void R_SetViewSize(int blocks)
405 {
406 guard(R_SetViewSize);
407 if (blocks > 2)
408 {
409 screen_size = blocks;
410 }
411 set_resolutioon_needed = true;
412 unguard;
413 }
414
415 //==========================================================================
416 //
417 // COMMAND SizeDown
418 //
419 //==========================================================================
420
COMMAND(SizeDown)421 COMMAND(SizeDown)
422 {
423 R_SetViewSize(screenblocks - 1);
424 GAudio->PlaySound(GSoundManager->GetSoundID("menu/change"),
425 TVec(0, 0, 0), TVec(0, 0, 0), 0, 0, 1, 0, false);
426 }
427
428 //==========================================================================
429 //
430 // COMMAND SizeUp
431 //
432 //==========================================================================
433
COMMAND(SizeUp)434 COMMAND(SizeUp)
435 {
436 R_SetViewSize(screenblocks + 1);
437 GAudio->PlaySound(GSoundManager->GetSoundID("menu/change"),
438 TVec(0, 0, 0), TVec(0, 0, 0), 0, 0, 1, 0, false);
439 }
440
441 //==========================================================================
442 //
443 // VRenderLevelShared::ExecuteSetViewSize
444 //
445 //==========================================================================
446
ExecuteSetViewSize()447 void VRenderLevelShared::ExecuteSetViewSize()
448 {
449 guard(VRenderLevelShared::ExecuteSetViewSize);
450 set_resolutioon_needed = false;
451 if (screen_size < 3)
452 {
453 screen_size = 3;
454 }
455 if (screen_size > 11)
456 {
457 screen_size = 11;
458 }
459 screenblocks = screen_size;
460
461 if (fov < 5.0)
462 {
463 fov = 5.0;
464 }
465 if (fov > 175.0)
466 {
467 fov = 175.0;
468 }
469 old_fov = fov;
470
471 if (screenblocks > 10)
472 {
473 refdef.width = ScreenWidth;
474 refdef.height = ScreenHeight;
475 refdef.y = 0;
476 }
477 else if (GGameInfo->NetMode == NM_TitleMap)
478 {
479 // No status bar for titlemap.
480 refdef.width = screenblocks * ScreenWidth / 10;
481 refdef.height = (screenblocks * ScreenHeight / 10);
482 refdef.y = (ScreenHeight - refdef.height) >> 1;
483 }
484 else
485 {
486 refdef.width = screenblocks * ScreenWidth / 10;
487 refdef.height = (screenblocks * (ScreenHeight - SB_REALHEIGHT) / 10);
488 refdef.y = (ScreenHeight - SB_REALHEIGHT - refdef.height) >> 1;
489 }
490 refdef.x = (ScreenWidth - refdef.width) >> 1;
491
492 if (aspect_ratio == 0)
493 {
494 // Original aspect ratio
495 PixelAspect = ((float)ScreenHeight * 320.0) / ((float)ScreenWidth * 200.0);
496 }
497 else if (aspect_ratio == 1)
498 {
499 // 4:3 aspect ratio
500 PixelAspect = ((float)ScreenHeight * 4.0) / ((float)ScreenWidth * 3.0);
501 }
502 else if (aspect_ratio == 2)
503 {
504 // 16:9 aspect ratio
505 PixelAspect = ((float)ScreenHeight * 16.0) / ((float)ScreenWidth * 9.0);
506 }
507 else
508 {
509 // 16:10 aspect ratio
510 PixelAspect = ((float)ScreenHeight * 16.0) / ((float)ScreenWidth * 10.0);
511 }
512 prev_aspect_ratio = aspect_ratio;
513
514 refdef.fovx = tan(DEG2RAD(fov) / 2);
515 refdef.fovy = refdef.fovx * refdef.height / refdef.width / PixelAspect;
516
517 // left side clip
518 clip_base[0] = Normalise(TVec(1, 1.0 / refdef.fovx, 0));
519
520 // right side clip
521 clip_base[1] = Normalise(TVec(1, -1.0 / refdef.fovx, 0));
522
523 // top side clip
524 clip_base[2] = Normalise(TVec(1, 0, -1.0 / refdef.fovy));
525
526 // bottom side clip
527 clip_base[3] = Normalise(TVec(1, 0, 1.0 / refdef.fovy));
528
529 refdef.drawworld = true;
530 unguard;
531 }
532
533 //==========================================================================
534 //
535 // R_DrawViewBorder
536 //
537 //==========================================================================
538
R_DrawViewBorder()539 void R_DrawViewBorder()
540 {
541 guard(R_DrawViewBorder);
542 if (GGameInfo->NetMode == NM_TitleMap)
543 {
544 GClGame->eventDrawViewBorder(320 - screenblocks * 32,
545 (480 - screenblocks * 480 / 10) / 2,
546 screenblocks * 64, screenblocks * 480 / 10);
547 }
548 else
549 {
550 GClGame->eventDrawViewBorder(320 - screenblocks * 32,
551 (480 - sb_height - screenblocks * (480 - sb_height) / 10) / 2,
552 screenblocks * 64, screenblocks * (480 - sb_height) / 10);
553 }
554 unguard;
555 }
556
557 //==========================================================================
558 //
559 // VRenderLevelShared::TransformFrustum
560 //
561 //==========================================================================
562
TransformFrustum()563 void VRenderLevelShared::TransformFrustum()
564 {
565 guard(VRenderLevelShared::TransformFrustum);
566 for (int i = 0; i < 4; i++)
567 {
568 TVec &v = clip_base[i];
569 TVec v2;
570
571 v2.x = v.y * viewright.x + v.z * viewup.x + v.x * viewforward.x;
572 v2.y = v.y * viewright.y + v.z * viewup.y + v.x * viewforward.y;
573 v2.z = v.y * viewright.z + v.z * viewup.z + v.x * viewforward.z;
574
575 view_clipplanes[i].Set(v2, DotProduct(vieworg, v2));
576
577 view_clipplanes[i].next = i == 3 ? NULL : &view_clipplanes[i + 1];
578 view_clipplanes[i].clipflag = 1 << i;
579 }
580 unguard;
581 }
582
583 //==========================================================================
584 //
585 // VRenderLevelShared::SetupFrame
586 //
587 //==========================================================================
588
589 VCvarI r_chasecam("r_chasecam", "0", CVAR_Archive);
590 VCvarF r_chase_dist("r_chase_dist", "32.0", CVAR_Archive);
591 VCvarF r_chase_up("r_chase_up", "128.0", CVAR_Archive);
592 VCvarF r_chase_right("r_chase_right", "0", CVAR_Archive);
593 VCvarI r_chase_front("r_chase_front", "0", CVAR_Archive);
594
SetupFrame()595 void VRenderLevelShared::SetupFrame()
596 {
597 guard(VRenderLevelShared::SetupFrame);
598 // change the view size if needed
599 if (screen_size != screenblocks || !screenblocks ||
600 set_resolutioon_needed || old_fov != fov ||
601 aspect_ratio != prev_aspect_ratio)
602 {
603 ExecuteSetViewSize();
604 }
605
606 ViewEnt = cl->Camera;
607 viewangles = cl->ViewAngles;
608 if (r_chasecam && r_chase_front)
609 {
610 // This is used to see how weapon looks in player's hands
611 viewangles.yaw = AngleMod(viewangles.yaw + 180);
612 viewangles.pitch = -viewangles.pitch;
613 }
614 AngleVectors(viewangles, viewforward, viewright, viewup);
615
616 if (r_chasecam && cl->MO == cl->Camera)
617 {
618 vieworg = cl->MO->Origin + TVec(0.0, 0.0, 32.0)
619 - r_chase_dist * viewforward + r_chase_up * viewup
620 + r_chase_right * viewright;
621 }
622 else
623 {
624 vieworg = cl->ViewOrg;
625 }
626
627 ExtraLight = ViewEnt->Player ? ViewEnt->Player->ExtraLight * 8 : 0;
628 if (cl->Camera == cl->MO)
629 {
630 ColourMap = CM_Default;
631 if (cl->FixedColourmap == INVERSECOLOURMAP)
632 {
633 ColourMap = CM_Inverse;
634 FixedLight = 255;
635 }
636 else if (cl->FixedColourmap == GOLDCOLOURMAP)
637 {
638 ColourMap = CM_Gold;
639 FixedLight = 255;
640 }
641 else if (cl->FixedColourmap == REDCOLOURMAP)
642 {
643 ColourMap = CM_Red;
644 FixedLight = 255;
645 }
646 else if (cl->FixedColourmap == GREENCOLOURMAP)
647 {
648 ColourMap = CM_Green;
649 FixedLight = 255;
650 }
651 else if (cl->FixedColourmap >= NUMCOLOURMAPS)
652 {
653 FixedLight = 255;
654 }
655 else if (cl->FixedColourmap)
656 {
657 FixedLight = 255 - (cl->FixedColourmap << 3);
658 }
659 else
660 {
661 FixedLight = 0;
662 }
663 }
664 else
665 {
666 FixedLight = 0;
667 ColourMap = 0;
668 }
669 // Inverse colourmap flash effect.
670 if (cl->ExtraLight == 255)
671 {
672 ExtraLight = 0;
673 ColourMap = CM_Inverse;
674 FixedLight = 255;
675 }
676
677 Drawer->SetupView(this, &refdef);
678 cacheframecount++;
679 PortalDepth = 0;
680 unguard;
681 }
682
683 //==========================================================================
684 //
685 // VRenderLevelShared::SetupCameraFrame
686 //
687 //==========================================================================
688
SetupCameraFrame(VEntity * Camera,VTexture * Tex,int FOV,refdef_t * rd)689 void VRenderLevelShared::SetupCameraFrame(VEntity* Camera, VTexture* Tex,
690 int FOV, refdef_t* rd)
691 {
692 guard(VRenderLevelShared::SetupCameraFrame);
693 rd->width = Tex->GetWidth();
694 rd->height = Tex->GetHeight();
695 rd->y = 0;
696 rd->x = 0;
697
698 if (aspect_ratio == 0)
699 {
700 PixelAspect = ((float)rd->height * 320.0) / ((float)rd->width * 200.0);
701 }
702 else if (aspect_ratio == 1)
703 {
704 PixelAspect = ((float)rd->height * 4.0) / ((float)rd->width * 3.0);
705 }
706 else if (aspect_ratio == 2)
707 {
708 PixelAspect = ((float)rd->height * 16.0) / ((float)rd->width * 9.0);
709 }
710 else if (aspect_ratio > 2)
711 {
712 PixelAspect = ((float)rd->height * 16.0) / ((float)rd->width * 10.0);
713 }
714
715 rd->fovx = tan(DEG2RAD(FOV) / 2);
716 rd->fovy = rd->fovx * rd->height / rd->width / PixelAspect;
717
718 // left side clip
719 clip_base[0] = Normalise(TVec(1, 1.0 / rd->fovx, 0));
720
721 // right side clip
722 clip_base[1] = Normalise(TVec(1, -1.0 / rd->fovx, 0));
723
724 // top side clip
725 clip_base[2] = Normalise(TVec(1, 0, -1.0 / rd->fovy));
726
727 // bottom side clip
728 clip_base[3] = Normalise(TVec(1, 0, 1.0 / rd->fovy));
729
730 rd->drawworld = true;
731
732 ViewEnt = Camera;
733 viewangles = Camera->Angles;
734 AngleVectors(viewangles, viewforward, viewright, viewup);
735
736 vieworg = Camera->Origin;
737
738 ExtraLight = 0;
739 FixedLight = 0;
740 ColourMap = 0;
741
742 Drawer->SetupView(this, rd);
743 cacheframecount++;
744 PortalDepth = 0;
745 set_resolutioon_needed = true;
746 unguard;
747 }
748
749 //==========================================================================
750 //
751 // VRenderLevelShared::MarkLeaves
752 //
753 //==========================================================================
754
MarkLeaves()755 void VRenderLevelShared::MarkLeaves()
756 {
757 guard(VRenderLevelShared::MarkLeaves);
758 byte *vis;
759 node_t *node;
760 int i;
761
762 if (r_oldviewleaf == r_viewleaf)
763 return;
764
765 r_visframecount++;
766 r_oldviewleaf = r_viewleaf;
767
768 vis = Level->LeafPVS(r_viewleaf);
769
770 for (i = 0; i < Level->NumSubsectors; i++)
771 {
772 if (vis[i >> 3] & (1 << (i & 7)))
773 {
774 subsector_t *sub = &Level->Subsectors[i];
775 sub->VisFrame = r_visframecount;
776 node = sub->parent;
777 while (node)
778 {
779 if (node->VisFrame == r_visframecount)
780 break;
781 node->VisFrame = r_visframecount;
782 node = node->parent;
783 }
784 }
785 }
786 unguard;
787 }
788
789 //==========================================================================
790 //
791 // VRenderLevel::RenderScene
792 //
793 //==========================================================================
794
RenderScene(const refdef_t * RD,const VViewClipper * Range)795 void VRenderLevel::RenderScene(const refdef_t* RD, const VViewClipper* Range)
796 {
797 guard(VRenderLevel::RenderScene);
798 r_viewleaf = Level->PointInSubsector(vieworg);
799
800 TransformFrustum();
801
802 Drawer->SetupViewOrg();
803
804 MarkLeaves();
805
806 UpdateWorld(RD, Range);
807
808 RenderWorld(RD, Range);
809
810 RenderMobjs(RPASS_Normal);
811
812 DrawParticles();
813
814 DrawTranslucentPolys();
815 unguard;
816 }
817
818 //==========================================================================
819 //
820 // VAdvancedRenderLevel::RenderScene
821 //
822 //==========================================================================
823
RenderScene(const refdef_t * RD,const VViewClipper * Range)824 void VAdvancedRenderLevel::RenderScene(const refdef_t* RD, const VViewClipper* Range)
825 {
826 guard(VAdvancedRenderLevel::RenderScene);
827 if (!Drawer->SupportsAdvancedRendering())
828 {
829 Host_Error("Advanced rendering not supported by graphics card");
830 }
831
832 r_viewleaf = Level->PointInSubsector(vieworg);
833
834 TransformFrustum();
835
836 Drawer->SetupViewOrg();
837
838 MarkLeaves();
839
840 UpdateWorld();
841
842 RenderWorld(RD, Range);
843 RenderMobjsAmbient();
844
845 Drawer->BeginShadowVolumesPass();
846 if (!FixedLight && r_dynamic)
847 {
848 dlight_t* l = DLights;
849 for (int i = 0; i < MAX_DLIGHTS; i++, l++)
850 {
851 if (l->die < Level->Time || !l->radius)
852 {
853 continue;
854 }
855 RenderLightShadows(RD, Range, l->origin, l->radius, l->colour);
856 }
857 }
858 if (!FixedLight && r_static_lights)
859 {
860 for (int i = 0; i < Lights.Num(); i++)
861 {
862 if (!Lights[i].radius)
863 {
864 continue;
865 }
866 RenderLightShadows(RD, Range, Lights[i].origin, Lights[i].radius, Lights[i].colour);
867 }
868 }
869
870 Drawer->DrawWorldTexturesPass();
871 RenderMobjsTextures();
872
873 Drawer->DrawWorldFogPass();
874 RenderMobjsFog();
875 Drawer->EndFogPass();
876
877 RenderMobjs(RPASS_NonShadow);
878
879 DrawParticles();
880
881 DrawTranslucentPolys();
882 unguard;
883 }
884
885 //==========================================================================
886 //
887 // R_RenderPlayerView
888 //
889 //==========================================================================
890
R_RenderPlayerView()891 void R_RenderPlayerView()
892 {
893 guard(R_RenderPlayerView);
894 GClLevel->RenderData->RenderPlayerView();
895 unguard;
896 }
897
898 //==========================================================================
899 //
900 // VRenderLevelShared::RenderPlayerView
901 //
902 //==========================================================================
903
RenderPlayerView()904 void VRenderLevelShared::RenderPlayerView()
905 {
906 guard(VRenderLevelShared::RenderPlayerView);
907 if (!Level->LevelInfo)
908 {
909 return;
910 }
911
912 GTextureManager.Time = Level->Time;
913
914 BuildPlayerTranslations();
915
916 AnimateSky(host_frametime);
917
918 UpdateParticles(host_frametime);
919
920 PushDlights();
921
922 // Update camera textures that were visible in last frame.
923 for (int i = 0; i < Level->CameraTextures.Num(); i++)
924 {
925 UpdateCameraTexture(Level->CameraTextures[i].Camera,
926 Level->CameraTextures[i].TexNum, Level->CameraTextures[i].FOV);
927 }
928
929 SetupFrame();
930
931 RenderScene(&refdef, NULL);
932
933 // draw the psprites on top of everything
934 if (fov <= 90.0 && cl->MO == cl->Camera &&
935 GGameInfo->NetMode != NM_TitleMap)
936 {
937 DrawPlayerSprites();
938 }
939
940 Drawer->EndView();
941
942 // Draw croshair
943 if (cl->MO == cl->Camera && GGameInfo->NetMode != NM_TitleMap)
944 {
945 DrawCroshair();
946 }
947 unguard;
948 }
949
950 //==========================================================================
951 //
952 // VRenderLevelShared::UpdateCameraTexture
953 //
954 //==========================================================================
955
UpdateCameraTexture(VEntity * Camera,int TexNum,int FOV)956 void VRenderLevelShared::UpdateCameraTexture(VEntity* Camera, int TexNum,
957 int FOV)
958 {
959 guard(VRenderLevelShared::UpdateCameraTexture);
960 if (!Camera)
961 {
962 return;
963 }
964
965 if (!GTextureManager[TexNum]->bIsCameraTexture)
966 {
967 return;
968 }
969 VCameraTexture* Tex = (VCameraTexture*)GTextureManager[TexNum];
970 if (!Tex->bNeedsUpdate)
971 {
972 return;
973 }
974
975 refdef_t CameraRefDef;
976 CameraRefDef.DrawCamera = true;
977
978 SetupCameraFrame(Camera, Tex, FOV, &CameraRefDef);
979
980 RenderScene(&CameraRefDef, NULL);
981
982 Drawer->EndView();
983
984 Tex->CopyImage();
985 unguard;
986 }
987
988 //==========================================================================
989 //
990 // VRenderLevelShared::GetFade
991 //
992 //==========================================================================
993
GetFade(sec_region_t * Reg)994 vuint32 VRenderLevelShared::GetFade(sec_region_t* Reg)
995 {
996 guard(VRenderLevelShared::GetFade);
997 if (r_fog_test)
998 {
999 return 0xff000000 | (int(255 * r_fog_r) << 16) |
1000 (int(255 * r_fog_g) << 8) | int(255 * r_fog_b);
1001 }
1002 if (Reg->params->Fade)
1003 {
1004 return Reg->params->Fade;
1005 }
1006 if (Level->LevelInfo->OutsideFog && Reg->ceiling->pic == skyflatnum)
1007 {
1008 return Level->LevelInfo->OutsideFog;
1009 }
1010 if (Level->LevelInfo->Fade)
1011 {
1012 return Level->LevelInfo->Fade;
1013 }
1014 if (Level->LevelInfo->FadeTable == NAME_fogmap)
1015 {
1016 return 0xff7f7f7f;
1017 }
1018 if (r_fade_light)
1019 {
1020 // Simulate light fading using dark fog
1021 return FADE_LIGHT;
1022 }
1023 else
1024 {
1025 return 0;
1026 }
1027 unguard;
1028 }
1029
1030 //==========================================================================
1031 //
1032 // R_DrawPic
1033 //
1034 //==========================================================================
1035
R_DrawPic(int x,int y,int handle,float Alpha)1036 void R_DrawPic(int x, int y, int handle, float Alpha)
1037 {
1038 guard(R_DrawPic);
1039 if (handle < 0)
1040 {
1041 return;
1042 }
1043
1044 VTexture* Tex = GTextureManager(handle);
1045 x -= Tex->GetScaledSOffset();
1046 y -= Tex->GetScaledTOffset();
1047 Drawer->DrawPic(fScaleX * x, fScaleY * y,
1048 fScaleX * (x + Tex->GetScaledWidth()), fScaleY * (y + Tex->GetScaledHeight()),
1049 0, 0, Tex->GetWidth(), Tex->GetHeight(), Tex, NULL, Alpha);
1050 unguard;
1051 }
1052
1053 //==========================================================================
1054 //
1055 // VRenderLevelShared::PrecacheLevel
1056 //
1057 // Preloads all relevant graphics for the level.
1058 //
1059 //==========================================================================
1060
PrecacheLevel()1061 void VRenderLevelShared::PrecacheLevel()
1062 {
1063 guard(VRenderLevelShared::PrecacheLevel);
1064 int i;
1065
1066 if (cls.demoplayback)
1067 return;
1068
1069 #ifdef __GNUC__
1070 char texturepresent[GTextureManager.GetNumTextures()];
1071 #else
1072 char* texturepresent = (char*)Z_Malloc(GTextureManager.GetNumTextures());
1073 #endif
1074 memset(texturepresent, 0, GTextureManager.GetNumTextures());
1075
1076 for (i = 0; i < Level->NumSectors; i++)
1077 {
1078 texturepresent[Level->Sectors[i].floor.pic] = true;
1079 texturepresent[Level->Sectors[i].ceiling.pic] = true;
1080 }
1081
1082 for (i = 0; i < Level->NumSides; i++)
1083 {
1084 texturepresent[Level->Sides[i].TopTexture] = true;
1085 texturepresent[Level->Sides[i].MidTexture] = true;
1086 texturepresent[Level->Sides[i].BottomTexture] = true;
1087 }
1088
1089 // Precache textures.
1090 for (i = 1; i < GTextureManager.GetNumTextures(); i++)
1091 {
1092 if (texturepresent[i])
1093 {
1094 Drawer->PrecacheTexture(GTextureManager[i]);
1095 }
1096 }
1097
1098 #ifndef __GNUC__
1099 Z_Free(texturepresent);
1100 #endif
1101 unguard;
1102 }
1103
1104 //==========================================================================
1105 //
1106 // VRenderLevelShared::GetTranslation
1107 //
1108 //==========================================================================
1109
GetTranslation(int TransNum)1110 VTextureTranslation* VRenderLevelShared::GetTranslation(int TransNum)
1111 {
1112 guard(VRenderLevelShared::GetTranslation);
1113 return R_GetCachedTranslation(TransNum, Level);
1114 unguard;
1115 }
1116
1117 //==========================================================================
1118 //
1119 // VRenderLevelShared::BuildPlayerTranslations
1120 //
1121 //==========================================================================
1122
BuildPlayerTranslations()1123 void VRenderLevelShared::BuildPlayerTranslations()
1124 {
1125 guard(VRenderLevelShared::BuildPlayerTranslations);
1126 for (TThinkerIterator<VPlayerReplicationInfo> It(Level); It; ++It)
1127 {
1128 if (It->PlayerNum < 0 || It->PlayerNum >= MAXPLAYERS)
1129 {
1130 // Should not happen.
1131 continue;
1132 }
1133 if (!It->TranslStart || !It->TranslEnd)
1134 {
1135 continue;
1136 }
1137
1138 VTextureTranslation* Tr = PlayerTranslations[It->PlayerNum];
1139 if (Tr && Tr->TranslStart == It->TranslStart &&
1140 Tr->TranslEnd == It->TranslEnd && Tr->Colour == It->Colour)
1141 {
1142 continue;
1143 }
1144
1145 if (!Tr)
1146 {
1147 Tr = new VTextureTranslation;
1148 PlayerTranslations[It->PlayerNum] = Tr;
1149 }
1150 // Don't waste time clearing if it's the same range.
1151 if (Tr->TranslStart != It->TranslStart ||
1152 Tr->TranslEnd != It->TranslEnd)
1153 {
1154 Tr->Clear();
1155 }
1156 Tr->BuildPlayerTrans(It->TranslStart, It->TranslEnd, It->Colour);
1157 }
1158 unguard;
1159 }
1160
1161 //==========================================================================
1162 //
1163 // R_SetMenuPlayerTrans
1164 //
1165 //==========================================================================
1166
R_SetMenuPlayerTrans(int Start,int End,int Col)1167 int R_SetMenuPlayerTrans(int Start, int End, int Col)
1168 {
1169 guard(R_SetMenuPlayerTrans);
1170 if (!Start || !End)
1171 {
1172 return 0;
1173 }
1174
1175 VTextureTranslation* Tr = PlayerTranslations[MAXPLAYERS];
1176 if (Tr && Tr->TranslStart == Start && Tr->TranslEnd == End &&
1177 Tr->Colour == Col)
1178 {
1179 return (TRANSL_Player << TRANSL_TYPE_SHIFT) + MAXPLAYERS;
1180 }
1181
1182 if (!Tr)
1183 {
1184 Tr = new VTextureTranslation;
1185 PlayerTranslations[MAXPLAYERS] = Tr;
1186 }
1187 if (Tr->TranslStart != Start || Tr->TranslEnd == End)
1188 {
1189 Tr->Clear();
1190 }
1191 Tr->BuildPlayerTrans(Start, End, Col);
1192 return (TRANSL_Player << TRANSL_TYPE_SHIFT) + MAXPLAYERS;
1193 unguard;
1194 }
1195
1196 //==========================================================================
1197 //
1198 // R_GetCachedTranslation
1199 //
1200 //==========================================================================
1201
R_GetCachedTranslation(int TransNum,VLevel * Level)1202 VTextureTranslation* R_GetCachedTranslation(int TransNum, VLevel* Level)
1203 {
1204 guard(R_GetCachedTranslation);
1205 int Type = TransNum >> TRANSL_TYPE_SHIFT;
1206 int Index = TransNum & ((1 << TRANSL_TYPE_SHIFT) - 1);
1207 VTextureTranslation* Tr;
1208 switch (Type)
1209 {
1210 case TRANSL_Standard:
1211 if (Index == 7)
1212 {
1213 Tr = &IceTranslation;
1214 }
1215 else
1216 {
1217 if (Index < 0 || Index >= NumTranslationTables)
1218 {
1219 return NULL;
1220 }
1221 Tr = TranslationTables[Index];
1222 }
1223 break;
1224
1225 case TRANSL_Player:
1226 if (Index < 0 || Index >= MAXPLAYERS + 1)
1227 {
1228 return NULL;
1229 }
1230 Tr = PlayerTranslations[Index];
1231 break;
1232
1233 case TRANSL_Level:
1234 if (!Level || Index < 0 || Index >= Level->Translations.Num())
1235 {
1236 return NULL;
1237 }
1238 Tr = Level->Translations[Index];
1239 break;
1240
1241 case TRANSL_BodyQueue:
1242 if (!Level || Index < 0 || Index >= Level->BodyQueueTrans.Num())
1243 {
1244 return NULL;
1245 }
1246 Tr = Level->BodyQueueTrans[Index];
1247 break;
1248
1249 case TRANSL_Decorate:
1250 if (Index < 0 || Index >= DecorateTranslations.Num())
1251 {
1252 return NULL;
1253 }
1254 Tr = DecorateTranslations[Index];
1255 break;
1256
1257 case TRANSL_Blood:
1258 if (Index < 0 || Index >= BloodTranslations.Num())
1259 {
1260 return NULL;
1261 }
1262 Tr = BloodTranslations[Index];
1263 break;
1264
1265 default:
1266 return NULL;
1267 }
1268
1269 if (!Tr)
1270 {
1271 return NULL;
1272 }
1273
1274 for (int i = 0; i < CachedTranslations.Num(); i++)
1275 {
1276 VTextureTranslation* Check = CachedTranslations[i];
1277 if (Check->Crc != Tr->Crc)
1278 {
1279 continue;
1280 }
1281 if (memcmp(Check->Palette, Tr->Palette, sizeof(Tr->Palette)))
1282 {
1283 continue;
1284 }
1285 return Check;
1286 }
1287
1288 VTextureTranslation* Copy = new VTextureTranslation;
1289 *Copy = *Tr;
1290 CachedTranslations.Append(Copy);
1291 return Copy;
1292 unguard;
1293 }
1294
1295 //==========================================================================
1296 //
1297 // COMMAND TimeRefresh
1298 //
1299 // For program optimization
1300 //
1301 //==========================================================================
1302
COMMAND(TimeRefresh)1303 COMMAND(TimeRefresh)
1304 {
1305 guard(COMMAND TimeRefresh);
1306 int i;
1307 double start, stop, time, RenderTime, UpdateTime;
1308 float startangle;
1309
1310 if (!cl)
1311 {
1312 return;
1313 }
1314
1315 startangle = cl->ViewAngles.yaw;
1316
1317 RenderTime = 0;
1318 UpdateTime = 0;
1319 start = Sys_Time();
1320 for (i = 0; i < 128; i++)
1321 {
1322 cl->ViewAngles.yaw = (float)(i) * 360.0 / 128.0;
1323
1324 Drawer->StartUpdate();
1325
1326 RenderTime -= Sys_Time();
1327 R_RenderPlayerView();
1328 RenderTime += Sys_Time();
1329
1330 UpdateTime -= Sys_Time();
1331 Drawer->Update();
1332 UpdateTime += Sys_Time();
1333 }
1334 stop = Sys_Time();
1335 time = stop - start;
1336 GCon->Logf("%f seconds (%f fps)", time, 128 / time);
1337 GCon->Logf("Render time %f, update time %f", RenderTime, UpdateTime);
1338
1339 cl->ViewAngles.yaw = startangle;
1340 unguard;
1341 }
1342
1343 //==========================================================================
1344 //
1345 // V_Init
1346 //
1347 //==========================================================================
1348
V_Init()1349 void V_Init()
1350 {
1351 guard(V_Init);
1352 int DIdx = -1;
1353 for (int i = 0; i < DRAWER_MAX; i++)
1354 {
1355 if (!DrawerList[i])
1356 continue;
1357 // Pick first available as default.
1358 if (DIdx == -1)
1359 DIdx = i;
1360 // Check for user driver selection.
1361 if (DrawerList[i]->CmdLineArg && GArgs.CheckParm(DrawerList[i]->CmdLineArg))
1362 DIdx = i;
1363 }
1364 if (DIdx == -1)
1365 Sys_Error("No drawers are available");
1366 _driver = DIdx;
1367 GCon->Logf(NAME_Init, "Selected %s", DrawerList[DIdx]->Description);
1368 // Create drawer.
1369 Drawer = DrawerList[DIdx]->Creator();
1370 Drawer->Init();
1371 unguard;
1372 }
1373
1374 //==========================================================================
1375 //
1376 // V_Shutdown
1377 //
1378 //==========================================================================
1379
V_Shutdown()1380 void V_Shutdown()
1381 {
1382 guard(V_Shutdown);
1383 if (Drawer)
1384 {
1385 Drawer->Shutdown();
1386 delete Drawer;
1387 Drawer = NULL;
1388 }
1389 R_FreeModels();
1390 for (int i = 0; i < MAXPLAYERS + 1; i++)
1391 {
1392 if (PlayerTranslations[i])
1393 {
1394 delete PlayerTranslations[i];
1395 PlayerTranslations[i] = NULL;
1396 }
1397 }
1398 for (int i = 0; i < CachedTranslations.Num(); i++)
1399 {
1400 delete CachedTranslations[i];
1401 CachedTranslations[i] = NULL;
1402 }
1403 CachedTranslations.Clear();
1404 R_FreeSkyboxData();
1405 unguard;
1406 }
1407