void CMistyFog2::Render(CWorldEffectsSystem *system) { if (mFadeAlpha <= 0.0) { return; } qglMatrixMode(GL_PROJECTION); qglPushMatrix(); qglLoadIdentity (); MYgluPerspective (80.0, 1.0, 4, 2048.0); qglMatrixMode(GL_MODELVIEW); qglPushMatrix(); qglLoadIdentity (); qglRotatef (-90, 1, 0, 0); // put Z going up qglRotatef (90, 0, 0, 1); // put Z going up qglRotatef (0, 1, 0, 0); qglRotatef (-90, 0, 1, 0); qglRotatef (-90, 0, 0, 1); qglDisable(GL_TEXTURE_2D); GL_State(GLS_SRCBLEND_SRC_ALPHA|GLS_DSTBLEND_ONE); qglShadeModel (GL_SMOOTH); qglColorPointer(4, GL_FLOAT, 0, mColors); qglEnableClientState(GL_COLOR_ARRAY); qglVertexPointer( 3, GL_FLOAT, 0, mVerts ); qglEnableClientState(GL_VERTEX_ARRAY); if (qglLockArraysEXT) { qglLockArraysEXT(0, MISTYFOG_HEIGHT*MISTYFOG_WIDTH); } qglDrawElements(GL_QUADS, (MISTYFOG_HEIGHT-1)*(MISTYFOG_WIDTH-1)*4, GL_UNSIGNED_INT, mIndexes); if ( qglUnlockArraysEXT ) { qglUnlockArraysEXT(); } qglDisableClientState(GL_COLOR_ARRAY); // qglDisableClientState(GL_VERTEX_ARRAY); backend doesn't ever re=enable this properly qglPopMatrix(); qglMatrixMode(GL_PROJECTION); qglPopMatrix(); qglMatrixMode(GL_MODELVIEW); // bug somewhere in the backend which requires this }
/* ================= RB_ShadowFinish Darken everything that is is a shadow volume. We have to delay this until everything has been shadowed, because otherwise shadows from different body parts would overlap and double darken. ================= */ void RB_ShadowFinish( void ) { #if defined(VV_LIGHTING) && defined(_XBOX) StencilShadower.FinishShadows(); #else if ( r_shadows->integer != 2 ) { return; } if ( glConfig.stencilBits < 4 ) { return; } #ifdef _DEBUG_STENCIL_SHADOWS return; #endif qglEnable( GL_STENCIL_TEST ); qglStencilFunc( GL_NOTEQUAL, 0, 255 ); qglStencilOp( GL_KEEP, GL_KEEP, GL_KEEP ); bool planeZeroBack = false; if (qglIsEnabled(GL_CLIP_PLANE0)) { planeZeroBack = true; qglDisable (GL_CLIP_PLANE0); } GL_Cull(CT_TWO_SIDED); //qglDisable (GL_CULL_FACE); GL_Bind( tr.whiteImage ); qglPushMatrix(); qglLoadIdentity (); // qglColor3f( 0.6f, 0.6f, 0.6f ); // GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO ); // qglColor3f( 1, 0, 0 ); // GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO ); qglColor4f( 0.0f, 0.0f, 0.0f, 0.5f ); //GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA ); GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA ); qglBegin( GL_QUADS ); qglVertex3f( -100, 100, -10 ); qglVertex3f( 100, 100, -10 ); qglVertex3f( 100, -100, -10 ); qglVertex3f( -100, -100, -10 ); qglEnd (); qglColor4f(1,1,1,1); qglDisable( GL_STENCIL_TEST ); if (planeZeroBack) { qglEnable (GL_CLIP_PLANE0); } qglPopMatrix(); #endif // VV_LIGHTING && _XBOX }
/* ================ RB_StageIteratorSky All of the visible sky triangles are in tess Other things could be stuck in here, like birds in the sky, etc ================ */ void RB_StageIteratorSky( void ) { if ( g_bRenderGlowingObjects ) return; if ( r_fastsky->integer ) { return; } if (skyboxportal && !(backEnd.refdef.rdflags & RDF_SKYBOXPORTAL)) { return; } // go through all the polygons and project them onto // the sky box to see which blocks on each side need // to be drawn RB_ClipSkyPolygons( &tess ); // r_showsky will let all the sky blocks be drawn in // front of everything to allow developers to see how // much sky is getting sucked in if ( r_showsky->integer ) { qglDepthRange( 0.0, 0.0 ); } else { qglDepthRange( 1.0, 1.0 ); } // draw the outer skybox if ( tess.shader->sky->outerbox[0] && tess.shader->sky->outerbox[0] != tr.defaultImage ) { qglColor3f( tr.identityLight, tr.identityLight, tr.identityLight ); qglPushMatrix (); GL_State( 0 ); qglTranslatef (backEnd.viewParms.ori.origin[0], backEnd.viewParms.ori.origin[1], backEnd.viewParms.ori.origin[2]); DrawSkyBox( tess.shader ); qglPopMatrix(); } // generate the vertexes for all the clouds, which will be drawn // by the generic shader routine R_BuildCloudData( &tess ); if (tess.numIndexes && tess.numVertexes) { RB_StageIteratorGeneric(); } // draw the inner skybox // back to normal depth range qglDepthRange( 0.0, 1.0 ); // note that sky was drawn so we will draw a sun later backEnd.skyRenderedThisView = qtrue; }
/* ================== RB_STD_LightScale Perform extra blending passes to multiply the entire buffer by a floating point value ================== */ void RB_STD_LightScale( void ) { float v, f; if ( backEnd.overBright == 1.0f ) { return; } if ( r_skipLightScale.GetBool() ) { return; } // the scissor may be smaller than the viewport for subviews if ( r_useScissor.GetBool() ) { qglScissor( backEnd.viewDef->viewport.x1 + backEnd.viewDef->scissor.x1, backEnd.viewDef->viewport.y1 + backEnd.viewDef->scissor.y1, backEnd.viewDef->scissor.x2 - backEnd.viewDef->scissor.x1 + 1, backEnd.viewDef->scissor.y2 - backEnd.viewDef->scissor.y1 + 1 ); backEnd.currentScissor = backEnd.viewDef->scissor; } // full screen blends qglLoadIdentity(); qglMatrixMode( GL_PROJECTION ); qglPushMatrix(); qglLoadIdentity(); qglOrtho( 0, 1, 0, 1, -1, 1 ); GL_State( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_SRC_COLOR ); GL_Cull( CT_TWO_SIDED ); // so mirror views also get it globalImages->BindNull(); qglDisable( GL_DEPTH_TEST ); qglDisable( GL_STENCIL_TEST ); v = 1; while ( idMath::Fabs( v - backEnd.overBright ) > 0.01 ) { // a little extra slop f = backEnd.overBright / v; f /= 2; if ( f > 1 ) { f = 1; } qglColor3f( f, f, f ); v = v * f * 2; qglBegin( GL_QUADS ); qglVertex2f( 0,0 ); qglVertex2f( 0,1 ); qglVertex2f( 1,1 ); qglVertex2f( 1,0 ); qglEnd(); } qglPopMatrix(); qglEnable( GL_DEPTH_TEST ); qglMatrixMode( GL_MODELVIEW ); GL_Cull( CT_FRONT_SIDED ); }
/* ============= RB_DrawRotatePic2 ============= */ const void *RB_RotatePic2 ( const void *data ) { const rotatePicCommand_t *cmd; image_t *image; shader_t *shader; cmd = (const rotatePicCommand_t *)data; shader = cmd->shader; if ( shader->stages[0] ) { image = shader->stages[0]->bundle[0].image[0]; if ( image ) { if ( !backEnd.projection2D ) { RB_SetGL2D(); } // Get our current blend mode, etc. GL_State( shader->stages[0]->stateBits ); qglColor4ubv( backEnd.color2D ); qglPushMatrix(); // rotation point is going to be around the center of the passed in coordinates qglTranslatef( cmd->x, cmd->y, 0 ); qglRotatef( cmd->a, 0.0, 0.0, 1.0 ); GL_Bind( image ); qglBegin( GL_QUADS ); qglTexCoord2f( cmd->s1, cmd->t1); qglVertex2f( -cmd->w * 0.5f, -cmd->h * 0.5f ); qglTexCoord2f( cmd->s2, cmd->t1 ); qglVertex2f( cmd->w * 0.5f, -cmd->h * 0.5f ); qglTexCoord2f( cmd->s2, cmd->t2 ); qglVertex2f( cmd->w * 0.5f, cmd->h * 0.5f ); qglTexCoord2f( cmd->s1, cmd->t2 ); qglVertex2f( -cmd->w * 0.5f, cmd->h * 0.5f ); qglEnd(); qglPopMatrix(); // Hmmm, this is not too cool GL_State( GLS_DEPTHTEST_DISABLE | GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA ); } } return (const void *)(cmd + 1); }
void R_DrawSkyBox (void) { int i; #if 0 qglEnable (GL_BLEND); GL_TexEnv( GL_MODULATE ); qglColor4f (1,1,1,0.5); qglDisable (GL_DEPTH_TEST); #endif if (skyrotate) { // check for no sky at all for (i=0 ; i<6 ; i++) if (skymins[0][i] < skymaxs[0][i] && skymins[1][i] < skymaxs[1][i]) break; if (i == 6) return; // nothing visible } qglPushMatrix (); qglTranslatef (r_origin[0], r_origin[1], r_origin[2]); qglRotatef (r_newrefdef.time * skyrotate, skyaxis[0], skyaxis[1], skyaxis[2]); for (i=0 ; i<6 ; i++) { if (skyrotate) { // hack, forces full sky to draw when rotating skymins[0][i] = -1; skymins[1][i] = -1; skymaxs[0][i] = 1; skymaxs[1][i] = 1; } if (skymins[0][i] >= skymaxs[0][i] || skymins[1][i] >= skymaxs[1][i]) continue; GL_Bind (sky_images[skytexorder[i]]->texnum); qglBegin (GL_QUADS); MakeSkyVec (skymins[0][i], skymins[1][i], i); MakeSkyVec (skymins[0][i], skymaxs[1][i], i); MakeSkyVec (skymaxs[0][i], skymaxs[1][i], i); MakeSkyVec (skymaxs[0][i], skymins[1][i], i); qglEnd (); } qglPopMatrix (); #if 0 glDisable (GL_BLEND); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glColor4f (1,1,1,0.5); glEnable (GL_DEPTH_TEST); #endif }
/* ============== R_DrawSkyBox ============== */ void R_DrawSkyBox( void ) { static const int skytexorder[6] = {0,2,1,3,4,5}; vec5_t verts[4]; int i; if( skyrotate ) { // hack, forces full sky to draw when rotating for( i = 0; i < 6; i++ ) { skymins[0][i] = -1; skymins[1][i] = -1; skymaxs[0][i] = 1; skymaxs[1][i] = 1; } } else { // check for no sky at all for( i = 0; i < 6; i++ ) { if( SKY_VISIBLE( i ) ) { break; } } if( i == 6 ) { return; // nothing visible } } qglPushMatrix (); qglTranslatef (glr.fd.vieworg[0], glr.fd.vieworg[1], glr.fd.vieworg[2]); if( skyrotate ) { qglRotatef (glr.fd.time * skyrotate, skyaxis[0], skyaxis[1], skyaxis[2]); } GL_TexEnv( GL_REPLACE ); GL_Bits( GLS_DEFAULT ); qglVertexPointer( 3, GL_FLOAT, 5*4, &verts[0][0] ); qglTexCoordPointer( 2, GL_FLOAT, 5*4, &verts[0][3] ); for( i = 0; i < 6; i++ ) { if( !SKY_VISIBLE( i ) ) { continue; } GL_BindTexture (sky_images[skytexorder[i]]); MakeSkyVec (skymaxs[0][i], skymins[1][i], i, verts[0]); MakeSkyVec (skymins[0][i], skymins[1][i], i, verts[1]); MakeSkyVec (skymaxs[0][i], skymaxs[1][i], i, verts[2]); MakeSkyVec (skymins[0][i], skymaxs[1][i], i, verts[3]); qglDrawArrays( GL_TRIANGLE_STRIP, 0, 4 ); } qglPopMatrix (); }
/* =================== RB_ShowDepthBuffer Draw the depth buffer as colors =================== */ static void RB_ShowDepthBuffer() { void *depthReadback; if ( !r_showDepth.GetBool() ) { return; } qglPushMatrix(); qglLoadIdentity(); qglMatrixMode( GL_PROJECTION ); qglPushMatrix(); qglLoadIdentity(); qglOrtho( 0, 1, 0, 1, -1, 1 ); qglRasterPos2f( 0, 0 ); qglPopMatrix(); qglMatrixMode( GL_MODELVIEW ); qglPopMatrix(); GL_State( GLS_DEPTHFUNC_ALWAYS ); GL_Color( 1, 1, 1 ); globalImages->BindNull(); depthReadback = R_StaticAlloc( renderSystem->GetWidth() * renderSystem->GetHeight()*4, TAG_RENDER_TOOLS ); memset( depthReadback, 0, renderSystem->GetWidth() * renderSystem->GetHeight()*4 ); qglReadPixels( 0, 0, renderSystem->GetWidth(), renderSystem->GetHeight(), GL_DEPTH_COMPONENT , GL_FLOAT, depthReadback ); #if 0 for ( i = 0; i < renderSystem->GetWidth() * renderSystem->GetHeight(); i++ ) { ((byte *)depthReadback)[i*4] = ((byte *)depthReadback)[i*4+1] = ((byte *)depthReadback)[i*4+2] = 255 * ((float *)depthReadback)[i]; ((byte *)depthReadback)[i*4+3] = 1; } #endif qglDrawPixels( renderSystem->GetWidth(), renderSystem->GetHeight(), GL_RGBA , GL_UNSIGNED_BYTE, depthReadback ); R_StaticFree( depthReadback ); }
void R_DrawSkyBox (void) { int i; if (skyrotate) { // check for no sky at all for (i=0 ; i<6 ; i++) if (skymins[0][i] < skymaxs[0][i] && skymins[1][i] < skymaxs[1][i]) break; if (i == 6) return; // nothing visible } qglPushMatrix (); qglTranslatef (r_origin[0], r_origin[1], r_origin[2]); qglRotatef (r_newrefdef.time * skyrotate, skyaxis[0], skyaxis[1], skyaxis[2]); for (i=0; i<6; i++) { if (skyrotate) { // hack, forces full sky to draw when rotating skymins[0][i] = -1; skymins[1][i] = -1; skymaxs[0][i] = 1; skymaxs[1][i] = 1; } if (skymins[0][i] >= skymaxs[0][i] || skymins[1][i] >= skymaxs[1][i]) continue; GL_Bind (sky_images[skytexorder[i]]->texnum); rb_vertex = rb_index = 0; indexArray[rb_index++] = rb_vertex+0; indexArray[rb_index++] = rb_vertex+1; indexArray[rb_index++] = rb_vertex+2; indexArray[rb_index++] = rb_vertex+0; indexArray[rb_index++] = rb_vertex+2; indexArray[rb_index++] = rb_vertex+3; MakeSkyVec (skymins[0][i], skymins[1][i], i); MakeSkyVec (skymins[0][i], skymaxs[1][i], i); MakeSkyVec (skymaxs[0][i], skymaxs[1][i], i); MakeSkyVec (skymaxs[0][i], skymins[1][i], i); RB_RenderMeshGeneric (true); } qglPopMatrix (); }
/* * RB_StageIteratorSky * * All of the visible sky triangles are in tess * * Other things could be stuck in here, like birds in the sky, etc */ void RB_StageIteratorSky(void) { if(r_fastsky->integer){ return; } /* go through all the polygons and project them onto * the sky box to see which blocks on each side need * to be drawn */ RB_ClipSkyPolygons(&tess); /* r_showsky will let all the sky blocks be drawn in * front of everything to allow developers to see how * much sky is getting sucked in */ if(r_showsky->integer){ qglDepthRange(0.0, 0.0); }else{ qglDepthRange(1.0, 1.0); } /* draw the outer skybox */ if(tess.shader->sky.outerbox[0] && tess.shader->sky.outerbox[0] != tr.defaultImage){ qglColor3f(tr.identityLight, tr.identityLight, tr.identityLight); qglPushMatrix (); GL_State(0); qglTranslatef (backEnd.viewParms.or.origin[0], backEnd.viewParms.or.origin[1], backEnd.viewParms.or.origin[2]); DrawSkyBox(tess.shader); qglPopMatrix(); } /* generate the vertexes for all the clouds, which will be drawn * by the generic shader routine */ R_BuildCloudData(&tess); RB_StageIteratorGeneric(); /* draw the inner skybox */ /* back to normal depth range */ qglDepthRange(0.0, 1.0); /* note that sky was drawn so we will draw a sun later */ backEnd.skyRenderedThisView = qtrue; }
/* =================== RB_ShowIntensity Debugging tool to see how much dynamic range a scene is using. The greatest of the rgb values at each pixel will be used, with the resulting color shading from red at 0 to green at 128 to blue at 255 =================== */ static void RB_ShowIntensity() { byte *colorReadback; int i, j, c; if ( !r_showIntensity.GetBool() ) { return; } colorReadback = (byte *)R_StaticAlloc( renderSystem->GetWidth() * renderSystem->GetHeight() * 4, TAG_RENDER_TOOLS ); qglReadPixels( 0, 0, renderSystem->GetWidth(), renderSystem->GetHeight(), GL_RGBA, GL_UNSIGNED_BYTE, colorReadback ); c = renderSystem->GetWidth() * renderSystem->GetHeight() * 4; for ( i = 0; i < c; i+=4 ) { j = colorReadback[i]; if ( colorReadback[i+1] > j ) { j = colorReadback[i+1]; } if ( colorReadback[i+2] > j ) { j = colorReadback[i+2]; } if ( j < 128 ) { colorReadback[i+0] = 2*(128-j); colorReadback[i+1] = 2*j; colorReadback[i+2] = 0; } else { colorReadback[i+0] = 0; colorReadback[i+1] = 2*(255-j); colorReadback[i+2] = 2*(j-128); } } // draw it back to the screen qglLoadIdentity(); qglMatrixMode( GL_PROJECTION ); GL_State( GLS_DEPTHFUNC_ALWAYS ); qglPushMatrix(); qglLoadIdentity(); qglOrtho( 0, 1, 0, 1, -1, 1 ); qglRasterPos2f( 0, 0 ); qglPopMatrix(); GL_Color( 1, 1, 1 ); globalImages->BindNull(); qglMatrixMode( GL_MODELVIEW ); qglDrawPixels( renderSystem->GetWidth(), renderSystem->GetHeight(), GL_RGBA , GL_UNSIGNED_BYTE, colorReadback ); R_StaticFree( colorReadback ); }
// All of the visible sky triangles are in tess // Other things could be stuck in here, like birds in the sky, etc void RB_StageIteratorSky( void ) { if ( r_fastsky->integer ) { return; } // go through all the polygons and project them onto // the sky box to see which blocks on each side need // to be drawn RB_ClipSkyPolygons( &tess ); // r_showsky will let all the sky blocks be drawn in // front of everything to allow developers to see how // much sky is getting sucked in if ( r_showsky->integer ) { qglDepthRange( 0.0, 0.0 ); } else { qglDepthRange( 1.0, 1.0 ); } // draw the outer skybox if ( tess.shader->sky.outerbox[0] && tess.shader->sky.outerbox[0] != tr.defaultImage ) { qglColor3f( tr.identityLight, tr.identityLight, tr.identityLight ); qglPushMatrix(); GL_State( 0 ); qglTranslatef ( backEnd.viewParms.or.origin.x, backEnd.viewParms.or.origin.y, backEnd.viewParms.or.origin.z ); DrawSkyBox( tess.shader ); qglPopMatrix(); } // generate the vertexes for all the clouds, which will be drawn // by the generic shader routine R_BuildCloudData( &tess ); //QTZFIXME: This causes a load of GL errors when postprocessing is active :S // RB_StageIteratorGeneric(); // draw the inner skybox // back to normal depth range qglDepthRange( 0.0, 1.0 ); // note that sky was drawn so we will draw a sun later backEnd.skyRenderedThisView = qtrue; }
/* ================= RB_PolygonClear This will cover the entire screen with normal rasterization. Texturing is disabled, but the existing glColor, glDepthMask, glColorMask, and the enabled state of depth buffering and stenciling will matter. ================= */ void RB_PolygonClear() { qglPushMatrix(); qglPushAttrib( GL_ALL_ATTRIB_BITS ); qglLoadIdentity(); qglDisable( GL_TEXTURE_2D ); qglDisable( GL_DEPTH_TEST ); qglDisable( GL_CULL_FACE ); qglDisable( GL_SCISSOR_TEST ); qglBegin( GL_POLYGON ); qglVertex3f( -20, -20, -10 ); qglVertex3f( 20, -20, -10 ); qglVertex3f( 20, 20, -10 ); qglVertex3f( -20, 20, -10 ); qglEnd(); qglPopAttrib(); qglPopMatrix(); }
void R_DrawSkyBox (void) { #ifndef PSP int i; if (skyrotate) { // check for no sky at all for (i=0 ; i<6 ; i++) if (skymins[0][i] < skymaxs[0][i] && skymins[1][i] < skymaxs[1][i]) break; if (i == 6) return; // nothing visible } qglPushMatrix (); qglTranslatef (r_origin[0], r_origin[1], r_origin[2]); qglRotatef (r_newrefdef.time * skyrotate, skyaxis[0], skyaxis[1], skyaxis[2]); for (i=0 ; i<6 ; i++) { if (skyrotate) { // hack, forces full sky to draw when rotating skymins[0][i] = -1; skymins[1][i] = -1; skymaxs[0][i] = 1; skymaxs[1][i] = 1; } if (skymins[0][i] >= skymaxs[0][i] || skymins[1][i] >= skymaxs[1][i]) continue; GL_Bind (sky_images[skytexorder[i]]->texnum); qglBegin (GL_QUADS); MakeSkyVec (skymins[0][i], skymins[1][i], i); MakeSkyVec (skymins[0][i], skymaxs[1][i], i); MakeSkyVec (skymaxs[0][i], skymaxs[1][i], i); MakeSkyVec (skymaxs[0][i], skymins[1][i], i); qglEnd (); } qglPopMatrix (); #endif }
/* ============= RB_DrawRotatePic ============= */ const void *RB_RotatePic ( const void *data ) { const rotatePicCommand_t *cmd; image_t *image; shader_t *shader; cmd = (const rotatePicCommand_t *)data; shader = cmd->shader; image = &shader->stages[0].bundle[0].image[0]; if ( image ) { if ( !backEnd.projection2D ) { RB_SetGL2D(); } qglColor4ubv( backEnd.color2D ); qglPushMatrix(); qglTranslatef(cmd->x+cmd->w,cmd->y,0); qglRotatef(cmd->a, 0.0, 0.0, 1.0); GL_Bind( image ); #ifdef _XBOX qglBeginEXT (GL_QUADS, 4, 0, 0, 4, 0); #else qglBegin (GL_QUADS); #endif qglTexCoord2f( cmd->s1, cmd->t1); qglVertex2f( -cmd->w, 0 ); qglTexCoord2f( cmd->s2, cmd->t1 ); qglVertex2f( 0, 0 ); qglTexCoord2f( cmd->s2, cmd->t2 ); qglVertex2f( 0, cmd->h ); qglTexCoord2f( cmd->s1, cmd->t2 ); qglVertex2f( -cmd->w, cmd->h ); qglEnd(); qglPopMatrix(); } return (const void *)(cmd + 1); }
void RB_StageIteratorSky() { if ( r_fastsky->integer ) { return; } GL_Program(); // project all the polygons onto the sky box // to see which blocks on each side need to be drawn RB_ClipSkyPolygons( &tess ); CalcSkyBounds(); // r_showsky will let all the sky blocks be drawn in // front of everything to allow developers to see how // much sky is getting sucked in if ( r_showsky->integer ) { qglDepthRange( 0.0, 0.0 ); } else { qglDepthRange( 1.0, 1.0 ); } // draw the outer skybox if ( tess.shader->sky.outerbox[0] && tess.shader->sky.outerbox[0] != tr.defaultImage ) { qglColor3f( tr.identityLight, tr.identityLight, tr.identityLight ); qglPushMatrix(); GL_State( 0 ); qglTranslatef (backEnd.viewParms.or.origin[0], backEnd.viewParms.or.origin[1], backEnd.viewParms.or.origin[2]); DrawSkyBox( tess.shader ); qglPopMatrix(); } // generate the vertexes for all the clouds (if any) // which will be drawn by the generic shader routine R_BuildCloudData( &tess ); if (tess.numVertexes) ARB_StageIterator(); // back to normal depth range qglDepthRange( 0.0, 1.0 ); }
void GLRB_DrawSkyBox( const skyboxDrawInfo_t* skybox, const float* eye_origin, const float* colorTint ) { int i, j, k; qglColor3fv( colorTint ); qglPushMatrix (); GL_State( 0 ); qglTranslatef( eye_origin[0], eye_origin[1], eye_origin[2] ); for ( i = 0; i < 6; ++i ) { const skyboxSideDrawInfo_t* side = &skybox->sides[i]; if ( !side->image ) continue; GL_Bind( side->image ); for ( j = 0; j < side->stripCount; ++j ) { int start = side->stripInfo[j].offset; int end = side->stripInfo[j].length + start; qglBegin( GL_TRIANGLE_STRIP ); for ( k = start; k < end; ++k ) { qglTexCoord2fv( skybox->tbuffer + 2 * k ); qglVertex3fv( skybox->vbuffer + 3 * k ); } qglEnd(); } } qglPopMatrix(); }
void RB_DistortionFill(void) { float alpha = tr_distortionAlpha; float spost = 0.0f; float spost2 = 0.0f; if ( glConfig.stencilBits < 4 ) { return; } //ok, cap the stupid thing now I guess if (!tr_distortionPrePost) { RB_CaptureScreenImage(); } qglEnable(GL_STENCIL_TEST); qglStencilFunc(GL_NOTEQUAL, 0, 0xFFFFFFFF); qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); qglDisable (GL_CLIP_PLANE0); GL_Cull( CT_TWO_SIDED ); //reset the view matrices and go into ortho mode qglMatrixMode(GL_PROJECTION); qglPushMatrix(); qglLoadIdentity(); qglOrtho(0, glConfig.vidWidth, glConfig.vidHeight, 32, -1, 1); qglMatrixMode(GL_MODELVIEW); qglPushMatrix(); qglLoadIdentity(); if (tr_distortionStretch) { //override spost = tr_distortionStretch; spost2 = tr_distortionStretch; } else { //do slow stretchy effect spost = sin(tr.refdef.time * 0.0005 + tr.refdef.timeFraction * 0.0005); if (spost < 0.0f) { spost = -spost; } spost *= 0.2f; spost2 = sin(tr.refdef.time * 0.0005 + tr.refdef.timeFraction * 0.0005); if (spost2 < 0.0f) { spost2 = -spost2; } spost2 *= 0.08f; } if (alpha != 1.0f) { //blend GL_State(GLS_SRCBLEND_SRC_ALPHA|GLS_DSTBLEND_SRC_ALPHA); } else { //be sure to reset the draw state GL_State(0); } #ifdef HAVE_GLES qglColor4f(1.0f, 1.0f, 1.0f, alpha); GLboolean text = qglIsEnabled(GL_TEXTURE_COORD_ARRAY); GLboolean glcol = qglIsEnabled(GL_COLOR_ARRAY); if (!text) qglEnableClientState(GL_TEXTURE_COORD_ARRAY); if (glcol) qglDisableClientState(GL_COLOR_ARRAY); GLfloat tex[] = { 0 + spost2, 1 - spost, 0 + spost2, 0 + spost, 1 - spost2, 0 + spost, 1 - spost2, 1 - spost }; GLfloat vtx[] = { 0, 0, 0, glConfig.vidHeight, glConfig.vidWidth, glConfig.vidHeight, glConfig.vidWidth, 0 }; qglTexCoordPointer(2, GL_FLOAT, 0, tex); qglVertexPointer(2, GL_FLOAT, 0, vtx); qglDrawArrays(GL_TRIANGLE_FAN, 0, 4); /* if (glcol) qglEnableClientState( GL_COLOR_ARRAY ); if (!text) qglDisableClientState( GL_TEXTURE_COORD_ARRAY );*/ #else qglBegin(GL_QUADS); qglColor4f(1.0f, 1.0f, 1.0f, alpha); qglTexCoord2f(0+spost2, 1-spost); qglVertex2f(0, 0); qglTexCoord2f(0+spost2, 0+spost); qglVertex2f(0, glConfig.vidHeight); qglTexCoord2f(1-spost2, 0+spost); qglVertex2f(glConfig.vidWidth, glConfig.vidHeight); qglTexCoord2f(1-spost2, 1-spost); qglVertex2f(glConfig.vidWidth, 0); qglEnd(); #endif if (tr_distortionAlpha == 1.0f && tr_distortionStretch == 0.0f) { //no overrides if (tr_distortionNegate) { //probably the crazy alternate saber trail alpha = 0.8f; GL_State(GLS_SRCBLEND_ZERO|GLS_DSTBLEND_ONE_MINUS_SRC_COLOR); } else { alpha = 0.5f; GL_State(GLS_SRCBLEND_SRC_ALPHA|GLS_DSTBLEND_SRC_ALPHA); } spost = sin(tr.refdef.time * 0.0008 + tr.refdef.timeFraction * 0.0008); if (spost < 0.0f) { spost = -spost; } spost *= 0.08f; spost2 = sin(tr.refdef.time * 0.0008 + tr.refdef.timeFraction * 0.0008); if (spost2 < 0.0f) { spost2 = -spost2; } spost2 *= 0.2f; #ifdef HAVE_GLES qglColor4f(1.0f, 1.0f, 1.0f, alpha); /* GLboolean text = qglIsEnabled(GL_TEXTURE_COORD_ARRAY); GLboolean glcol = qglIsEnabled(GL_COLOR_ARRAY); if (!text) qglEnableClientState( GL_TEXTURE_COORD_ARRAY ); if (glcol) qglDisableClientState( GL_COLOR_ARRAY );*/ GLfloat tex[] = { 0 + spost2, 1 - spost, 0 + spost2, 0 + spost, 1 - spost2, 0 + spost, 1 - spost2, 1 - spost }; GLfloat vtx[] = { 0, 0, 0, glConfig.vidHeight, glConfig.vidWidth, glConfig.vidHeight, glConfig.vidWidth, 0 }; qglTexCoordPointer(2, GL_FLOAT, 0, tex); qglVertexPointer(2, GL_FLOAT, 0, vtx); qglDrawArrays(GL_TRIANGLE_FAN, 0, 4); #else qglBegin(GL_QUADS); qglColor4f(1.0f, 1.0f, 1.0f, alpha); qglTexCoord2f(0+spost2, 1-spost); qglVertex2f(0, 0); qglTexCoord2f(0+spost2, 0+spost); qglVertex2f(0, glConfig.vidHeight); qglTexCoord2f(1-spost2, 0+spost); qglVertex2f(glConfig.vidWidth, glConfig.vidHeight); qglTexCoord2f(1-spost2, 1-spost); qglVertex2f(glConfig.vidWidth, 0); qglEnd(); #endif } #ifdef HAVE_GLES if (glcol) qglEnableClientState(GL_COLOR_ARRAY); if (!text) qglDisableClientState(GL_TEXTURE_COORD_ARRAY); #endif //pop the view matrices back qglMatrixMode(GL_PROJECTION); qglPopMatrix(); qglMatrixMode(GL_MODELVIEW); qglPopMatrix(); qglDisable( GL_STENCIL_TEST ); }
/* ================= RB_ShadowFinish Darken everything that is is a shadow volume. We have to delay this until everything has been shadowed, because otherwise shadows from different body parts would overlap and double darken. ================= */ void RB_ShadowFinish( void ) { if ( r_shadows->integer != 2 ) { return; } if ( glConfig.stencilBits < 4 ) { return; } #ifdef _DEBUG_STENCIL_SHADOWS return; #endif qglEnable( GL_STENCIL_TEST ); qglStencilFunc( GL_NOTEQUAL, 0, 255 ); qglStencilOp( GL_KEEP, GL_KEEP, GL_KEEP ); bool planeZeroBack = false; if (qglIsEnabled(GL_CLIP_PLANE0)) { planeZeroBack = true; qglDisable (GL_CLIP_PLANE0); } GL_Cull(CT_TWO_SIDED); //qglDisable (GL_CULL_FACE); GL_Bind( tr.whiteImage ); qglPushMatrix(); qglLoadIdentity (); // qglColor3f( 0.6f, 0.6f, 0.6f ); // GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO ); // qglColor3f( 1, 0, 0 ); // GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO ); qglColor4f( 0.0f, 0.0f, 0.0f, 0.5f ); //GL_State( GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA ); GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA ); #ifdef HAVE_GLES GLfloat vtx[] = { -100, 100, -10, 100, 100, -10, 100, -100, -10, -100, -100, -10 }; GLboolean text = qglIsEnabled(GL_TEXTURE_COORD_ARRAY); GLboolean glcol = qglIsEnabled(GL_COLOR_ARRAY); if (text) qglDisableClientState( GL_TEXTURE_COORD_ARRAY ); if (glcol) qglDisableClientState( GL_COLOR_ARRAY ); qglVertexPointer ( 3, GL_FLOAT, 0, vtx ); qglDrawArrays( GL_TRIANGLE_FAN, 0, 4 ); if (text) qglEnableClientState( GL_TEXTURE_COORD_ARRAY ); if (glcol) qglEnableClientState( GL_COLOR_ARRAY ); #else qglBegin( GL_QUADS ); qglVertex3f( -100, 100, -10 ); qglVertex3f( 100, 100, -10 ); qglVertex3f( 100, -100, -10 ); qglVertex3f( -100, -100, -10 ); qglEnd (); #endif qglColor4f(1,1,1,1); qglDisable( GL_STENCIL_TEST ); if (planeZeroBack) { qglEnable (GL_CLIP_PLANE0); } qglPopMatrix(); }
/* ============== RB_DrawSun FIXME: sun should render behind clouds, so passing dark areas cover it up ============== */ void RB_DrawSun(void) { float size; float dist; vec3_t origin, vec1, vec2; byte color[4]; if (!tr.sunShader) { return; } if (!backEnd.skyRenderedThisView) { return; } if (!r_drawSun->integer) { return; } qglPushMatrix(); qglLoadMatrixf(backEnd.viewParms.world.modelMatrix); qglTranslatef(backEnd.viewParms.orientation.origin[0], backEnd.viewParms.orientation.origin[1], backEnd.viewParms.orientation.origin[2]); dist = backEnd.viewParms.zFar / 1.75; // div sqrt(3) // shrunk the size of the sun size = dist * 0.2; VectorScale(tr.sunDirection, dist, origin); PerpendicularVector(vec1, tr.sunDirection); CrossProduct(tr.sunDirection, vec1, vec2); VectorScale(vec1, size, vec1); VectorScale(vec2, size, vec2); // farthest depth range qglDepthRange(1.0, 1.0); color[0] = color[1] = color[2] = color[3] = 255; // simpler sun drawing RB_BeginSurface(tr.sunShader, tess.fogNum); RB_AddQuadStamp(origin, vec1, vec2, color); /* // vec3_t temp; init moved down VectorCopy( origin, temp ); VectorSubtract( temp, vec1, temp ); VectorSubtract( temp, vec2, temp ); VectorCopy( temp, tess.xyz[tess.numVertexes].v ); tess.texCoords0[tess.numVertexes].v[0] = 0; tess.texCoords0[tess.numVertexes].v[1] = 0; tess.vertexColors[tess.numVertexes].v[0] = 255; tess.vertexColors[tess.numVertexes].v[1] = 255; tess.vertexColors[tess.numVertexes].v[2] = 255; tess.numVertexes++; VectorCopy( origin, temp ); VectorAdd( temp, vec1, temp ); VectorSubtract( temp, vec2, temp ); VectorCopy( temp, tess.xyz[tess.numVertexes].v ); tess.texCoords0[tess.numVertexes].v[0] = 0; tess.texCoords0[tess.numVertexes].v[1] = 1; tess.vertexColors[tess.numVertexes].v[0] = 255; tess.vertexColors[tess.numVertexes].v[1] = 255; tess.vertexColors[tess.numVertexes].v[2] = 255; tess.numVertexes++; VectorCopy( origin, temp ); VectorAdd( temp, vec1, temp ); VectorAdd( temp, vec2, temp ); VectorCopy( temp, tess.xyz[tess.numVertexes].v ); tess.texCoords0[tess.numVertexes].v[0] = 1; tess.texCoords0[tess.numVertexes].v[1] = 1; tess.vertexColors[tess.numVertexes].v[0] = 255; tess.vertexColors[tess.numVertexes].v[1] = 255; tess.vertexColors[tess.numVertexes].v[2] = 255; tess.numVertexes++; VectorCopy( origin, temp ); VectorSubtract( temp, vec1, temp ); VectorAdd( temp, vec2, temp ); VectorCopy( temp, tess.xyz[tess.numVertexes].v ); tess.texCoords0[tess.numVertexes].v[0] = 1; tess.texCoords0[tess.numVertexes].v[1] = 0; tess.vertexColors[tess.numVertexes].v[0] = 255; tess.vertexColors[tess.numVertexes].v[1] = 255; tess.vertexColors[tess.numVertexes].v[2] = 255; tess.numVertexes++; tess.indexes[tess.numIndexes++] = 0; tess.indexes[tess.numIndexes++] = 1; tess.indexes[tess.numIndexes++] = 2; tess.indexes[tess.numIndexes++] = 0; tess.indexes[tess.numIndexes++] = 2; tess.indexes[tess.numIndexes++] = 3; */ RB_EndSurface(); if (r_drawSun->integer > 1) // draw flare effect { vec3_t temp; // FYI: This is cheezy and was only a test so far. // If we decide to use the flare business I will /definatly/ improve all this // get a point a little closer dist = dist * 0.7; VectorScale(tr.sunDirection, dist, origin); // and make the flare a little smaller VectorScale(vec1, 0.5f, vec1); VectorScale(vec2, 0.5f, vec2); // add the vectors to give an 'off angle' result VectorAdd(tr.sunDirection, backEnd.viewParms.orientation.axis[0], temp); VectorNormalize(temp); // amplify the result origin[0] += temp[0] * 500.0; origin[1] += temp[1] * 500.0; origin[2] += temp[2] * 500.0; // FIXME: todo: flare effect should render last (on top of everything else) and only when sun is in view (sun moving out of camera past degree n should start to cause flare dimming until view angle to sun is off by angle n + x. // draw the flare RB_BeginSurface(tr.sunflareShader[0], tess.fogNum); RB_AddQuadStamp(origin, vec1, vec2, color); RB_EndSurface(); } // back to normal depth range qglDepthRange(0.0, 1.0); qglPopMatrix(); }
/* ================= R_DrawAliasModel ================= */ void R_DrawAliasModel (entity_t *e) { int i; dmdl_t *paliashdr; float an; vec3_t bbox[8]; image_t *skin; if ( !( e->flags & RF_WEAPONMODEL ) ) { if ( R_CullAliasModel( bbox, e ) ) return; } if ( e->flags & RF_WEAPONMODEL ) { if ( r_lefthand->value == 2 ) return; } paliashdr = (dmdl_t *)currentmodel->extradata; // // get lighting information // // PMM - rewrote, reordered to handle new shells & mixing // if ( currententity->flags & ( RF_SHELL_HALF_DAM | RF_SHELL_GREEN | RF_SHELL_RED | RF_SHELL_BLUE | RF_SHELL_DOUBLE ) ) { // PMM -special case for godmode if ( (currententity->flags & RF_SHELL_RED) && (currententity->flags & RF_SHELL_BLUE) && (currententity->flags & RF_SHELL_GREEN) ) { for (i=0 ; i<3 ; i++) shadelight[i] = 1.0; } else if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_BLUE | RF_SHELL_DOUBLE ) ) { VectorClear (shadelight); if ( currententity->flags & RF_SHELL_RED ) { shadelight[0] = 1.0; if (currententity->flags & (RF_SHELL_BLUE|RF_SHELL_DOUBLE) ) shadelight[2] = 1.0; } else if ( currententity->flags & RF_SHELL_BLUE ) { if ( currententity->flags & RF_SHELL_DOUBLE ) { shadelight[1] = 1.0; shadelight[2] = 1.0; } else { shadelight[2] = 1.0; } } else if ( currententity->flags & RF_SHELL_DOUBLE ) { shadelight[0] = 0.9; shadelight[1] = 0.7; } } else if ( currententity->flags & ( RF_SHELL_HALF_DAM | RF_SHELL_GREEN ) ) { VectorClear (shadelight); // PMM - new colors if ( currententity->flags & RF_SHELL_HALF_DAM ) { shadelight[0] = 0.56; shadelight[1] = 0.59; shadelight[2] = 0.45; } if ( currententity->flags & RF_SHELL_GREEN ) { shadelight[1] = 1.0; } } } //PMM - ok, now flatten these down to range from 0 to 1.0. // max_shell_val = max(shadelight[0], max(shadelight[1], shadelight[2])); // if (max_shell_val > 0) // { // for (i=0; i<3; i++) // { // shadelight[i] = shadelight[i] / max_shell_val; // } // } // pmm else if ( currententity->flags & RF_FULLBRIGHT ) { for (i=0 ; i<3 ; i++) shadelight[i] = 1.0; } else { R_LightPoint (currententity->origin, shadelight); // player lighting hack for communication back to server // big hack! if ( currententity->flags & RF_WEAPONMODEL ) { // pick the greatest component, which should be the same // as the mono value returned by software if (shadelight[0] > shadelight[1]) { if (shadelight[0] > shadelight[2]) r_lightlevel->value = 150*shadelight[0]; else r_lightlevel->value = 150*shadelight[2]; } else { if (shadelight[1] > shadelight[2]) r_lightlevel->value = 150*shadelight[1]; else r_lightlevel->value = 150*shadelight[2]; } } if ( gl_monolightmap->string[0] != '0' ) { float s = shadelight[0]; if ( s < shadelight[1] ) s = shadelight[1]; if ( s < shadelight[2] ) s = shadelight[2]; shadelight[0] = s; shadelight[1] = s; shadelight[2] = s; } } if ( currententity->flags & RF_MINLIGHT ) { for (i=0 ; i<3 ; i++) if (shadelight[i] > 0.1) break; if (i == 3) { shadelight[0] = 0.1; shadelight[1] = 0.1; shadelight[2] = 0.1; } } if ( currententity->flags & RF_GLOW ) { // bonus items will pulse with time float scale; float min; scale = 0.1 * sin(r_newrefdef.time*7); for (i=0 ; i<3 ; i++) { min = shadelight[i] * 0.8; shadelight[i] += scale; if (shadelight[i] < min) shadelight[i] = min; } } // ================= // PGM ir goggles color override if ( r_newrefdef.rdflags & RDF_IRGOGGLES && currententity->flags & RF_IR_VISIBLE) { shadelight[0] = 1.0; shadelight[1] = 0.0; shadelight[2] = 0.0; } // PGM // ================= shadedots = r_avertexnormal_dots[((int)(currententity->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)]; an = currententity->angles[1]/180*M_PI; shadevector[0] = cos(-an); shadevector[1] = sin(-an); shadevector[2] = 1; VectorNormalize (shadevector); // // locate the proper data // c_alias_polys += paliashdr->num_tris; // // draw all the triangles // if (currententity->flags & RF_DEPTHHACK) // hack the depth range to prevent view model from poking into walls qglDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin)); if ( ( currententity->flags & RF_WEAPONMODEL ) && ( r_lefthand->value == 1.0F ) ) { extern void MYgluPerspective( GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar ); qglMatrixMode( GL_PROJECTION ); qglPushMatrix(); qglLoadIdentity(); qglScalef( -1, 1, 1 ); MYgluPerspective( r_newrefdef.fov_y, ( float ) r_newrefdef.width / r_newrefdef.height, 4, 4096); qglMatrixMode( GL_MODELVIEW ); qglCullFace( GL_BACK ); } qglPushMatrix (); e->angles[PITCH] = -e->angles[PITCH]; // sigh. R_RotateForEntity (e); e->angles[PITCH] = -e->angles[PITCH]; // sigh. // select skin if (currententity->skin) skin = currententity->skin; // custom player skin else { if (currententity->skinnum >= MAX_MD2SKINS) skin = currentmodel->skins[0]; else { skin = currentmodel->skins[currententity->skinnum]; if (!skin) skin = currentmodel->skins[0]; } } if (!skin) skin = r_notexture; // fallback... GL_Bind(skin->texnum); // draw it qglShadeModel (GL_SMOOTH); GL_TexEnv( GL_MODULATE ); if ( currententity->flags & RF_TRANSLUCENT ) { qglEnable (GL_BLEND); } if ( (currententity->frame >= paliashdr->num_frames) || (currententity->frame < 0) ) { ri.Con_Printf (PRINT_ALL, "R_DrawAliasModel %s: no such frame %d\n", currentmodel->name, currententity->frame); currententity->frame = 0; currententity->oldframe = 0; } if ( (currententity->oldframe >= paliashdr->num_frames) || (currententity->oldframe < 0)) { ri.Con_Printf (PRINT_ALL, "R_DrawAliasModel %s: no such oldframe %d\n", currentmodel->name, currententity->oldframe); currententity->frame = 0; currententity->oldframe = 0; } if ( !r_lerpmodels->value ) currententity->backlerp = 0; GL_DrawAliasFrameLerp (paliashdr, currententity->backlerp); GL_TexEnv( GL_REPLACE ); qglShadeModel (GL_FLAT); qglPopMatrix (); #if 0 qglDisable( GL_CULL_FACE ); qglPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); qglDisable( GL_TEXTURE_2D ); qglBegin( GL_TRIANGLE_STRIP ); for ( i = 0; i < 8; i++ ) { qglVertex3fv( bbox[i] ); } qglEnd(); qglEnable( GL_TEXTURE_2D ); qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); qglEnable( GL_CULL_FACE ); #endif if ( ( currententity->flags & RF_WEAPONMODEL ) && ( r_lefthand->value == 1.0F ) ) { qglMatrixMode( GL_PROJECTION ); qglPopMatrix(); qglMatrixMode( GL_MODELVIEW ); qglCullFace( GL_FRONT ); } if ( currententity->flags & RF_TRANSLUCENT ) { qglDisable (GL_BLEND); } if (currententity->flags & RF_DEPTHHACK) qglDepthRange (gldepthmin, gldepthmax); #if 1 if (gl_shadows->value && !(currententity->flags & (RF_TRANSLUCENT | RF_WEAPONMODEL))) { qglPushMatrix (); R_RotateForEntity (e); qglDisable (GL_TEXTURE_2D); qglEnable (GL_BLEND); qglColor4f (0,0,0,0.5); GL_DrawAliasShadow (paliashdr, currententity->frame ); qglEnable (GL_TEXTURE_2D); qglDisable (GL_BLEND); qglPopMatrix (); } #endif qglColor4f (1,1,1,1); }
static inline void RB_BlurGlowTexture() { qglDisable (GL_CLIP_PLANE0); GL_Cull( CT_TWO_SIDED ); // Go into orthographic 2d mode. qglMatrixMode(GL_PROJECTION); qglPushMatrix(); qglLoadIdentity(); qglOrtho(0, backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight, 0, -1, 1); qglMatrixMode(GL_MODELVIEW); qglPushMatrix(); qglLoadIdentity(); GL_State(GLS_DEPTHTEST_DISABLE); ///////////////////////////////////////////////////////// // Setup vertex and pixel programs. ///////////////////////////////////////////////////////// // NOTE: The 0.25 is because we're blending 4 textures (so = 1.0) and we want a relatively normalized pixel // intensity distribution, but this won't happen anyways if intensity is higher than 1.0. float fBlurDistribution = r_DynamicGlowIntensity->value * 0.25f; float fBlurWeight[4] = { fBlurDistribution, fBlurDistribution, fBlurDistribution, 1.0f }; // Enable and set the Vertex Program. qglEnable( GL_VERTEX_PROGRAM_ARB ); qglBindProgramARB( GL_VERTEX_PROGRAM_ARB, tr.glowVShader ); // Apply Pixel Shaders. if ( qglCombinerParameterfvNV ) { BeginPixelShader( GL_REGISTER_COMBINERS_NV, tr.glowPShader ); // Pass the blur weight to the regcom. qglCombinerParameterfvNV( GL_CONSTANT_COLOR0_NV, (float*)&fBlurWeight ); } else if ( qglProgramEnvParameter4fARB ) { BeginPixelShader( GL_FRAGMENT_PROGRAM_ARB, tr.glowPShader ); // Pass the blur weight to the Fragment Program. qglProgramEnvParameter4fARB( GL_FRAGMENT_PROGRAM_ARB, 0, fBlurWeight[0], fBlurWeight[1], fBlurWeight[2], fBlurWeight[3] ); } ///////////////////////////////////////////////////////// // Set the blur texture to the 4 texture stages. ///////////////////////////////////////////////////////// // How much to offset each texel by. float fTexelWidthOffset = 0.1f, fTexelHeightOffset = 0.1f; GLuint uiTex = tr.screenGlow; qglActiveTextureARB( GL_TEXTURE3_ARB ); qglEnable( GL_TEXTURE_RECTANGLE_EXT ); qglBindTexture( GL_TEXTURE_RECTANGLE_EXT, uiTex ); qglActiveTextureARB( GL_TEXTURE2_ARB ); qglEnable( GL_TEXTURE_RECTANGLE_EXT ); qglBindTexture( GL_TEXTURE_RECTANGLE_EXT, uiTex ); qglActiveTextureARB( GL_TEXTURE1_ARB ); qglEnable( GL_TEXTURE_RECTANGLE_EXT ); qglBindTexture( GL_TEXTURE_RECTANGLE_EXT, uiTex ); qglActiveTextureARB(GL_TEXTURE0_ARB ); qglDisable( GL_TEXTURE_2D ); qglEnable( GL_TEXTURE_RECTANGLE_EXT ); qglBindTexture( GL_TEXTURE_RECTANGLE_EXT, uiTex ); ///////////////////////////////////////////////////////// // Draw the blur passes (each pass blurs it more, increasing the blur radius ). ///////////////////////////////////////////////////////// //int iTexWidth = backEnd.viewParms.viewportWidth, iTexHeight = backEnd.viewParms.viewportHeight; int iTexWidth = glConfig.vidWidth, iTexHeight = glConfig.vidHeight; for ( int iNumBlurPasses = 0; iNumBlurPasses < r_DynamicGlowPasses->integer; iNumBlurPasses++ ) { // Load the Texel Offsets into the Vertex Program. qglProgramEnvParameter4fARB( GL_VERTEX_PROGRAM_ARB, 0, -fTexelWidthOffset, -fTexelWidthOffset, 0.0f, 0.0f ); qglProgramEnvParameter4fARB( GL_VERTEX_PROGRAM_ARB, 1, -fTexelWidthOffset, fTexelWidthOffset, 0.0f, 0.0f ); qglProgramEnvParameter4fARB( GL_VERTEX_PROGRAM_ARB, 2, fTexelWidthOffset, -fTexelWidthOffset, 0.0f, 0.0f ); qglProgramEnvParameter4fARB( GL_VERTEX_PROGRAM_ARB, 3, fTexelWidthOffset, fTexelWidthOffset, 0.0f, 0.0f ); // After first pass put the tex coords to the viewport size. if ( iNumBlurPasses == 1 ) { if ( !g_bTextureRectangleHack ) { iTexWidth = backEnd.viewParms.viewportWidth; iTexHeight = backEnd.viewParms.viewportHeight; } uiTex = tr.blurImage; qglActiveTextureARB( GL_TEXTURE3_ARB ); qglDisable( GL_TEXTURE_2D ); qglEnable( GL_TEXTURE_RECTANGLE_EXT ); qglBindTexture( GL_TEXTURE_RECTANGLE_EXT, uiTex ); qglActiveTextureARB( GL_TEXTURE2_ARB ); qglDisable( GL_TEXTURE_2D ); qglEnable( GL_TEXTURE_RECTANGLE_EXT ); qglBindTexture( GL_TEXTURE_RECTANGLE_EXT, uiTex ); qglActiveTextureARB( GL_TEXTURE1_ARB ); qglDisable( GL_TEXTURE_2D ); qglEnable( GL_TEXTURE_RECTANGLE_EXT ); qglBindTexture( GL_TEXTURE_RECTANGLE_EXT, uiTex ); qglActiveTextureARB(GL_TEXTURE0_ARB ); qglDisable( GL_TEXTURE_2D ); qglEnable( GL_TEXTURE_RECTANGLE_EXT ); qglBindTexture( GL_TEXTURE_RECTANGLE_EXT, uiTex ); // Copy the current image over. qglBindTexture( GL_TEXTURE_RECTANGLE_EXT, uiTex ); qglCopyTexSubImage2D( GL_TEXTURE_RECTANGLE_EXT, 0, 0, 0, 0, 0, backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight ); } // Draw the fullscreen quad. qglBegin( GL_QUADS ); qglMultiTexCoord2fARB( GL_TEXTURE0_ARB, 0, iTexHeight ); qglVertex2f( 0, 0 ); qglMultiTexCoord2fARB( GL_TEXTURE0_ARB, 0, 0 ); qglVertex2f( 0, backEnd.viewParms.viewportHeight ); qglMultiTexCoord2fARB( GL_TEXTURE0_ARB, iTexWidth, 0 ); qglVertex2f( backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight ); qglMultiTexCoord2fARB( GL_TEXTURE0_ARB, iTexWidth, iTexHeight ); qglVertex2f( backEnd.viewParms.viewportWidth, 0 ); qglEnd(); qglBindTexture( GL_TEXTURE_RECTANGLE_EXT, tr.blurImage ); qglCopyTexSubImage2D( GL_TEXTURE_RECTANGLE_EXT, 0, 0, 0, 0, 0, backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight ); // Increase the texel offsets. // NOTE: This is possibly the most important input to the effect. Even by using an exponential function I've been able to // make it look better (at a much higher cost of course). This is cheap though and still looks pretty great. In the future // I might want to use an actual gaussian equation to correctly calculate the pixel coefficients and attenuates, texel // offsets, gaussian amplitude and radius... fTexelWidthOffset += r_DynamicGlowDelta->value; fTexelHeightOffset += r_DynamicGlowDelta->value; } // Disable multi-texturing. qglActiveTextureARB( GL_TEXTURE3_ARB ); qglDisable( GL_TEXTURE_RECTANGLE_EXT ); qglActiveTextureARB( GL_TEXTURE2_ARB ); qglDisable( GL_TEXTURE_RECTANGLE_EXT ); qglActiveTextureARB( GL_TEXTURE1_ARB ); qglDisable( GL_TEXTURE_RECTANGLE_EXT ); qglActiveTextureARB(GL_TEXTURE0_ARB ); qglDisable( GL_TEXTURE_RECTANGLE_EXT ); qglEnable( GL_TEXTURE_2D ); qglDisable( GL_VERTEX_PROGRAM_ARB ); EndPixelShader(); qglMatrixMode(GL_PROJECTION); qglPopMatrix(); qglMatrixMode(GL_MODELVIEW); qglPopMatrix(); qglDisable( GL_BLEND ); glState.currenttmu = 0; //this matches the last one we activated }
// Draw the glow blur over the screen additively. static inline void RB_DrawGlowOverlay() { qglDisable (GL_CLIP_PLANE0); GL_Cull( CT_TWO_SIDED ); // Go into orthographic 2d mode. qglMatrixMode(GL_PROJECTION); qglPushMatrix(); qglLoadIdentity(); qglOrtho(0, glConfig.vidWidth, glConfig.vidHeight, 0, -1, 1); qglMatrixMode(GL_MODELVIEW); qglPushMatrix(); qglLoadIdentity(); GL_State(GLS_DEPTHTEST_DISABLE); qglDisable( GL_TEXTURE_2D ); qglEnable( GL_TEXTURE_RECTANGLE_EXT ); // For debug purposes. if ( r_DynamicGlow->integer != 2 ) { // Render the normal scene texture. qglBindTexture( GL_TEXTURE_RECTANGLE_EXT, tr.sceneImage ); qglBegin(GL_QUADS); qglColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); qglTexCoord2f( 0, glConfig.vidHeight ); qglVertex2f( 0, 0 ); qglTexCoord2f( 0, 0 ); qglVertex2f( 0, glConfig.vidHeight ); qglTexCoord2f( glConfig.vidWidth, 0 ); qglVertex2f( glConfig.vidWidth, glConfig.vidHeight ); qglTexCoord2f( glConfig.vidWidth, glConfig.vidHeight ); qglVertex2f( glConfig.vidWidth, 0 ); qglEnd(); } // One and Inverse Src Color give a very soft addition, while one one is a bit stronger. With one one we can // use additive blending through multitexture though. if ( r_DynamicGlowSoft->integer ) { qglBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_COLOR ); } else { qglBlendFunc( GL_ONE, GL_ONE ); } qglEnable( GL_BLEND ); // Now additively render the glow texture. qglBindTexture( GL_TEXTURE_RECTANGLE_EXT, tr.blurImage ); qglBegin(GL_QUADS); qglColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); qglTexCoord2f( 0, r_DynamicGlowHeight->integer ); qglVertex2f( 0, 0 ); qglTexCoord2f( 0, 0 ); qglVertex2f( 0, glConfig.vidHeight ); qglTexCoord2f( r_DynamicGlowWidth->integer, 0 ); qglVertex2f( glConfig.vidWidth, glConfig.vidHeight ); qglTexCoord2f( r_DynamicGlowWidth->integer, r_DynamicGlowHeight->integer ); qglVertex2f( glConfig.vidWidth, 0 ); qglEnd(); qglDisable( GL_TEXTURE_RECTANGLE_EXT ); qglEnable( GL_TEXTURE_2D ); qglBlendFunc( GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR ); qglDisable( GL_BLEND ); qglMatrixMode(GL_PROJECTION); qglPopMatrix(); qglMatrixMode(GL_MODELVIEW); qglPopMatrix(); }
void GL_DrawAliasShadow (entity_t *e, dmdl_t *paliashdr, int posenum) { dtrivertx_t *verts; int *order; vec3_t point; float height, lheight; int count; daliasframe_t *frame; lheight = currententity->origin[2] - lightspot[2]; frame = (daliasframe_t *)((byte *)paliashdr + paliashdr->ofs_frames + currententity->frame * paliashdr->framesize); verts = frame->verts; // height = 0; order = (int *)((byte *)paliashdr + paliashdr->ofs_glcmds); height = -lheight + 0.1f; // was 1.0f, lowered shadows to ground more - MrG // Knightmare- don't draw shadow above entity if ((currententity->origin[2]+height) > currententity->origin[2]) return; // Knightmare- don't draw shadows above view origin if (r_newrefdef.vieworg[2] < (currententity->origin[2] + height)) return; qglPushMatrix (); R_RotateForEntity (e, false); qglDisable (GL_TEXTURE_2D); qglEnable (GL_BLEND); qglColor4f (0, 0, 0, gl_shadowalpha->value); // was 0.5 // Knightmare- Stencil shadows by MrG if (gl_config.have_stencil) { qglEnable(GL_STENCIL_TEST); qglStencilFunc(GL_EQUAL, 1, 2); qglStencilOp(GL_KEEP,GL_KEEP,GL_INCR); } // End Stencil shadows - MrG while (1) { // get the vertex count and primitive type count = *order++; if (!count) break; // done if (count < 0) { count = -count; qglBegin (GL_TRIANGLE_FAN); } else qglBegin (GL_TRIANGLE_STRIP); do { // normals and vertexes come from the frame list /* point[0] = verts[order[2]].v[0] * frame->scale[0] + frame->translate[0]; point[1] = verts[order[2]].v[1] * frame->scale[1] + frame->translate[1]; point[2] = verts[order[2]].v[2] * frame->scale[2] + frame->translate[2]; */ memcpy( point, s_lerped[order[2]], sizeof( point ) ); point[0] -= shadevector[0]*(point[2]+lheight); point[1] -= shadevector[1]*(point[2]+lheight); point[2] = height; // height -= 0.001; qglVertex3fv (point); order += 3; // verts++; } while (--count); qglEnd (); } // Knightmare- disable Stencil shadows if (gl_config.have_stencil) qglDisable(GL_STENCIL_TEST); qglColor4f (1,1,1,1); qglEnable (GL_TEXTURE_2D); qglDisable (GL_BLEND); qglPopMatrix (); }
void RB_DistortionFill(void) { float alpha = tr_distortionAlpha; float spost = 0.0f; float spost2 = 0.0f; if ( glConfig.stencilBits < 4 ) { return; } //ok, cap the stupid thing now I guess if (!tr_distortionPrePost) { RB_CaptureScreenImage(); } qglEnable(GL_STENCIL_TEST); qglStencilFunc(GL_NOTEQUAL, 0, 0xFFFFFFFF); qglStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); qglDisable (GL_CLIP_PLANE0); GL_Cull( CT_TWO_SIDED ); //reset the view matrices and go into ortho mode qglMatrixMode(GL_PROJECTION); qglPushMatrix(); qglLoadIdentity(); qglOrtho(0, glConfig.vidWidth, glConfig.vidHeight, 32, -1, 1); qglMatrixMode(GL_MODELVIEW); qglPushMatrix(); qglLoadIdentity(); if (tr_distortionStretch) { //override spost = tr_distortionStretch; spost2 = tr_distortionStretch; } else { //do slow stretchy effect spost = sin(tr.refdef.time*0.0005f); if (spost < 0.0f) { spost = -spost; } spost *= 0.2f; spost2 = sin(tr.refdef.time*0.0005f); if (spost2 < 0.0f) { spost2 = -spost2; } spost2 *= 0.08f; } if (alpha != 1.0f) { //blend GL_State(GLS_SRCBLEND_SRC_ALPHA|GLS_DSTBLEND_SRC_ALPHA); } else { //be sure to reset the draw state GL_State(0); } #ifdef _XBOX qglBeginEXT(GL_QUADS, 4, 0, 0, 4, 0); #else qglBegin(GL_QUADS); #endif // _XBOX qglColor4f(1.0f, 1.0f, 1.0f, alpha); qglTexCoord2f(0+spost2, 1-spost); qglVertex2f(0, 0); qglTexCoord2f(0+spost2, 0+spost); qglVertex2f(0, glConfig.vidHeight); qglTexCoord2f(1-spost2, 0+spost); qglVertex2f(glConfig.vidWidth, glConfig.vidHeight); qglTexCoord2f(1-spost2, 1-spost); qglVertex2f(glConfig.vidWidth, 0); qglEnd(); if (tr_distortionAlpha == 1.0f && tr_distortionStretch == 0.0f) { //no overrides if (tr_distortionNegate) { //probably the crazy alternate saber trail alpha = 0.8f; GL_State(GLS_SRCBLEND_ZERO|GLS_DSTBLEND_ONE_MINUS_SRC_COLOR); } else { alpha = 0.5f; GL_State(GLS_SRCBLEND_SRC_ALPHA|GLS_DSTBLEND_SRC_ALPHA); } spost = sin(tr.refdef.time*0.0008f); if (spost < 0.0f) { spost = -spost; } spost *= 0.08f; spost2 = sin(tr.refdef.time*0.0008f); if (spost2 < 0.0f) { spost2 = -spost2; } spost2 *= 0.2f; #ifdef _XBOX qglBeginEXT(GL_QUADS, 4, 0, 0, 4, 0); #else qglBegin(GL_QUADS); #endif // _XBOX qglColor4f(1.0f, 1.0f, 1.0f, alpha); qglTexCoord2f(0+spost2, 1-spost); qglVertex2f(0, 0); qglTexCoord2f(0+spost2, 0+spost); qglVertex2f(0, glConfig.vidHeight); qglTexCoord2f(1-spost2, 0+spost); qglVertex2f(glConfig.vidWidth, glConfig.vidHeight); qglTexCoord2f(1-spost2, 1-spost); qglVertex2f(glConfig.vidWidth, 0); qglEnd(); } //pop the view matrices back qglMatrixMode(GL_PROJECTION); qglPopMatrix(); qglMatrixMode(GL_MODELVIEW); qglPopMatrix(); qglDisable( GL_STENCIL_TEST ); }
/* ================== RB_RenderFlares Because flares are simulating an occular effect, they should be drawn after everything (all views) in the entire frame has been drawn. Because of the way portals use the depth buffer to mark off areas, the needed information would be lost after each view, so we are forced to draw flares after each view. The resulting artifact is that flares in mirrors or portals don't dim properly when occluded by something in the main view, and portal flares that should extend past the portal edge will be overwritten. ================== */ void RB_RenderFlares(void) { flare_t *f; flare_t **prev; qboolean draw; if (!r_flares->integer) { return; } // turned light flares back on. must evaluate problem id had with this RB_AddDlightFlares(); RB_AddCoronaFlares(); // perform z buffer readback on each flare in this view draw = qfalse; prev = &r_activeFlares; while ((f = *prev) != NULL) { // throw out any flares that weren't added last frame if (f->addedFrame < backEnd.viewParms.frameCount - 1) { *prev = f->next; f->next = r_inactiveFlares; r_inactiveFlares = f; continue; } // don't draw any here that aren't from this scene / portal f->drawIntensity = 0; if (f->frameSceneNum == backEnd.viewParms.frameSceneNum && f->inPortal == backEnd.viewParms.isPortal) { RB_TestFlare(f); if (f->drawIntensity) { draw = qtrue; } else { // this flare has completely faded out, so remove it from the chain *prev = f->next; f->next = r_inactiveFlares; r_inactiveFlares = f; continue; } } prev = &f->next; } if (!draw) { return; // none visible } if (backEnd.viewParms.isPortal) { qglDisable(GL_CLIP_PLANE0); } qglPushMatrix(); qglLoadIdentity(); qglMatrixMode(GL_PROJECTION); qglPushMatrix(); qglLoadIdentity(); qglOrtho(backEnd.viewParms.viewportX, backEnd.viewParms.viewportX + backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportY, backEnd.viewParms.viewportY + backEnd.viewParms.viewportHeight, -99999, 99999); for (f = r_activeFlares ; f ; f = f->next) { if (f->frameSceneNum == backEnd.viewParms.frameSceneNum && f->inPortal == backEnd.viewParms.isPortal && f->drawIntensity) { RB_RenderFlare(f); } } qglPopMatrix(); qglMatrixMode(GL_MODELVIEW); qglPopMatrix(); }
/* ================ RB_StageIteratorSky All of the visible sky triangles are in tess Other things could be stuck in here, like birds in the sky, etc ================ */ void RB_StageIteratorSky( void ) { int clearBits = 0; if ( r_fastsky->integer ) { if (r_fastsky->integer == 2 && !(backEnd.refdef.rdflags & RDF_NOWORLDMODEL)) { clearBits |= GL_COLOR_BUFFER_BIT; // FIXME: only if sky shaders have been used if (*r_fastSkyColor->string) { int v, tr, tg, tb; v = r_fastSkyColor->integer; tr = (v & 0xff0000) / 0x010000; tg = (v & 0x00ff00) / 0x000100; tb = (v & 0x0000ff) / 0x000001; qglClearColor((float)tr / 255.0, (float)tg / 255.0, (float)tb / 255.0, 1.0); } else { qglClearColor(0.0f, 0.0f, 0.0f, 1.0f); // FIXME: get color of sky } qglClear(clearBits); } return; } // go through all the polygons and project them onto // the sky box to see which blocks on each side need // to be drawn RB_ClipSkyPolygons( &tess ); // r_showsky will let all the sky blocks be drawn in // front of everything to allow developers to see how // much sky is getting sucked in if ( r_showsky->integer ) { qglDepthRange( 0.0, 0.0 ); } else { qglDepthRange( 1.0, 1.0 ); } // draw the outer skybox if ( tess.shader->sky.outerbox[0] && tess.shader->sky.outerbox[0] != tr.defaultImage ) { qglColor3f( tr.identityLight, tr.identityLight, tr.identityLight ); qglPushMatrix (); GL_State( 0 ); GL_Cull( CT_FRONT_SIDED ); qglTranslatef (backEnd.viewParms.or.origin[0], backEnd.viewParms.or.origin[1], backEnd.viewParms.or.origin[2]); DrawSkyBox( tess.shader ); qglPopMatrix(); } // generate the vertexes for all the clouds, which will be drawn // by the generic shader routine R_BuildCloudData( &tess ); if (tess.numVertexes) { // yes, sky has cloud stages RB_StageIteratorGeneric(); } // draw the inner skybox //FIXME not even done // back to normal depth range qglDepthRange( 0.0, 1.0 ); // note that sky was drawn so we will draw a sun later backEnd.skyRenderedThisView = qtrue; }
/* ================ RB_StageIteratorSky All of the visible sky triangles are in tess Other things could be stuck in here, like birds in the sky, etc ================ */ void RB_StageIteratorSky( void ) { if ( r_fastsky->integer ) { return; } // when portal sky exists, only render skybox for the portal sky scene if ( skyboxportal && !( backEnd.refdef.rdflags & RDF_SKYBOXPORTAL ) ) { return; } // does the current fog require fastsky? if ( backEnd.viewParms.glFog.registered ) { if ( !backEnd.viewParms.glFog.drawsky ) { return; } } else if ( glfogNum > FOG_NONE ) { if ( !glfogsettings[FOG_CURRENT].drawsky ) { return; } } backEnd.refdef.rdflags |= RDF_DRAWINGSKY; // go through all the polygons and project them onto // the sky box to see which blocks on each side need // to be drawn RB_ClipSkyPolygons( &tess ); // r_showsky will let all the sky blocks be drawn in // front of everything to allow developers to see how // much sky is getting sucked in if ( r_showsky->integer ) { qglDepthRange( 0.0, 0.0 ); } else { qglDepthRange( 1.0, 1.0 ); } // draw the outer skybox if ( tess.shader->sky.outerbox[0] && tess.shader->sky.outerbox[0] != tr.defaultImage ) { qglColor3f( tr.identityLight, tr.identityLight, tr.identityLight ); qglPushMatrix(); GL_State( 0 ); qglTranslatef( backEnd.viewParms.or.origin[0], backEnd.viewParms.or.origin[1], backEnd.viewParms.or.origin[2] ); DrawSkyBox( tess.shader ); qglPopMatrix(); } // generate the vertexes for all the clouds, which will be drawn // by the generic shader routine R_BuildCloudData( &tess ); RB_StageIteratorGeneric(); // draw the inner skybox // Rafael - drawing inner skybox if ( tess.shader->sky.innerbox[0] && tess.shader->sky.innerbox[0] != tr.defaultImage ) { qglColor3f( tr.identityLight, tr.identityLight, tr.identityLight ); qglPushMatrix(); GL_State( 0 ); qglTranslatef( backEnd.viewParms.or.origin[0], backEnd.viewParms.or.origin[1], backEnd.viewParms.or.origin[2] ); DrawSkyBoxInner( tess.shader ); qglPopMatrix(); } // Rafael - end // back to normal depth range qglDepthRange( 0.0, 1.0 ); backEnd.refdef.rdflags &= ~RDF_DRAWINGSKY; // note that sky was drawn so we will draw a sun later backEnd.skyRenderedThisView = qtrue; }
/* ================== RB_RenderFlares Because flares are simulating an occular effect, they should be drawn after everything (all views) in the entire frame has been drawn. Because of the way portals use the depth buffer to mark off areas, the needed information would be lost after each view, so we are forced to draw flares after each view. The resulting artifact is that flares in mirrors or portals don't dim properly when occluded by something in the main view, and portal flares that should extend past the portal edge will be overwritten. ================== */ void RB_RenderFlares (void) { flare_t *f; flare_t **prev; qboolean draw; if ( !r_flares->value ) { return; } if(r_flareCoeff->modified) { if(r_flareCoeff->value == 0.0f) flareCoeff = atof(FLARE_STDCOEFF); else flareCoeff = r_flareCoeff->value; r_flareCoeff->modified = qfalse; } // Reset currentEntity to world so that any previously referenced entities // don't have influence on the rendering of these flares (i.e. RF_ renderer flags). backEnd.currentEntity = &tr.worldEntity; backEnd.or = backEnd.viewParms.world; // RB_AddDlightFlares(); // perform z buffer readback on each flare in this view draw = qfalse; prev = &r_activeFlares; while ( ( f = *prev ) != NULL ) { // throw out any flares that weren't added last frame if ( f->addedFrame < backEnd.viewParms.frameCount - 1 ) { *prev = f->next; f->next = r_inactiveFlares; r_inactiveFlares = f; continue; } // don't draw any here that aren't from this scene / portal f->drawIntensity = 0; if ( f->frameSceneNum == backEnd.viewParms.frameSceneNum && f->inPortal == backEnd.viewParms.isPortal ) { RB_TestFlare( f ); if ( f->drawIntensity ) { draw = qtrue; } else { // this flare has completely faded out, so remove it from the chain *prev = f->next; f->next = r_inactiveFlares; r_inactiveFlares = f; continue; } } prev = &f->next; } if ( !draw ) { return; // none visible } if ( backEnd.viewParms.isPortal ) { qglDisable (GL_CLIP_PLANE0); } qglPushMatrix(); qglLoadIdentity(); qglMatrixMode( GL_PROJECTION ); qglPushMatrix(); qglLoadIdentity(); qglOrtho( backEnd.viewParms.viewportX, backEnd.viewParms.viewportX + backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportY, backEnd.viewParms.viewportY + backEnd.viewParms.viewportHeight, -99999, 99999 ); for ( f = r_activeFlares ; f ; f = f->next ) { if ( f->frameSceneNum == backEnd.viewParms.frameSceneNum && f->inPortal == backEnd.viewParms.isPortal && f->drawIntensity ) { RB_RenderFlare( f ); } } qglPopMatrix(); qglMatrixMode( GL_MODELVIEW ); qglPopMatrix(); }
void R_DrawAliasModel ( entity_t *e ) { int i; dmdl_t *paliashdr; float an; vec3_t bbox [ 8 ]; image_t *skin; if ( !( e->flags & RF_WEAPONMODEL ) ) { if ( R_CullAliasModel( bbox, e ) ) { return; } } if ( e->flags & RF_WEAPONMODEL ) { if ( gl_lefthand->value == 2 ) { return; } } paliashdr = (dmdl_t *) currentmodel->extradata; /* get lighting information */ if ( currententity->flags & ( RF_SHELL_HALF_DAM | RF_SHELL_GREEN | RF_SHELL_RED | RF_SHELL_BLUE | RF_SHELL_DOUBLE ) ) { VectorClear( shadelight ); if ( currententity->flags & RF_SHELL_HALF_DAM ) { shadelight [ 0 ] = 0.56; shadelight [ 1 ] = 0.59; shadelight [ 2 ] = 0.45; } if ( currententity->flags & RF_SHELL_DOUBLE ) { shadelight [ 0 ] = 0.9; shadelight [ 1 ] = 0.7; } if ( currententity->flags & RF_SHELL_RED ) { shadelight [ 0 ] = 1.0; } if ( currententity->flags & RF_SHELL_GREEN ) { shadelight [ 1 ] = 1.0; } if ( currententity->flags & RF_SHELL_BLUE ) { shadelight [ 2 ] = 1.0; } } else if ( currententity->flags & RF_FULLBRIGHT ) { for ( i = 0; i < 3; i++ ) { shadelight [ i ] = 1.0; } } else { R_LightPoint( currententity->origin, shadelight ); /* player lighting hack for communication back to server */ if ( currententity->flags & RF_WEAPONMODEL ) { /* pick the greatest component, which should be the same as the mono value returned by software */ if ( shadelight [ 0 ] > shadelight [ 1 ] ) { if ( shadelight [ 0 ] > shadelight [ 2 ] ) { gl_lightlevel->value = 150 * shadelight [ 0 ]; } else { gl_lightlevel->value = 150 * shadelight [ 2 ]; } } else { if ( shadelight [ 1 ] > shadelight [ 2 ] ) { gl_lightlevel->value = 150 * shadelight [ 1 ]; } else { gl_lightlevel->value = 150 * shadelight [ 2 ]; } } } } if ( currententity->flags & RF_MINLIGHT ) { for ( i = 0; i < 3; i++ ) { if ( shadelight [ i ] > 0.1 ) { break; } } if ( i == 3 ) { shadelight [ 0 ] = 0.1; shadelight [ 1 ] = 0.1; shadelight [ 2 ] = 0.1; } } if ( currententity->flags & RF_GLOW ) { /* bonus items will pulse with time */ float scale; float min; scale = 0.1 * sin( r_newrefdef.time * 7 ); for ( i = 0; i < 3; i++ ) { min = shadelight [ i ] * 0.8; shadelight [ i ] += scale; if ( shadelight [ i ] < min ) { shadelight [ i ] = min; } } } /* ir goggles color override */ if ( r_newrefdef.rdflags & RDF_IRGOGGLES && currententity->flags & RF_IR_VISIBLE ) { shadelight [ 0 ] = 1.0; shadelight [ 1 ] = 0.0; shadelight [ 2 ] = 0.0; } shadedots = r_avertexnormal_dots [ ( (int) ( currententity->angles [ 1 ] * ( SHADEDOT_QUANT / 360.0 ) ) ) & ( SHADEDOT_QUANT - 1 ) ]; an = currententity->angles [ 1 ] / 180 * M_PI; shadevector [ 0 ] = cos( -an ); shadevector [ 1 ] = sin( -an ); shadevector [ 2 ] = 1; VectorNormalize( shadevector ); /* locate the proper data */ c_alias_polys += paliashdr->num_tris; /* draw all the triangles */ if ( currententity->flags & RF_DEPTHHACK ) /* hack the depth range to prevent view model from poking into walls */ { qglDepthRange( gldepthmin, gldepthmin + 0.3 * ( gldepthmax - gldepthmin ) ); } if ( ( currententity->flags & RF_WEAPONMODEL ) && ( gl_lefthand->value == 1.0F ) ) { extern void R_MYgluPerspective ( GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar ); qglMatrixMode( GL_PROJECTION ); qglPushMatrix(); qglLoadIdentity(); qglScalef( -1, 1, 1 ); R_MYgluPerspective( r_newrefdef.fov_y, (float) r_newrefdef.width / r_newrefdef.height, 4, 4096 ); qglMatrixMode( GL_MODELVIEW ); qglCullFace( GL_BACK ); } qglPushMatrix(); e->angles [ PITCH ] = -e->angles [ PITCH ]; R_RotateForEntity( e ); e->angles [ PITCH ] = -e->angles [ PITCH ]; /* select skin */ if ( currententity->skin ) { skin = currententity->skin; /* custom player skin */ } else { if ( currententity->skinnum >= MAX_MD2SKINS ) { skin = currentmodel->skins [ 0 ]; } else { skin = currentmodel->skins [ currententity->skinnum ]; if ( !skin ) { skin = currentmodel->skins [ 0 ]; } } } if ( !skin ) { skin = r_notexture; /* fallback... */ } R_Bind( skin->texnum ); /* draw it */ qglShadeModel( GL_SMOOTH ); R_TexEnv( GL_MODULATE ); if ( currententity->flags & RF_TRANSLUCENT ) { qglEnable( GL_BLEND ); } if ( ( currententity->frame >= paliashdr->num_frames ) || ( currententity->frame < 0 ) ) { ri.Con_Printf( PRINT_ALL, "R_DrawAliasModel %s: no such frame %d\n", currentmodel->name, currententity->frame ); currententity->frame = 0; currententity->oldframe = 0; } if ( ( currententity->oldframe >= paliashdr->num_frames ) || ( currententity->oldframe < 0 ) ) { ri.Con_Printf( PRINT_ALL, "R_DrawAliasModel %s: no such oldframe %d\n", currentmodel->name, currententity->oldframe ); currententity->frame = 0; currententity->oldframe = 0; } if ( !gl_lerpmodels->value ) { currententity->backlerp = 0; } R_DrawAliasFrameLerp( paliashdr, currententity->backlerp ); R_TexEnv( GL_REPLACE ); qglShadeModel( GL_FLAT ); qglPopMatrix(); if ( ( currententity->flags & RF_WEAPONMODEL ) && ( gl_lefthand->value == 1.0F ) ) { qglMatrixMode( GL_PROJECTION ); qglPopMatrix(); qglMatrixMode( GL_MODELVIEW ); qglCullFace( GL_FRONT ); } if ( currententity->flags & RF_TRANSLUCENT ) { qglDisable( GL_BLEND ); } if ( currententity->flags & RF_DEPTHHACK ) { qglDepthRange( gldepthmin, gldepthmax ); } if ( gl_shadows->value && !( currententity->flags & ( RF_TRANSLUCENT | RF_WEAPONMODEL | RF_NOSHADOW ) ) ) { qglPushMatrix(); /* don't rotate shadows on ungodly axes */ qglTranslatef( e->origin [ 0 ], e->origin [ 1 ], e->origin [ 2 ] ); qglRotatef( e->angles [ 1 ], 0, 0, 1 ); qglDisable( GL_TEXTURE_2D ); qglEnable( GL_BLEND ); qglColor4f( 0, 0, 0, 0.5f ); R_DrawAliasShadow( paliashdr, currententity->frame ); qglEnable( GL_TEXTURE_2D ); qglDisable( GL_BLEND ); qglPopMatrix(); } qglColor4f( 1, 1, 1, 1 ); }