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