From 84391888ef7da5ffccf22b155a31243ccdc24752 Mon Sep 17 00:00:00 2001 From: divverent Date: Sun, 9 Dec 2007 20:59:57 +0000 Subject: [PATCH] fog gets additional parameters mindist and maxdist that specify where fog "starts" and "ends"; sky is only fogged as if it were distance "maxdist" away (example: fog 1 0.5 1 0 0 1 gives a slight greenish haze like a view tint) git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@7781 d7cf8633-e32d-0410-b094-e92efae38249 --- cl_main.c | 20 +++++++++++++++----- cl_parse.c | 6 +++++- client.h | 2 ++ darkplaces.txt | 2 +- gl_rmain.c | 32 +++++++++++++++++++++++++++----- r_sky.c | 25 ++++++++++++++++++++++++- 6 files changed, 74 insertions(+), 13 deletions(-) diff --git a/cl_main.c b/cl_main.c index 9e1c7fb3..e44fdf1d 100644 --- a/cl_main.c +++ b/cl_main.c @@ -1833,13 +1833,23 @@ static void CL_Fog_f (void) { if (Cmd_Argc () == 1) { - Con_Printf("\"fog\" is \"%f %f %f %f\"\n", r_refdef.fog_density, r_refdef.fog_red, r_refdef.fog_green, r_refdef.fog_blue); + Con_Printf("\"fog\" is \"%f %f %f %f %f %f\"\n", r_refdef.fog_density, r_refdef.fog_red, r_refdef.fog_green, r_refdef.fog_blue, r_refdef.fog_start, r_refdef.fog_end); return; } - r_refdef.fog_density = atof(Cmd_Argv(1)); - r_refdef.fog_red = atof(Cmd_Argv(2)); - r_refdef.fog_green = atof(Cmd_Argv(3)); - r_refdef.fog_blue = atof(Cmd_Argv(4)); + r_refdef.fog_start = 0; + r_refdef.fog_end = 1000000000; + if(Cmd_Argc() > 1) + r_refdef.fog_density = atof(Cmd_Argv(1)); + if(Cmd_Argc() > 2) + r_refdef.fog_red = atof(Cmd_Argv(2)); + if(Cmd_Argc() > 3) + r_refdef.fog_green = atof(Cmd_Argv(3)); + if(Cmd_Argc() > 4) + r_refdef.fog_blue = atof(Cmd_Argv(4)); + if(Cmd_Argc() > 5) + r_refdef.fog_start = atof(Cmd_Argv(5)); + if(Cmd_Argc() > 6) + r_refdef.fog_end = atof(Cmd_Argv(6)); } /* diff --git a/cl_parse.c b/cl_parse.c index 9c541155..0cb0133e 100644 --- a/cl_parse.c +++ b/cl_parse.c @@ -362,7 +362,11 @@ void CL_ParseEntityLump(char *entdata) else if (!strcmp("qlsky", key)) // non-standard, introduced by QuakeLives (EEK) R_SetSkyBox(value); else if (!strcmp("fog", key)) - sscanf(value, "%f %f %f %f", &r_refdef.fog_density, &r_refdef.fog_red, &r_refdef.fog_green, &r_refdef.fog_blue); + { + r_refdef.fog_start = 0; + r_refdef.fog_end = 1000000000; + sscanf(value, "%f %f %f %f %f %f", &r_refdef.fog_density, &r_refdef.fog_red, &r_refdef.fog_green, &r_refdef.fog_blue, &r_refdef.fog_start, &r_refdef.fog_end); + } else if (!strcmp("fog_density", key)) r_refdef.fog_density = atof(value); else if (!strcmp("fog_red", key)) diff --git a/client.h b/client.h index adced357..b98beec1 100644 --- a/client.h +++ b/client.h @@ -1315,6 +1315,7 @@ extern qboolean sb_showscores; float FogPoint_World(const vec3_t p); float FogPoint_Model(const vec3_t p); +float FogForDistance(vec_t dist); typedef struct r_refdef_stats_s { @@ -1399,6 +1400,7 @@ typedef struct r_refdef_s float fog_red; float fog_green; float fog_blue; + float fog_start, fog_end; qboolean fogenabled; qboolean oldgl_fogenable; diff --git a/darkplaces.txt b/darkplaces.txt index da06f689..8c2153a3 100644 --- a/darkplaces.txt +++ b/darkplaces.txt @@ -1081,7 +1081,7 @@ entities print information on network e envmap render a cubemap (skybox) of the current scene exec execute a script file fly fly mode (flight) -fog set global fog parameters (density red green blue) +fog set global fog parameters (density red green blue mindist maxdist) force_centerview recenters view (stops looking up/down) fs_rescan rescans filesystem for new pack archives and any other changes fullinfo allows client to modify their userinfo diff --git a/gl_rmain.c b/gl_rmain.c index 777dea45..05205957 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -247,18 +247,24 @@ void FOG_clear(void) Cvar_Set("gl_fogblue", "0.3"); } r_refdef.fog_density = r_refdef.fog_red = r_refdef.fog_green = r_refdef.fog_blue = 0.0f; + r_refdef.fog_start = 0; + r_refdef.fog_end = 1000000000; } -float FogPoint_World(const vec3_t p) +float FogForDistance(vec_t dist) { - unsigned int fogmasktableindex = (unsigned int)(VectorDistance((p), r_view.origin) * r_refdef.fogmasktabledistmultiplier); + unsigned int fogmasktableindex = (unsigned int)(bound(0, dist - r_refdef.fog_start, r_refdef.fog_end - r_refdef.fog_start) * r_refdef.fogmasktabledistmultiplier); return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)]; } +float FogPoint_World(const vec3_t p) +{ + return FogForDistance(VectorDistance((p), r_view.origin)); +} + float FogPoint_Model(const vec3_t p) { - unsigned int fogmasktableindex = (unsigned int)(VectorDistance((p), rsurface.modelorg) * r_refdef.fogmasktabledistmultiplier); - return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)]; + return FogForDistance(VectorDistance((p), rsurface.modelorg)); } static void R_BuildBlankTextures(void) @@ -604,6 +610,8 @@ static const char *builtinshaderstring = "uniform float OffsetMapping_Scale;\n" "uniform float OffsetMapping_Bias;\n" "uniform float FogRangeRecip;\n" +"uniform float FogStart;\n" +"uniform float FogLength;\n" "\n" "uniform myhalf AmbientScale;\n" "uniform myhalf DiffuseScale;\n" @@ -855,7 +863,8 @@ static const char *builtinshaderstring = "\n" "#ifdef USEFOG\n" " // apply fog\n" -" color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n" +" color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhvec2(max(0.0, min(length(EyeVectorModelSpace) - FogStart, FogLength))*FogRangeRecip, 0.0))));\n" +//" color.rgb = mix(FogColor, color.rgb, myhalf(texture2D(Texture_FogMask, myhvec2(length(EyeVectorModelSpace)*FogRangeRecip, 0.0))));\n" "#endif\n" "\n" " gl_FragColor = vec4(color);\n" @@ -950,6 +959,8 @@ typedef struct r_glsl_permutation_s int loc_Color_Pants; int loc_Color_Shirt; int loc_FogRangeRecip; + int loc_FogStart; + int loc_FogLength; int loc_AmbientScale; int loc_DiffuseScale; int loc_SpecularScale; @@ -1081,6 +1092,8 @@ static void R_GLSL_CompilePermutation(const char *filename, int permutation, int p->loc_Color_Pants = qglGetUniformLocationARB(p->program, "Color_Pants"); p->loc_Color_Shirt = qglGetUniformLocationARB(p->program, "Color_Shirt"); p->loc_FogRangeRecip = qglGetUniformLocationARB(p->program, "FogRangeRecip"); + p->loc_FogStart = qglGetUniformLocationARB(p->program, "FogStart"); + p->loc_FogLength = qglGetUniformLocationARB(p->program, "FogLength"); p->loc_AmbientScale = qglGetUniformLocationARB(p->program, "AmbientScale"); p->loc_DiffuseScale = qglGetUniformLocationARB(p->program, "DiffuseScale"); p->loc_SpecularPower = qglGetUniformLocationARB(p->program, "SpecularPower"); @@ -1411,6 +1424,8 @@ int R_SetupSurfaceShader(const vec3_t lightcolorbase, qboolean modellighting, fl qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0); } if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, r_refdef.fograngerecip); + if (r_glsl_permutation->loc_FogStart >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogStart, r_refdef.fog_start); + if (r_glsl_permutation->loc_FogLength >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogLength, r_refdef.fog_end - r_refdef.fog_start); if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower); if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value); if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor); @@ -3273,6 +3288,13 @@ void R_UpdateVariables(void) } } + if (r_refdef.fog_start >= r_refdef.fog_end || r_refdef.fog_start < 0) + { + r_refdef.fog_start = 0; + r_refdef.fog_end = 1000000000; + // TODO update fog cvars here too + } + if (r_refdef.fog_density) { r_refdef.fogenabled = true; diff --git a/r_sky.c b/r_sky.c index 5d6362f8..9bd6992c 100644 --- a/r_sky.c +++ b/r_sky.c @@ -56,7 +56,7 @@ void R_SkyStartFrame(void) skyrendersphere = false; skyrenderbox = false; skyrendermasked = false; - if (r_sky.integer && !r_refdef.fogenabled) + if (r_sky.integer && !(r_refdef.fogenabled && r_refdef.fog_end >= 1000000000)) { if (skyboxside[0] || skyboxside[1] || skyboxside[2] || skyboxside[3] || skyboxside[4] || skyboxside[5]) skyrenderbox = true; @@ -286,6 +286,18 @@ static void R_SkyBox(void) R_Mesh_TexBind(0, R_GetTexture(skyboxside[i])); R_Mesh_Draw(0, 6*4, 2, skyboxelements + i * 6, 0, 0); } + + if(r_refdef.fogenabled) + { + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1 - FogForDistance(r_refdef.fog_end)); + for (i = 0;i < 6;i++) + { + R_Mesh_TexBind(0, 0); + R_Mesh_Draw(0, 6*4, 2, skyboxelements + i * 6, 0, 0); + } + } + GL_LockArrays(0, 0); } @@ -393,6 +405,7 @@ static void R_SkySphere(void) GL_LockArrays(0, skysphere_numverts); R_Mesh_Draw(0, skysphere_numverts, skysphere_numtriangles, skysphere_element3i, 0, 0); GL_LockArrays(0, 0); + R_Mesh_TexBind(1, 0); } else { @@ -407,6 +420,16 @@ static void R_SkySphere(void) R_Mesh_Draw(0, skysphere_numverts, skysphere_numtriangles, skysphere_element3i, 0, 0); GL_LockArrays(0, 0); } + + if(r_refdef.fogenabled) + { + R_Mesh_TexBind(0, 0); + GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + GL_Color(r_refdef.fogcolor[0] * r_view.colorscale, r_refdef.fogcolor[1] * r_view.colorscale, r_refdef.fogcolor[2] * r_view.colorscale, 1 - FogForDistance(r_refdef.fog_end)); + GL_LockArrays(0, skysphere_numverts); + R_Mesh_Draw(0, skysphere_numverts, skysphere_numtriangles, skysphere_element3i, 0, 0); + GL_LockArrays(0, 0); + } } void R_Sky(void) -- 2.39.2