/* ==================== RE_SetGlobalFog rgb = colour depthForOpaque is depth for opaque the restore flag can be used to restore the original level fog duration can be set to fade over a certain period ==================== */ void RE_SetGlobalFog(qboolean restore, int duration, float r, float g, float b, float depthForOpaque) { ri.Printf(PRINT_DEVELOPER, "RE_SetGlobalFog( restore = %i, duration = %i, r = %f, g = %f, b = %f, depthForOpaque = %f )\n", restore, duration, r, g, b, depthForOpaque); if(restore) { if(duration > 0) { VectorCopy(tr.world->fogs[tr.world->globalFog].fogParms.color, tr.world->globalTransStartFog); tr.world->globalTransStartFog[3] = tr.world->fogs[tr.world->globalFog].fogParms.depthForOpaque; Vector4Copy(tr.world->globalOriginalFog, tr.world->globalTransEndFog); tr.world->globalFogTransStartTime = tr.refdef.time; tr.world->globalFogTransEndTime = tr.refdef.time + duration; } else { VectorCopy(tr.world->globalOriginalFog, tr.world->fogs[tr.world->globalFog].fogParms.color); tr.world->fogs[tr.world->globalFog].fogParms.colorInt = ColorBytes4(tr.world->globalOriginalFog[0] * tr.identityLight, tr.world->globalOriginalFog[1] * tr.identityLight, tr.world->globalOriginalFog[2] * tr.identityLight, 1.0); tr.world->fogs[tr.world->globalFog].fogParms.depthForOpaque = tr.world->globalOriginalFog[3]; tr.world->fogs[tr.world->globalFog].tcScale = 1.0f / (tr.world->fogs[tr.world->globalFog].fogParms.depthForOpaque); } } else { if(duration > 0) { VectorCopy(tr.world->fogs[tr.world->globalFog].fogParms.color, tr.world->globalTransStartFog); tr.world->globalTransStartFog[3] = tr.world->fogs[tr.world->globalFog].fogParms.depthForOpaque; VectorSet(tr.world->globalTransEndFog, r, g, b); tr.world->globalTransEndFog[3] = depthForOpaque < 1 ? 1 : depthForOpaque; tr.world->globalFogTransStartTime = tr.refdef.time; tr.world->globalFogTransEndTime = tr.refdef.time + duration; } else { VectorSet(tr.world->fogs[tr.world->globalFog].fogParms.color, r, g, b); tr.world->fogs[tr.world->globalFog].fogParms.colorInt = ColorBytes4(r * tr.identityLight, g * tr.identityLight, b * tr.identityLight, 1.0); tr.world->fogs[tr.world->globalFog].fogParms.depthForOpaque = depthForOpaque < 1 ? 1 : depthForOpaque; tr.world->fogs[tr.world->globalFog].tcScale = 1.0f / (tr.world->fogs[tr.world->globalFog].fogParms.depthForOpaque); } } }
/* ==================== RE_SetGlobalFog rgb = colour depthForOpaque is depth for opaque the restore flag can be used to restore the original level fog duration can be set to fade over a certain period ==================== */ void RE_SetGlobalFog(bool restore, int duration, float r, float g, float b, float depthForOpaque) { if(restore) { if(duration > 0) { VectorCopy(tr.world->fogs[tr.world->globalFog].shader->fogParms.color, tr.world->globalTransStartFog); tr.world->globalTransStartFog[3] = tr.world->fogs[tr.world->globalFog].shader->fogParms.depthForOpaque; Vector4Copy(tr.world->globalOriginalFog, tr.world->globalTransEndFog); tr.world->globalFogTransStartTime = tr.refdef.time; tr.world->globalFogTransEndTime = tr.refdef.time + duration; } else { VectorCopy(tr.world->globalOriginalFog, tr.world->fogs[tr.world->globalFog].shader->fogParms.color); tr.world->fogs[tr.world->globalFog].shader->fogParms.colorInt = ColorBytes4(tr.world->globalOriginalFog[0] * tr.identityLight, tr.world->globalOriginalFog[1] * tr.identityLight, tr.world->globalOriginalFog[2] * tr.identityLight, 1.0); tr.world->fogs[tr.world->globalFog].shader->fogParms.depthForOpaque = tr.world->globalOriginalFog[3]; tr.world->fogs[tr.world->globalFog].shader->fogParms.tcScale = 1.0f / (tr.world->fogs[tr.world->globalFog].shader->fogParms.depthForOpaque); } } else { if(duration > 0) { VectorCopy(tr.world->fogs[tr.world->globalFog].shader->fogParms.color, tr.world->globalTransStartFog); tr.world->globalTransStartFog[3] = tr.world->fogs[tr.world->globalFog].shader->fogParms.depthForOpaque; VectorSet(tr.world->globalTransEndFog, r, g, b); tr.world->globalTransEndFog[3] = depthForOpaque < 1 ? 1 : depthForOpaque; tr.world->globalFogTransStartTime = tr.refdef.time; tr.world->globalFogTransEndTime = tr.refdef.time + duration; } else { VectorSet(tr.world->fogs[tr.world->globalFog].shader->fogParms.color, r, g, b); tr.world->fogs[tr.world->globalFog].shader->fogParms.colorInt = ColorBytes4(r * tr.identityLight, g * tr.identityLight, b * tr.identityLight, 1.0); tr.world->fogs[tr.world->globalFog].shader->fogParms.depthForOpaque = depthForOpaque < 1 ? 1 : depthForOpaque; tr.world->fogs[tr.world->globalFog].shader->fogParms.tcScale = 1.0f / (tr.world->fogs[tr.world->globalFog].shader->fogParms.depthForOpaque); } } }
/************************************************************************************************ * R_FogColor_f * * Console command to change the global fog color. Specifying nothing on the command will * * display the current global fog color. Specifying a float R G B values between 0.0 and * * 1.0 will change the fog color. * * * * Input * * none * * * * Output / Return * * none * * * ************************************************************************************************/ void R_FogColor_f(void) { if (!tr.world) { ri.Printf(PRINT_ALL, "R_FogColor_f: World is not initialized\n"); return; } if (tr.world->globalFog == -1) { ri.Printf(PRINT_ALL, "R_FogColor_f: World does not have a global fog\n"); return; } if (ri.Cmd_Argc() <= 1) { unsigned i = tr.world->fogs[tr.world->globalFog].colorInt; ri.Printf(PRINT_ALL, "R_FogColor_f: Current Color: %0f %0f %0f\n", ( (byte *)&i )[0] / 255.0, ( (byte *)&i )[1] / 255.0, ( (byte *)&i )[2] / 255.0); return; } if (ri.Cmd_Argc() != 4) { ri.Printf(PRINT_ALL, "R_FogColor_f: Invalid number of arguments to set color\n"); return; } tr.world->fogs[tr.world->globalFog].colorInt = ColorBytes4 ( atof(ri.Cmd_Argv(1)) * tr.identityLight, atof(ri.Cmd_Argv(2)) * tr.identityLight, atof(ri.Cmd_Argv(3)) * tr.identityLight, 1.0 ); }
void RE_LAGoggles( void ) { tr.refdef.rdflags |= (RDF_doLAGoggles|RDF_doFullbright); tr.refdef.doLAGoggles = qtrue; fog_t *fog = &tr.world->fogs[tr.world->numfogs]; fog->parms.color[0] = 0.75f; fog->parms.color[1] = 0.42f + random() * 0.025f; fog->parms.color[2] = 0.07f; fog->parms.depthForOpaque = 10000; fog->colorInt = ColorBytes4(fog->parms.color[0], fog->parms.color[1], fog->parms.color[2], 1.0f); fog->tcScale = 2.0f / ( fog->parms.depthForOpaque * (1.0f + cos( tr.refdef.floatTime) * 0.1f)); }
/* =================== RB_HazePass Blends a fog texture on top of everything but the skybox =================== */ static void RB_HazePass( void ) { int i; unsigned int color[3], colorInt; // TODO; Get color from worlspawn. Use black for now. color[0] = 0; color[1] = 0; color[2] = 0; colorInt = ColorBytes4( color[0] * tr.identityLight, color[1] * tr.identityLight, color[2] * tr.identityLight, 1.0 ); qglEnableClientState( GL_COLOR_ARRAY ); qglColorPointer( 4, GL_UNSIGNED_BYTE, 0, tess.svars.colors ); qglEnableClientState( GL_TEXTURE_COORD_ARRAY); qglTexCoordPointer( 2, GL_FLOAT, 0, tess.svars.texcoords[0] ); //fog = tr.world->fogs + tess.fogNum; for ( i = 0; i < tess.numVertexes; i++ ) { * ( int * )&tess.svars.colors[i] = colorInt; } RB_CalcFogTexCoords( ( float * ) tess.svars.texcoords[0] ); GL_Bind( tr.fogImage ); if ( tess.shader->fogPass == FP_EQUAL ) { GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_DEPTHFUNC_EQUAL ); } else { GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA ); } R_DrawElements( tess.numIndexes, tess.indexes ); }
/* ================= R_LoadFogs ================= */ static void R_LoadFogs( lump_t *l, lump_t *brushesLump, lump_t *sidesLump ) { int i; fog_t *out; dfog_t *fogs; dbrush_t *brushes, *brush; dbrushside_t *sides; int count, brushesCount, sidesCount; int sideNum; int planeNum; shader_t *shader; float d; int firstSide=0; int lightmaps[MAXLIGHTMAPS] = { LIGHTMAP_NONE } ; fogs = (dfog_t *)(fileBase + l->fileofs); if (l->filelen % sizeof(*fogs)) { ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name); } count = l->filelen / sizeof(*fogs); // create fog structres for them // NOTE: we allocate memory for an extra one so that the LA goggles can turn on their own fog s_worldData.numfogs = count + 1; s_worldData.fogs = (fog_t *)ri.Hunk_Alloc (( s_worldData.numfogs + 1)*sizeof(*out), qtrue ); s_worldData.globalFog = -1; out = s_worldData.fogs + 1; if ( !count ) { return; } brushes = (dbrush_t *)(fileBase + brushesLump->fileofs); if (brushesLump->filelen % sizeof(*brushes)) { ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name); } brushesCount = brushesLump->filelen / sizeof(*brushes); sides = (dbrushside_t *)(fileBase + sidesLump->fileofs); if (sidesLump->filelen % sizeof(*sides)) { ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",s_worldData.name); } sidesCount = sidesLump->filelen / sizeof(*sides); for ( i=0 ; i<count ; i++, fogs++) { out->originalBrushNumber = LittleLong( fogs->brushNum ); if (out->originalBrushNumber == -1) { out->bounds[0][0] = out->bounds[0][1] = out->bounds[0][2] = MIN_WORLD_COORD; out->bounds[1][0] = out->bounds[1][1] = out->bounds[1][2] = MAX_WORLD_COORD; s_worldData.globalFog = i+1; } else { if ( (unsigned)out->originalBrushNumber >= brushesCount ) { ri.Error( ERR_DROP, "fog brushNumber out of range" ); } brush = brushes + out->originalBrushNumber; firstSide = LittleLong( brush->firstSide ); if ( (unsigned)firstSide > sidesCount - 6 ) { ri.Error( ERR_DROP, "fog brush sideNumber out of range" ); } // brushes are always sorted with the axial sides first sideNum = firstSide + 0; planeNum = LittleLong( sides[ sideNum ].planeNum ); out->bounds[0][0] = -s_worldData.planes[ planeNum ].dist; sideNum = firstSide + 1; planeNum = LittleLong( sides[ sideNum ].planeNum ); out->bounds[1][0] = s_worldData.planes[ planeNum ].dist; sideNum = firstSide + 2; planeNum = LittleLong( sides[ sideNum ].planeNum ); out->bounds[0][1] = -s_worldData.planes[ planeNum ].dist; sideNum = firstSide + 3; planeNum = LittleLong( sides[ sideNum ].planeNum ); out->bounds[1][1] = s_worldData.planes[ planeNum ].dist; sideNum = firstSide + 4; planeNum = LittleLong( sides[ sideNum ].planeNum ); out->bounds[0][2] = -s_worldData.planes[ planeNum ].dist; sideNum = firstSide + 5; planeNum = LittleLong( sides[ sideNum ].planeNum ); out->bounds[1][2] = s_worldData.planes[ planeNum ].dist; } // get information from the shader for fog parameters shader = R_FindShader( fogs->shader, lightmaps, stylesDefault, qtrue ); out->parms = shader->fogParms; out->colorInt = ColorBytes4 ( shader->fogParms.color[0] * tr.identityLight, shader->fogParms.color[1] * tr.identityLight, shader->fogParms.color[2] * tr.identityLight, 1.0 ); d = shader->fogParms.depthForOpaque < 1 ? 1 : shader->fogParms.depthForOpaque; out->tcScale = 1.0 / ( d * 8 ); // set the gradient vector sideNum = LittleLong( fogs->visibleSide ); if ( sideNum == -1 ) { out->hasSurface = qfalse; } else { out->hasSurface = qtrue; planeNum = LittleLong( sides[ firstSide + sideNum ].planeNum ); VectorSubtract( vec3_origin, s_worldData.planes[ planeNum ].normal, out->surface ); out->surface[3] = -s_worldData.planes[ planeNum ].dist; } out++; } // Initialise the last fog so we can use it with the LA Goggles // NOTE: We are might appear to be off the end of the array, but we allocated an extra memory slot above but [purposely] didn't // increment the total world numFogs to match our array size VectorSet(out->bounds[0], MIN_WORLD_COORD, MIN_WORLD_COORD, MIN_WORLD_COORD); VectorSet(out->bounds[1], MAX_WORLD_COORD, MAX_WORLD_COORD, MAX_WORLD_COORD); out->originalBrushNumber = -1; out->parms.color[0] = 0.0f; out->parms.color[1] = 0.0f; out->parms.color[2] = 0.0f; out->parms.color[3] = 0.0f; out->parms.depthForOpaque = 0.0f; out->colorInt = 0x00000000; out->tcScale = 0.0f; out->hasSurface = false; }
void R_RMGInit(void) { char newSky[MAX_QPATH]; char newFog[MAX_QPATH]; shader_t *fog; fog_t *gfog; mgrid_t *grid; char temp[MAX_QPATH]; int i; unsigned short *pos; ri.Cvar_VariableStringBuffer("RMG_sky", newSky, MAX_QPATH); // Get sunlight - this should set up all the sunlight data R_FindShader( newSky, lightmapsNone, stylesDefault, qfalse ); // Remap sky R_RemapShader("textures/tools/_sky", newSky, NULL); // Fill in the lightgrid with sunlight if(tr.world->lightGridData) { grid = tr.world->lightGridData; grid->ambientLight[0][0] = (byte)Com_Clampi(0, 255, tr.sunAmbient[0] * 255.0f); grid->ambientLight[0][1] = (byte)Com_Clampi(0, 255, tr.sunAmbient[1] * 255.0f); grid->ambientLight[0][2] = (byte)Com_Clampi(0, 255, tr.sunAmbient[2] * 255.0f); R_ColorShiftLightingBytes(grid->ambientLight[0], grid->ambientLight[0]); grid->directLight[0][0] = (byte)Com_Clampi(0, 255, tr.sunLight[0]); grid->directLight[0][1] = (byte)Com_Clampi(0, 255, tr.sunLight[1]); grid->directLight[0][2] = (byte)Com_Clampi(0, 255, tr.sunLight[2]); R_ColorShiftLightingBytes(grid->directLight[0], grid->directLight[0]); NormalToLatLong(tr.sunDirection, grid->latLong); pos = tr.world->lightGridArray; for(i=0;i<tr.world->numGridArrayElements;i++) { *pos = 0; pos++; } } // Override the global fog with the defined one if(tr.world->globalFog != -1) { ri.Cvar_VariableStringBuffer("RMG_fog", newFog, MAX_QPATH); fog = R_FindShader( newFog, lightmapsNone, stylesDefault, qfalse); if (fog != tr.defaultShader) { gfog = tr.world->fogs + tr.world->globalFog; gfog->parms = *fog->fogParms; if (gfog->parms.depthForOpaque) { gfog->tcScale = 1.0f / ( gfog->parms.depthForOpaque * 8.0f ); tr.distanceCull = gfog->parms.depthForOpaque; tr.distanceCullSquared = tr.distanceCull * tr.distanceCull; ri.Cvar_Set("RMG_distancecull", va("%f", tr.distanceCull)); } else { gfog->tcScale = 1.0f; } gfog->colorInt = ColorBytes4 ( gfog->parms.color[0], gfog->parms.color[1], gfog->parms.color[2], 1.0f ); } } ri.Cvar_VariableStringBuffer("RMG_weather", temp, MAX_QPATH); // Set up any weather effects switch(atol(temp)) { case 0: break; case 1: RE_WorldEffectCommand("rain init 1000"); RE_WorldEffectCommand("rain outside"); break; case 2: RE_WorldEffectCommand("snow init 1000 outside"); RE_WorldEffectCommand("snow outside"); break; } }
/* ================= R_LoadFogs ================= */ static void R_LoadFogs( lump_t *l, lump_t *brushesLump, lump_t *sidesLump, world_t &worldData, int index ) { int i; fog_t *out; dfog_t *fogs; dbrush_t *brushes, *brush; dbrushside_t *sides; int count, brushesCount, sidesCount; int sideNum; int planeNum; shader_t *shader; float d; int firstSide=0; int lightmaps[MAXLIGHTMAPS] = { LIGHTMAP_NONE } ; fogs = (dfog_t *)(fileBase + l->fileofs); if (l->filelen % sizeof(*fogs)) { Com_Error (ERR_DROP, "LoadMap: funny lump size in %s",worldData.name); } count = l->filelen / sizeof(*fogs); // create fog strucutres for them worldData.numfogs = count + 1; worldData.fogs = (fog_t *)R_Hunk_Alloc ( (worldData.numfogs+1)*sizeof(*out), qtrue); worldData.globalFog = -1; out = worldData.fogs + 1; // Copy the global fog from the main world into the bsp instance if(index) { if(tr.world && (tr.world->globalFog != -1)) { // Use the nightvision fog slot worldData.fogs[worldData.numfogs] = tr.world->fogs[tr.world->globalFog]; worldData.globalFog = worldData.numfogs; worldData.numfogs++; } } if ( !count ) { return; } brushes = (dbrush_t *)(fileBase + brushesLump->fileofs); if (brushesLump->filelen % sizeof(*brushes)) { Com_Error (ERR_DROP, "LoadMap: funny lump size in %s",worldData.name); } brushesCount = brushesLump->filelen / sizeof(*brushes); sides = (dbrushside_t *)(fileBase + sidesLump->fileofs); if (sidesLump->filelen % sizeof(*sides)) { Com_Error (ERR_DROP, "LoadMap: funny lump size in %s",worldData.name); } sidesCount = sidesLump->filelen / sizeof(*sides); for ( i=0 ; i<count ; i++, fogs++) { out->originalBrushNumber = LittleLong( fogs->brushNum ); if (out->originalBrushNumber == -1) { if(index) { Com_Error (ERR_DROP, "LoadMap: global fog not allowed in bsp instances - %s", worldData.name); } VectorSet(out->bounds[0], MIN_WORLD_COORD, MIN_WORLD_COORD, MIN_WORLD_COORD); VectorSet(out->bounds[1], MAX_WORLD_COORD, MAX_WORLD_COORD, MAX_WORLD_COORD); worldData.globalFog = i + 1; } else { if ( (unsigned)out->originalBrushNumber >= (unsigned)brushesCount ) { Com_Error( ERR_DROP, "fog brushNumber out of range" ); } brush = brushes + out->originalBrushNumber; firstSide = LittleLong( brush->firstSide ); if ( (unsigned)firstSide > (unsigned)(sidesCount - 6) ) { Com_Error( ERR_DROP, "fog brush sideNumber out of range" ); } // brushes are always sorted with the axial sides first sideNum = firstSide + 0; planeNum = LittleLong( sides[ sideNum ].planeNum ); out->bounds[0][0] = -worldData.planes[ planeNum ].dist; sideNum = firstSide + 1; planeNum = LittleLong( sides[ sideNum ].planeNum ); out->bounds[1][0] = worldData.planes[ planeNum ].dist; sideNum = firstSide + 2; planeNum = LittleLong( sides[ sideNum ].planeNum ); out->bounds[0][1] = -worldData.planes[ planeNum ].dist; sideNum = firstSide + 3; planeNum = LittleLong( sides[ sideNum ].planeNum ); out->bounds[1][1] = worldData.planes[ planeNum ].dist; sideNum = firstSide + 4; planeNum = LittleLong( sides[ sideNum ].planeNum ); out->bounds[0][2] = -worldData.planes[ planeNum ].dist; sideNum = firstSide + 5; planeNum = LittleLong( sides[ sideNum ].planeNum ); out->bounds[1][2] = worldData.planes[ planeNum ].dist; } // get information from the shader for fog parameters shader = R_FindShader( fogs->shader, lightmaps, stylesDefault, qtrue ); assert(shader->fogParms); if (!shader->fogParms) {//bad shader!! out->parms.color[0] = 1.0f; out->parms.color[1] = 0.0f; out->parms.color[2] = 0.0f; out->parms.depthForOpaque = 250.0f; } else { out->parms = *shader->fogParms; } out->colorInt = ColorBytes4 ( out->parms.color[0], out->parms.color[1], out->parms.color[2], 1.0 ); d = out->parms.depthForOpaque < 1 ? 1 : out->parms.depthForOpaque; out->tcScale = 1.0f / ( d * 8 ); // set the gradient vector sideNum = LittleLong( fogs->visibleSide ); if ( sideNum == -1 ) { out->hasSurface = qfalse; } else { out->hasSurface = qtrue; planeNum = LittleLong( sides[ firstSide + sideNum ].planeNum ); VectorSubtract( vec3_origin, worldData.planes[ planeNum ].normal, out->surface ); out->surface[3] = -worldData.planes[ planeNum ].dist; } out++; } if (!index) { // Initialise the last fog so we can use it with the LA Goggles // NOTE: We are might appear to be off the end of the array, but we allocated an extra memory slot above but [purposely] didn't // increment the total world numFogs to match our array size VectorSet(out->bounds[0], MIN_WORLD_COORD, MIN_WORLD_COORD, MIN_WORLD_COORD); VectorSet(out->bounds[1], MAX_WORLD_COORD, MAX_WORLD_COORD, MAX_WORLD_COORD); out->originalBrushNumber = -1; out->parms.color[0] = 0.0f; out->parms.color[1] = 0.0f; out->parms.color[2] = 0.0f; out->parms.depthForOpaque = 0.0f; out->colorInt = 0x00000000; out->tcScale = 0.0f; out->hasSurface = qfalse; } }
/* @@@@@@@@@@@@@@@@@@@@@ RE_RenderScene Draw a 3D view into a part of the window, then return to 2D drawing. Rendering a scene may require multiple views to be rendered to handle mirrors, @@@@@@@@@@@@@@@@@@@@@ */ void RE_RenderScene( const refdef_t *vmRefDef, int vmRefDefSize ) { refdef_t fd; viewParms_t parms; int startTime; if ( !tr.registered ) { return; } GLimp_LogComment( "====== RE_RenderScene =====\n" ); if ( r_norefresh->integer ) { return; } startTime = ri.Milliseconds(); Com_Memcpy2( &fd, sizeof ( refdef_t ), vmRefDef, vmRefDefSize ); if (!tr.world && !( fd.rdflags & RDF_NOWORLDMODEL ) ) { ri.Error (ERR_DROP, "R_RenderScene: NULL worldmodel"); } Com_Memcpy( tr.refdef.text, fd.text, sizeof( tr.refdef.text ) ); tr.refdef.x = fd.x; tr.refdef.y = fd.y; tr.refdef.width = fd.width; tr.refdef.height = fd.height; tr.refdef.fov_x = fd.fov_x; tr.refdef.fov_y = fd.fov_y; VectorCopy( fd.vieworg, tr.refdef.vieworg ); VectorCopy( fd.viewaxis[0], tr.refdef.viewaxis[0] ); VectorCopy( fd.viewaxis[1], tr.refdef.viewaxis[1] ); VectorCopy( fd.viewaxis[2], tr.refdef.viewaxis[2] ); tr.refdef.time = fd.time; tr.refdef.rdflags = fd.rdflags; tr.refdef.skyAlpha = fd.skyAlpha; tr.refdef.fogType = fd.fogType; if ( tr.refdef.fogType < FT_NONE || tr.refdef.fogType >= FT_MAX_FOG_TYPE ) { tr.refdef.fogType = FT_NONE; } tr.refdef.fogColor[0] = fd.fogColor[0] * tr.identityLight; tr.refdef.fogColor[1] = fd.fogColor[1] * tr.identityLight; tr.refdef.fogColor[2] = fd.fogColor[2] * tr.identityLight; tr.refdef.fogColorInt = ColorBytes4( tr.refdef.fogColor[0], tr.refdef.fogColor[1], tr.refdef.fogColor[2], 1.0 ); tr.refdef.fogDensity = fd.fogDensity; if ( r_zfar->value ) { tr.refdef.fogDepthForOpaque = r_zfar->value < 1 ? 1 : r_zfar->value; } else { tr.refdef.fogDepthForOpaque = fd.fogDepthForOpaque < 1 ? 1 : fd.fogDepthForOpaque; } tr.refdef.fogTcScale = R_FogTcScale( tr.refdef.fogType, tr.refdef.fogDepthForOpaque, tr.refdef.fogDensity ); // copy the areamask data over and note if it has changed, which // will force a reset of the visible leafs even if the view hasn't moved tr.refdef.areamaskModified = qfalse; if ( ! (tr.refdef.rdflags & RDF_NOWORLDMODEL) ) { int areaDiff; int i; // compare the area bits areaDiff = 0; for (i = 0 ; i < MAX_MAP_AREA_BYTES/4 ; i++) { areaDiff |= ((int *)tr.refdef.areamask)[i] ^ ((int *)fd.areamask)[i]; ((int *)tr.refdef.areamask)[i] = ((int *)fd.areamask)[i]; } if ( areaDiff ) { // a door just opened or something tr.refdef.areamaskModified = qtrue; } } // derived info tr.refdef.floatTime = tr.refdef.time * 0.001f; tr.refdef.numDrawSurfs = r_firstSceneDrawSurf; tr.refdef.drawSurfs = backEndData->drawSurfs; tr.refdef.numSkins = r_numskins; tr.refdef.skins = backEndData->skins; tr.refdef.num_entities = r_numentities - r_firstSceneEntity; tr.refdef.entities = &backEndData->entities[r_firstSceneEntity]; tr.refdef.num_dlights = r_numdlights - r_firstSceneDlight; tr.refdef.dlights = &backEndData->dlights[r_firstSceneDlight]; tr.refdef.dlightBits = 0; tr.refdef.num_coronas = r_numcoronas - r_firstSceneCorona; tr.refdef.coronas = &backEndData->coronas[r_firstSceneCorona]; tr.refdef.numPolys = r_numpolys - r_firstScenePoly; tr.refdef.polys = &backEndData->polys[r_firstScenePoly]; tr.refdef.numPolyBuffers = r_numpolybuffers - r_firstScenePolybuffer; tr.refdef.polybuffers = &backEndData->polybuffers[r_firstScenePolybuffer]; // turn off dynamic lighting globally by clearing all the // dlights if it needs to be disabled or if vertex lighting is enabled if ( r_dynamiclight->integer == 0 || r_vertexLight->integer == 1 ) { tr.refdef.num_dlights = 0; } // a single frame may have multiple scenes draw inside it -- // a 3D game view, 3D status bar renderings, 3D menus, etc. // They need to be distinguished by the light flare code, because // the visibility state for a given surface may be different in // each scene / view. tr.frameSceneNum++; tr.sceneCount++; // setup view parms for the initial view // // set up viewport // The refdef takes 0-at-the-top y coordinates, so // convert to GL's 0-at-the-bottom space // Com_Memset( &parms, 0, sizeof( parms ) ); parms.viewportX = tr.refdef.x; parms.viewportY = glConfig.vidHeight - ( tr.refdef.y + tr.refdef.height ); parms.viewportWidth = tr.refdef.width; parms.viewportHeight = tr.refdef.height; parms.isPortal = qfalse; parms.fovX = tr.refdef.fov_x; parms.fovY = tr.refdef.fov_y; parms.stereoFrame = tr.refdef.stereoFrame; VectorCopy( fd.vieworg, parms.or.origin ); VectorCopy( fd.viewaxis[0], parms.or.axis[0] ); VectorCopy( fd.viewaxis[1], parms.or.axis[1] ); VectorCopy( fd.viewaxis[2], parms.or.axis[2] ); VectorCopy( fd.vieworg, parms.pvsOrigin ); R_RenderView( &parms ); // the next scene rendered in this frame will tack on after this one r_firstSceneDrawSurf = tr.refdef.numDrawSurfs; r_firstSceneEntity = r_numentities; r_firstSceneDlight = r_numdlights; r_firstScenePoly = r_numpolys; r_firstScenePolybuffer = r_numpolybuffers; tr.frontEndMsec += ri.Milliseconds() - startTime; }
/* ============== R_SetFrameFog ============== */ void R_SetFrameFog() { if(!tr.world) return; // Arnout: new style global fog transitions if(tr.world->globalFogTransEndTime) { if(tr.world->globalFogTransEndTime >= tr.refdef.time) { float lerpPos; int fadeTime; fadeTime = tr.world->globalFogTransEndTime - tr.world->globalFogTransStartTime; lerpPos = (float)(tr.refdef.time - tr.world->globalFogTransStartTime) / (float)fadeTime; if(lerpPos > 1) { lerpPos = 1; } tr.world->fogs[tr.world->globalFog].fogParms.color[0] = tr.world->globalTransStartFog[0] + ((tr.world->globalTransEndFog[0] - tr.world->globalTransStartFog[0]) * lerpPos); tr.world->fogs[tr.world->globalFog].fogParms.color[1] = tr.world->globalTransStartFog[1] + ((tr.world->globalTransEndFog[1] - tr.world->globalTransStartFog[1]) * lerpPos); tr.world->fogs[tr.world->globalFog].fogParms.color[2] = tr.world->globalTransStartFog[2] + ((tr.world->globalTransEndFog[2] - tr.world->globalTransStartFog[2]) * lerpPos); tr.world->fogs[tr.world->globalFog].fogParms.colorInt = ColorBytes4(tr.world->fogs[tr.world->globalFog].fogParms.color[0] * tr.identityLight, tr.world->fogs[tr.world->globalFog].fogParms.color[1] * tr.identityLight, tr.world->fogs[tr.world->globalFog].fogParms.color[2] * tr.identityLight, 1.0); tr.world->fogs[tr.world->globalFog].fogParms.depthForOpaque = tr.world->globalTransStartFog[3] + ((tr.world->globalTransEndFog[3] - tr.world->globalTransStartFog[3]) * lerpPos); tr.world->fogs[tr.world->globalFog].tcScale = 1.0f / (tr.world->fogs[tr.world->globalFog].fogParms.depthForOpaque * 8); } else { // transition complete VectorCopy(tr.world->globalTransEndFog, tr.world->fogs[tr.world->globalFog].fogParms.color); tr.world->fogs[tr.world->globalFog].fogParms.colorInt = ColorBytes4(tr.world->globalTransEndFog[0] * tr.identityLight, tr.world->globalTransEndFog[1] * tr.identityLight, tr.world->globalTransEndFog[2] * tr.identityLight, 1.0); tr.world->fogs[tr.world->globalFog].fogParms.depthForOpaque = tr.world->globalTransEndFog[3]; tr.world->fogs[tr.world->globalFog].tcScale = 1.0f / (tr.world->fogs[tr.world->globalFog].fogParms.depthForOpaque * 8); tr.world->globalFogTransEndTime = 0; } } if(r_speeds->integer == RSPEEDS_FOG) { if(!tr.glfogsettings[FOG_TARGET].registered) { ri.Printf(PRINT_ALL, "no fog - calc zFar: %0.1f\n", tr.viewParms.zFar); return; } } // DHM - Nerve :: If fog is not valid, don't use it if(!tr.glfogsettings[FOG_TARGET].registered) { return; } // still fading if(tr.glfogsettings[FOG_TARGET].finishTime && tr.glfogsettings[FOG_TARGET].finishTime >= tr.refdef.time) { float lerpPos; int fadeTime; // transitioning from density to distance #if !defined(USE_D3D10) if(tr.glfogsettings[FOG_LAST].mode == GL_EXP && tr.glfogsettings[FOG_TARGET].mode == GL_LINEAR) { // for now just fast transition to the target when dissimilar fogs are memcpy(&tr.glfogsettings[FOG_CURRENT], &tr.glfogsettings[FOG_TARGET], sizeof(glfog_t)); tr.glfogsettings[FOG_TARGET].finishTime = 0; } // transitioning from distance to density else if(tr.glfogsettings[FOG_LAST].mode == GL_LINEAR && tr.glfogsettings[FOG_TARGET].mode == GL_EXP) { memcpy(&tr.glfogsettings[FOG_CURRENT], &tr.glfogsettings[FOG_TARGET], sizeof(glfog_t)); tr.glfogsettings[FOG_TARGET].finishTime = 0; } // transitioning like fog modes else { fadeTime = tr.glfogsettings[FOG_TARGET].finishTime - tr.glfogsettings[FOG_TARGET].startTime; if(fadeTime <= 0) { fadeTime = 1; // avoid divide by zero } lerpPos = (float)(tr.refdef.time - tr.glfogsettings[FOG_TARGET].startTime) / (float)fadeTime; if(lerpPos > 1) { lerpPos = 1; } // lerp near/far tr.glfogsettings[FOG_CURRENT].start = tr.glfogsettings[FOG_LAST].start + ((tr.glfogsettings[FOG_TARGET].start - tr.glfogsettings[FOG_LAST].start) * lerpPos); tr.glfogsettings[FOG_CURRENT].end = tr.glfogsettings[FOG_LAST].end + ((tr.glfogsettings[FOG_TARGET].end - tr.glfogsettings[FOG_LAST].end) * lerpPos); // lerp color tr.glfogsettings[FOG_CURRENT].color[0] = tr.glfogsettings[FOG_LAST].color[0] + ((tr.glfogsettings[FOG_TARGET].color[0] - tr.glfogsettings[FOG_LAST].color[0]) * lerpPos); tr.glfogsettings[FOG_CURRENT].color[1] = tr.glfogsettings[FOG_LAST].color[1] + ((tr.glfogsettings[FOG_TARGET].color[1] - tr.glfogsettings[FOG_LAST].color[1]) * lerpPos); tr.glfogsettings[FOG_CURRENT].color[2] = tr.glfogsettings[FOG_LAST].color[2] + ((tr.glfogsettings[FOG_TARGET].color[2] - tr.glfogsettings[FOG_LAST].color[2]) * lerpPos); tr.glfogsettings[FOG_CURRENT].density = tr.glfogsettings[FOG_TARGET].density; tr.glfogsettings[FOG_CURRENT].mode = tr.glfogsettings[FOG_TARGET].mode; tr.glfogsettings[FOG_CURRENT].registered = qtrue; // if either fog in the transition clears the screen, clear the background this frame to avoid hall of mirrors tr.glfogsettings[FOG_CURRENT].clearscreen = (qboolean)(tr.glfogsettings[FOG_TARGET].clearscreen || tr.glfogsettings[FOG_LAST].clearscreen); } #endif } else { // probably usually not necessary to copy the whole thing. // potential FIXME: since this is the most common occurance, diff first and only set changes memcpy(&tr.glfogsettings[FOG_CURRENT], &tr.glfogsettings[FOG_TARGET], sizeof(glfog_t)); } // shorten the far clip if the fog opaque distance is closer than the procedural farcip dist #if defined(USE_D3D10) // TODO #else if(tr.glfogsettings[FOG_CURRENT].mode == GL_LINEAR) #endif { if(tr.glfogsettings[FOG_CURRENT].end < tr.viewParms.zFar) { tr.viewParms.zFar = tr.glfogsettings[FOG_CURRENT].end; } } // else // tr.glfogsettings[FOG_CURRENT].end = 5; if(r_speeds->integer == RSPEEDS_FOG) { #if !defined(USE_D3D10) if(tr.glfogsettings[FOG_CURRENT].mode == GL_LINEAR) { ri.Printf(PRINT_ALL, "farclip fog - den: %0.1f calc zFar: %0.1f fog zfar: %0.1f\n", tr.glfogsettings[FOG_CURRENT].density, tr.viewParms.zFar, tr.glfogsettings[FOG_CURRENT].end); } else { ri.Printf(PRINT_ALL, "density fog - den: %0.4f calc zFar: %0.1f fog zFar: %0.1f\n", tr.glfogsettings[FOG_CURRENT].density, tr.viewParms.zFar, tr.glfogsettings[FOG_CURRENT].end); } #endif } }