2 ===========================================================================
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
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.
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.
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/>.
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.
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.
26 ===========================================================================
28 #include "../idlib/precompiled.h"
35 RB_BakeTextureMatrixIntoTexgen
38 void RB_BakeTextureMatrixIntoTexgen( idPlane lightProject[3], const float *textureMatrix ) {
42 genMatrix[0] = lightProject[0][0];
43 genMatrix[4] = lightProject[0][1];
44 genMatrix[8] = lightProject[0][2];
45 genMatrix[12] = lightProject[0][3];
47 genMatrix[1] = lightProject[1][0];
48 genMatrix[5] = lightProject[1][1];
49 genMatrix[9] = lightProject[1][2];
50 genMatrix[13] = lightProject[1][3];
57 genMatrix[3] = lightProject[2][0];
58 genMatrix[7] = lightProject[2][1];
59 genMatrix[11] = lightProject[2][2];
60 genMatrix[15] = lightProject[2][3];
62 myGlMultMatrix( genMatrix, backEnd.lightTextureMatrix, final );
64 lightProject[0][0] = final[0];
65 lightProject[0][1] = final[4];
66 lightProject[0][2] = final[8];
67 lightProject[0][3] = final[12];
69 lightProject[1][0] = final[1];
70 lightProject[1][1] = final[5];
71 lightProject[1][2] = final[9];
72 lightProject[1][3] = final[13];
77 RB_PrepareStageTexturing
80 void RB_PrepareStageTexturing( const shaderStage_t *pStage, const drawSurf_t *surf, idDrawVert *ac ) {
81 // set privatePolygonOffset if necessary
82 if ( pStage->privatePolygonOffset ) {
83 qglEnable( GL_POLYGON_OFFSET_FILL );
84 qglPolygonOffset( r_offsetFactor.GetFloat(), r_offsetUnits.GetFloat() * pStage->privatePolygonOffset );
87 // set the texture matrix if needed
88 if ( pStage->texture.hasMatrix ) {
89 RB_LoadShaderTextureMatrix( surf->shaderRegisters, &pStage->texture );
93 if ( pStage->texture.texgen == TG_DIFFUSE_CUBE ) {
94 qglTexCoordPointer( 3, GL_FLOAT, sizeof( idDrawVert ), ac->normal.ToFloatPtr() );
96 if ( pStage->texture.texgen == TG_SKYBOX_CUBE || pStage->texture.texgen == TG_WOBBLESKY_CUBE ) {
97 qglTexCoordPointer( 3, GL_FLOAT, 0, vertexCache.Position( surf->dynamicTexCoords ) );
99 if ( pStage->texture.texgen == TG_SCREEN ) {
100 qglEnable( GL_TEXTURE_GEN_S );
101 qglEnable( GL_TEXTURE_GEN_T );
102 qglEnable( GL_TEXTURE_GEN_Q );
104 float mat[16], plane[4];
105 myGlMultMatrix( surf->space->modelViewMatrix, backEnd.viewDef->projectionMatrix, mat );
111 qglTexGenfv( GL_S, GL_OBJECT_PLANE, plane );
117 qglTexGenfv( GL_T, GL_OBJECT_PLANE, plane );
123 qglTexGenfv( GL_Q, GL_OBJECT_PLANE, plane );
126 if ( pStage->texture.texgen == TG_SCREEN2 ) {
127 qglEnable( GL_TEXTURE_GEN_S );
128 qglEnable( GL_TEXTURE_GEN_T );
129 qglEnable( GL_TEXTURE_GEN_Q );
131 float mat[16], plane[4];
132 myGlMultMatrix( surf->space->modelViewMatrix, backEnd.viewDef->projectionMatrix, mat );
138 qglTexGenfv( GL_S, GL_OBJECT_PLANE, plane );
144 qglTexGenfv( GL_T, GL_OBJECT_PLANE, plane );
150 qglTexGenfv( GL_Q, GL_OBJECT_PLANE, plane );
153 if ( pStage->texture.texgen == TG_GLASSWARP ) {
154 if ( tr.backEndRenderer == BE_ARB2 /*|| tr.backEndRenderer == BE_NV30*/ ) {
155 qglBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, FPROG_GLASSWARP );
156 qglEnable( GL_FRAGMENT_PROGRAM_ARB );
158 GL_SelectTexture( 2 );
159 globalImages->scratchImage->Bind();
161 GL_SelectTexture( 1 );
162 globalImages->scratchImage2->Bind();
164 qglEnable( GL_TEXTURE_GEN_S );
165 qglEnable( GL_TEXTURE_GEN_T );
166 qglEnable( GL_TEXTURE_GEN_Q );
168 float mat[16], plane[4];
169 myGlMultMatrix( surf->space->modelViewMatrix, backEnd.viewDef->projectionMatrix, mat );
175 qglTexGenfv( GL_S, GL_OBJECT_PLANE, plane );
181 qglTexGenfv( GL_T, GL_OBJECT_PLANE, plane );
187 qglTexGenfv( GL_Q, GL_OBJECT_PLANE, plane );
189 GL_SelectTexture( 0 );
193 if ( pStage->texture.texgen == TG_REFLECT_CUBE ) {
194 if ( tr.backEndRenderer == BE_ARB2 ) {
195 // see if there is also a bump map specified
196 const shaderStage_t *bumpStage = surf->material->GetBumpStage();
198 // per-pixel reflection mapping with bump mapping
199 GL_SelectTexture( 1 );
200 bumpStage->texture.image->Bind();
201 GL_SelectTexture( 0 );
203 qglNormalPointer( GL_FLOAT, sizeof( idDrawVert ), ac->normal.ToFloatPtr() );
204 qglVertexAttribPointerARB( 10, 3, GL_FLOAT, false, sizeof( idDrawVert ), ac->tangents[1].ToFloatPtr() );
205 qglVertexAttribPointerARB( 9, 3, GL_FLOAT, false, sizeof( idDrawVert ), ac->tangents[0].ToFloatPtr() );
207 qglEnableVertexAttribArrayARB( 9 );
208 qglEnableVertexAttribArrayARB( 10 );
209 qglEnableClientState( GL_NORMAL_ARRAY );
211 // Program env 5, 6, 7, 8 have been set in RB_SetProgramEnvironmentSpace
213 qglBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, FPROG_BUMPY_ENVIRONMENT );
214 qglEnable( GL_FRAGMENT_PROGRAM_ARB );
215 qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, VPROG_BUMPY_ENVIRONMENT );
216 qglEnable( GL_VERTEX_PROGRAM_ARB );
218 // per-pixel reflection mapping without a normal map
219 qglNormalPointer( GL_FLOAT, sizeof( idDrawVert ), ac->normal.ToFloatPtr() );
220 qglEnableClientState( GL_NORMAL_ARRAY );
222 qglBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, FPROG_ENVIRONMENT );
223 qglEnable( GL_FRAGMENT_PROGRAM_ARB );
224 qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, VPROG_ENVIRONMENT );
225 qglEnable( GL_VERTEX_PROGRAM_ARB );
228 qglEnable( GL_TEXTURE_GEN_S );
229 qglEnable( GL_TEXTURE_GEN_T );
230 qglEnable( GL_TEXTURE_GEN_R );
231 qglTexGenf( GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_EXT );
232 qglTexGenf( GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_EXT );
233 qglTexGenf( GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_EXT );
234 qglEnableClientState( GL_NORMAL_ARRAY );
235 qglNormalPointer( GL_FLOAT, sizeof( idDrawVert ), ac->normal.ToFloatPtr() );
237 qglMatrixMode( GL_TEXTURE );
240 R_TransposeGLMatrix( backEnd.viewDef->worldSpace.modelViewMatrix, mat );
242 qglLoadMatrixf( mat );
243 qglMatrixMode( GL_MODELVIEW );
250 RB_FinishStageTexturing
253 void RB_FinishStageTexturing( const shaderStage_t *pStage, const drawSurf_t *surf, idDrawVert *ac ) {
254 // unset privatePolygonOffset if necessary
255 if ( pStage->privatePolygonOffset && !surf->material->TestMaterialFlag(MF_POLYGONOFFSET) ) {
256 qglDisable( GL_POLYGON_OFFSET_FILL );
259 if ( pStage->texture.texgen == TG_DIFFUSE_CUBE || pStage->texture.texgen == TG_SKYBOX_CUBE
260 || pStage->texture.texgen == TG_WOBBLESKY_CUBE ) {
261 qglTexCoordPointer( 2, GL_FLOAT, sizeof( idDrawVert ), (void *)&ac->st );
264 if ( pStage->texture.texgen == TG_SCREEN ) {
265 qglDisable( GL_TEXTURE_GEN_S );
266 qglDisable( GL_TEXTURE_GEN_T );
267 qglDisable( GL_TEXTURE_GEN_Q );
269 if ( pStage->texture.texgen == TG_SCREEN2 ) {
270 qglDisable( GL_TEXTURE_GEN_S );
271 qglDisable( GL_TEXTURE_GEN_T );
272 qglDisable( GL_TEXTURE_GEN_Q );
275 if ( pStage->texture.texgen == TG_GLASSWARP ) {
276 if ( tr.backEndRenderer == BE_ARB2 /*|| tr.backEndRenderer == BE_NV30*/ ) {
277 GL_SelectTexture( 2 );
278 globalImages->BindNull();
280 GL_SelectTexture( 1 );
281 if ( pStage->texture.hasMatrix ) {
282 RB_LoadShaderTextureMatrix( surf->shaderRegisters, &pStage->texture );
284 qglDisable( GL_TEXTURE_GEN_S );
285 qglDisable( GL_TEXTURE_GEN_T );
286 qglDisable( GL_TEXTURE_GEN_Q );
287 qglDisable( GL_FRAGMENT_PROGRAM_ARB );
288 globalImages->BindNull();
289 GL_SelectTexture( 0 );
293 if ( pStage->texture.texgen == TG_REFLECT_CUBE ) {
294 if ( tr.backEndRenderer == BE_ARB2 ) {
295 // see if there is also a bump map specified
296 const shaderStage_t *bumpStage = surf->material->GetBumpStage();
298 // per-pixel reflection mapping with bump mapping
299 GL_SelectTexture( 1 );
300 globalImages->BindNull();
301 GL_SelectTexture( 0 );
303 qglDisableVertexAttribArrayARB( 9 );
304 qglDisableVertexAttribArrayARB( 10 );
306 // per-pixel reflection mapping without bump mapping
309 qglDisableClientState( GL_NORMAL_ARRAY );
310 qglDisable( GL_FRAGMENT_PROGRAM_ARB );
311 qglDisable( GL_VERTEX_PROGRAM_ARB );
312 // Fixme: Hack to get around an apparent bug in ATI drivers. Should remove as soon as it gets fixed.
313 qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, 0 );
315 qglDisable( GL_TEXTURE_GEN_S );
316 qglDisable( GL_TEXTURE_GEN_T );
317 qglDisable( GL_TEXTURE_GEN_R );
318 qglTexGenf( GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
319 qglTexGenf( GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
320 qglTexGenf( GL_R, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR );
321 qglDisableClientState( GL_NORMAL_ARRAY );
323 qglMatrixMode( GL_TEXTURE );
325 qglMatrixMode( GL_MODELVIEW );
329 if ( pStage->texture.hasMatrix ) {
330 qglMatrixMode( GL_TEXTURE );
332 qglMatrixMode( GL_MODELVIEW );
337 =============================================================================================
341 =============================================================================================
350 void RB_T_FillDepthBuffer( const drawSurf_t *surf ) {
352 const idMaterial *shader;
353 const shaderStage_t *pStage;
356 const srfTriangles_t *tri;
359 shader = surf->material;
361 // update the clip plane if needed
362 if ( backEnd.viewDef->numClipPlanes && surf->space != backEnd.currentSpace ) {
363 GL_SelectTexture( 1 );
367 R_GlobalPlaneToLocal( surf->space->modelMatrix, backEnd.viewDef->clipPlanes[0], plane );
368 plane[3] += 0.5; // the notch is in the middle
369 qglTexGenfv( GL_S, GL_OBJECT_PLANE, plane.ToFloatPtr() );
370 GL_SelectTexture( 0 );
373 if ( !shader->IsDrawn() ) {
377 // some deforms may disable themselves by setting numIndexes = 0
378 if ( !tri->numIndexes ) {
382 // translucent surfaces don't put anything in the depth buffer and don't
383 // test against it, which makes them fail the mirror clip plane operation
384 if ( shader->Coverage() == MC_TRANSLUCENT ) {
388 if ( !tri->ambientCache ) {
389 common->Printf( "RB_T_FillDepthBuffer: !tri->ambientCache\n" );
393 // get the expressions for conditionals / color / texcoords
394 regs = surf->shaderRegisters;
396 // if all stages of a material have been conditioned off, don't do anything
397 for ( stage = 0; stage < shader->GetNumStages() ; stage++ ) {
398 pStage = shader->GetStage(stage);
399 // check the stage enable condition
400 if ( regs[ pStage->conditionRegister ] != 0 ) {
404 if ( stage == shader->GetNumStages() ) {
408 // set polygon offset if necessary
409 if ( shader->TestMaterialFlag(MF_POLYGONOFFSET) ) {
410 qglEnable( GL_POLYGON_OFFSET_FILL );
411 qglPolygonOffset( r_offsetFactor.GetFloat(), r_offsetUnits.GetFloat() * shader->GetPolygonOffset() );
414 // subviews will just down-modulate the color buffer by overbright
415 if ( shader->GetSort() == SS_SUBVIEW ) {
416 GL_State( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO | GLS_DEPTHFUNC_LESS );
419 color[2] = ( 1.0 / backEnd.overBright );
422 // others just draw black
429 idDrawVert *ac = (idDrawVert *)vertexCache.Position( tri->ambientCache );
430 qglVertexPointer( 3, GL_FLOAT, sizeof( idDrawVert ), ac->xyz.ToFloatPtr() );
431 qglTexCoordPointer( 2, GL_FLOAT, sizeof( idDrawVert ), reinterpret_cast<void *>(&ac->st) );
433 bool drawSolid = false;
435 if ( shader->Coverage() == MC_OPAQUE ) {
439 // we may have multiple alpha tested stages
440 if ( shader->Coverage() == MC_PERFORATED ) {
441 // if the only alpha tested stages are condition register omitted,
442 // draw a normal opaque surface
443 bool didDraw = false;
445 qglEnable( GL_ALPHA_TEST );
446 // perforated surfaces may have multiple alpha tested stages
447 for ( stage = 0; stage < shader->GetNumStages() ; stage++ ) {
448 pStage = shader->GetStage(stage);
450 if ( !pStage->hasAlphaTest ) {
454 // check the stage enable condition
455 if ( regs[ pStage->conditionRegister ] == 0 ) {
459 // if we at least tried to draw an alpha tested stage,
460 // we won't draw the opaque surface
463 // set the alpha modulate
464 color[3] = regs[ pStage->color.registers[3] ];
466 // skip the entire stage if alpha would be black
467 if ( color[3] <= 0 ) {
470 qglColor4fv( color );
472 qglAlphaFunc( GL_GREATER, regs[ pStage->alphaTestRegister ] );
475 pStage->texture.image->Bind();
477 // set texture matrix and texGens
478 RB_PrepareStageTexturing( pStage, surf, ac );
481 RB_DrawElementsWithCounters( tri );
483 RB_FinishStageTexturing( pStage, surf, ac );
485 qglDisable( GL_ALPHA_TEST );
491 // draw the entire surface solid
493 qglColor4fv( color );
494 globalImages->whiteImage->Bind();
497 RB_DrawElementsWithCounters( tri );
501 // reset polygon offset
502 if ( shader->TestMaterialFlag(MF_POLYGONOFFSET) ) {
503 qglDisable( GL_POLYGON_OFFSET_FILL );
507 if ( shader->GetSort() == SS_SUBVIEW ) {
508 GL_State( GLS_DEPTHFUNC_LESS );
514 =====================
515 RB_STD_FillDepthBuffer
517 If we are rendering a subview with a near clip plane, use a second texture
518 to force the alpha test to fail when behind that clip plane
519 =====================
521 void RB_STD_FillDepthBuffer( drawSurf_t **drawSurfs, int numDrawSurfs ) {
522 // if we are just doing 2D rendering, no need to fill the depth buffer
523 if ( !backEnd.viewDef->viewEntitys ) {
527 RB_LogComment( "---------- RB_STD_FillDepthBuffer ----------\n" );
529 // enable the second texture for mirror plane clipping if needed
530 if ( backEnd.viewDef->numClipPlanes ) {
531 GL_SelectTexture( 1 );
532 globalImages->alphaNotchImage->Bind();
533 qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
534 qglEnable( GL_TEXTURE_GEN_S );
535 qglTexCoord2f( 1, 0.5 );
538 // the first texture will be used for alpha tested surfaces
539 GL_SelectTexture( 0 );
540 qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
542 // decal surfaces may enable polygon offset
543 qglPolygonOffset( r_offsetFactor.GetFloat(), r_offsetUnits.GetFloat() );
545 GL_State( GLS_DEPTHFUNC_LESS );
547 // Enable stencil test if we are going to be using it for shadows.
548 // If we didn't do this, it would be legal behavior to get z fighting
549 // from the ambient pass and the light passes.
550 qglEnable( GL_STENCIL_TEST );
551 qglStencilFunc( GL_ALWAYS, 1, 255 );
553 RB_RenderDrawSurfListWithFunction( drawSurfs, numDrawSurfs, RB_T_FillDepthBuffer );
555 if ( backEnd.viewDef->numClipPlanes ) {
556 GL_SelectTexture( 1 );
557 globalImages->BindNull();
558 qglDisable( GL_TEXTURE_GEN_S );
559 GL_SelectTexture( 0 );
565 =============================================================================================
569 =============================================================================================
574 RB_SetProgramEnvironment
576 Sets variables that can be used by all vertex programs
579 void RB_SetProgramEnvironment( void ) {
583 if ( !glConfig.ARBVertexProgramAvailable ) {
588 // screen power of two correction factor, one pixel in so we don't get a bilerp
589 // of an uncopied pixel
590 int w = backEnd.viewDef->viewport.x2 - backEnd.viewDef->viewport.x1 + 1;
591 pot = globalImages->currentRenderImage->uploadWidth;
595 parm[0] = (float)(w-1) / pot;
598 int h = backEnd.viewDef->viewport.y2 - backEnd.viewDef->viewport.y1 + 1;
599 pot = globalImages->currentRenderImage->uploadHeight;
603 parm[1] = (float)(h-1) / pot;
608 qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, 0, parm );
610 // screen power of two correction factor, assuming the copy to _currentRender
611 // also copied an extra row and column for the bilerp
612 int w = backEnd.viewDef->viewport.x2 - backEnd.viewDef->viewport.x1 + 1;
613 pot = globalImages->currentRenderImage->uploadWidth;
614 parm[0] = (float)w / pot;
616 int h = backEnd.viewDef->viewport.y2 - backEnd.viewDef->viewport.y1 + 1;
617 pot = globalImages->currentRenderImage->uploadHeight;
618 parm[1] = (float)h / pot;
622 qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, 0, parm );
625 qglProgramEnvParameter4fvARB( GL_FRAGMENT_PROGRAM_ARB, 0, parm );
627 // window coord to 0.0 to 1.0 conversion
632 qglProgramEnvParameter4fvARB( GL_FRAGMENT_PROGRAM_ARB, 1, parm );
635 // set eye position in global space
637 parm[0] = backEnd.viewDef->renderView.vieworg[0];
638 parm[1] = backEnd.viewDef->renderView.vieworg[1];
639 parm[2] = backEnd.viewDef->renderView.vieworg[2];
641 qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, 1, parm );
648 RB_SetProgramEnvironmentSpace
650 Sets variables related to the current space that can be used by all vertex programs
653 void RB_SetProgramEnvironmentSpace( void ) {
654 if ( !glConfig.ARBVertexProgramAvailable ) {
658 const struct viewEntity_s *space = backEnd.currentSpace;
661 // set eye position in local space
662 R_GlobalPointToLocal( space->modelMatrix, backEnd.viewDef->renderView.vieworg, *(idVec3 *)parm );
664 qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, 5, parm );
666 // we need the model matrix without it being combined with the view matrix
667 // so we can transform local vectors to global coordinates
668 parm[0] = space->modelMatrix[0];
669 parm[1] = space->modelMatrix[4];
670 parm[2] = space->modelMatrix[8];
671 parm[3] = space->modelMatrix[12];
672 qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, 6, parm );
673 parm[0] = space->modelMatrix[1];
674 parm[1] = space->modelMatrix[5];
675 parm[2] = space->modelMatrix[9];
676 parm[3] = space->modelMatrix[13];
677 qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, 7, parm );
678 parm[0] = space->modelMatrix[2];
679 parm[1] = space->modelMatrix[6];
680 parm[2] = space->modelMatrix[10];
681 parm[3] = space->modelMatrix[14];
682 qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, 8, parm );
687 RB_STD_T_RenderShaderPasses
689 This is also called for the generated 2D rendering
692 void RB_STD_T_RenderShaderPasses( const drawSurf_t *surf ) {
694 const idMaterial *shader;
695 const shaderStage_t *pStage;
698 const srfTriangles_t *tri;
701 shader = surf->material;
703 if ( !shader->HasAmbient() ) {
707 if ( shader->IsPortalSky() ) {
711 // change the matrix if needed
712 if ( surf->space != backEnd.currentSpace ) {
713 qglLoadMatrixf( surf->space->modelViewMatrix );
714 backEnd.currentSpace = surf->space;
715 RB_SetProgramEnvironmentSpace();
718 // change the scissor if needed
719 if ( r_useScissor.GetBool() && !backEnd.currentScissor.Equals( surf->scissorRect ) ) {
720 backEnd.currentScissor = surf->scissorRect;
721 qglScissor( backEnd.viewDef->viewport.x1 + backEnd.currentScissor.x1,
722 backEnd.viewDef->viewport.y1 + backEnd.currentScissor.y1,
723 backEnd.currentScissor.x2 + 1 - backEnd.currentScissor.x1,
724 backEnd.currentScissor.y2 + 1 - backEnd.currentScissor.y1 );
727 // some deforms may disable themselves by setting numIndexes = 0
728 if ( !tri->numIndexes ) {
732 if ( !tri->ambientCache ) {
733 common->Printf( "RB_T_RenderShaderPasses: !tri->ambientCache\n" );
737 // get the expressions for conditionals / color / texcoords
738 regs = surf->shaderRegisters;
740 // set face culling appropriately
741 GL_Cull( shader->GetCullType() );
743 // set polygon offset if necessary
744 if ( shader->TestMaterialFlag(MF_POLYGONOFFSET) ) {
745 qglEnable( GL_POLYGON_OFFSET_FILL );
746 qglPolygonOffset( r_offsetFactor.GetFloat(), r_offsetUnits.GetFloat() * shader->GetPolygonOffset() );
749 if ( surf->space->weaponDepthHack ) {
750 RB_EnterWeaponDepthHack();
753 if ( surf->space->modelDepthHack != 0.0f ) {
754 RB_EnterModelDepthHack( surf->space->modelDepthHack );
757 idDrawVert *ac = (idDrawVert *)vertexCache.Position( tri->ambientCache );
758 qglVertexPointer( 3, GL_FLOAT, sizeof( idDrawVert ), ac->xyz.ToFloatPtr() );
759 qglTexCoordPointer( 2, GL_FLOAT, sizeof( idDrawVert ), reinterpret_cast<void *>(&ac->st) );
761 for ( stage = 0; stage < shader->GetNumStages() ; stage++ ) {
762 pStage = shader->GetStage(stage);
764 // check the enable condition
765 if ( regs[ pStage->conditionRegister ] == 0 ) {
769 // skip the stages involved in lighting
770 if ( pStage->lighting != SL_AMBIENT ) {
774 // skip if the stage is ( GL_ZERO, GL_ONE ), which is used for some alpha masks
775 if ( ( pStage->drawStateBits & (GLS_SRCBLEND_BITS|GLS_DSTBLEND_BITS) ) == ( GLS_SRCBLEND_ZERO | GLS_DSTBLEND_ONE ) ) {
779 // see if we are a new-style stage
780 newShaderStage_t *newStage = pStage->newStage;
782 //--------------------------
786 //--------------------------
788 // completely skip the stage if we don't have the capability
789 if ( tr.backEndRenderer != BE_ARB2 ) {
792 if ( r_skipNewAmbient.GetBool() ) {
795 qglColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( idDrawVert ), (void *)&ac->color );
796 qglVertexAttribPointerARB( 9, 3, GL_FLOAT, false, sizeof( idDrawVert ), ac->tangents[0].ToFloatPtr() );
797 qglVertexAttribPointerARB( 10, 3, GL_FLOAT, false, sizeof( idDrawVert ), ac->tangents[1].ToFloatPtr() );
798 qglNormalPointer( GL_FLOAT, sizeof( idDrawVert ), ac->normal.ToFloatPtr() );
800 qglEnableClientState( GL_COLOR_ARRAY );
801 qglEnableVertexAttribArrayARB( 9 );
802 qglEnableVertexAttribArrayARB( 10 );
803 qglEnableClientState( GL_NORMAL_ARRAY );
805 GL_State( pStage->drawStateBits );
807 qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, newStage->vertexProgram );
808 qglEnable( GL_VERTEX_PROGRAM_ARB );
810 // megaTextures bind a lot of images and set a lot of parameters
811 if ( newStage->megaTexture ) {
812 newStage->megaTexture->SetMappingForSurface( tri );
814 R_GlobalPointToLocal( surf->space->modelMatrix, backEnd.viewDef->renderView.vieworg, localViewer );
815 newStage->megaTexture->BindForViewOrigin( localViewer );
818 for ( int i = 0 ; i < newStage->numVertexParms ; i++ ) {
820 parm[0] = regs[ newStage->vertexParms[i][0] ];
821 parm[1] = regs[ newStage->vertexParms[i][1] ];
822 parm[2] = regs[ newStage->vertexParms[i][2] ];
823 parm[3] = regs[ newStage->vertexParms[i][3] ];
824 qglProgramLocalParameter4fvARB( GL_VERTEX_PROGRAM_ARB, i, parm );
827 for ( int i = 0 ; i < newStage->numFragmentProgramImages ; i++ ) {
828 if ( newStage->fragmentProgramImages[i] ) {
829 GL_SelectTexture( i );
830 newStage->fragmentProgramImages[i]->Bind();
833 qglBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, newStage->fragmentProgram );
834 qglEnable( GL_FRAGMENT_PROGRAM_ARB );
837 RB_DrawElementsWithCounters( tri );
839 for ( int i = 1 ; i < newStage->numFragmentProgramImages ; i++ ) {
840 if ( newStage->fragmentProgramImages[i] ) {
841 GL_SelectTexture( i );
842 globalImages->BindNull();
845 if ( newStage->megaTexture ) {
846 newStage->megaTexture->Unbind();
849 GL_SelectTexture( 0 );
851 qglDisable( GL_VERTEX_PROGRAM_ARB );
852 qglDisable( GL_FRAGMENT_PROGRAM_ARB );
853 // Fixme: Hack to get around an apparent bug in ATI drivers. Should remove as soon as it gets fixed.
854 qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, 0 );
856 qglDisableClientState( GL_COLOR_ARRAY );
857 qglDisableVertexAttribArrayARB( 9 );
858 qglDisableVertexAttribArrayARB( 10 );
859 qglDisableClientState( GL_NORMAL_ARRAY );
863 //--------------------------
867 //--------------------------
870 color[0] = regs[ pStage->color.registers[0] ];
871 color[1] = regs[ pStage->color.registers[1] ];
872 color[2] = regs[ pStage->color.registers[2] ];
873 color[3] = regs[ pStage->color.registers[3] ];
875 // skip the entire stage if an add would be black
876 if ( ( pStage->drawStateBits & (GLS_SRCBLEND_BITS|GLS_DSTBLEND_BITS) ) == ( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE )
877 && color[0] <= 0 && color[1] <= 0 && color[2] <= 0 ) {
881 // skip the entire stage if a blend would be completely transparent
882 if ( ( pStage->drawStateBits & (GLS_SRCBLEND_BITS|GLS_DSTBLEND_BITS) ) == ( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA )
887 // select the vertex color source
888 if ( pStage->vertexColor == SVC_IGNORE ) {
889 qglColor4fv( color );
891 qglColorPointer( 4, GL_UNSIGNED_BYTE, sizeof( idDrawVert ), (void *)&ac->color );
892 qglEnableClientState( GL_COLOR_ARRAY );
894 if ( pStage->vertexColor == SVC_INVERSE_MODULATE ) {
895 GL_TexEnv( GL_COMBINE_ARB );
896 qglTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE );
897 qglTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE );
898 qglTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PRIMARY_COLOR_ARB );
899 qglTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR );
900 qglTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_ONE_MINUS_SRC_COLOR );
901 qglTexEnvi( GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1 );
904 // for vertex color and modulated color, we need to enable a second
906 if ( color[0] != 1 || color[1] != 1 || color[2] != 1 || color[3] != 1 ) {
907 GL_SelectTexture( 1 );
909 globalImages->whiteImage->Bind();
910 GL_TexEnv( GL_COMBINE_ARB );
912 qglTexEnvfv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color );
914 qglTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE );
915 qglTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS_ARB );
916 qglTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_CONSTANT_ARB );
917 qglTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR );
918 qglTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, GL_SRC_COLOR );
919 qglTexEnvi( GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, 1 );
921 qglTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE );
922 qglTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PREVIOUS_ARB );
923 qglTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_CONSTANT_ARB );
924 qglTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA );
925 qglTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA );
926 qglTexEnvi( GL_TEXTURE_ENV, GL_ALPHA_SCALE, 1 );
928 GL_SelectTexture( 0 );
933 RB_BindVariableStageImage( &pStage->texture, regs );
936 GL_State( pStage->drawStateBits );
938 RB_PrepareStageTexturing( pStage, surf, ac );
941 RB_DrawElementsWithCounters( tri );
943 RB_FinishStageTexturing( pStage, surf, ac );
945 if ( pStage->vertexColor != SVC_IGNORE ) {
946 qglDisableClientState( GL_COLOR_ARRAY );
948 GL_SelectTexture( 1 );
949 GL_TexEnv( GL_MODULATE );
950 globalImages->BindNull();
951 GL_SelectTexture( 0 );
952 GL_TexEnv( GL_MODULATE );
956 // reset polygon offset
957 if ( shader->TestMaterialFlag(MF_POLYGONOFFSET) ) {
958 qglDisable( GL_POLYGON_OFFSET_FILL );
960 if ( surf->space->weaponDepthHack || surf->space->modelDepthHack != 0.0f ) {
966 =====================
967 RB_STD_DrawShaderPasses
969 Draw non-light dependent passes
970 =====================
972 int RB_STD_DrawShaderPasses( drawSurf_t **drawSurfs, int numDrawSurfs ) {
975 // only obey skipAmbient if we are rendering a view
976 if ( backEnd.viewDef->viewEntitys && r_skipAmbient.GetBool() ) {
980 RB_LogComment( "---------- RB_STD_DrawShaderPasses ----------\n" );
982 // if we are about to draw the first surface that needs
983 // the rendering in a texture, copy it over
984 if ( drawSurfs[0]->material->GetSort() >= SS_POST_PROCESS ) {
985 if ( r_skipPostProcess.GetBool() ) {
989 // only dump if in a 3d view
990 if ( backEnd.viewDef->viewEntitys && tr.backEndRenderer == BE_ARB2 ) {
991 globalImages->currentRenderImage->CopyFramebuffer( backEnd.viewDef->viewport.x1,
992 backEnd.viewDef->viewport.y1, backEnd.viewDef->viewport.x2 - backEnd.viewDef->viewport.x1 + 1,
993 backEnd.viewDef->viewport.y2 - backEnd.viewDef->viewport.y1 + 1, true );
995 backEnd.currentRenderCopied = true;
998 GL_SelectTexture( 1 );
999 globalImages->BindNull();
1001 GL_SelectTexture( 0 );
1002 qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
1004 RB_SetProgramEnvironment();
1006 // we don't use RB_RenderDrawSurfListWithFunction()
1007 // because we want to defer the matrix load because many
1008 // surfaces won't draw any ambient passes
1009 backEnd.currentSpace = NULL;
1010 for (i = 0 ; i < numDrawSurfs ; i++ ) {
1011 if ( drawSurfs[i]->material->SuppressInSubview() ) {
1015 if ( backEnd.viewDef->isXraySubview && drawSurfs[i]->space->entityDef ) {
1016 if ( drawSurfs[i]->space->entityDef->parms.xrayIndex != 2 ) {
1021 // we need to draw the post process shaders after we have drawn the fog lights
1022 if ( drawSurfs[i]->material->GetSort() >= SS_POST_PROCESS
1023 && !backEnd.currentRenderCopied ) {
1027 RB_STD_T_RenderShaderPasses( drawSurfs[i] );
1030 GL_Cull( CT_FRONT_SIDED );
1031 qglColor3f( 1, 1, 1 );
1039 ==============================================================================
1041 BACK END RENDERING OF STENCIL SHADOWS
1043 ==============================================================================
1047 =====================
1050 the shadow volumes face INSIDE
1051 =====================
1053 static void RB_T_Shadow( const drawSurf_t *surf ) {
1054 const srfTriangles_t *tri;
1056 // set the light position if we are using a vertex program to project the rear surfaces
1057 if ( tr.backEndRendererHasVertexPrograms && r_useShadowVertexProgram.GetBool()
1058 && surf->space != backEnd.currentSpace ) {
1061 R_GlobalPointToLocal( surf->space->modelMatrix, backEnd.vLight->globalLightOrigin, localLight.ToVec3() );
1062 localLight.w = 0.0f;
1063 qglProgramEnvParameter4fvARB( GL_VERTEX_PROGRAM_ARB, PP_LIGHT_ORIGIN, localLight.ToFloatPtr() );
1068 if ( !tri->shadowCache ) {
1072 qglVertexPointer( 4, GL_FLOAT, sizeof( shadowCache_t ), vertexCache.Position(tri->shadowCache) );
1074 // we always draw the sil planes, but we may not need to draw the front or rear caps
1076 bool external = false;
1078 if ( !r_useExternalShadows.GetInteger() ) {
1079 numIndexes = tri->numIndexes;
1080 } else if ( r_useExternalShadows.GetInteger() == 2 ) { // force to no caps for testing
1081 numIndexes = tri->numShadowIndexesNoCaps;
1082 } else if ( !(surf->dsFlags & DSF_VIEW_INSIDE_SHADOW) ) {
1083 // if we aren't inside the shadow projection, no caps are ever needed needed
1084 numIndexes = tri->numShadowIndexesNoCaps;
1086 } else if ( !backEnd.vLight->viewInsideLight && !(surf->geo->shadowCapPlaneBits & SHADOW_CAP_INFINITE) ) {
1087 // if we are inside the shadow projection, but outside the light, and drawing
1088 // a non-infinite shadow, we can skip some caps
1089 if ( backEnd.vLight->viewSeesShadowPlaneBits & surf->geo->shadowCapPlaneBits ) {
1090 // we can see through a rear cap, so we need to draw it, but we can skip the
1091 // caps on the actual surface
1092 numIndexes = tri->numShadowIndexesNoFrontCaps;
1094 // we don't need to draw any caps
1095 numIndexes = tri->numShadowIndexesNoCaps;
1099 // must draw everything
1100 numIndexes = tri->numIndexes;
1104 if( glConfig.depthBoundsTestAvailable && r_useDepthBoundsTest.GetBool() ) {
1105 qglDepthBoundsEXT( surf->scissorRect.zmin, surf->scissorRect.zmax );
1108 // debug visualization
1109 if ( r_showShadows.GetInteger() ) {
1110 if ( r_showShadows.GetInteger() == 3 ) {
1112 qglColor3f( 0.1/backEnd.overBright, 1/backEnd.overBright, 0.1/backEnd.overBright );
1114 // these are the surfaces that require the reverse
1115 qglColor3f( 1/backEnd.overBright, 0.1/backEnd.overBright, 0.1/backEnd.overBright );
1118 // draw different color for turboshadows
1119 if ( surf->geo->shadowCapPlaneBits & SHADOW_CAP_INFINITE ) {
1120 if ( numIndexes == tri->numIndexes ) {
1121 qglColor3f( 1/backEnd.overBright, 0.1/backEnd.overBright, 0.1/backEnd.overBright );
1123 qglColor3f( 1/backEnd.overBright, 0.4/backEnd.overBright, 0.1/backEnd.overBright );
1126 if ( numIndexes == tri->numIndexes ) {
1127 qglColor3f( 0.1/backEnd.overBright, 1/backEnd.overBright, 0.1/backEnd.overBright );
1128 } else if ( numIndexes == tri->numShadowIndexesNoFrontCaps ) {
1129 qglColor3f( 0.1/backEnd.overBright, 1/backEnd.overBright, 0.6/backEnd.overBright );
1131 qglColor3f( 0.6/backEnd.overBright, 1/backEnd.overBright, 0.1/backEnd.overBright );
1136 qglStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
1137 qglDisable( GL_STENCIL_TEST );
1138 GL_Cull( CT_TWO_SIDED );
1139 RB_DrawShadowElementsWithCounters( tri, numIndexes );
1140 GL_Cull( CT_FRONT_SIDED );
1141 qglEnable( GL_STENCIL_TEST );
1146 // patent-free work around
1148 // "preload" the stencil buffer with the number of volumes
1149 // that get clipped by the near or far clip plane
1150 qglStencilOp( GL_KEEP, tr.stencilDecr, tr.stencilDecr );
1151 GL_Cull( CT_FRONT_SIDED );
1152 RB_DrawShadowElementsWithCounters( tri, numIndexes );
1153 qglStencilOp( GL_KEEP, tr.stencilIncr, tr.stencilIncr );
1154 GL_Cull( CT_BACK_SIDED );
1155 RB_DrawShadowElementsWithCounters( tri, numIndexes );
1158 // traditional depth-pass stencil shadows
1159 qglStencilOp( GL_KEEP, GL_KEEP, tr.stencilIncr );
1160 GL_Cull( CT_FRONT_SIDED );
1161 RB_DrawShadowElementsWithCounters( tri, numIndexes );
1163 qglStencilOp( GL_KEEP, GL_KEEP, tr.stencilDecr );
1164 GL_Cull( CT_BACK_SIDED );
1165 RB_DrawShadowElementsWithCounters( tri, numIndexes );
1169 =====================
1170 RB_StencilShadowPass
1172 Stencil test should already be enabled, and the stencil buffer should have
1173 been set to 128 on any surfaces that might receive shadows
1174 =====================
1176 void RB_StencilShadowPass( const drawSurf_t *drawSurfs ) {
1177 if ( !r_shadows.GetBool() ) {
1185 RB_LogComment( "---------- RB_StencilShadowPass ----------\n" );
1187 globalImages->BindNull();
1188 qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
1190 // for visualizing the shadows
1191 if ( r_showShadows.GetInteger() ) {
1192 if ( r_showShadows.GetInteger() == 2 ) {
1194 GL_State( GLS_DEPTHMASK | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_LESS );
1196 // draw as lines, filling the depth buffer
1197 GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO | GLS_POLYMODE_LINE | GLS_DEPTHFUNC_ALWAYS );
1200 // don't write to the color buffer, just the stencil buffer
1201 GL_State( GLS_DEPTHMASK | GLS_COLORMASK | GLS_ALPHAMASK | GLS_DEPTHFUNC_LESS );
1204 if ( r_shadowPolygonFactor.GetFloat() || r_shadowPolygonOffset.GetFloat() ) {
1205 qglPolygonOffset( r_shadowPolygonFactor.GetFloat(), -r_shadowPolygonOffset.GetFloat() );
1206 qglEnable( GL_POLYGON_OFFSET_FILL );
1209 qglStencilFunc( GL_ALWAYS, 1, 255 );
1211 if ( glConfig.depthBoundsTestAvailable && r_useDepthBoundsTest.GetBool() ) {
1212 qglEnable( GL_DEPTH_BOUNDS_TEST_EXT );
1215 RB_RenderDrawSurfChainWithFunction( drawSurfs, RB_T_Shadow );
1217 GL_Cull( CT_FRONT_SIDED );
1219 if ( r_shadowPolygonFactor.GetFloat() || r_shadowPolygonOffset.GetFloat() ) {
1220 qglDisable( GL_POLYGON_OFFSET_FILL );
1223 if ( glConfig.depthBoundsTestAvailable && r_useDepthBoundsTest.GetBool() ) {
1224 qglDisable( GL_DEPTH_BOUNDS_TEST_EXT );
1227 qglEnableClientState( GL_TEXTURE_COORD_ARRAY );
1229 qglStencilFunc( GL_GEQUAL, 128, 255 );
1230 qglStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
1236 =============================================================================================
1238 BLEND LIGHT PROJECTION
1240 =============================================================================================
1244 =====================
1247 =====================
1249 static void RB_T_BlendLight( const drawSurf_t *surf ) {
1250 const srfTriangles_t *tri;
1254 if ( backEnd.currentSpace != surf->space ) {
1255 idPlane lightProject[4];
1258 for ( i = 0 ; i < 4 ; i++ ) {
1259 R_GlobalPlaneToLocal( surf->space->modelMatrix, backEnd.vLight->lightProject[i], lightProject[i] );
1262 GL_SelectTexture( 0 );
1263 qglTexGenfv( GL_S, GL_OBJECT_PLANE, lightProject[0].ToFloatPtr() );
1264 qglTexGenfv( GL_T, GL_OBJECT_PLANE, lightProject[1].ToFloatPtr() );
1265 qglTexGenfv( GL_Q, GL_OBJECT_PLANE, lightProject[2].ToFloatPtr() );
1267 GL_SelectTexture( 1 );
1268 qglTexGenfv( GL_S, GL_OBJECT_PLANE, lightProject[3].ToFloatPtr() );
1271 // this gets used for both blend lights and shadow draws
1272 if ( tri->ambientCache ) {
1273 idDrawVert *ac = (idDrawVert *)vertexCache.Position( tri->ambientCache );
1274 qglVertexPointer( 3, GL_FLOAT, sizeof( idDrawVert ), ac->xyz.ToFloatPtr() );
1275 } else if ( tri->shadowCache ) {
1276 shadowCache_t *sc = (shadowCache_t *)vertexCache.Position( tri->shadowCache );
1277 qglVertexPointer( 3, GL_FLOAT, sizeof( shadowCache_t ), sc->xyz.ToFloatPtr() );
1280 RB_DrawElementsWithCounters( tri );
1285 =====================
1288 Dual texture together the falloff and projection texture with a blend
1289 mode to the framebuffer, instead of interacting with the surface texture
1290 =====================
1292 static void RB_BlendLight( const drawSurf_t *drawSurfs, const drawSurf_t *drawSurfs2 ) {
1293 const idMaterial *lightShader;
1294 const shaderStage_t *stage;
1301 if ( r_skipBlendLights.GetBool() ) {
1304 RB_LogComment( "---------- RB_BlendLight ----------\n" );
1306 lightShader = backEnd.vLight->lightShader;
1307 regs = backEnd.vLight->shaderRegisters;
1309 // texture 1 will get the falloff texture
1310 GL_SelectTexture( 1 );
1311 qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
1312 qglEnable( GL_TEXTURE_GEN_S );
1313 qglTexCoord2f( 0, 0.5 );
1314 backEnd.vLight->falloffImage->Bind();
1316 // texture 0 will get the projected texture
1317 GL_SelectTexture( 0 );
1318 qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
1319 qglEnable( GL_TEXTURE_GEN_S );
1320 qglEnable( GL_TEXTURE_GEN_T );
1321 qglEnable( GL_TEXTURE_GEN_Q );
1323 for ( i = 0 ; i < lightShader->GetNumStages() ; i++ ) {
1324 stage = lightShader->GetStage(i);
1326 if ( !regs[ stage->conditionRegister ] ) {
1330 GL_State( GLS_DEPTHMASK | stage->drawStateBits | GLS_DEPTHFUNC_EQUAL );
1332 GL_SelectTexture( 0 );
1333 stage->texture.image->Bind();
1335 if ( stage->texture.hasMatrix ) {
1336 RB_LoadShaderTextureMatrix( regs, &stage->texture );
1339 // get the modulate values from the light, including alpha, unlike normal lights
1340 backEnd.lightColor[0] = regs[ stage->color.registers[0] ];
1341 backEnd.lightColor[1] = regs[ stage->color.registers[1] ];
1342 backEnd.lightColor[2] = regs[ stage->color.registers[2] ];
1343 backEnd.lightColor[3] = regs[ stage->color.registers[3] ];
1344 qglColor4fv( backEnd.lightColor );
1346 RB_RenderDrawSurfChainWithFunction( drawSurfs, RB_T_BlendLight );
1347 RB_RenderDrawSurfChainWithFunction( drawSurfs2, RB_T_BlendLight );
1349 if ( stage->texture.hasMatrix ) {
1350 GL_SelectTexture( 0 );
1351 qglMatrixMode( GL_TEXTURE );
1353 qglMatrixMode( GL_MODELVIEW );
1357 GL_SelectTexture( 1 );
1358 qglDisable( GL_TEXTURE_GEN_S );
1359 globalImages->BindNull();
1361 GL_SelectTexture( 0 );
1362 qglDisable( GL_TEXTURE_GEN_S );
1363 qglDisable( GL_TEXTURE_GEN_T );
1364 qglDisable( GL_TEXTURE_GEN_Q );
1368 //========================================================================
1370 static idPlane fogPlanes[4];
1373 =====================
1376 =====================
1378 static void RB_T_BasicFog( const drawSurf_t *surf ) {
1379 if ( backEnd.currentSpace != surf->space ) {
1382 GL_SelectTexture( 0 );
1384 R_GlobalPlaneToLocal( surf->space->modelMatrix, fogPlanes[0], local );
1386 qglTexGenfv( GL_S, GL_OBJECT_PLANE, local.ToFloatPtr() );
1388 // R_GlobalPlaneToLocal( surf->space->modelMatrix, fogPlanes[1], local );
1390 local[0] = local[1] = local[2] = 0; local[3] = 0.5;
1391 qglTexGenfv( GL_T, GL_OBJECT_PLANE, local.ToFloatPtr() );
1393 GL_SelectTexture( 1 );
1395 // GL_S is constant per viewer
1396 R_GlobalPlaneToLocal( surf->space->modelMatrix, fogPlanes[2], local );
1397 local[3] += FOG_ENTER;
1398 qglTexGenfv( GL_T, GL_OBJECT_PLANE, local.ToFloatPtr() );
1400 R_GlobalPlaneToLocal( surf->space->modelMatrix, fogPlanes[3], local );
1401 qglTexGenfv( GL_S, GL_OBJECT_PLANE, local.ToFloatPtr() );
1404 RB_T_RenderTriangleSurface( surf );
1414 static void RB_FogPass( const drawSurf_t *drawSurfs, const drawSurf_t *drawSurfs2 ) {
1415 const srfTriangles_t*frustumTris;
1417 const idMaterial *lightShader;
1418 const shaderStage_t *stage;
1421 RB_LogComment( "---------- RB_FogPass ----------\n" );
1423 // create a surface for the light frustom triangles, which are oriented drawn side out
1424 frustumTris = backEnd.vLight->frustumTris;
1426 // if we ran out of vertex cache memory, skip it
1427 if ( !frustumTris->ambientCache ) {
1430 memset( &ds, 0, sizeof( ds ) );
1431 ds.space = &backEnd.viewDef->worldSpace;
1432 ds.geo = frustumTris;
1433 ds.scissorRect = backEnd.viewDef->scissor;
1435 // find the current color and density of the fog
1436 lightShader = backEnd.vLight->lightShader;
1437 regs = backEnd.vLight->shaderRegisters;
1438 // assume fog shaders have only a single stage
1439 stage = lightShader->GetStage(0);
1441 backEnd.lightColor[0] = regs[ stage->color.registers[0] ];
1442 backEnd.lightColor[1] = regs[ stage->color.registers[1] ];
1443 backEnd.lightColor[2] = regs[ stage->color.registers[2] ];
1444 backEnd.lightColor[3] = regs[ stage->color.registers[3] ];
1446 qglColor3fv( backEnd.lightColor );
1448 // calculate the falloff planes
1451 // if they left the default value on, set a fog distance of 500
1452 if ( backEnd.lightColor[3] <= 1.0 ) {
1453 a = -0.5f / DEFAULT_FOG_DISTANCE;
1455 // otherwise, distance = alpha color
1456 a = -0.5f / backEnd.lightColor[3];
1459 GL_State( GLS_DEPTHMASK | GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_DEPTHFUNC_EQUAL );
1461 // texture 0 is the falloff image
1462 GL_SelectTexture( 0 );
1463 globalImages->fogImage->Bind();
1464 //GL_Bind( tr.whiteImage );
1465 qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
1466 qglEnable( GL_TEXTURE_GEN_S );
1467 qglEnable( GL_TEXTURE_GEN_T );
1468 qglTexCoord2f( 0.5f, 0.5f ); // make sure Q is set
1470 fogPlanes[0][0] = a * backEnd.viewDef->worldSpace.modelViewMatrix[2];
1471 fogPlanes[0][1] = a * backEnd.viewDef->worldSpace.modelViewMatrix[6];
1472 fogPlanes[0][2] = a * backEnd.viewDef->worldSpace.modelViewMatrix[10];
1473 fogPlanes[0][3] = a * backEnd.viewDef->worldSpace.modelViewMatrix[14];
1475 fogPlanes[1][0] = a * backEnd.viewDef->worldSpace.modelViewMatrix[0];
1476 fogPlanes[1][1] = a * backEnd.viewDef->worldSpace.modelViewMatrix[4];
1477 fogPlanes[1][2] = a * backEnd.viewDef->worldSpace.modelViewMatrix[8];
1478 fogPlanes[1][3] = a * backEnd.viewDef->worldSpace.modelViewMatrix[12];
1481 // texture 1 is the entering plane fade correction
1482 GL_SelectTexture( 1 );
1483 globalImages->fogEnterImage->Bind();
1484 qglDisableClientState( GL_TEXTURE_COORD_ARRAY );
1485 qglEnable( GL_TEXTURE_GEN_S );
1486 qglEnable( GL_TEXTURE_GEN_T );
1488 // T will get a texgen for the fade plane, which is always the "top" plane on unrotated lights
1489 fogPlanes[2][0] = 0.001f * backEnd.vLight->fogPlane[0];
1490 fogPlanes[2][1] = 0.001f * backEnd.vLight->fogPlane[1];
1491 fogPlanes[2][2] = 0.001f * backEnd.vLight->fogPlane[2];
1492 fogPlanes[2][3] = 0.001f * backEnd.vLight->fogPlane[3];
1494 // S is based on the view origin
1495 float s = backEnd.viewDef->renderView.vieworg * fogPlanes[2].Normal() + fogPlanes[2][3];
1497 fogPlanes[3][0] = 0;
1498 fogPlanes[3][1] = 0;
1499 fogPlanes[3][2] = 0;
1500 fogPlanes[3][3] = FOG_ENTER + s;
1502 qglTexCoord2f( FOG_ENTER + s, FOG_ENTER );
1506 RB_RenderDrawSurfChainWithFunction( drawSurfs, RB_T_BasicFog );
1507 RB_RenderDrawSurfChainWithFunction( drawSurfs2, RB_T_BasicFog );
1509 // the light frustum bounding planes aren't in the depth buffer, so use depthfunc_less instead
1510 // of depthfunc_equal
1511 GL_State( GLS_DEPTHMASK | GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_DEPTHFUNC_LESS );
1512 GL_Cull( CT_BACK_SIDED );
1513 RB_RenderDrawSurfChainWithFunction( &ds, RB_T_BasicFog );
1514 GL_Cull( CT_FRONT_SIDED );
1516 GL_SelectTexture( 1 );
1517 qglDisable( GL_TEXTURE_GEN_S );
1518 qglDisable( GL_TEXTURE_GEN_T );
1519 globalImages->BindNull();
1521 GL_SelectTexture( 0 );
1522 qglDisable( GL_TEXTURE_GEN_S );
1523 qglDisable( GL_TEXTURE_GEN_T );
1532 void RB_STD_FogAllLights( void ) {
1533 viewLight_t *vLight;
1535 if ( r_skipFogLights.GetBool() || r_showOverDraw.GetInteger() != 0
1536 || backEnd.viewDef->isXraySubview /* dont fog in xray mode*/
1541 RB_LogComment( "---------- RB_STD_FogAllLights ----------\n" );
1543 qglDisable( GL_STENCIL_TEST );
1545 for ( vLight = backEnd.viewDef->viewLights ; vLight ; vLight = vLight->next ) {
1546 backEnd.vLight = vLight;
1548 if ( !vLight->lightShader->IsFogLight() && !vLight->lightShader->IsBlendLight() ) {
1552 #if 0 // _D3XP disabled that
1553 if ( r_ignore.GetInteger() ) {
1554 // we use the stencil buffer to guarantee that no pixels will be
1555 // double fogged, which happens in some areas that are thousands of
1556 // units from the origin
1557 backEnd.currentScissor = vLight->scissorRect;
1558 if ( r_useScissor.GetBool() ) {
1559 qglScissor( backEnd.viewDef->viewport.x1 + backEnd.currentScissor.x1,
1560 backEnd.viewDef->viewport.y1 + backEnd.currentScissor.y1,
1561 backEnd.currentScissor.x2 + 1 - backEnd.currentScissor.x1,
1562 backEnd.currentScissor.y2 + 1 - backEnd.currentScissor.y1 );
1564 qglClear( GL_STENCIL_BUFFER_BIT );
1566 qglEnable( GL_STENCIL_TEST );
1568 // only pass on the cleared stencil values
1569 qglStencilFunc( GL_EQUAL, 128, 255 );
1571 // when we pass the stencil test and depth test and are going to draw,
1572 // increment the stencil buffer so we don't ever draw on that pixel again
1573 qglStencilOp( GL_KEEP, GL_KEEP, GL_INCR );
1577 if ( vLight->lightShader->IsFogLight() ) {
1578 RB_FogPass( vLight->globalInteractions, vLight->localInteractions );
1579 } else if ( vLight->lightShader->IsBlendLight() ) {
1580 RB_BlendLight( vLight->globalInteractions, vLight->localInteractions );
1582 qglDisable( GL_STENCIL_TEST );
1585 qglEnable( GL_STENCIL_TEST );
1588 //=========================================================================================
1594 Perform extra blending passes to multiply the entire buffer by
1595 a floating point value
1598 void RB_STD_LightScale( void ) {
1601 if ( backEnd.overBright == 1.0f ) {
1605 if ( r_skipLightScale.GetBool() ) {
1609 RB_LogComment( "---------- RB_STD_LightScale ----------\n" );
1611 // the scissor may be smaller than the viewport for subviews
1612 if ( r_useScissor.GetBool() ) {
1613 qglScissor( backEnd.viewDef->viewport.x1 + backEnd.viewDef->scissor.x1,
1614 backEnd.viewDef->viewport.y1 + backEnd.viewDef->scissor.y1,
1615 backEnd.viewDef->scissor.x2 - backEnd.viewDef->scissor.x1 + 1,
1616 backEnd.viewDef->scissor.y2 - backEnd.viewDef->scissor.y1 + 1 );
1617 backEnd.currentScissor = backEnd.viewDef->scissor;
1620 // full screen blends
1622 qglMatrixMode( GL_PROJECTION );
1625 qglOrtho( 0, 1, 0, 1, -1, 1 );
1627 GL_State( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_SRC_COLOR );
1628 GL_Cull( CT_TWO_SIDED ); // so mirror views also get it
1629 globalImages->BindNull();
1630 qglDisable( GL_DEPTH_TEST );
1631 qglDisable( GL_STENCIL_TEST );
1634 while ( idMath::Fabs( v - backEnd.overBright ) > 0.01 ) { // a little extra slop
1635 f = backEnd.overBright / v;
1640 qglColor3f( f, f, f );
1643 qglBegin( GL_QUADS );
1653 qglEnable( GL_DEPTH_TEST );
1654 qglMatrixMode( GL_MODELVIEW );
1655 GL_Cull( CT_FRONT_SIDED );
1658 //=========================================================================================
1666 void RB_STD_DrawView( void ) {
1667 drawSurf_t **drawSurfs;
1670 RB_LogComment( "---------- RB_STD_DrawView ----------\n" );
1672 backEnd.depthFunc = GLS_DEPTHFUNC_EQUAL;
1674 drawSurfs = (drawSurf_t **)&backEnd.viewDef->drawSurfs[0];
1675 numDrawSurfs = backEnd.viewDef->numDrawSurfs;
1677 // clear the z buffer, set the projection matrix, etc
1678 RB_BeginDrawingView();
1680 // decide how much overbrighting we are going to do
1681 RB_DetermineLightScale();
1683 // fill the depth buffer and clear color buffer to black except on
1685 RB_STD_FillDepthBuffer( drawSurfs, numDrawSurfs );
1687 // main light renderer
1688 switch( tr.backEndRenderer ) {
1690 RB_ARB_DrawInteractions();
1693 RB_ARB2_DrawInteractions();
1696 RB_NV20_DrawInteractions();
1699 RB_NV10_DrawInteractions();
1702 RB_R200_DrawInteractions();
1706 // disable stencil shadow test
1707 qglStencilFunc( GL_ALWAYS, 128, 255 );
1709 // uplight the entire screen to crutch up not having better blending range
1710 RB_STD_LightScale();
1712 // now draw any non-light dependent shading passes
1713 int processed = RB_STD_DrawShaderPasses( drawSurfs, numDrawSurfs );
1715 // fob and blend lights
1716 RB_STD_FogAllLights();
1718 // now draw any post-processing effects using _currentRender
1719 if ( processed < numDrawSurfs ) {
1720 RB_STD_DrawShaderPasses( drawSurfs+processed, numDrawSurfs-processed );
1723 RB_RenderDebugTools( drawSurfs, numDrawSurfs );