/* ================= R_Fog (void) ================= */ void R_Fog( glfog_t *curfog ) { if ( !r_wolffog->integer ) { R_FogOff(); return; } if ( !curfog->registered ) { //----(SA) R_FogOff(); return; } //----(SA) assme values of '0' for these parameters means 'use default' if ( !curfog->density ) { curfog->density = 1; } if ( !curfog->hint ) { curfog->hint = GL_DONT_CARE; } if ( !curfog->mode ) { curfog->mode = GL_LINEAR; } //----(SA) end R_FogOn(); // only send changes if necessary #ifndef VCMODS_OPENGLES qglFogi( GL_FOG_MODE, curfog->mode ); #endif qglFogfv( GL_FOG_COLOR, curfog->color ); qglFogf( GL_FOG_DENSITY, curfog->density ); qglHint( GL_FOG_HINT, curfog->hint ); qglFogf( GL_FOG_START, curfog->start ); if ( r_zfar->value ) { // (SA) allow override for helping level designers test fog distances qglFogf( GL_FOG_END, r_zfar->value ); } else { qglFogf( GL_FOG_END, curfog->end ); } #ifndef VCMODS_OPENGLES // TTimo - from SP NV fog code // NV fog mode if ( glConfig.NVFogAvailable ) { qglFogi( GL_FOG_DISTANCE_MODE_NV, glConfig.NVFogMode ); } // end #endif qglClearColor( curfog->color[0], curfog->color[1], curfog->color[2], curfog->color[3] ); }
/* =========== R_Fog NeVo - draw fog in an area =========== */ void R_Fog (fogmode_t fog) { float colors[4]; // disable fog for now qglDisable(GL_FOG); // Set up our colors colors[0] = fog.red; colors[1] = fog.green; colors[2] = fog.blue; colors[3] = fog.alpha; // Set our mode switch (fog.mode) { case FOGMODE_LINEAR: qglFogi(GL_FOG_MODE, GL_LINEAR); break; case FOGMODE_EXP: qglFogi(GL_FOG_MODE, GL_EXP); break; case FOGMODE_EXP2: qglFogi(GL_FOG_MODE, GL_EXP2); break; default: qglFogi(GL_FOG_MODE, GL_LINEAR); break; } if (gl_config.coordinatefog && fog.usecoords) qglFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT); else qglFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT); // Hint for nicest fog possible qglHint(GL_FOG_HINT, GL_NICEST); qglFogfv(GL_FOG_COLOR, colors); qglFogf(GL_FOG_START, fog.neardist); qglFogf(GL_FOG_END, fog.fardist); qglFogf(GL_FOG_DENSITY, fog.fogdensity); // Reenable fog if (gl_state.fogenabled) qglEnable(GL_FOG); }
/* ================ R_SetFog ================ */ void R_SetFog (void) { if (!r_fogenable) // engine fog not enabled return; // leave fog enabled if set by game DLL r_fogColor[3] = 1.0; qglEnable(GL_FOG); qglClearColor (r_fogColor[0], r_fogColor[1], r_fogColor[2], r_fogColor[3]); // Clear the background color to the fog color qglFogi(GL_FOG_MODE, r_fogmodel); qglFogfv(GL_FOG_COLOR, r_fogColor); if (r_fogmodel == GL_LINEAR) { qglFogf(GL_FOG_START, r_fognear); qglFogf(GL_FOG_END, r_fogfar); } else qglFogf(GL_FOG_DENSITY, r_fogdensity/10000.f); qglHint (GL_FOG_HINT, GL_NICEST); }
/* ===================== RE_AddFogToScene ===================== */ void RE_AddFogToScene( float start, float end, float r, float g, float b, float opacity, float mode, float hint ) { int fogMode[] = { GL_EXP, GL_EXP2, GL_LINEAR }; // Storage For Three Types Of Fog int fogModefilter = mode; // Which Fog To Use int fogHint[] = { GL_DONT_CARE, GL_FASTEST, GL_NICEST };// Storage For Three Types Of Fog int fogHintfilter = hint; // Which Fog To Use float fogColor[4] = {r, g, b, 1.0f}; // Fog Color if ( ( start == 0 && end == 0 ) || opacity == 0 ){ qglDisable(GL_FOG); // Disables GL_FOG return; } else { qglEnable(GL_FOG); // Enables GL_FOG } qglFogi(GL_FOG_MODE, fogMode[fogModefilter]); // Fog Mode qglFogfv(GL_FOG_COLOR, fogColor); // Set Fog Color qglFogf(GL_FOG_DENSITY, opacity); // How Dense Will The Fog Be qglHint(GL_FOG_HINT, fogHint[fogHintfilter]); // Fog Hint Value qglFogf(GL_FOG_START, start); // Fog Start Depth qglFogf(GL_FOG_END, end); // Fog End Depth }
static void RB_IterateStagesGeneric( shaderCommands_t *input ) { int stage; bool UseGLFog = false; bool FogColorChange = false; fog_t *fog = NULL; if (tess.fogNum && tess.shader->fogPass && (tess.fogNum == tr.world->globalFog || tess.fogNum == tr.world->numfogs) && r_drawfog->value == 2) { // only gl fog global fog and the "special fog" fog = tr.world->fogs + tess.fogNum; if (tr.rangedFog) { //ranged fog, used for sniper scope float fStart = fog->parms.depthForOpaque; if (tr.rangedFog < 0.0f) { //special designer override fStart = -tr.rangedFog; } else { //the greater tr.rangedFog is, the more fog we will get between the view point and cull distance if ((tr.distanceCull-fStart) < tr.rangedFog) { //assure a minimum range between fog beginning and cutoff distance fStart = tr.distanceCull-tr.rangedFog; if (fStart < 16.0f) { fStart = 16.0f; } } } qglFogi(GL_FOG_MODE, GL_LINEAR); qglFogf(GL_FOG_START, fStart); qglFogf(GL_FOG_END, tr.distanceCull); } else { qglFogi(GL_FOG_MODE, GL_EXP2); qglFogf(GL_FOG_DENSITY, logtestExp2 / fog->parms.depthForOpaque); } if ( g_bRenderGlowingObjects ) { const float fogColor[3] = { 0.0f, 0.0f, 0.0f }; qglFogfv(GL_FOG_COLOR, fogColor ); } else { qglFogfv(GL_FOG_COLOR, fog->parms.color); } qglEnable(GL_FOG); UseGLFog = true; } for ( stage = 0; stage < input->shader->numUnfoggedPasses; stage++ ) { shaderStage_t *pStage = &tess.xstages[stage]; int forceRGBGen = 0; int stateBits = 0; if ( !pStage->active ) { break; } // Reject this stage if it's not a glow stage but we are doing a glow pass. if ( g_bRenderGlowingObjects && !pStage->glow ) { continue; } if ( stage && r_lightmap->integer && !( pStage->bundle[0].isLightmap || pStage->bundle[1].isLightmap || pStage->bundle[0].vertexLightmap ) ) { break; } stateBits = pStage->stateBits; if ( backEnd.currentEntity ) { assert(backEnd.currentEntity->e.renderfx >= 0); if ( backEnd.currentEntity->e.renderfx & RF_DISINTEGRATE1 ) { // we want to be able to rip a hole in the thing being disintegrated, and by doing the depth-testing it avoids some kinds of artefacts, but will probably introduce others? stateBits = GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_DEPTHMASK_TRUE | GLS_ATEST_GE_C0; } if ( backEnd.currentEntity->e.renderfx & RF_RGB_TINT ) {//want to use RGBGen from ent forceRGBGen = CGEN_ENTITY; } } if (pStage->ss && pStage->ss->surfaceSpriteType) { // We check for surfacesprites AFTER drawing everything else continue; } if (UseGLFog) { if (pStage->mGLFogColorOverride) { qglFogfv(GL_FOG_COLOR, GLFogOverrideColors[pStage->mGLFogColorOverride]); FogColorChange = true; } else if (FogColorChange && fog) { FogColorChange = false; qglFogfv(GL_FOG_COLOR, fog->parms.color); } } if (!input->fading) { //this means ignore this, while we do a fade-out ComputeColors( pStage, forceRGBGen ); } ComputeTexCoords( pStage ); if ( !setArraysOnce ) { qglEnableClientState( GL_COLOR_ARRAY ); qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, input->svars.colors ); } // // do multitexture // if ( pStage->bundle[1].image != 0 ) { DrawMultitextured( input, stage ); } else { static bool lStencilled = false; if ( !setArraysOnce ) { qglTexCoordPointer( 2, GL_FLOAT, 0, input->svars.texcoords[0] ); } // // set state // if ( (tess.shader == tr.distortionShader) || (backEnd.currentEntity && (backEnd.currentEntity->e.renderfx & RF_DISTORTION)) ) { //special distortion effect -rww //tr.screenImage should have been set for this specific entity before we got in here. GL_Bind( tr.screenImage ); GL_Cull(CT_TWO_SIDED); } else if ( pStage->bundle[0].vertexLightmap && ( r_vertexLight->integer && !r_uiFullScreen->integer ) && r_lightmap->integer ) { GL_Bind( tr.whiteImage ); } else R_BindAnimatedImage( &pStage->bundle[0] ); if (tess.shader == tr.distortionShader && glConfig.stencilBits >= 4) { //draw it to the stencil buffer! tr_stencilled = true; lStencilled = true; qglEnable(GL_STENCIL_TEST); qglStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF); qglStencilOp(GL_KEEP, GL_KEEP, GL_INCR); qglColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); //don't depthmask, don't blend.. don't do anything GL_State(0); } else if (backEnd.currentEntity && (backEnd.currentEntity->e.renderfx & RF_FORCE_ENT_ALPHA)) { ForceAlpha((unsigned char *) tess.svars.colors, backEnd.currentEntity->e.shaderRGBA[3]); if (backEnd.currentEntity->e.renderfx & RF_ALPHA_DEPTH) { //depth write, so faces through the model will be stomped over by nearer ones. this works because //we draw RF_FORCE_ENT_ALPHA stuff after everything else, including standard alpha surfs. GL_State(GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_DEPTHMASK_TRUE); } else { GL_State(GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA); } } else { GL_State( stateBits ); } // // draw // R_DrawElements( input->numIndexes, input->indexes ); if (lStencilled) { //re-enable the color buffer, disable stencil test lStencilled = false; qglDisable(GL_STENCIL_TEST); qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } } } if (FogColorChange) { qglFogfv(GL_FOG_COLOR, fog->parms.color); } }
/* ================= RB_Fog ================= */ void RB_Fog( int fogNum ) { //static int lastFogMode = 0; //static vec3_t lastColor = { -1, -1, -1 }; //static float lastDensity = -1; //static int lastHint = -1; //static float lastStart = -1, lastEnd = -1; int fogMode; vec3_t color; float density; int hint; float start, end; if ( !r_useGlFog->integer ) { R_FogOff(); lastGlfogType = FT_NONE; return; } if ( R_IsGlobalFog( fogNum ) ) { lastGlfogType = backEnd.refdef.fogType; switch ( backEnd.refdef.fogType ) { case FT_LINEAR: fogMode = GL_LINEAR; break; case FT_EXP: fogMode = GL_EXP; break; default: R_FogOff(); lastGlfogType = FT_NONE; return; } VectorCopy( backEnd.refdef.fogColor, color ); end = backEnd.refdef.fogDepthForOpaque; density = backEnd.refdef.fogDensity; } else { fog_t *fog; fog = tr.world->fogs + fogNum; if ( !fog->shader ) { R_FogOff(); lastGlfogType = FT_NONE; return; } lastGlfogType = fog->shader->fogParms.fogType; switch ( fog->shader->fogParms.fogType ) { case FT_LINEAR: fogMode = GL_LINEAR; break; case FT_EXP: fogMode = GL_EXP; break; default: R_FogOff(); return; } VectorCopy( fog->shader->fogParms.color, color ); end = fog->shader->fogParms.depthForOpaque; density = fog->shader->fogParms.density; } hint = GL_DONT_CARE; start = 0; RB_FogOn(); // only send changes if necessary //if ( fogMode != lastFogMode ) { qglFogi( GL_FOG_MODE, fogMode ); // lastFogMode = fogMode; //} //if ( color[0] != lastColor[0] || color[1] != lastColor[1] || color[2] != lastColor[2] || !lastFogMode ) { qglFogfv( GL_FOG_COLOR, color ); // VectorCopy( lastColor, color ); //} //if ( density != lastDensity || !lastFogMode ) { qglFogf( GL_FOG_DENSITY, density ); // lastDensity = density; //} //if ( hint != lastHint || !lastFogMode ) { qglHint( GL_FOG_HINT, hint ); // lastHint = hint; //} //if ( start != lastStart || !lastFogMode ) { qglFogf( GL_FOG_START, start ); // lastStart = start; //} //if ( end != lastEnd || !lastFogMode ) { qglFogf( GL_FOG_END, end ); // lastEnd = end; //} #if 0 // ZTM: TODO: Add NVidia fog code? // TTimo - from SP NV fog code // NV fog mode if ( glConfig.NVFogAvailable ) { qglFogi( GL_FOG_DISTANCE_MODE_NV, glConfig.NVFogMode ); } // end #endif //qglClearColor( color[0], color[1], color[2], 1.0f ); }
/* ================= R_Fog (void) ================= */ void R_Fog(glfog_t *curfog) { if (!r_wolffog->integer) { R_FogOff(); return; } if (!curfog->registered) { //----(SA) R_FogOff(); return; } //----(SA) assme values of '0' for these parameters means 'use default' if (!curfog->density) { curfog->density = 1; } if (!curfog->hint) { curfog->hint = GL_DONT_CARE; } if (!curfog->mode) { curfog->mode = GL_LINEAR; } //----(SA) end R_FogOn(); qglFogi(GL_FOG_MODE, curfog->mode); qglFogfv(GL_FOG_COLOR, curfog->color); qglFogf(GL_FOG_DENSITY, curfog->density); qglHint(GL_FOG_HINT, curfog->hint); if (backEnd.refdef.rdflags & RDF_SNOOPERVIEW) { qglFogf(GL_FOG_START, curfog->end); // snooper starts GL fog out further } else { qglFogf(GL_FOG_START, curfog->start); } if (r_zfar->value) { // (SA) allow override for helping level designers test fog distances qglFogf(GL_FOG_END, r_zfar->value); } else { if (backEnd.refdef.rdflags & RDF_SNOOPERVIEW) { qglFogf(GL_FOG_END, curfog->end + 1000); // snooper ends GL fog out further. this works fine with our maps, but could be 'funky' with later maps } else { qglFogf(GL_FOG_END, curfog->end); } } #ifndef USE_OPENGLES //----(SA) added // NV fog mode if (glConfig.NVFogAvailable) { qglFogi(GL_FOG_DISTANCE_MODE_NV, glConfig.NVFogMode); } //----(SA) end #endif qglClearColor(curfog->color[0], curfog->color[1], curfog->color[2], curfog->color[3]); }