{
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));
}
/*
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))
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
{
float fog_red;
float fog_green;
float fog_blue;
+ float fog_start, fog_end;
qboolean fogenabled;
qboolean oldgl_fogenable;
envmap render a cubemap (skybox) of the current scene\r
exec execute a script file\r
fly fly mode (flight)\r
-fog set global fog parameters (density red green blue)\r
+fog set global fog parameters (density red green blue mindist maxdist)\r
force_centerview recenters view (stops looking up/down)\r
fs_rescan rescans filesystem for new pack archives and any other changes\r
fullinfo allows client to modify their userinfo\r
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)
"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"
"\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"
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;
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");
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);
}
}
+ 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;
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;
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);
}
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
{
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)