1 /*
2 ===========================================================================
3
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6
7 This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
8
9 Doom 3 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 Doom 3 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 Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
21
22 In addition, the Doom 3 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 Doom 3 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 #include "sys/platform.h"
30 #include "renderer/VertexCache.h"
31
32 #include "renderer/tr_local.h"
33
34 extern idCVar r_useCarmacksReverse;
35 extern idCVar r_useStencilOpSeparate;
36 /*
37 =====================
38 RB_BakeTextureMatrixIntoTexgen
39 =====================
40 */
RB_BakeTextureMatrixIntoTexgen(idPlane lightProject[3],const float * textureMatrix)41 void RB_BakeTextureMatrixIntoTexgen( idPlane lightProject[3], const float *textureMatrix ) {
42 float genMatrix[16];
43 float final[16];
44
45 genMatrix[0] = lightProject[0][0];
46 genMatrix[4] = lightProject[0][1];
47 genMatrix[8] = lightProject[0][2];
48 genMatrix[12] = lightProject[0][3];
49
50 genMatrix[1] = lightProject[1][0];
51 genMatrix[5] = lightProject[1][1];
52 genMatrix[9] = lightProject[1][2];
53 genMatrix[13] = lightProject[1][3];
54
55 genMatrix[2] = 0;
56 genMatrix[6] = 0;
57 genMatrix[10] = 0;
58 genMatrix[14] = 0;
59
60 genMatrix[3] = lightProject[2][0];
61 genMatrix[7] = lightProject[2][1];
62 genMatrix[11] = lightProject[2][2];
63 genMatrix[15] = lightProject[2][3];
64
65 myGlMultMatrix( genMatrix, backEnd.lightTextureMatrix, final );
66
67 lightProject[0][0] = final[0];
68 lightProject[0][1] = final[4];
69 lightProject[0][2] = final[8];
70 lightProject[0][3] = final[12];
71
72 lightProject[1][0] = final[1];
73 lightProject[1][1] = final[5];
74 lightProject[1][2] = final[9];
75 lightProject[1][3] = final[13];
76 }
77
78 /*
79 ================
80 RB_PrepareStageTexturing
81 ================
82 */
RB_PrepareStageTexturing(const shaderStage_t * pStage,const drawSurf_t * surf,idDrawVert * ac)83 void RB_PrepareStageTexturing( const shaderStage_t *pStage, const drawSurf_t *surf, idDrawVert *ac ) {
84 // set privatePolygonOffset if necessary
85 if ( pStage->privatePolygonOffset ) {
86 qglEnable( GL_POLYGON_OFFSET_FILL );
87 qglPolygonOffset( r_offsetFactor.GetFloat(), r_offsetUnits.GetFloat() * pStage->privatePolygonOffset );
88 }
89
90 // set the texture matrix if needed
91 if ( pStage->texture.hasMatrix ) {
92 RB_LoadShaderTextureMatrix( surf->shaderRegisters, &pStage->texture );
93 }
94
95 // texgens
96 if ( pStage->texture.texgen == TG_DIFFUSE_CUBE ) {
97 qglTexCoordPointer( 3, GL_FLOAT, sizeof( idDrawVert ), ac->normal.ToFloatPtr() );
98 }
99 if ( pStage->texture.texgen == TG_SKYBOX_CUBE || pStage->texture.texgen == TG_WOBBLESKY_CUBE ) {
100 qglTexCoordPointer( 3, GL_FLOAT, 0, vertexCache.Position( surf->dynamicTexCoords ) );
101 }
102 if ( pStage->texture.texgen == TG_SCREEN ) {
103 qglEnable( GL_TEXTURE_GEN_S );
104 qglEnable( GL_TEXTURE_GEN_T );
105 qglEnable( GL_TEXTURE_GEN_Q );
106
107 float mat[16], plane[4];
108 myGlMultMatrix( surf->space->modelViewMatrix, backEnd.viewDef->projectionMatrix, mat );
109
110 plane[0] = mat[0];
111 plane[1] = mat[4];
112 plane[2] = mat[8];
113 plane[3] = mat[12];
114 qglTexGenfv( GL_S, GL_OBJECT_PLANE, plane );
115
116 plane[0] = mat[1];
117 plane[1] = mat[5];
118 plane[2] = mat[9];
119 plane[3] = mat[13];
120 qglTexGenfv( GL_T, GL_OBJECT_PLANE, plane );
121
122 plane[0] = mat[3];
123 plane[1] = mat[7];
124 plane[2] = mat[11];
125 plane[3] = mat[15];
126 qglTexGenfv( GL_Q, GL_OBJECT_PLANE, plane );
127 }
128
129 if ( pStage->texture.texgen == TG_SCREEN2 ) {
130 qglEnable( GL_TEXTURE_GEN_S );
131 qglEnable( GL_TEXTURE_GEN_T );
132 qglEnable( GL_TEXTURE_GEN_Q );
133
134 float mat[16], plane[4];
135 myGlMultMatrix( surf->space->modelViewMatrix, backEnd.viewDef->projectionMatrix, mat );
136
137 plane[0] = mat[0];
138 plane[1] = mat[4];
139 plane[2] = mat[8];
140 plane[3] = mat[12];
141 qglTexGenfv( GL_S, GL_OBJECT_PLANE, plane );
142
143 plane[0] = mat[1];
144 plane[1] = mat[5];
145 plane[2] = mat[9];
146 plane[3] = mat[13];
147 qglTexGenfv( GL_T, GL_OBJECT_PLANE, plane );
148
149 plane[0] = mat[3];
150 plane[1] = mat[7];
151 plane[2] = mat[11];
152 plane[3] = mat[15];
153 qglTexGenfv( GL_Q, GL_OBJECT_PLANE, plane );
154 }
155
156 if ( pStage->texture.texgen == TG_GLASSWARP ) {
157 if ( tr.backEndRenderer == BE_ARB2 /*|| tr.backEndRenderer == BE_NV30*/ ) {
158 qglBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, FPROG_GLASSWARP );
159 qglEnable( GL_FRAGMENT_PROGRAM_ARB );
160
161 GL_SelectTexture( 2 );
162 globalImages->scratchImage->Bind();
163
164 GL_SelectTexture( 1 );
165 globalImages->scratchImage2->Bind();
166
167 qglEnable( GL_TEXTURE_GEN_S );
168 qglEnable( GL_TEXTURE_GEN_T );
169 qglEnable( GL_TEXTURE_GEN_Q );
170
171 float mat[16], plane[4];
172 myGlMultMatrix( surf->space->modelViewMatrix, backEnd.viewDef->projectionMatrix, mat );
173
174 plane[0] = mat[0];
175 plane[1] = mat[4];
176 plane[2] = mat[8];
177 plane[3] = mat[12];
178 qglTexGenfv( GL_S, GL_OBJECT_PLANE, plane );
179
180 plane[0] = mat[1];
181 plane[1] = mat[5];
182 plane[2] = mat[9];
183 plane[3] = mat[13];
184 qglTexGenfv( GL_T, GL_OBJECT_PLANE, plane );
185
186 plane[0] = mat[3];
187 plane[1] = mat[7];
188 plane[2] = mat[11];
189 plane[3] = mat[15];
190 qglTexGenfv( GL_Q, GL_OBJECT_PLANE, plane );
191
192 GL_SelectTexture( 0 );
193 }
194 }
195
196 if ( pStage->texture.texgen == TG_REFLECT_CUBE ) {
197 if ( tr.backEndRenderer == BE_ARB2 ) {
198 // see if there is also a bump map specified
199 const shaderStage_t *bumpStage = surf->material->GetBumpStage();
200 if ( bumpStage ) {
201 // per-pixel reflection mapping with bump mapping
202 GL_SelectTexture( 1 );
203 bumpStage->texture.image->Bind();
204 GL_SelectTexture( 0 );
205
206 qglNormalPointer( GL_FLOAT, sizeof( idDrawVert ), ac->normal.ToFloatPtr() );
207 qglVertexAttribPointerARB( 10, 3, GL_FLOAT, false, sizeof( idDrawVert ), ac->tangents[1].ToFloatPtr() );
208 qglVertexAttribPointerARB( 9, 3, GL_FLOAT, false, sizeof( idDrawVert ), ac->tangents[0].ToFloatPtr() );
209
210 qglEnableVertexAttribArrayARB( 9 );
211 qglEnableVertexAttribArrayARB( 10 );
212 qglEnableClientState( GL_NORMAL_ARRAY );
213
214 // Program env 5, 6, 7, 8 have been set in RB_SetProgramEnvironmentSpace
215
216 qglBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, FPROG_BUMPY_ENVIRONMENT );
217 qglEnable( GL_FRAGMENT_PROGRAM_ARB );
218 qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, VPROG_BUMPY_ENVIRONMENT );
219 qglEnable( GL_VERTEX_PROGRAM_ARB );
220 } else {
221 // per-pixel reflection mapping without a normal map
222 qglNormalPointer( GL_FLOAT, sizeof( idDrawVert ), ac->normal.ToFloatPtr() );
223 qglEnableClientState( GL_NORMAL_ARRAY );
224
225 qglBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, FPROG_ENVIRONMENT );
226 qglEnable( GL_FRAGMENT_PROGRAM_ARB );
227 qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, VPROG_ENVIRONMENT );
228 qglEnable( GL_VERTEX_PROGRAM_ARB );
229 }
230 } else {
231 qglEnable( GL_TEXTURE_GEN_S );
232 qglEnable( GL_TEXTURE_GEN_T );
233 qglEnable( GL_TEXTURE_GEN_R );
234 qglTexGenf( GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_EXT );
235 qglTexGenf( GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_EXT );
236 qglTexGenf( GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_EXT );
237 qglEnableClientState( GL_NORMAL_ARRAY );
238 qglNormalPointer( GL_FLOAT, sizeof( idDrawVert ), ac->normal.ToFloatPtr() );
239
240 qglMatrixMode( GL_TEXTURE );
241 float mat[16];
242
243 R_TransposeGLMatrix( backEnd.viewDef->worldSpace.modelViewMatrix, mat );
244
245 qglLoadMatrixf( mat );
246 qglMatrixMode( GL_MODELVIEW );
247 }
248 }
249 }
250
251 /*
252 ================
253 RB_FinishStageTexturing
254 ================
255 */
RB_FinishStageTexturing(const shaderStage_t * pStage,const drawSurf_t * surf,idDrawVert * ac)256 void RB_FinishStageTexturing( const shaderStage_t *pStage, const drawSurf_t *surf, idDrawVert *ac ) {
257 // unset privatePolygonOffset if necessary
258 if ( pStage->privatePolygonOffset && !surf->material->TestMaterialFlag(MF_POLYGONOFFSET) ) {
259 qglDisable( GL_POLYGON_OFFSET_FILL );
260 }
261
262 if ( pStage->texture.texgen == TG_DIFFUSE_CUBE || pStage->texture.texgen == TG_SKYBOX_CUBE
263 || pStage->texture.texgen == TG_WOBBLESKY_CUBE ) {
264 qglTexCoordPointer( 2, GL_FLOAT, sizeof( idDrawVert ), (void *)&ac->st );
265 }
266
267 if ( pStage->texture.texgen == TG_SCREEN ) {
268 qglDisable( GL_TEXTURE_GEN_S );
269 qglDisable( GL_TEXTURE_GEN_T );
270 qglDisable( GL_TEXTURE_GEN_Q );
271 }
272 if ( pStage->texture.texgen == TG_SCREEN2 ) {
273 qglDisable( GL_TEXTURE_GEN_S );
274 qglDisable( GL_TEXTURE_GEN_T );
275 qglDisable( GL_TEXTURE_GEN_Q );
276 }
277
278 if ( pStage->texture.texgen == TG_GLASSWARP ) {
279 if ( tr.backEndRenderer == BE_ARB2 /*|| tr.backEndRenderer == BE_NV30*/ ) {
280 GL_SelectTexture( 2 );
281 globalImages->BindNull();
282
283 GL_SelectTexture( 1 );
284 if ( pStage->texture.hasMatrix ) {
285 RB_LoadShaderTextureMatrix( surf->shaderRegisters, &pStage->texture );
286 }
287 qglDisable( GL_TEXTURE_GEN_S );
288 qglDisable( GL_TEXTURE_GEN_T );
289 qglDisable( GL_TEXTURE_GEN_Q );
290 qglDisable( GL_FRAGMENT_PROGRAM_ARB );
291 globalImages->BindNull();
292 GL_SelectTexture( 0 );
293 }
294 }
295
296 if ( pStage->texture.texgen == TG_REFLECT_CUBE ) {
297 if ( tr.backEndRenderer == BE_ARB2 ) {
298 // see if there is also a bump map specified
299 const shaderStage_t *bumpStage = surf->material->GetBumpStage();
300 if ( bumpStage ) {
301 // per-pixel reflection mapping with bump mapping
302 GL_SelectTexture( 1 );
303 globalImages->BindNull();
304 GL_SelectTexture( 0 );
305
306 qglDisableVertexAttribArrayARB( 9 );
307 qglDisableVertexAttribArrayARB( 10 );
308 } else {
309 // per-pixel reflection mapping without bump mapping
310 }
311
312 qglDisableClientState( GL_NORMAL_ARRAY );
313 qglDisable( GL_FRAGMENT_PROGRAM_ARB );
314 qglDisable( GL_VERTEX_PROGRAM_ARB );
315 // Fixme: Hack to get around an apparent bug in ATI drivers. Should remove as soon as it gets fixed.
316 qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, 0 );
317 } else {
318 qglDisable( GL_TEXTURE_GEN_S );
319 qglDisable( GL_TEXTURE_GEN_T );
320 qglDisable( GL_TEXTURE_GEN_R );
321 qglTexGenf( GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
322 qglTexGenf( GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
323 qglTexGenf( GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
324 qglDisableClientState( GL_NORMAL_ARRAY );
325
326 qglMatrixMode( GL_TEXTURE );
327 qglLoadIdentity();
328 qglMatrixMode( GL_MODELVIEW );
329 }
330 }
331
332 if ( pStage->texture.hasMatrix ) {
333 qglMatrixMode( GL_TEXTURE );
334 qglLoadIdentity();
335 qglMatrixMode( GL_MODELVIEW );
336 }
337 }
338
339 /*
340 =============================================================================================
341
342 FILL DEPTH BUFFER
343
344 =============================================================================================
345 */
346
347
348 /*
349 ==================
350 RB_T_FillDepthBuffer
351 ==================
352 */
RB_T_FillDepthBuffer(const drawSurf_t * surf)353 void RB_T_FillDepthBuffer( const drawSurf_t *surf ) {
354 int stage;
355 const idMaterial *shader;
356 const shaderStage_t *pStage;
357 const float *regs;
358 float color[4];
359 const srfTriangles_t *tri;
360
361 tri = surf->geo;
362 shader = surf->material;
363
364 // update the clip plane if needed
365 if ( backEnd.viewDef->numClipPlanes && surf->space != backEnd.currentSpace ) {
366 GL_SelectTexture( 1 );
367
368 idPlane plane;
369
370 R_GlobalPlaneToLocal( surf->space->modelMatrix, backEnd.viewDef->clipPlanes[0], plane );
371 plane[3] += 0.5; // the notch is in the middle
372 qglTexGenfv( GL_S, GL_OBJECT_PLANE, plane.ToFloatPtr() );
373 GL_SelectTexture( 0 );
374 }
375
376 if ( !shader->IsDrawn() ) {
377 return;
378 }
379
380 // some deforms may disable themselves by setting numIndexes = 0
381 if ( !tri->numIndexes ) {
382 return;
383 }
384
385 // translucent surfaces don't put anything in the depth buffer and don't
386 // test against it, which makes them fail the mirror clip plane operation
387 if ( shader->Coverage() == MC_TRANSLUCENT ) {
388 return;
389 }
390
391 if ( !tri->ambientCache ) {
392 common->Printf( "RB_T_FillDepthBuffer: !tri->ambientCache\n" );
393 return;
394 }
395
396 // get the expressions for conditionals / color / texcoords
397 regs = surf->shaderRegisters;
398
399 // if all stages of a material have been conditioned off, don't do anything
400 for ( stage = 0; stage < shader->GetNumStages() ; stage++ ) {
401 pStage = shader->GetStage(stage);
402 // check the stage enable condition
403 if ( regs[ pStage->conditionRegister ] != 0 ) {
404 break;
405 }
406 }
407 if ( stage == shader->GetNumStages() ) {
408 return;
409 }
410
411 // set polygon offset if necessary
412 if ( shader->TestMaterialFlag(MF_POLYGONOFFSET) ) {
413 qglEnable( GL_POLYGON_OFFSET_FILL );
414 qglPolygonOffset( r_offsetFactor.GetFloat(), r_offsetUnits.GetFloat() * shader->GetPolygonOffset() );
415 }
416
417 // subviews will just down-modulate the color buffer by overbright
418 if ( shader->GetSort() == SS_SUBVIEW ) {
419 GL_State( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO | GLS_DEPTHFUNC_LESS );
420 color[0] =
421 color[1] =
422 color[2] = ( 1.0 / backEnd.overBright );
423 color[3] = 1;
424 } else {
425 // others just draw black
426 color[0] = 0;
427 color[1] = 0;
428 color[2] = 0;
429 color[3] = 1;
430 }
431
432 idDrawVert *ac = (idDrawVert *)vertexCache.Position( tri->ambientCache );
433 qglVertexPointer( 3, GL_FLOAT, sizeof( idDrawVert ), ac->xyz.ToFloatPtr() );
434 qglTexCoordPointer( 2, GL_FLOAT, sizeof( idDrawVert ), reinterpret_cast<void *>(&ac->st) );
435
436 bool drawSolid = false;
437
438 if ( shader->Coverage() == MC_OPAQUE ) {
439 drawSolid = true;
440 }
441
442 // we may have multiple alpha tested stages
443 if ( shader->Coverage() == MC_PERFORATED ) {
444 // if the only alpha tested stages are condition register omitted,
445 // draw a normal opaque surface
446 bool didDraw = false;
447
448 qglEnable( GL_ALPHA_TEST );
449 // perforated surfaces may have multiple alpha tested stages
450 for ( stage = 0; stage < shader->GetNumStages() ; stage++ ) {
451 pStage = shader->GetStage(stage);
452
453 if ( !pStage->hasAlphaTest ) {
454 continue;
455 }
456
457 // check the stage enable condition
458 if ( regs[ pStage->conditionRegister ] == 0 ) {
459 continue;
460 }
461
462 // if we at least tried to draw an alpha tested stage,
463 // we won't draw the opaque surface
464 didDraw = true;
465
466 // set the alpha modulate
467 color[3] = regs[ pStage->color.registers[3] ];
468
469 // skip the entire stage if alpha would be black
470 if ( color[3] <= 0 ) {
471 continue;
472 }
473 qglColor4fv( color );
474
475 qglAlphaFunc( GL_GREATER, regs[ pStage->alphaTestRegister ] );
476
477 // bind the texture
478 pStage->texture.image->Bind();
479
480 // set texture matrix and texGens
481 RB_PrepareStageTexturing( pStage, surf, ac );
482
483 // draw it
484 RB_DrawElementsWithCounters( tri );
485
486 RB_FinishStageTexturing( pStage, surf, ac );
487 }
488 qglDisable( GL_ALPHA_TEST );
489 if ( !didDraw ) {
490 drawSolid = true;
491 }
492 }
493
494 // draw the entire surface solid
495 if ( drawSolid ) {
496 qglColor4fv( color );
497 globalImages->whiteImage->Bind();
498
499 // draw it
500 RB_DrawElementsWithCounters( tri );
501 }
502
503
504 // reset polygon offset
505 if ( shader->TestMaterialFlag(MF_POLYGONOFFSET) ) {
506 qglDisable( GL_POLYGON_OFFSET_FILL );
507 }
508
509 // reset blending
510 if ( shader->GetSort() == SS_SUBVIEW ) {
511 GL_State( GLS_DEPTHFUNC_LESS );
512 }
513
514 }
515
516 /*
517 =====================
518 RB_STD_FillDepthBuffer
519
520 If we are rendering a subview with a near clip plane, use a second texture
521 to force the alpha test to fail when behind that clip plane
522 =====================
523 */
RB_STD_FillDepthBuffer(drawSurf_t ** drawSurfs,int numDrawSurfs)524 void RB_STD_FillDepthBuffer( drawSurf_t **drawSurfs, int numDrawSurfs ) {
525 // if we are just doing 2D rendering, no need to fill the depth buffer
526 if ( !backEnd.viewDef->viewEntitys ) {
527 return;
528 }
529
530 // enable the second texture for mirror plane clipping if needed
531 if ( backEnd.viewDef->numClipPlanes ) {
532 GL_SelectTexture( 1 );
533 globalImages->alphaNotchImage->Bind();
534 qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
535 qglEnable( GL_TEXTURE_GEN_S );
536 qglTexCoord2f( 1, 0.5 );
537 }
538
539 // the first texture will be used for alpha tested surfaces
540 GL_SelectTexture( 0 );
541 qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
542
543 // decal surfaces may enable polygon offset
544 qglPolygonOffset( r_offsetFactor.GetFloat(), r_offsetUnits.GetFloat() );
545
546 GL_State( GLS_DEPTHFUNC_LESS );
547
548 // Enable stencil test if we are going to be using it for shadows.
549 // If we didn't do this, it would be legal behavior to get z fighting
550 // from the ambient pass and the light passes.
551 qglEnable( GL_STENCIL_TEST );
552 qglStencilFunc( GL_ALWAYS, 1, 255 );
553
554 RB_RenderDrawSurfListWithFunction( drawSurfs, numDrawSurfs, RB_T_FillDepthBuffer );
555
556 if ( backEnd.viewDef->numClipPlanes ) {
557 GL_SelectTexture( 1 );
558 globalImages->BindNull();
559 qglDisable( GL_TEXTURE_GEN_S );
560 GL_SelectTexture( 0 );
561 }
562
563 }
564
565 /*
566 =============================================================================================
567
568 SHADER PASSES
569
570 =============================================================================================
571 */
572
573 /*
574 ==================
575 RB_SetProgramEnvironment
576
577 Sets variables that can be used by all vertex programs
578 ==================
579 */
RB_SetProgramEnvironment(void)580 void RB_SetProgramEnvironment( void ) {
581 float parm[4];
582 int pot;
583
584 if ( !glConfig.ARBVertexProgramAvailable ) {
585 return;
586 }
587
588 #if 0
589 // screen power of two correction factor, one pixel in so we don't get a bilerp
590 // of an uncopied pixel
591 int w = backEnd.viewDef->viewport.x2 - backEnd.viewDef->viewport.x1 + 1;
592 pot = globalImages->currentRenderImage->uploadWidth;
593 if ( w == pot ) {
594 parm[0] = 1.0;
595 } else {
596 parm[0] = (float)(w-1) / pot;
597 }
598
599 int h = backEnd.viewDef->viewport.y2 - backEnd.viewDef->viewport.y1 + 1;
600 pot = globalImages->currentRenderImage->uploadHeight;
601 if ( h == pot ) {
602 parm[1] = 1.0;
603 } else {
604 parm[1] = (float)(h-1) / pot;
605 }
606
607 parm[2] = 0;
608 parm[3] = 1;
609 qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, 0, parm );
610 #else
611 // screen power of two correction factor, assuming the copy to _currentRender
612 // also copied an extra row and column for the bilerp
613 int w = backEnd.viewDef->viewport.x2 - backEnd.viewDef->viewport.x1 + 1;
614 pot = globalImages->currentRenderImage->uploadWidth;
615 parm[0] = (float)w / pot;
616
617 int h = backEnd.viewDef->viewport.y2 - backEnd.viewDef->viewport.y1 + 1;
618 pot = globalImages->currentRenderImage->uploadHeight;
619 parm[1] = (float)h / pot;
620
621 parm[2] = 0;
622 parm[3] = 1;
623 qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, 0, parm );
624 #endif
625
626 qglProgramEnvParameter4fvARB( GL_FRAGMENT_PROGRAM_ARB, 0, parm );
627
628 // window coord to 0.0 to 1.0 conversion
629 parm[0] = 1.0 / w;
630 parm[1] = 1.0 / h;
631 parm[2] = 0;
632 parm[3] = 1;
633 qglProgramEnvParameter4fvARB( GL_FRAGMENT_PROGRAM_ARB, 1, parm );
634
635 //
636 // set eye position in global space
637 //
638 parm[0] = backEnd.viewDef->renderView.vieworg[0];
639 parm[1] = backEnd.viewDef->renderView.vieworg[1];
640 parm[2] = backEnd.viewDef->renderView.vieworg[2];
641 parm[3] = 1.0;
642 qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, 1, parm );
643
644
645 }
646
647 /*
648 ==================
649 RB_SetProgramEnvironmentSpace
650
651 Sets variables related to the current space that can be used by all vertex programs
652 ==================
653 */
RB_SetProgramEnvironmentSpace(void)654 void RB_SetProgramEnvironmentSpace( void ) {
655 if ( !glConfig.ARBVertexProgramAvailable ) {
656 return;
657 }
658
659 const struct viewEntity_s *space = backEnd.currentSpace;
660 float parm[4];
661
662 // set eye position in local space
663 R_GlobalPointToLocal( space->modelMatrix, backEnd.viewDef->renderView.vieworg, *(idVec3 *)parm );
664 parm[3] = 1.0;
665 qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, 5, parm );
666
667 // we need the model matrix without it being combined with the view matrix
668 // so we can transform local vectors to global coordinates
669 parm[0] = space->modelMatrix[0];
670 parm[1] = space->modelMatrix[4];
671 parm[2] = space->modelMatrix[8];
672 parm[3] = space->modelMatrix[12];
673 qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, 6, parm );
674 parm[0] = space->modelMatrix[1];
675 parm[1] = space->modelMatrix[5];
676 parm[2] = space->modelMatrix[9];
677 parm[3] = space->modelMatrix[13];
678 qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, 7, parm );
679 parm[0] = space->modelMatrix[2];
680 parm[1] = space->modelMatrix[6];
681 parm[2] = space->modelMatrix[10];
682 parm[3] = space->modelMatrix[14];
683 qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, 8, parm );
684 }
685
686 /*
687 ==================
688 RB_STD_T_RenderShaderPasses
689
690 This is also called for the generated 2D rendering
691 ==================
692 */
RB_STD_T_RenderShaderPasses(const drawSurf_t * surf)693 void RB_STD_T_RenderShaderPasses( const drawSurf_t *surf ) {
694 int stage;
695 const idMaterial *shader;
696 const shaderStage_t *pStage;
697 const float *regs;
698 float color[4];
699 const srfTriangles_t *tri;
700
701 tri = surf->geo;
702 shader = surf->material;
703
704 if ( !shader->HasAmbient() ) {
705 return;
706 }
707
708 if ( shader->IsPortalSky() ) {
709 return;
710 }
711
712 // change the matrix if needed
713 if ( surf->space != backEnd.currentSpace ) {
714 qglLoadMatrixf( surf->space->modelViewMatrix );
715 backEnd.currentSpace = surf->space;
716 RB_SetProgramEnvironmentSpace();
717 }
718
719 // change the scissor if needed
720 if ( r_useScissor.GetBool() && !backEnd.currentScissor.Equals( surf->scissorRect ) ) {
721 backEnd.currentScissor = surf->scissorRect;
722 qglScissor( backEnd.viewDef->viewport.x1 + backEnd.currentScissor.x1,
723 backEnd.viewDef->viewport.y1 + backEnd.currentScissor.y1,
724 backEnd.currentScissor.x2 + 1 - backEnd.currentScissor.x1,
725 backEnd.currentScissor.y2 + 1 - backEnd.currentScissor.y1 );
726 }
727
728 // some deforms may disable themselves by setting numIndexes = 0
729 if ( !tri->numIndexes ) {
730 return;
731 }
732
733 if ( !tri->ambientCache ) {
734 common->Printf( "RB_T_RenderShaderPasses: !tri->ambientCache\n" );
735 return;
736 }
737
738 // get the expressions for conditionals / color / texcoords
739 regs = surf->shaderRegisters;
740
741 // set face culling appropriately
742 GL_Cull( shader->GetCullType() );
743
744 // set polygon offset if necessary
745 if ( shader->TestMaterialFlag(MF_POLYGONOFFSET) ) {
746 qglEnable( GL_POLYGON_OFFSET_FILL );
747 qglPolygonOffset( r_offsetFactor.GetFloat(), r_offsetUnits.GetFloat() * shader->GetPolygonOffset() );
748 }
749
750 if ( surf->space->weaponDepthHack ) {
751 RB_EnterWeaponDepthHack();
752 }
753
754 if ( surf->space->modelDepthHack != 0.0f ) {
755 RB_EnterModelDepthHack( surf->space->modelDepthHack );
756 }
757
758 idDrawVert *ac = (idDrawVert *)vertexCache.Position( tri->ambientCache );
759 qglVertexPointer( 3, GL_FLOAT, sizeof( idDrawVert ), ac->xyz.ToFloatPtr() );
760 qglTexCoordPointer( 2, GL_FLOAT, sizeof( idDrawVert ), reinterpret_cast<void *>(&ac->st) );
761
762 for ( stage = 0; stage < shader->GetNumStages() ; stage++ ) {
763 pStage = shader->GetStage(stage);
764
765 // check the enable condition
766 if ( regs[ pStage->conditionRegister ] == 0 ) {
767 continue;
768 }
769
770 // skip the stages involved in lighting
771 if ( pStage->lighting != SL_AMBIENT ) {
772 continue;
773 }
774
775 // skip if the stage is ( GL_ZERO, GL_ONE ), which is used for some alpha masks
776 if ( ( pStage->drawStateBits & (GLS_SRCBLEND_BITS|GLS_DSTBLEND_BITS) ) == ( GLS_SRCBLEND_ZERO | GLS_DSTBLEND_ONE ) ) {
777 continue;
778 }
779
780 // see if we are a new-style stage
781 newShaderStage_t *newStage = pStage->newStage;
782 if ( newStage ) {
783 //--------------------------
784 //
785 // new style stages
786 //
787 //--------------------------
788
789 // completely skip the stage if we don't have the capability
790 if ( tr.backEndRenderer != BE_ARB2 ) {
791 continue;
792 }
793 if ( r_skipNewAmbient.GetBool() ) {
794 continue;
795 }
796 qglColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( idDrawVert ), (void *)&ac->color );
797 qglVertexAttribPointerARB( 9, 3, GL_FLOAT, false, sizeof( idDrawVert ), ac->tangents[0].ToFloatPtr() );
798 qglVertexAttribPointerARB( 10, 3, GL_FLOAT, false, sizeof( idDrawVert ), ac->tangents[1].ToFloatPtr() );
799 qglNormalPointer( GL_FLOAT, sizeof( idDrawVert ), ac->normal.ToFloatPtr() );
800
801 qglEnableClientState( GL_COLOR_ARRAY );
802 qglEnableVertexAttribArrayARB( 9 );
803 qglEnableVertexAttribArrayARB( 10 );
804 qglEnableClientState( GL_NORMAL_ARRAY );
805
806 GL_State( pStage->drawStateBits );
807
808 qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, newStage->vertexProgram );
809 qglEnable( GL_VERTEX_PROGRAM_ARB );
810
811 // megaTextures bind a lot of images and set a lot of parameters
812 if ( newStage->megaTexture ) {
813 newStage->megaTexture->SetMappingForSurface( tri );
814 idVec3 localViewer;
815 R_GlobalPointToLocal( surf->space->modelMatrix, backEnd.viewDef->renderView.vieworg, localViewer );
816 newStage->megaTexture->BindForViewOrigin( localViewer );
817 }
818
819 for ( int i = 0 ; i < newStage->numVertexParms ; i++ ) {
820 float parm[4];
821 parm[0] = regs[ newStage->vertexParms[i][0] ];
822 parm[1] = regs[ newStage->vertexParms[i][1] ];
823 parm[2] = regs[ newStage->vertexParms[i][2] ];
824 parm[3] = regs[ newStage->vertexParms[i][3] ];
825 qglProgramLocalParameter4fvARB( GL_VERTEX_PROGRAM_ARB, i, parm );
826 }
827
828 for ( int i = 0 ; i < newStage->numFragmentProgramImages ; i++ ) {
829 if ( newStage->fragmentProgramImages[i] ) {
830 GL_SelectTexture( i );
831 newStage->fragmentProgramImages[i]->Bind();
832 }
833 }
834 qglBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, newStage->fragmentProgram );
835 qglEnable( GL_FRAGMENT_PROGRAM_ARB );
836
837 // draw it
838 RB_DrawElementsWithCounters( tri );
839
840 for ( int i = 1 ; i < newStage->numFragmentProgramImages ; i++ ) {
841 if ( newStage->fragmentProgramImages[i] ) {
842 GL_SelectTexture( i );
843 globalImages->BindNull();
844 }
845 }
846 if ( newStage->megaTexture ) {
847 newStage->megaTexture->Unbind();
848 }
849
850 GL_SelectTexture( 0 );
851
852 qglDisable( GL_VERTEX_PROGRAM_ARB );
853 qglDisable( GL_FRAGMENT_PROGRAM_ARB );
854 // Fixme: Hack to get around an apparent bug in ATI drivers. Should remove as soon as it gets fixed.
855 qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, 0 );
856
857 qglDisableClientState( GL_COLOR_ARRAY );
858 qglDisableVertexAttribArrayARB( 9 );
859 qglDisableVertexAttribArrayARB( 10 );
860 qglDisableClientState( GL_NORMAL_ARRAY );
861 continue;
862 }
863
864 //--------------------------
865 //
866 // old style stages
867 //
868 //--------------------------
869
870 // set the color
871 color[0] = regs[ pStage->color.registers[0] ];
872 color[1] = regs[ pStage->color.registers[1] ];
873 color[2] = regs[ pStage->color.registers[2] ];
874 color[3] = regs[ pStage->color.registers[3] ];
875
876 // skip the entire stage if an add would be black
877 if ( ( pStage->drawStateBits & (GLS_SRCBLEND_BITS|GLS_DSTBLEND_BITS) ) == ( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE )
878 && color[0] <= 0 && color[1] <= 0 && color[2] <= 0 ) {
879 continue;
880 }
881
882 // skip the entire stage if a blend would be completely transparent
883 if ( ( pStage->drawStateBits & (GLS_SRCBLEND_BITS|GLS_DSTBLEND_BITS) ) == ( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA )
884 && color[3] <= 0 ) {
885 continue;
886 }
887
888 // select the vertex color source
889 if ( pStage->vertexColor == SVC_IGNORE ) {
890 qglColor4fv( color );
891 } else {
892 qglColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( idDrawVert ), (void *)&ac->color );
893 qglEnableClientState( GL_COLOR_ARRAY );
894
895 if ( pStage->vertexColor == SVC_INVERSE_MODULATE ) {
896 GL_TexEnv( GL_COMBINE_ARB );
897 qglTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE );
898 qglTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE );
899 qglTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB );
900 qglTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR );
901 qglTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_ONE_MINUS_SRC_COLOR );
902 qglTexEnvi( GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1 );
903 }
904
905 // for vertex color and modulated color, we need to enable a second
906 // texture stage
907 if ( color[0] != 1 || color[1] != 1 || color[2] != 1 || color[3] != 1 ) {
908 GL_SelectTexture( 1 );
909
910 globalImages->whiteImage->Bind();
911 GL_TexEnv( GL_COMBINE_ARB );
912
913 qglTexEnvfv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color );
914
915 qglTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE );
916 qglTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB );
917 qglTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_CONSTANT_ARB );
918 qglTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR );
919 qglTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR );
920 qglTexEnvi( GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1 );
921
922 qglTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE );
923 qglTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB );
924 qglTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_CONSTANT_ARB );
925 qglTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA );
926 qglTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA );
927 qglTexEnvi( GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1 );
928
929 GL_SelectTexture( 0 );
930 }
931 }
932
933 // bind the texture
934 RB_BindVariableStageImage( &pStage->texture, regs );
935
936 // set the state
937 GL_State( pStage->drawStateBits );
938
939 RB_PrepareStageTexturing( pStage, surf, ac );
940
941 // draw it
942 RB_DrawElementsWithCounters( tri );
943
944 RB_FinishStageTexturing( pStage, surf, ac );
945
946 if ( pStage->vertexColor != SVC_IGNORE ) {
947 qglDisableClientState( GL_COLOR_ARRAY );
948
949 GL_SelectTexture( 1 );
950 GL_TexEnv( GL_MODULATE );
951 globalImages->BindNull();
952 GL_SelectTexture( 0 );
953 GL_TexEnv( GL_MODULATE );
954 }
955 }
956
957 // reset polygon offset
958 if ( shader->TestMaterialFlag(MF_POLYGONOFFSET) ) {
959 qglDisable( GL_POLYGON_OFFSET_FILL );
960 }
961 if ( surf->space->weaponDepthHack || surf->space->modelDepthHack != 0.0f ) {
962 RB_LeaveDepthHack();
963 }
964 }
965
966 /*
967 =====================
968 RB_STD_DrawShaderPasses
969
970 Draw non-light dependent passes
971 =====================
972 */
RB_STD_DrawShaderPasses(drawSurf_t ** drawSurfs,int numDrawSurfs)973 int RB_STD_DrawShaderPasses( drawSurf_t **drawSurfs, int numDrawSurfs ) {
974 int i;
975
976 // only obey skipAmbient if we are rendering a view
977 if ( backEnd.viewDef->viewEntitys && r_skipAmbient.GetBool() ) {
978 return numDrawSurfs;
979 }
980
981 // if we are about to draw the first surface that needs
982 // the rendering in a texture, copy it over
983 if ( drawSurfs[0]->material->GetSort() >= SS_POST_PROCESS ) {
984 if ( r_skipPostProcess.GetBool() ) {
985 return 0;
986 }
987
988 // only dump if in a 3d view
989 if ( backEnd.viewDef->viewEntitys && tr.backEndRenderer == BE_ARB2 ) {
990 globalImages->currentRenderImage->CopyFramebuffer( backEnd.viewDef->viewport.x1,
991 backEnd.viewDef->viewport.y1, backEnd.viewDef->viewport.x2 - backEnd.viewDef->viewport.x1 + 1,
992 backEnd.viewDef->viewport.y2 - backEnd.viewDef->viewport.y1 + 1, true );
993 }
994 backEnd.currentRenderCopied = true;
995 }
996
997 GL_SelectTexture( 1 );
998 globalImages->BindNull();
999
1000 GL_SelectTexture( 0 );
1001 qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
1002
1003 RB_SetProgramEnvironment();
1004
1005 // we don't use RB_RenderDrawSurfListWithFunction()
1006 // because we want to defer the matrix load because many
1007 // surfaces won't draw any ambient passes
1008 backEnd.currentSpace = NULL;
1009 for (i = 0 ; i < numDrawSurfs ; i++ ) {
1010 if ( drawSurfs[i]->material->SuppressInSubview() ) {
1011 continue;
1012 }
1013
1014 if ( backEnd.viewDef->isXraySubview && drawSurfs[i]->space->entityDef ) {
1015 if ( drawSurfs[i]->space->entityDef->parms.xrayIndex != 2 ) {
1016 continue;
1017 }
1018 }
1019
1020 // we need to draw the post process shaders after we have drawn the fog lights
1021 if ( drawSurfs[i]->material->GetSort() >= SS_POST_PROCESS
1022 && !backEnd.currentRenderCopied ) {
1023 break;
1024 }
1025
1026 RB_STD_T_RenderShaderPasses( drawSurfs[i] );
1027 }
1028
1029 GL_Cull( CT_FRONT_SIDED );
1030 qglColor3f( 1, 1, 1 );
1031
1032 return i;
1033 }
1034
1035
1036
1037 /*
1038 ==============================================================================
1039
1040 BACK END RENDERING OF STENCIL SHADOWS
1041
1042 ==============================================================================
1043 */
1044
1045 /*
1046 =====================
1047 RB_T_Shadow
1048
1049 the shadow volumes face INSIDE
1050 =====================
1051 */
RB_T_Shadow(const drawSurf_t * surf)1052 static void RB_T_Shadow( const drawSurf_t *surf ) {
1053 const srfTriangles_t *tri;
1054
1055 // set the light position if we are using a vertex program to project the rear surfaces
1056 if ( tr.backEndRendererHasVertexPrograms && r_useShadowVertexProgram.GetBool()
1057 && surf->space != backEnd.currentSpace ) {
1058 idVec4 localLight;
1059
1060 R_GlobalPointToLocal( surf->space->modelMatrix, backEnd.vLight->globalLightOrigin, localLight.ToVec3() );
1061 localLight.w = 0.0f;
1062 qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_LIGHT_ORIGIN, localLight.ToFloatPtr() );
1063 }
1064
1065 tri = surf->geo;
1066
1067 if ( !tri->shadowCache ) {
1068 return;
1069 }
1070
1071 qglVertexPointer( 4, GL_FLOAT, sizeof( shadowCache_t ), vertexCache.Position(tri->shadowCache) );
1072
1073 // we always draw the sil planes, but we may not need to draw the front or rear caps
1074 int numIndexes;
1075 bool external = false;
1076
1077 if ( !r_useExternalShadows.GetInteger() ) {
1078 numIndexes = tri->numIndexes;
1079 } else if ( r_useExternalShadows.GetInteger() == 2 ) { // force to no caps for testing
1080 numIndexes = tri->numShadowIndexesNoCaps;
1081 } else if ( !(surf->dsFlags & DSF_VIEW_INSIDE_SHADOW) ) {
1082 // if we aren't inside the shadow projection, no caps are ever needed needed
1083 numIndexes = tri->numShadowIndexesNoCaps;
1084 external = true;
1085 } else if ( !backEnd.vLight->viewInsideLight && !(surf->geo->shadowCapPlaneBits & SHADOW_CAP_INFINITE) ) {
1086 // if we are inside the shadow projection, but outside the light, and drawing
1087 // a non-infinite shadow, we can skip some caps
1088 if ( backEnd.vLight->viewSeesShadowPlaneBits & surf->geo->shadowCapPlaneBits ) {
1089 // we can see through a rear cap, so we need to draw it, but we can skip the
1090 // caps on the actual surface
1091 numIndexes = tri->numShadowIndexesNoFrontCaps;
1092 } else {
1093 // we don't need to draw any caps
1094 numIndexes = tri->numShadowIndexesNoCaps;
1095 }
1096 external = true;
1097 } else {
1098 // must draw everything
1099 numIndexes = tri->numIndexes;
1100 }
1101
1102 // set depth bounds
1103 if( glConfig.depthBoundsTestAvailable && r_useDepthBoundsTest.GetBool() ) {
1104 qglDepthBoundsEXT( surf->scissorRect.zmin, surf->scissorRect.zmax );
1105 }
1106
1107 // debug visualization
1108 if ( r_showShadows.GetInteger() ) {
1109 if ( r_showShadows.GetInteger() == 3 ) {
1110 if ( external ) {
1111 qglColor3f( 0.1/backEnd.overBright, 1/backEnd.overBright, 0.1/backEnd.overBright );
1112 } else {
1113 // these are the surfaces that require the reverse
1114 qglColor3f( 1/backEnd.overBright, 0.1/backEnd.overBright, 0.1/backEnd.overBright );
1115 }
1116 } else {
1117 // draw different color for turboshadows
1118 if ( surf->geo->shadowCapPlaneBits & SHADOW_CAP_INFINITE ) {
1119 if ( numIndexes == tri->numIndexes ) {
1120 qglColor3f( 1/backEnd.overBright, 0.1/backEnd.overBright, 0.1/backEnd.overBright );
1121 } else {
1122 qglColor3f( 1/backEnd.overBright, 0.4/backEnd.overBright, 0.1/backEnd.overBright );
1123 }
1124 } else {
1125 if ( numIndexes == tri->numIndexes ) {
1126 qglColor3f( 0.1/backEnd.overBright, 1/backEnd.overBright, 0.1/backEnd.overBright );
1127 } else if ( numIndexes == tri->numShadowIndexesNoFrontCaps ) {
1128 qglColor3f( 0.1/backEnd.overBright, 1/backEnd.overBright, 0.6/backEnd.overBright );
1129 } else {
1130 qglColor3f( 0.6/backEnd.overBright, 1/backEnd.overBright, 0.1/backEnd.overBright );
1131 }
1132 }
1133 }
1134
1135 qglStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
1136 qglDisable( GL_STENCIL_TEST );
1137 GL_Cull( CT_TWO_SIDED );
1138 RB_DrawShadowElementsWithCounters( tri, numIndexes );
1139 GL_Cull( CT_FRONT_SIDED );
1140 qglEnable( GL_STENCIL_TEST );
1141
1142 return;
1143 }
1144
1145 // DG: that bloody patent on depth-fail stencil shadows has finally expired on 2019-10-13,
1146 // so use them (see https://patents.google.com/patent/US6384822B1/en for expiration status)
1147 bool useStencilOpSeperate = r_useStencilOpSeparate.GetBool() && qglStencilOpSeparate != NULL;
1148 if( !r_useCarmacksReverse.GetBool() ) {
1149 if( useStencilOpSeperate ) {
1150 // not using z-fail, but using qglStencilOpSeparate()
1151 GLenum firstFace = backEnd.viewDef->isMirror ? GL_FRONT : GL_BACK;
1152 GLenum secondFace = backEnd.viewDef->isMirror ? GL_BACK : GL_FRONT;
1153 GL_Cull( CT_TWO_SIDED );
1154 if ( !external ) {
1155 qglStencilOpSeparate( firstFace, GL_KEEP, tr.stencilDecr, tr.stencilDecr );
1156 qglStencilOpSeparate( secondFace, GL_KEEP, tr.stencilIncr, tr.stencilIncr );
1157 RB_DrawShadowElementsWithCounters( tri, numIndexes );
1158 }
1159
1160 qglStencilOpSeparate( firstFace, GL_KEEP, GL_KEEP, tr.stencilIncr );
1161 qglStencilOpSeparate( secondFace, GL_KEEP, GL_KEEP, tr.stencilDecr );
1162
1163 RB_DrawShadowElementsWithCounters( tri, numIndexes );
1164
1165 } else { // DG: this is the original code:
1166 // patent-free work around
1167 if ( !external ) {
1168 // "preload" the stencil buffer with the number of volumes
1169 // that get clipped by the near or far clip plane
1170 qglStencilOp( GL_KEEP, tr.stencilDecr, tr.stencilDecr );
1171 GL_Cull( CT_FRONT_SIDED );
1172 RB_DrawShadowElementsWithCounters( tri, numIndexes );
1173 qglStencilOp( GL_KEEP, tr.stencilIncr, tr.stencilIncr );
1174 GL_Cull( CT_BACK_SIDED );
1175 RB_DrawShadowElementsWithCounters( tri, numIndexes );
1176 }
1177
1178 // traditional depth-pass stencil shadows
1179 qglStencilOp( GL_KEEP, GL_KEEP, tr.stencilIncr );
1180 GL_Cull( CT_FRONT_SIDED );
1181 RB_DrawShadowElementsWithCounters( tri, numIndexes );
1182
1183 qglStencilOp( GL_KEEP, GL_KEEP, tr.stencilDecr );
1184 GL_Cull( CT_BACK_SIDED );
1185 RB_DrawShadowElementsWithCounters( tri, numIndexes );
1186 }
1187 } else { // use the formerly patented "Carmack's Reverse" Z-Fail code
1188 if( useStencilOpSeperate ) {
1189 // Z-Fail with glStencilOpSeparate() which will reduce draw calls
1190 GLenum firstFace = backEnd.viewDef->isMirror ? GL_FRONT : GL_BACK;
1191 GLenum secondFace = backEnd.viewDef->isMirror ? GL_BACK : GL_FRONT;
1192 if ( !external ) { // z-fail
1193 qglStencilOpSeparate( firstFace, GL_KEEP, tr.stencilDecr, GL_KEEP );
1194 qglStencilOpSeparate( secondFace, GL_KEEP, tr.stencilIncr, GL_KEEP );
1195 } else { // depth-pass
1196 qglStencilOpSeparate( firstFace, GL_KEEP, GL_KEEP, tr.stencilIncr );
1197 qglStencilOpSeparate( secondFace, GL_KEEP, GL_KEEP, tr.stencilDecr );
1198 }
1199 GL_Cull( CT_TWO_SIDED );
1200 RB_DrawShadowElementsWithCounters( tri, numIndexes );
1201
1202 } else { // Z-Fail without glStencilOpSeparate()
1203
1204 // LEITH: the (formerly patented) "Carmack's Reverse" code
1205
1206 // depth-fail/Z-Fail stencil shadows
1207 if ( !external ) {
1208 qglStencilOp( GL_KEEP, tr.stencilDecr, GL_KEEP );
1209 GL_Cull( CT_FRONT_SIDED );
1210 RB_DrawShadowElementsWithCounters( tri, numIndexes );
1211 qglStencilOp( GL_KEEP, tr.stencilIncr, GL_KEEP );
1212 GL_Cull( CT_BACK_SIDED );
1213 RB_DrawShadowElementsWithCounters( tri, numIndexes );
1214 }
1215 // traditional depth-pass stencil shadows
1216 else {
1217 qglStencilOp( GL_KEEP, GL_KEEP, tr.stencilIncr );
1218 GL_Cull( CT_FRONT_SIDED );
1219 RB_DrawShadowElementsWithCounters( tri, numIndexes );
1220
1221 qglStencilOp( GL_KEEP, GL_KEEP, tr.stencilDecr );
1222 GL_Cull( CT_BACK_SIDED );
1223 RB_DrawShadowElementsWithCounters( tri, numIndexes );
1224 }
1225 }
1226 }
1227 }
1228
1229 /*
1230 =====================
1231 RB_StencilShadowPass
1232
1233 Stencil test should already be enabled, and the stencil buffer should have
1234 been set to 128 on any surfaces that might receive shadows
1235 =====================
1236 */
RB_StencilShadowPass(const drawSurf_t * drawSurfs)1237 void RB_StencilShadowPass( const drawSurf_t *drawSurfs ) {
1238 if ( !r_shadows.GetBool() ) {
1239 return;
1240 }
1241
1242 if ( !drawSurfs ) {
1243 return;
1244 }
1245
1246 globalImages->BindNull();
1247 qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
1248
1249 // for visualizing the shadows
1250 if ( r_showShadows.GetInteger() ) {
1251 if ( r_showShadows.GetInteger() == 2 ) {
1252 // draw filled in
1253 GL_State( GLS_DEPTHMASK | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_LESS );
1254 } else {
1255 // draw as lines, filling the depth buffer
1256 GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO | GLS_POLYMODE_LINE | GLS_DEPTHFUNC_ALWAYS );
1257 }
1258 } else {
1259 // don't write to the color buffer, just the stencil buffer
1260 GL_State( GLS_DEPTHMASK | GLS_COLORMASK | GLS_ALPHAMASK | GLS_DEPTHFUNC_LESS );
1261 }
1262
1263 if ( r_shadowPolygonFactor.GetFloat() || r_shadowPolygonOffset.GetFloat() ) {
1264 qglPolygonOffset( r_shadowPolygonFactor.GetFloat(), -r_shadowPolygonOffset.GetFloat() );
1265 qglEnable( GL_POLYGON_OFFSET_FILL );
1266 }
1267
1268 qglStencilFunc( GL_ALWAYS, 1, 255 );
1269
1270 if ( glConfig.depthBoundsTestAvailable && r_useDepthBoundsTest.GetBool() ) {
1271 qglEnable( GL_DEPTH_BOUNDS_TEST_EXT );
1272 }
1273
1274 RB_RenderDrawSurfChainWithFunction( drawSurfs, RB_T_Shadow );
1275
1276 GL_Cull( CT_FRONT_SIDED );
1277
1278 if ( r_shadowPolygonFactor.GetFloat() || r_shadowPolygonOffset.GetFloat() ) {
1279 qglDisable( GL_POLYGON_OFFSET_FILL );
1280 }
1281
1282 if ( glConfig.depthBoundsTestAvailable && r_useDepthBoundsTest.GetBool() ) {
1283 qglDisable( GL_DEPTH_BOUNDS_TEST_EXT );
1284 }
1285
1286 qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
1287
1288 qglStencilFunc( GL_GEQUAL, 128, 255 );
1289 qglStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
1290 }
1291
1292
1293
1294 /*
1295 =============================================================================================
1296
1297 BLEND LIGHT PROJECTION
1298
1299 =============================================================================================
1300 */
1301
1302 /*
1303 =====================
1304 RB_T_BlendLight
1305
1306 =====================
1307 */
RB_T_BlendLight(const drawSurf_t * surf)1308 static void RB_T_BlendLight( const drawSurf_t *surf ) {
1309 const srfTriangles_t *tri;
1310
1311 tri = surf->geo;
1312
1313 if ( backEnd.currentSpace != surf->space ) {
1314 idPlane lightProject[4];
1315 int i;
1316
1317 for ( i = 0 ; i < 4 ; i++ ) {
1318 R_GlobalPlaneToLocal( surf->space->modelMatrix, backEnd.vLight->lightProject[i], lightProject[i] );
1319 }
1320
1321 GL_SelectTexture( 0 );
1322 qglTexGenfv( GL_S, GL_OBJECT_PLANE, lightProject[0].ToFloatPtr() );
1323 qglTexGenfv( GL_T, GL_OBJECT_PLANE, lightProject[1].ToFloatPtr() );
1324 qglTexGenfv( GL_Q, GL_OBJECT_PLANE, lightProject[2].ToFloatPtr() );
1325
1326 GL_SelectTexture( 1 );
1327 qglTexGenfv( GL_S, GL_OBJECT_PLANE, lightProject[3].ToFloatPtr() );
1328 }
1329
1330 // this gets used for both blend lights and shadow draws
1331 if ( tri->ambientCache ) {
1332 idDrawVert *ac = (idDrawVert *)vertexCache.Position( tri->ambientCache );
1333 qglVertexPointer( 3, GL_FLOAT, sizeof( idDrawVert ), ac->xyz.ToFloatPtr() );
1334 } else if ( tri->shadowCache ) {
1335 shadowCache_t *sc = (shadowCache_t *)vertexCache.Position( tri->shadowCache );
1336 qglVertexPointer( 3, GL_FLOAT, sizeof( shadowCache_t ), sc->xyz.ToFloatPtr() );
1337 }
1338
1339 RB_DrawElementsWithCounters( tri );
1340 }
1341
1342
1343 /*
1344 =====================
1345 RB_BlendLight
1346
1347 Dual texture together the falloff and projection texture with a blend
1348 mode to the framebuffer, instead of interacting with the surface texture
1349 =====================
1350 */
RB_BlendLight(const drawSurf_t * drawSurfs,const drawSurf_t * drawSurfs2)1351 static void RB_BlendLight( const drawSurf_t *drawSurfs, const drawSurf_t *drawSurfs2 ) {
1352 const idMaterial *lightShader;
1353 const shaderStage_t *stage;
1354 int i;
1355 const float *regs;
1356
1357 if ( !drawSurfs ) {
1358 return;
1359 }
1360 if ( r_skipBlendLights.GetBool() ) {
1361 return;
1362 }
1363
1364 lightShader = backEnd.vLight->lightShader;
1365 regs = backEnd.vLight->shaderRegisters;
1366
1367 // texture 1 will get the falloff texture
1368 GL_SelectTexture( 1 );
1369 qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
1370 qglEnable( GL_TEXTURE_GEN_S );
1371 qglTexCoord2f( 0, 0.5 );
1372 backEnd.vLight->falloffImage->Bind();
1373
1374 // texture 0 will get the projected texture
1375 GL_SelectTexture( 0 );
1376 qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
1377 qglEnable( GL_TEXTURE_GEN_S );
1378 qglEnable( GL_TEXTURE_GEN_T );
1379 qglEnable( GL_TEXTURE_GEN_Q );
1380
1381 for ( i = 0 ; i < lightShader->GetNumStages() ; i++ ) {
1382 stage = lightShader->GetStage(i);
1383
1384 if ( !regs[ stage->conditionRegister ] ) {
1385 continue;
1386 }
1387
1388 GL_State( GLS_DEPTHMASK | stage->drawStateBits | GLS_DEPTHFUNC_EQUAL );
1389
1390 GL_SelectTexture( 0 );
1391 stage->texture.image->Bind();
1392
1393 if ( stage->texture.hasMatrix ) {
1394 RB_LoadShaderTextureMatrix( regs, &stage->texture );
1395 }
1396
1397 // get the modulate values from the light, including alpha, unlike normal lights
1398 backEnd.lightColor[0] = regs[ stage->color.registers[0] ];
1399 backEnd.lightColor[1] = regs[ stage->color.registers[1] ];
1400 backEnd.lightColor[2] = regs[ stage->color.registers[2] ];
1401 backEnd.lightColor[3] = regs[ stage->color.registers[3] ];
1402 qglColor4fv( backEnd.lightColor );
1403
1404 RB_RenderDrawSurfChainWithFunction( drawSurfs, RB_T_BlendLight );
1405 RB_RenderDrawSurfChainWithFunction( drawSurfs2, RB_T_BlendLight );
1406
1407 if ( stage->texture.hasMatrix ) {
1408 GL_SelectTexture( 0 );
1409 qglMatrixMode( GL_TEXTURE );
1410 qglLoadIdentity();
1411 qglMatrixMode( GL_MODELVIEW );
1412 }
1413 }
1414
1415 GL_SelectTexture( 1 );
1416 qglDisable( GL_TEXTURE_GEN_S );
1417 globalImages->BindNull();
1418
1419 GL_SelectTexture( 0 );
1420 qglDisable( GL_TEXTURE_GEN_S );
1421 qglDisable( GL_TEXTURE_GEN_T );
1422 qglDisable( GL_TEXTURE_GEN_Q );
1423 }
1424
1425
1426 //========================================================================
1427
1428 static idPlane fogPlanes[4];
1429
1430 /*
1431 =====================
1432 RB_T_BasicFog
1433
1434 =====================
1435 */
RB_T_BasicFog(const drawSurf_t * surf)1436 static void RB_T_BasicFog( const drawSurf_t *surf ) {
1437 if ( backEnd.currentSpace != surf->space ) {
1438 idPlane local;
1439
1440 GL_SelectTexture( 0 );
1441
1442 R_GlobalPlaneToLocal( surf->space->modelMatrix, fogPlanes[0], local );
1443 local[3] += 0.5;
1444 qglTexGenfv( GL_S, GL_OBJECT_PLANE, local.ToFloatPtr() );
1445
1446 // R_GlobalPlaneToLocal( surf->space->modelMatrix, fogPlanes[1], local );
1447 // local[3] += 0.5;
1448 local[0] = local[1] = local[2] = 0; local[3] = 0.5;
1449 qglTexGenfv( GL_T, GL_OBJECT_PLANE, local.ToFloatPtr() );
1450
1451 GL_SelectTexture( 1 );
1452
1453 // GL_S is constant per viewer
1454 R_GlobalPlaneToLocal( surf->space->modelMatrix, fogPlanes[2], local );
1455 local[3] += FOG_ENTER;
1456 qglTexGenfv( GL_T, GL_OBJECT_PLANE, local.ToFloatPtr() );
1457
1458 R_GlobalPlaneToLocal( surf->space->modelMatrix, fogPlanes[3], local );
1459 qglTexGenfv( GL_S, GL_OBJECT_PLANE, local.ToFloatPtr() );
1460 }
1461
1462 RB_T_RenderTriangleSurface( surf );
1463 }
1464
1465
1466
1467 /*
1468 ==================
1469 RB_FogPass
1470 ==================
1471 */
RB_FogPass(const drawSurf_t * drawSurfs,const drawSurf_t * drawSurfs2)1472 static void RB_FogPass( const drawSurf_t *drawSurfs, const drawSurf_t *drawSurfs2 ) {
1473 const srfTriangles_t*frustumTris;
1474 drawSurf_t ds;
1475 const idMaterial *lightShader;
1476 const shaderStage_t *stage;
1477 const float *regs;
1478
1479 // create a surface for the light frustom triangles, which are oriented drawn side out
1480 frustumTris = backEnd.vLight->frustumTris;
1481
1482 // if we ran out of vertex cache memory, skip it
1483 if ( !frustumTris->ambientCache ) {
1484 return;
1485 }
1486 memset( &ds, 0, sizeof( ds ) );
1487 ds.space = &backEnd.viewDef->worldSpace;
1488 ds.geo = frustumTris;
1489 ds.scissorRect = backEnd.viewDef->scissor;
1490
1491 // find the current color and density of the fog
1492 lightShader = backEnd.vLight->lightShader;
1493 regs = backEnd.vLight->shaderRegisters;
1494 // assume fog shaders have only a single stage
1495 stage = lightShader->GetStage(0);
1496
1497 backEnd.lightColor[0] = regs[ stage->color.registers[0] ];
1498 backEnd.lightColor[1] = regs[ stage->color.registers[1] ];
1499 backEnd.lightColor[2] = regs[ stage->color.registers[2] ];
1500 backEnd.lightColor[3] = regs[ stage->color.registers[3] ];
1501
1502 qglColor3fv( backEnd.lightColor );
1503
1504 // calculate the falloff planes
1505 float a;
1506
1507 // if they left the default value on, set a fog distance of 500
1508 if ( backEnd.lightColor[3] <= 1.0 ) {
1509 a = -0.5f / DEFAULT_FOG_DISTANCE;
1510 } else {
1511 // otherwise, distance = alpha color
1512 a = -0.5f / backEnd.lightColor[3];
1513 }
1514
1515 GL_State( GLS_DEPTHMASK | GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_DEPTHFUNC_EQUAL );
1516
1517 // texture 0 is the falloff image
1518 GL_SelectTexture( 0 );
1519 globalImages->fogImage->Bind();
1520 //GL_Bind( tr.whiteImage );
1521 qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
1522 qglEnable( GL_TEXTURE_GEN_S );
1523 qglEnable( GL_TEXTURE_GEN_T );
1524 qglTexCoord2f( 0.5f, 0.5f ); // make sure Q is set
1525
1526 fogPlanes[0][0] = a * backEnd.viewDef->worldSpace.modelViewMatrix[2];
1527 fogPlanes[0][1] = a * backEnd.viewDef->worldSpace.modelViewMatrix[6];
1528 fogPlanes[0][2] = a * backEnd.viewDef->worldSpace.modelViewMatrix[10];
1529 fogPlanes[0][3] = a * backEnd.viewDef->worldSpace.modelViewMatrix[14];
1530
1531 fogPlanes[1][0] = a * backEnd.viewDef->worldSpace.modelViewMatrix[0];
1532 fogPlanes[1][1] = a * backEnd.viewDef->worldSpace.modelViewMatrix[4];
1533 fogPlanes[1][2] = a * backEnd.viewDef->worldSpace.modelViewMatrix[8];
1534 fogPlanes[1][3] = a * backEnd.viewDef->worldSpace.modelViewMatrix[12];
1535
1536
1537 // texture 1 is the entering plane fade correction
1538 GL_SelectTexture( 1 );
1539 globalImages->fogEnterImage->Bind();
1540 qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
1541 qglEnable( GL_TEXTURE_GEN_S );
1542 qglEnable( GL_TEXTURE_GEN_T );
1543
1544 // T will get a texgen for the fade plane, which is always the "top" plane on unrotated lights
1545 fogPlanes[2][0] = 0.001f * backEnd.vLight->fogPlane[0];
1546 fogPlanes[2][1] = 0.001f * backEnd.vLight->fogPlane[1];
1547 fogPlanes[2][2] = 0.001f * backEnd.vLight->fogPlane[2];
1548 fogPlanes[2][3] = 0.001f * backEnd.vLight->fogPlane[3];
1549
1550 // S is based on the view origin
1551 float s = backEnd.viewDef->renderView.vieworg * fogPlanes[2].Normal() + fogPlanes[2][3];
1552
1553 fogPlanes[3][0] = 0;
1554 fogPlanes[3][1] = 0;
1555 fogPlanes[3][2] = 0;
1556 fogPlanes[3][3] = FOG_ENTER + s;
1557
1558 qglTexCoord2f( FOG_ENTER + s, FOG_ENTER );
1559
1560
1561 // draw it
1562 RB_RenderDrawSurfChainWithFunction( drawSurfs, RB_T_BasicFog );
1563 RB_RenderDrawSurfChainWithFunction( drawSurfs2, RB_T_BasicFog );
1564
1565 // the light frustum bounding planes aren't in the depth buffer, so use depthfunc_less instead
1566 // of depthfunc_equal
1567 GL_State( GLS_DEPTHMASK | GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_DEPTHFUNC_LESS );
1568 GL_Cull( CT_BACK_SIDED );
1569 RB_RenderDrawSurfChainWithFunction( &ds, RB_T_BasicFog );
1570 GL_Cull( CT_FRONT_SIDED );
1571
1572 GL_SelectTexture( 1 );
1573 qglDisable( GL_TEXTURE_GEN_S );
1574 qglDisable( GL_TEXTURE_GEN_T );
1575 globalImages->BindNull();
1576
1577 GL_SelectTexture( 0 );
1578 qglDisable( GL_TEXTURE_GEN_S );
1579 qglDisable( GL_TEXTURE_GEN_T );
1580 }
1581
1582
1583 /*
1584 ==================
1585 RB_STD_FogAllLights
1586 ==================
1587 */
RB_STD_FogAllLights(void)1588 void RB_STD_FogAllLights( void ) {
1589 viewLight_t *vLight;
1590
1591 if ( r_skipFogLights.GetBool() || r_showOverDraw.GetInteger() != 0
1592 || backEnd.viewDef->isXraySubview /* dont fog in xray mode*/
1593 ) {
1594 return;
1595 }
1596
1597 qglDisable( GL_STENCIL_TEST );
1598
1599 for ( vLight = backEnd.viewDef->viewLights ; vLight ; vLight = vLight->next ) {
1600 backEnd.vLight = vLight;
1601
1602 if ( !vLight->lightShader->IsFogLight() && !vLight->lightShader->IsBlendLight() ) {
1603 continue;
1604 }
1605
1606 #if 0 // _D3XP disabled that
1607 if ( r_ignore.GetInteger() ) {
1608 // we use the stencil buffer to guarantee that no pixels will be
1609 // double fogged, which happens in some areas that are thousands of
1610 // units from the origin
1611 backEnd.currentScissor = vLight->scissorRect;
1612 if ( r_useScissor.GetBool() ) {
1613 qglScissor( backEnd.viewDef->viewport.x1 + backEnd.currentScissor.x1,
1614 backEnd.viewDef->viewport.y1 + backEnd.currentScissor.y1,
1615 backEnd.currentScissor.x2 + 1 - backEnd.currentScissor.x1,
1616 backEnd.currentScissor.y2 + 1 - backEnd.currentScissor.y1 );
1617 }
1618 qglClear( GL_STENCIL_BUFFER_BIT );
1619
1620 qglEnable( GL_STENCIL_TEST );
1621
1622 // only pass on the cleared stencil values
1623 qglStencilFunc( GL_EQUAL, 128, 255 );
1624
1625 // when we pass the stencil test and depth test and are going to draw,
1626 // increment the stencil buffer so we don't ever draw on that pixel again
1627 qglStencilOp( GL_KEEP, GL_KEEP, GL_INCR );
1628 }
1629 #endif
1630
1631 if ( vLight->lightShader->IsFogLight() ) {
1632 RB_FogPass( vLight->globalInteractions, vLight->localInteractions );
1633 } else if ( vLight->lightShader->IsBlendLight() ) {
1634 RB_BlendLight( vLight->globalInteractions, vLight->localInteractions );
1635 }
1636 qglDisable( GL_STENCIL_TEST );
1637 }
1638
1639 qglEnable( GL_STENCIL_TEST );
1640 }
1641
1642 //=========================================================================================
1643
1644 /*
1645 ==================
1646 RB_STD_LightScale
1647
1648 Perform extra blending passes to multiply the entire buffer by
1649 a floating point value
1650 ==================
1651 */
RB_STD_LightScale(void)1652 void RB_STD_LightScale( void ) {
1653 float v, f;
1654
1655 if ( backEnd.overBright == 1.0f ) {
1656 return;
1657 }
1658
1659 if ( r_skipLightScale.GetBool() ) {
1660 return;
1661 }
1662
1663 // the scissor may be smaller than the viewport for subviews
1664 if ( r_useScissor.GetBool() ) {
1665 qglScissor( backEnd.viewDef->viewport.x1 + backEnd.viewDef->scissor.x1,
1666 backEnd.viewDef->viewport.y1 + backEnd.viewDef->scissor.y1,
1667 backEnd.viewDef->scissor.x2 - backEnd.viewDef->scissor.x1 + 1,
1668 backEnd.viewDef->scissor.y2 - backEnd.viewDef->scissor.y1 + 1 );
1669 backEnd.currentScissor = backEnd.viewDef->scissor;
1670 }
1671
1672 // full screen blends
1673 qglLoadIdentity();
1674 qglMatrixMode( GL_PROJECTION );
1675 qglPushMatrix();
1676 qglLoadIdentity();
1677 qglOrtho( 0, 1, 0, 1, -1, 1 );
1678
1679 GL_State( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_SRC_COLOR );
1680 GL_Cull( CT_TWO_SIDED ); // so mirror views also get it
1681 globalImages->BindNull();
1682 qglDisable( GL_DEPTH_TEST );
1683 qglDisable( GL_STENCIL_TEST );
1684
1685 v = 1;
1686 while ( idMath::Fabs( v - backEnd.overBright ) > 0.01 ) { // a little extra slop
1687 f = backEnd.overBright / v;
1688 f /= 2;
1689 if ( f > 1 ) {
1690 f = 1;
1691 }
1692 qglColor3f( f, f, f );
1693 v = v * f * 2;
1694
1695 qglBegin( GL_QUADS );
1696 qglVertex2f( 0,0 );
1697 qglVertex2f( 0,1 );
1698 qglVertex2f( 1,1 );
1699 qglVertex2f( 1,0 );
1700 qglEnd();
1701 }
1702
1703
1704 qglPopMatrix();
1705 qglEnable( GL_DEPTH_TEST );
1706 qglMatrixMode( GL_MODELVIEW );
1707 GL_Cull( CT_FRONT_SIDED );
1708 }
1709
1710 //=========================================================================================
1711
1712 /*
1713 =============
1714 RB_STD_DrawView
1715
1716 =============
1717 */
RB_STD_DrawView(void)1718 void RB_STD_DrawView( void ) {
1719 drawSurf_t **drawSurfs;
1720 int numDrawSurfs;
1721
1722 backEnd.depthFunc = GLS_DEPTHFUNC_EQUAL;
1723
1724 drawSurfs = (drawSurf_t **)&backEnd.viewDef->drawSurfs[0];
1725 numDrawSurfs = backEnd.viewDef->numDrawSurfs;
1726
1727 // clear the z buffer, set the projection matrix, etc
1728 RB_BeginDrawingView();
1729
1730 // decide how much overbrighting we are going to do
1731 RB_DetermineLightScale();
1732
1733 // fill the depth buffer and clear color buffer to black except on
1734 // subviews
1735 RB_STD_FillDepthBuffer( drawSurfs, numDrawSurfs );
1736
1737 // main light renderer
1738 switch( tr.backEndRenderer ) {
1739 case BE_ARB2:
1740 RB_ARB2_DrawInteractions();
1741 break;
1742 }
1743
1744 // disable stencil shadow test
1745 qglStencilFunc( GL_ALWAYS, 128, 255 );
1746
1747 // uplight the entire screen to crutch up not having better blending range
1748 RB_STD_LightScale();
1749
1750 // now draw any non-light dependent shading passes
1751 int processed = RB_STD_DrawShaderPasses( drawSurfs, numDrawSurfs );
1752
1753 // fob and blend lights
1754 RB_STD_FogAllLights();
1755
1756 // now draw any post-processing effects using _currentRender
1757 if ( processed < numDrawSurfs ) {
1758 RB_STD_DrawShaderPasses( drawSurfs+processed, numDrawSurfs-processed );
1759 }
1760
1761 RB_RenderDebugTools( drawSurfs, numDrawSurfs );
1762
1763 }
1764