Skip to content

Commit a4124eb

Browse files
committed
Introduce fogGradient shader keyword
Add a shader keyword that can be used to configure a gradient for fog density, which tapers to 0 at the edge of the fog. The density of the fog is scaled by a factor of (1 - exp(-k * t)) where t is the distance under the fog plane and k a configurable constant. fogGradient expFalloff <dist> configures the exponential falloff such that the density is at 50% of the maximum at <dist> qu from the fog plane. fogGradient const does the same thing as the current default - no gradient; hard-edged fog.
1 parent 7287599 commit a4124eb

10 files changed

Lines changed: 104 additions & 19 deletions

File tree

src/engine/renderer/Material.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1114,7 +1114,8 @@ void BindShaderFog( Material* material ) {
11141114
// since fognum is grouped with the GL state stuff, segregating each fognum in a separate draw call.
11151115

11161116
gl_fogQuake3ShaderMaterial->SetUniform_ViewOrigin( backEnd.viewParms.orientation.origin );
1117-
gl_fogQuake3ShaderMaterial->SetUniform_FogDensity( 1.0f / fog->shader->fogParms.depthForOpaque );
1117+
gl_fogQuake3ShaderMaterial->SetUniform_FogGradient(
1118+
1.0f / fog->shader->fogParms.depthForOpaque, fog->shader->fogParms.falloffExp );
11181119
gl_fogQuake3ShaderMaterial->SetUniform_FogDepthVector( fogDepthVector );
11191120
gl_fogQuake3ShaderMaterial->SetUniform_FogEyeT( eyeT );
11201121

src/engine/renderer/gl_shader.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2697,7 +2697,7 @@ GLShader_fogQuake3::GLShader_fogQuake3() :
26972697
u_Bones( this ),
26982698
u_VertexInterpolation( this ),
26992699
u_ViewOrigin( this ),
2700-
u_FogDensity( this ),
2700+
u_FogGradient( this ),
27012701
u_FogDepthVector( this ),
27022702
u_FogEyeT( this ),
27032703
GLDeformStage( this ),
@@ -2713,7 +2713,7 @@ GLShader_fogQuake3Material::GLShader_fogQuake3Material() :
27132713
u_ModelViewProjectionMatrix( this ),
27142714
u_ColorGlobal_Uint( this ),
27152715
u_ViewOrigin( this ),
2716-
u_FogDensity( this ),
2716+
u_FogGradient( this ),
27172717
u_FogDepthVector( this ),
27182718
u_FogEyeT( this ),
27192719
GLDeformStage( this ) {

src/engine/renderer/gl_shader.h

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1859,6 +1859,22 @@ class u_FogDensity :
18591859
}
18601860
};
18611861

1862+
class u_FogGradient :
1863+
GLUniform2f
1864+
{
1865+
public:
1866+
u_FogGradient( GLShader *shader ) :
1867+
GLUniform2f( shader, "u_FogGradient", PUSH )
1868+
{
1869+
}
1870+
1871+
void SetUniform_FogGradient( float density, float falloffExp )
1872+
{
1873+
vec2_t value{ density, falloffExp };
1874+
this->SetValue( value );
1875+
}
1876+
};
1877+
18621878
class u_FogColor :
18631879
GLUniform3f
18641880
{
@@ -3166,7 +3182,7 @@ class GLShader_fogQuake3 :
31663182
public u_Bones,
31673183
public u_VertexInterpolation,
31683184
public u_ViewOrigin,
3169-
public u_FogDensity,
3185+
public u_FogGradient,
31703186
public u_FogDepthVector,
31713187
public u_FogEyeT,
31723188
public GLDeformStage,
@@ -3183,7 +3199,7 @@ class GLShader_fogQuake3Material :
31833199
public u_ModelViewProjectionMatrix,
31843200
public u_ColorGlobal_Uint,
31853201
public u_ViewOrigin,
3186-
public u_FogDensity,
3202+
public u_FogGradient,
31873203
public u_FogDepthVector,
31883204
public u_FogEyeT,
31893205
public GLDeformStage {

src/engine/renderer/glsl_source/fogEquation_fp.glsl

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,35 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3232
===========================================================================
3333
*/
3434

35-
float GetFogAlpha(float s, float t)
35+
float FogGradientFunction(float k, float t)
3636
{
37-
t = clamp(t, 0.0, 1.0);
37+
return 1 - exp(-k * t);
38+
}
3839

39-
float x = min(1, s * t);
40+
float FogGradientAntiderivative(float k, float t)
41+
{
42+
return t + exp(-k * t) / k;
43+
}
44+
45+
float GetFogGradientModifier(float k, float t0, float t1)
46+
{
47+
t0 = max(0.0, t0);
48+
t1 = max(0.0, t1);
49+
50+
float deltaT = t1 - t0;
51+
if (abs(deltaT) > 0.1)
52+
{
53+
return ( FogGradientAntiderivative(k, t1) - FogGradientAntiderivative(k, t0) ) / deltaT;
54+
}
55+
else
56+
{
57+
return FogGradientFunction(k, t0);
58+
}
59+
}
60+
61+
float GetFogAlpha(float x)
62+
{
63+
x = clamp(x, 0.0, 1.0);
4064

4165
// sqrt(x) is bad near 0 because it increases too quickly resulting in sharp edges.
4266
// x ≤ 1/32: √32 * x

src/engine/renderer/glsl_source/fogGlobal_fp.glsl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,10 @@ void main()
4949
vec4 P = u_UnprojectMatrix * vec4(gl_FragCoord.xy, depth, 1.0);
5050
P.xyz /= P.w;
5151

52-
// calculate the length in fog (t is always 1 if eye is in fog)
52+
// calculate the length in fog
5353
float s = distance(u_ViewOrigin, P.xyz) * u_FogDensity;
5454

55-
vec4 color = vec4(1, 1, 1, GetFogAlpha(s, 1.0));
55+
vec4 color = vec4(1, 1, 1, GetFogAlpha(s));
5656

5757
outputColor = UnpackColor( u_Color ) * color;
5858
}

src/engine/renderer/glsl_source/fogQuake3_fp.glsl

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,11 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2626

2727
#define DEPTHMAP_GLSL
2828

29+
uniform vec2 u_FogGradient;
2930
uniform float u_FogEyeT;
3031

3132
IN(smooth) float var_FogPlaneDistance;
32-
IN(smooth) vec3 var_ScaledViewerOffset;
33+
IN(smooth) vec3 var_ViewerOffset;
3334
IN(smooth) vec4 var_Color;
3435

3536
DECLARE_OUTPUT(vec4)
@@ -38,16 +39,22 @@ void main()
3839
{
3940
#insert material_fp
4041

41-
float s = length(var_ScaledViewerOffset);
42-
float t = step( 0, var_FogPlaneDistance );
42+
if ( var_FogPlaneDistance < -0.01 )
43+
{
44+
discard;
45+
}
46+
47+
float distInFog = length(var_ViewerOffset);
4348

4449
if ( u_FogEyeT < 0 ) // eye outside fog
4550
{
4651
// fraction of the viewer-to-vertex ray which is inside fog
47-
t *= var_FogPlaneDistance / ( max( 0, var_FogPlaneDistance ) - u_FogEyeT );
52+
distInFog *= var_FogPlaneDistance / ( max( 0, var_FogPlaneDistance ) - u_FogEyeT );
4853
}
4954

50-
vec4 color = vec4(1, 1, 1, GetFogAlpha(s, t));
55+
float gradient = GetFogGradientModifier(u_FogGradient.y, u_FogEyeT, var_FogPlaneDistance);
56+
57+
vec4 color = vec4(1, 1, 1, GetFogAlpha(gradient * u_FogGradient.x * distInFog));
5158

5259
color *= var_Color;
5360

src/engine/renderer/glsl_source/fogQuake3_vp.glsl

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,12 @@ uniform mat4 u_ModelMatrix;
3535
uniform mat4 u_ModelViewProjectionMatrix;
3636
uniform vec3 u_ViewOrigin;
3737

38-
uniform float u_FogDensity;
3938
uniform vec4 u_FogDepthVector; // fog plane
4039

4140
// how far the vertex is under the fog plane
4241
OUT(smooth) float var_FogPlaneDistance;
4342

44-
OUT(smooth) vec3 var_ScaledViewerOffset;
43+
OUT(smooth) vec3 var_ViewerOffset;
4544
OUT(smooth) vec4 var_Color;
4645

4746
void DeformVertex( inout vec4 pos,
@@ -76,7 +75,7 @@ void main()
7675
position = u_ModelMatrix * position;
7776
position.xyz /= position.w;
7877

79-
var_ScaledViewerOffset = u_FogDensity * (position.xyz - u_ViewOrigin);
78+
var_ViewerOffset = position.xyz - u_ViewOrigin;
8079

8180
// calculate the length in fog
8281
var_FogPlaneDistance = dot(position.xyz, u_FogDepthVector.xyz) + u_FogDepthVector.w;

src/engine/renderer/tr_local.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,6 +1127,7 @@ enum
11271127
{
11281128
Color::Color color;
11291129
float depthForOpaque;
1130+
float falloffExp;
11301131
};
11311132

11321133
struct shader_t

src/engine/renderer/tr_shade.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1636,7 +1636,8 @@ void Render_fog( shaderStage_t* pStage )
16361636
gl_fogQuake3Shader->BindProgram();
16371637

16381638
gl_fogQuake3Shader->SetUniform_ViewOrigin( backEnd.viewParms.orientation.origin );
1639-
gl_fogQuake3Shader->SetUniform_FogDensity( 1.0f / fog->shader->fogParms.depthForOpaque );
1639+
gl_fogQuake3Shader->SetUniform_FogGradient(
1640+
1.0f / fog->shader->fogParms.depthForOpaque, fog->shader->fogParms.falloffExp );
16401641
gl_fogQuake3Shader->SetUniform_FogDepthVector( fogDepthVector );
16411642
gl_fogQuake3Shader->SetUniform_FogEyeT( eyeT );
16421643

src/engine/renderer/tr_shader.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4636,6 +4636,37 @@ static bool ParseShader( const char *_text )
46364636
SkipRestOfLine( text );
46374637
continue;
46384638
}
4639+
// fogGradient
4640+
else if ( !Q_stricmp( token, "fogGradient" ) )
4641+
{
4642+
token = COM_ParseExt2( text, false );
4643+
4644+
if ( !Q_stricmp( token, "const" ) )
4645+
{
4646+
shader.fogParms.falloffExp = 9999;
4647+
}
4648+
// fogGradient expFalloff <dist from edge at which density is 50% of max>
4649+
// scales density by 1 - exp(-k*t) where t is distance under fog plane
4650+
else if ( !Q_stricmp( token, "expFalloff" ) )
4651+
{
4652+
token = COM_ParseExt2( text, false );
4653+
float val = atof( token );
4654+
4655+
if ( val > 0.0f )
4656+
{
4657+
shader.fogParms.falloffExp = M_LN2 / val;
4658+
}
4659+
else
4660+
{
4661+
Log::Warn( "bad expFalloff value in shader '%s'", shader.name );
4662+
}
4663+
}
4664+
else
4665+
{
4666+
Log::Warn( "invalid fogGradient type '%s' in shader '%s'", token, shader.name );
4667+
}
4668+
continue;
4669+
}
46394670
// noFog
46404671
else if ( !Q_stricmp( token, "noFog" ) )
46414672
{
@@ -5991,6 +6022,11 @@ static shader_t *FinishShader()
59916022
shader.portalRange = r_portalDefaultRange.Get();
59926023
}
59936024

6025+
if ( shader.fogParms.falloffExp == 0.0f )
6026+
{
6027+
shader.fogParms.falloffExp = 9999;
6028+
}
6029+
59946030
numStages = MAX_SHADER_STAGES;
59956031
GroupActiveStages();
59966032

0 commit comments

Comments
 (0)