1 /*
2 ===========================================================================
3
4 Return to Castle Wolfenstein single player GPL Source Code
5 Copyright (C) 1999-2010 id Software LLC, a ZeniMax Media company.
6
7 This file is part of the Return to Castle Wolfenstein single player GPL Source Code (RTCW SP Source Code).
8
9 RTCW SP Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 RTCW SP Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with RTCW SP Source Code. If not, see <http://www.gnu.org/licenses/>.
21
22 In addition, the RTCW SP Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the RTCW SP Source Code. If not, please request a copy in writing from id Software at the address below.
23
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25
26 ===========================================================================
27 */
28
29
30 #include "tr_local.h"
31
32 int r_firstSceneDrawSurf;
33
34 int r_numdlights;
35 int r_firstSceneDlight;
36
37 int r_numcoronas;
38 int r_firstSceneCorona;
39
40 int r_numentities;
41 int r_firstSceneEntity;
42
43 int r_numpolys;
44 int r_firstScenePoly;
45
46 int r_numpolyverts;
47
48 int skyboxportal;
49 int drawskyboxportal;
50
51 /*
52 ====================
53 R_InitNextFrame
54 ====================
55 */
R_InitNextFrame(void)56 void R_InitNextFrame( void ) {
57 backEndData->commands.used = 0;
58
59 r_firstSceneDrawSurf = 0;
60
61 r_numdlights = 0;
62 r_firstSceneDlight = 0;
63
64 r_numcoronas = 0;
65 r_firstSceneCorona = 0;
66
67 r_numentities = 0;
68 r_firstSceneEntity = 0;
69
70 r_numpolys = 0;
71 r_firstScenePoly = 0;
72
73 r_numpolyverts = 0;
74 }
75
76
77 /*
78 ====================
79 RE_ClearScene
80
81 ====================
82 */
RE_ClearScene(void)83 void RE_ClearScene( void ) {
84 r_firstSceneDlight = r_numdlights;
85 r_firstSceneCorona = r_numcoronas;
86 r_firstSceneEntity = r_numentities;
87 r_firstScenePoly = r_numpolys;
88 }
89
90 /*
91 ===========================================================================
92
93 DISCRETE POLYS
94
95 ===========================================================================
96 */
97
98 /*
99 =====================
100 R_AddPolygonSurfaces
101
102 Adds all the scene's polys into this view's drawsurf list
103 =====================
104 */
R_AddPolygonSurfaces(void)105 void R_AddPolygonSurfaces( void ) {
106 int i;
107 shader_t *sh;
108 srfPoly_t *poly;
109 int fogMask;
110
111 tr.currentEntityNum = REFENTITYNUM_WORLD;
112 tr.shiftedEntityNum = tr.currentEntityNum << QSORT_REFENTITYNUM_SHIFT;
113 fogMask = -((tr.refdef.rdflags & RDF_NOFOG) == 0);
114
115 for ( i = 0, poly = tr.refdef.polys; i < tr.refdef.numPolys ; i++, poly++ ) {
116 sh = R_GetShaderByHandle( poly->hShader );
117 // GR - not tessellated
118 R_AddDrawSurf( ( void * )poly, sh, poly->fogIndex & fogMask, qfalse, qfalse, 0, /*cubeMap*/ ATI_TESS_NONE );
119 }
120 }
121
122 /*
123 =====================
124 RE_AddPolyToScene
125
126 =====================
127 */
RE_AddPolyToScene(qhandle_t hShader,int numVerts,const polyVert_t * verts)128 void RE_AddPolyToScene( qhandle_t hShader, int numVerts, const polyVert_t *verts ) {
129 srfPoly_t *poly;
130 int i;
131 int fogIndex;
132 fog_t *fog;
133 vec3_t bounds[2];
134
135 if ( !tr.registered ) {
136 return;
137 }
138
139 if ( !hShader ) {
140 // This isn't a useful warning, and an hShader of zero isn't a null shader, it's
141 // the default shader.
142 //ri.Printf( PRINT_WARNING, "WARNING: RE_AddPolyToScene: NULL poly shader\n");
143 //return;
144 }
145
146 if ( ( ( r_numpolyverts + numVerts ) >= max_polyverts ) || ( r_numpolys >= max_polys ) ) {
147 return;
148 }
149
150 poly = &backEndData->polys[r_numpolys];
151 poly->surfaceType = SF_POLY;
152 poly->hShader = hShader;
153 poly->numVerts = numVerts;
154 poly->verts = &backEndData->polyVerts[r_numpolyverts];
155
156 memcpy( poly->verts, verts, numVerts * sizeof( *verts ) );
157 // Ridah
158 if ( glConfig.hardwareType == GLHW_RAGEPRO ) {
159 poly->verts->modulate[0] = 255;
160 poly->verts->modulate[1] = 255;
161 poly->verts->modulate[2] = 255;
162 poly->verts->modulate[3] = 255;
163 }
164 // done.
165 r_numpolys++;
166 r_numpolyverts += numVerts;
167
168 // see if it is in a fog volume
169 if ( tr.world->numfogs == 1 ) {
170 fogIndex = 0;
171 } else {
172 // find which fog volume the poly is in
173 VectorCopy( poly->verts[0].xyz, bounds[0] );
174 VectorCopy( poly->verts[0].xyz, bounds[1] );
175 for ( i = 1 ; i < poly->numVerts ; i++ ) {
176 AddPointToBounds( poly->verts[i].xyz, bounds[0], bounds[1] );
177 }
178 for ( fogIndex = 1 ; fogIndex < tr.world->numfogs ; fogIndex++ ) {
179 fog = &tr.world->fogs[fogIndex];
180 if ( bounds[1][0] >= fog->bounds[0][0]
181 && bounds[1][1] >= fog->bounds[0][1]
182 && bounds[1][2] >= fog->bounds[0][2]
183 && bounds[0][0] <= fog->bounds[1][0]
184 && bounds[0][1] <= fog->bounds[1][1]
185 && bounds[0][2] <= fog->bounds[1][2] ) {
186 break;
187 }
188 }
189 if ( fogIndex == tr.world->numfogs ) {
190 fogIndex = 0;
191 }
192 }
193 poly->fogIndex = fogIndex;
194 }
195
196 // Ridah
197 /*
198 =====================
199 RE_AddPolysToScene
200
201 =====================
202 */
RE_AddPolysToScene(qhandle_t hShader,int numVerts,const polyVert_t * verts,int numPolys)203 void RE_AddPolysToScene( qhandle_t hShader, int numVerts, const polyVert_t *verts, int numPolys ) {
204 srfPoly_t *poly;
205 int i;
206 int fogIndex;
207 fog_t *fog;
208 vec3_t bounds[2];
209 int j;
210
211 if ( !tr.registered ) {
212 return;
213 }
214
215 if ( !hShader ) {
216 ri.Printf( PRINT_WARNING, "WARNING: RE_AddPolysToScene: NULL poly shader\n" );
217 return;
218 }
219
220 for ( j = 0; j < numPolys; j++ ) {
221 if ( r_numpolyverts + numVerts >= max_polyverts || r_numpolys >= max_polys ) {
222 // ri.Printf( PRINT_WARNING, "WARNING: RE_AddPolysToScene: MAX_POLYS or MAX_POLYVERTS reached\n");
223 return;
224 }
225
226 poly = &backEndData->polys[r_numpolys];
227 poly->surfaceType = SF_POLY;
228 poly->hShader = hShader;
229 poly->numVerts = numVerts;
230 poly->verts = &backEndData->polyVerts[r_numpolyverts];
231
232 memcpy( poly->verts, &verts[numVerts * j], numVerts * sizeof( *verts ) );
233 // Ridah
234 if ( glConfig.hardwareType == GLHW_RAGEPRO ) {
235 poly->verts->modulate[0] = 255;
236 poly->verts->modulate[1] = 255;
237 poly->verts->modulate[2] = 255;
238 poly->verts->modulate[3] = 255;
239 }
240 // done.
241 r_numpolys++;
242 r_numpolyverts += numVerts;
243
244 // if no world is loaded
245 if ( tr.world == NULL ) {
246 fogIndex = 0;
247 }
248 // see if it is in a fog volume
249 else if ( tr.world->numfogs == 1 ) {
250 fogIndex = 0;
251 } else {
252 // find which fog volume the poly is in
253 VectorCopy( poly->verts[0].xyz, bounds[0] );
254 VectorCopy( poly->verts[0].xyz, bounds[1] );
255 for ( i = 1 ; i < poly->numVerts ; i++ ) {
256 AddPointToBounds( poly->verts[i].xyz, bounds[0], bounds[1] );
257 }
258 for ( fogIndex = 1 ; fogIndex < tr.world->numfogs ; fogIndex++ ) {
259 fog = &tr.world->fogs[fogIndex];
260 if ( bounds[1][0] >= fog->bounds[0][0]
261 && bounds[1][1] >= fog->bounds[0][1]
262 && bounds[1][2] >= fog->bounds[0][2]
263 && bounds[0][0] <= fog->bounds[1][0]
264 && bounds[0][1] <= fog->bounds[1][1]
265 && bounds[0][2] <= fog->bounds[1][2] ) {
266 break;
267 }
268 }
269 if ( fogIndex == tr.world->numfogs ) {
270 fogIndex = 0;
271 }
272 }
273 poly->fogIndex = fogIndex;
274 }
275 }
276 // done.
277
278
279 //=================================================================================
280
281
282 /*
283 =====================
284 RE_AddRefEntityToScene
285
286 =====================
287 */
RE_AddRefEntityToScene(const refEntity_t * ent)288 void RE_AddRefEntityToScene( const refEntity_t *ent ) {
289 vec3_t cross;
290
291 if ( !tr.registered ) {
292 return;
293 }
294 // show_bug.cgi?id=402
295 if ( r_numentities >= MAX_REFENTITIES ) {
296 ri.Printf(PRINT_DEVELOPER, "RE_AddRefEntityToScene: Dropping refEntity, reached MAX_REFENTITIES\n");
297 return;
298 }
299 if ( Q_isnan(ent->origin[0]) || Q_isnan(ent->origin[1]) || Q_isnan(ent->origin[2]) ) {
300 static qboolean firstTime = qtrue;
301 if (firstTime) {
302 firstTime = qfalse;
303 ri.Printf( PRINT_WARNING, "RE_AddRefEntityToScene passed a refEntity which has an origin with a NaN component\n");
304 }
305 return;
306 }
307 if ( (int)ent->reType < 0 || ent->reType >= RT_MAX_REF_ENTITY_TYPE ) {
308 ri.Error( ERR_DROP, "RE_AddRefEntityToScene: bad reType %i", ent->reType );
309 }
310
311 backEndData->entities[r_numentities].e = *ent;
312 backEndData->entities[r_numentities].lightingCalculated = qfalse;
313
314 CrossProduct(ent->axis[0], ent->axis[1], cross);
315 backEndData->entities[r_numentities].mirrored = (DotProduct(ent->axis[2], cross) < 0.f);
316
317 r_numentities++;
318 }
319
320 // Ridah, added support for overdraw field
321 /*
322 =====================
323 RE_AddLightToScene
324
325 =====================
326 */
RE_AddLightToScene(const vec3_t org,float intensity,float r,float g,float b,int overdraw)327 void RE_AddLightToScene( const vec3_t org, float intensity, float r, float g, float b, int overdraw ) {
328 dlight_t *dl;
329
330 if ( !tr.registered ) {
331 return;
332 }
333 if ( r_numdlights >= MAX_DLIGHTS ) {
334 return;
335 }
336 if ( intensity <= 0 ) {
337 return;
338 }
339 // these cards don't have the correct blend mode
340 if ( glConfig.hardwareType == GLHW_RIVA128 || glConfig.hardwareType == GLHW_PERMEDIA2 ) {
341 return;
342 }
343 // RF, allow us to force some dlights under all circumstances
344 if ( !( overdraw & REF_FORCE_DLIGHT ) ) {
345 if ( r_dynamiclight->integer == 0 ) {
346 return;
347 }
348 if ( r_dynamiclight->integer == 2 && !( backEndData->dlights[r_numdlights].forced ) ) {
349 return;
350 }
351 }
352
353 if ( r_dlightScale->value <= 0 ) { //----(SA) added
354 return;
355 }
356
357 overdraw &= ~REF_FORCE_DLIGHT;
358 overdraw &= ~REF_JUNIOR_DLIGHT;
359
360 dl = &backEndData->dlights[r_numdlights++];
361 VectorCopy( org, dl->origin );
362
363 dl->radius = intensity * r_dlightScale->value; //----(SA) modified
364 dl->color[0] = r;
365 dl->color[1] = g;
366 dl->color[2] = b;
367 dl->dlshader = NULL;
368 dl->overdraw = 0;
369
370 if ( overdraw == 10 ) { // sorry, hijacking 10 for a quick hack (SA)
371 dl->dlshader = R_GetShaderByHandle( RE_RegisterShader( "negdlightshader" ) );
372 } else if ( overdraw == 11 ) { // 11 is flames
373 dl->dlshader = R_GetShaderByHandle( RE_RegisterShader( "flamedlightshader" ) );
374 } else {
375 dl->overdraw = overdraw;
376 }
377 }
378 // done.
379
380
381 /*
382 ==============
383 RE_AddCoronaToScene
384 ==============
385 */
RE_AddCoronaToScene(const vec3_t org,float r,float g,float b,float scale,int id,int flags)386 void RE_AddCoronaToScene( const vec3_t org, float r, float g, float b, float scale, int id, int flags ) {
387 corona_t *cor;
388
389 if ( !tr.registered ) {
390 return;
391 }
392 if ( r_numcoronas >= MAX_CORONAS ) {
393 return;
394 }
395
396 cor = &backEndData->coronas[r_numcoronas++];
397 VectorCopy( org, cor->origin );
398 cor->color[0] = r;
399 cor->color[1] = g;
400 cor->color[2] = b;
401 cor->scale = scale;
402 cor->id = id;
403 cor->flags = flags;
404 }
405
RE_BeginScene(const refdef_t * fd)406 void RE_BeginScene(const refdef_t *fd)
407 {
408 memcpy( tr.refdef.text, fd->text, sizeof( tr.refdef.text ) );
409
410 tr.refdef.x = fd->x;
411 tr.refdef.y = fd->y;
412 tr.refdef.width = fd->width;
413 tr.refdef.height = fd->height;
414 tr.refdef.fov_x = fd->fov_x;
415 tr.refdef.fov_y = fd->fov_y;
416
417 VectorCopy( fd->vieworg, tr.refdef.vieworg );
418 VectorCopy( fd->viewaxis[0], tr.refdef.viewaxis[0] );
419 VectorCopy( fd->viewaxis[1], tr.refdef.viewaxis[1] );
420 VectorCopy( fd->viewaxis[2], tr.refdef.viewaxis[2] );
421
422 tr.refdef.time = fd->time;
423 tr.refdef.rdflags = fd->rdflags;
424
425 if ( fd->rdflags & RDF_SKYBOXPORTAL ) {
426 skyboxportal = 1;
427 }
428
429 if ( fd->rdflags & RDF_DRAWSKYBOX ) {
430 drawskyboxportal = 1;
431 } else {
432 drawskyboxportal = 0;
433 }
434
435 // copy the areamask data over and note if it has changed, which
436 // will force a reset of the visible leafs even if the view hasn't moved
437 tr.refdef.areamaskModified = qfalse;
438 if ( !( tr.refdef.rdflags & RDF_NOWORLDMODEL ) ) {
439 int areaDiff;
440 int i;
441
442 // compare the area bits
443 areaDiff = 0;
444 for ( i = 0 ; i < MAX_MAP_AREA_BYTES / 4 ; i++ ) {
445 areaDiff |= ( (int *)tr.refdef.areamask )[i] ^ ( (int *)fd->areamask )[i];
446 ( (int *)tr.refdef.areamask )[i] = ( (int *)fd->areamask )[i];
447 }
448
449 if ( areaDiff ) {
450 // a door just opened or something
451 tr.refdef.areamaskModified = qtrue;
452 }
453 }
454
455 tr.refdef.sunDir[3] = 0.0f;
456 tr.refdef.sunCol[3] = 1.0f;
457 tr.refdef.sunAmbCol[3] = 1.0f;
458
459 VectorCopy(tr.sunDirection, tr.refdef.sunDir);
460 if ( (tr.refdef.rdflags & RDF_NOWORLDMODEL) || !(r_depthPrepass->value) ){
461 VectorSet(tr.refdef.sunCol, 0, 0, 0);
462 VectorSet(tr.refdef.sunAmbCol, 0, 0, 0);
463 }
464 else
465 {
466 float scale = (1 << r_mapOverBrightBits->integer) / 255.0f;
467
468 if (r_forceSun->integer)
469 VectorScale(tr.sunLight, scale * r_forceSunLightScale->value, tr.refdef.sunCol);
470 else
471 VectorScale(tr.sunLight, scale, tr.refdef.sunCol);
472
473 if (r_sunlightMode->integer == 1)
474 {
475 tr.refdef.sunAmbCol[0] =
476 tr.refdef.sunAmbCol[1] =
477 tr.refdef.sunAmbCol[2] = r_forceSun->integer ? r_forceSunAmbientScale->value : tr.sunShadowScale;
478 }
479 else
480 {
481 if (r_forceSun->integer)
482 VectorScale(tr.sunLight, scale * r_forceSunAmbientScale->value, tr.refdef.sunAmbCol);
483 else
484 VectorScale(tr.sunLight, scale * tr.sunShadowScale, tr.refdef.sunAmbCol);
485 }
486 }
487
488 if (r_forceAutoExposure->integer)
489 {
490 tr.refdef.autoExposureMinMax[0] = r_forceAutoExposureMin->value;
491 tr.refdef.autoExposureMinMax[1] = r_forceAutoExposureMax->value;
492 }
493 else
494 {
495 tr.refdef.autoExposureMinMax[0] = tr.autoExposureMinMax[0];
496 tr.refdef.autoExposureMinMax[1] = tr.autoExposureMinMax[1];
497 }
498
499 if (r_forceToneMap->integer)
500 {
501 tr.refdef.toneMinAvgMaxLinear[0] = pow(2, r_forceToneMapMin->value);
502 tr.refdef.toneMinAvgMaxLinear[1] = pow(2, r_forceToneMapAvg->value);
503 tr.refdef.toneMinAvgMaxLinear[2] = pow(2, r_forceToneMapMax->value);
504 }
505 else
506 {
507 tr.refdef.toneMinAvgMaxLinear[0] = pow(2, tr.toneMinAvgMaxLevel[0]);
508 tr.refdef.toneMinAvgMaxLinear[1] = pow(2, tr.toneMinAvgMaxLevel[1]);
509 tr.refdef.toneMinAvgMaxLinear[2] = pow(2, tr.toneMinAvgMaxLevel[2]);
510 }
511
512 // Makro - copy exta info if present
513 if (fd->rdflags & RDF_EXTRA) {
514 const refdefex_t* extra = (const refdefex_t*) (fd+1);
515
516 tr.refdef.blurFactor = extra->blurFactor;
517
518 if (fd->rdflags & RDF_SUNLIGHT)
519 {
520 VectorCopy(extra->sunDir, tr.refdef.sunDir);
521 VectorCopy(extra->sunCol, tr.refdef.sunCol);
522 VectorCopy(extra->sunAmbCol, tr.refdef.sunAmbCol);
523 }
524 }
525 else
526 {
527 tr.refdef.blurFactor = 0.0f;
528 }
529
530 // derived info
531
532 tr.refdef.floatTime = tr.refdef.time * 0.001;
533
534 tr.refdef.numDrawSurfs = r_firstSceneDrawSurf;
535 tr.refdef.drawSurfs = backEndData->drawSurfs;
536
537 tr.refdef.num_entities = r_numentities - r_firstSceneEntity;
538 tr.refdef.entities = &backEndData->entities[r_firstSceneEntity];
539
540 tr.refdef.num_dlights = r_numdlights - r_firstSceneDlight;
541 tr.refdef.dlights = &backEndData->dlights[r_firstSceneDlight];
542
543 tr.refdef.num_coronas = r_numcoronas - r_firstSceneCorona;
544 tr.refdef.coronas = &backEndData->coronas[r_firstSceneCorona];
545
546 tr.refdef.numPolys = r_numpolys - r_firstScenePoly;
547 tr.refdef.polys = &backEndData->polys[r_firstScenePoly];
548
549 tr.refdef.num_pshadows = 0;
550 tr.refdef.pshadows = &backEndData->pshadows[0];
551
552 // turn off dynamic lighting globally by clearing all the
553 // dlights if it needs to be disabled or if vertex lighting is enabled
554 if ( /*r_dynamiclight->integer == 0 ||*/ // RF, disabled so we can force things like lightning dlights
555 r_vertexLight->integer == 1 ||
556 glConfig.hardwareType == GLHW_PERMEDIA2 ) {
557 tr.refdef.num_dlights = 0;
558 }
559
560 // a single frame may have multiple scenes draw inside it --
561 // a 3D game view, 3D status bar renderings, 3D menus, etc.
562 // They need to be distinguished by the light flare code, because
563 // the visibility state for a given surface may be different in
564 // each scene / view.
565 tr.frameSceneNum++;
566 tr.sceneCount++;
567 }
568
RE_EndScene(void)569 void RE_EndScene(void)
570 {
571 // the next scene rendered in this frame will tack on after this one
572 r_firstSceneDrawSurf = tr.refdef.numDrawSurfs;
573 r_firstSceneEntity = r_numentities;
574 r_firstSceneDlight = r_numdlights;
575 r_firstScenePoly = r_numpolys;
576 }
577
578 /*
579 @@@@@@@@@@@@@@@@@@@@@
580 RE_RenderScene
581
582 Draw a 3D view into a part of the window, then return
583 to 2D drawing.
584
585 Rendering a scene may require multiple views to be rendered
586 to handle mirrors,
587 @@@@@@@@@@@@@@@@@@@@@
588 */
RE_RenderScene(const refdef_t * fd)589 void RE_RenderScene( const refdef_t *fd ) {
590 viewParms_t parms;
591 int startTime;
592
593 if ( !tr.registered ) {
594 return;
595 }
596 GLimp_LogComment( "====== RE_RenderScene =====\n" );
597
598 if ( r_norefresh->integer ) {
599 return;
600 }
601
602 startTime = ri.Milliseconds();
603
604 if (!tr.world && !( fd->rdflags & RDF_NOWORLDMODEL ) ) {
605 ri.Error (ERR_DROP, "R_RenderScene: NULL worldmodel");
606 }
607
608 RE_BeginScene(fd);
609
610 // SmileTheory: playing with shadow mapping
611 if (!( fd->rdflags & RDF_NOWORLDMODEL ) && tr.refdef.num_dlights && r_dlightMode->integer >= 2)
612 {
613 R_RenderDlightCubemaps(fd);
614 }
615
616 /* playing with more shadows */
617 if(glRefConfig.framebufferObject && !( fd->rdflags & RDF_NOWORLDMODEL ) && r_shadows->integer == 4)
618 {
619 R_RenderPshadowMaps(fd);
620 }
621
622 // playing with even more shadows
623 if(glRefConfig.framebufferObject && r_sunlightMode->integer && !( fd->rdflags & RDF_NOWORLDMODEL ) && (r_forceSun->integer || tr.sunShadows))
624 {
625 if (r_shadowCascadeZFar->integer != 0)
626 {
627 R_RenderSunShadowMaps(fd, 0);
628 R_RenderSunShadowMaps(fd, 1);
629 R_RenderSunShadowMaps(fd, 2);
630 }
631 else
632 {
633 Mat4Zero(tr.refdef.sunShadowMvp[0]);
634 Mat4Zero(tr.refdef.sunShadowMvp[1]);
635 Mat4Zero(tr.refdef.sunShadowMvp[2]);
636 }
637
638 // only rerender last cascade if sun has changed position
639 if (r_forceSun->integer == 2 || !VectorCompare(tr.refdef.sunDir, tr.lastCascadeSunDirection))
640 {
641 VectorCopy(tr.refdef.sunDir, tr.lastCascadeSunDirection);
642 R_RenderSunShadowMaps(fd, 3);
643 Mat4Copy(tr.refdef.sunShadowMvp[3], tr.lastCascadeSunMvp);
644 }
645 else
646 {
647 Mat4Copy(tr.lastCascadeSunMvp, tr.refdef.sunShadowMvp[3]);
648 }
649 }
650
651 // playing with cube maps
652 // this is where dynamic cubemaps would be rendered
653 if (0) //(glRefConfig.framebufferObject && !( fd->rdflags & RDF_NOWORLDMODEL ))
654 {
655 int i, j;
656
657 for (i = 0; i < tr.numCubemaps; i++)
658 {
659 for (j = 0; j < 6; j++)
660 {
661 R_RenderCubemapSide(i, j, qtrue);
662 }
663 }
664 }
665
666 // setup view parms for the initial view
667 //
668 // set up viewport
669 // The refdef takes 0-at-the-top y coordinates, so
670 // convert to GL's 0-at-the-bottom space
671 //
672 memset( &parms, 0, sizeof( parms ) );
673 parms.viewportX = tr.refdef.x;
674 parms.viewportY = glConfig.vidHeight - ( tr.refdef.y + tr.refdef.height );
675 parms.viewportWidth = tr.refdef.width;
676 parms.viewportHeight = tr.refdef.height;
677 parms.isPortal = qfalse;
678
679 parms.fovX = tr.refdef.fov_x;
680 parms.fovY = tr.refdef.fov_y;
681
682 parms.stereoFrame = tr.refdef.stereoFrame;
683
684 VectorCopy( fd->vieworg, parms.or.origin );
685 VectorCopy( fd->viewaxis[0], parms.or.axis[0] );
686 VectorCopy( fd->viewaxis[1], parms.or.axis[1] );
687 VectorCopy( fd->viewaxis[2], parms.or.axis[2] );
688
689 VectorCopy( fd->vieworg, parms.pvsOrigin );
690
691 if(!( fd->rdflags & RDF_NOWORLDMODEL ) && r_depthPrepass->value && ((r_forceSun->integer) || tr.sunShadows))
692 {
693 parms.flags = VPF_USESUNLIGHT;
694 }
695
696 R_RenderView( &parms );
697
698 if(!( fd->rdflags & RDF_NOWORLDMODEL ))
699 R_AddPostProcessCmd();
700
701 RE_EndScene();
702
703 tr.frontEndMsec += ri.Milliseconds() - startTime;
704 }
705