Calculating y position in Post15.vert?

I am trying to create a new fog filter that applies a gradient to the fog. It’s important to my game (called The Fog, by the way) to be able to climb above the fog, and look down on the fog, like a fuzzy sea. I’m trying to calculate a fog factor in the vertex shader and pass it through to the fragment shader, but I’m not clear on how to calculate the the absolute y position of a vertex in a JME way. I had a look at the advanced water fragment shader because it also does a height test, but that is rather complicated for my limited GLSL skills.

I’m doing this:

uniform mat4 g_WorldViewProjectionMatrix;

in vec4 inPosition;
in vec2 inTexCoord;

out vec2 texCoord;

varying float fogGradientFactor;

void main() {
    vec2 pos = (g_WorldViewProjectionMatrix * inPosition).xy;
    fogGradientFactor = clamp((((clamp(pos.y, 60, 100) / pos.y) - 1.0) * 4) + 1.0, 0.5, 7.0);
    gl_Position = vec4(pos, 0.0, 1.0);
    texCoord = inTexCoord;
}

I thought that Post15.vert did something to calculate the y position for use by the water rendering, so it should be possible to calculate the fog factor and pass it on in a varying - any help from somebody who knows more about GLSL and the JME shaders would be wonderful.

You can’t really do this as a post effect, I think. Not without passing some other stuff to the shader.

The vertexes in a post processing shader are the corners of the screen.

Ah!

But the post water shader seems to have this knowledge, so maybe I should work the other way and strip down the water effect until I just have my depth tested fog?

Note: for your use case it might be better to just bite the bullet and add fog to your regular material shaders… fork lighting.j3md or something.

I am hoping to avoid forking. Especially as I hear JME is getting a new lighting system soon!

I have done it! @nehon pointed me in the right direction, and I extracted the necessary code from WaterFilter.

I needed to add this to my filter:

    @Override
    protected void preFrame(float tpf) {
        Camera sceneCam = viewPort.getCamera();
       //the matrix to get world position in the fragment shader
        material.setMatrix4("ViewProjectionMatrixInverse", sceneCam.getViewProjectionMatrix().invert());
       //need the camera position to - depth in fog is (simplistically) min(pixelHeight, cameraHeight)
        material.setVector3("CameraPosition", sceneCam.getLocation());
    }

Then the fragment shader looks like this:

#import "Common/ShaderLib/MultiSample.glsllib"
#import "Common/ShaderLib/WaterUtil.glsllib"

uniform COLORTEXTURE m_Texture;
uniform DEPTHTEXTURE m_DepthTexture;

uniform vec4 m_FogColor;
uniform float m_FogDensity;
uniform float m_FogDistance;
uniform mat4 m_ViewProjectionMatrixInverse;
uniform vec3 m_CameraPosition;
uniform float m_FogBase;
uniform float m_FogTop;
uniform float m_FadeSpeed;
uniform float m_FogMaxDensity;
uniform float m_FogMinDensity;

in vec2 texCoord;

vec2 m_FrustumNearFar=vec2(1.0,m_FogDistance);
const float LOG2 = 1.442695;


vec3 getPosition(in float depth, in vec2 uv){
    vec4 pos = vec4(uv, depth, 1.0) * 2.0 - 1.0;
    pos = m_ViewProjectionMatrixInverse * pos;
    return pos.xyz / pos.w;
}

void main() {
       vec4 texVal = getColor(m_Texture, texCoord);
       float fogVal = getDepth(m_DepthTexture,texCoord).r;

       int sampleNum = 1;
       float sceneDepth = fetchTextureSample(m_DepthTexture, texCoord, sampleNum).r;
       vec3 position = getPosition(sceneDepth, texCoord);
       float fogY = min(position.y, m_CameraPosition.y);
       if (fogY <= 0.0) {
           //no fog below sea level
           gl_FragColor = texVal;
       } else {
           float depth= (2.0 * m_FrustumNearFar.x) / (m_FrustumNearFar.y + m_FrustumNearFar.x - fogVal* (m_FrustumNearFar.y-m_FrustumNearFar.x));
           float fogGradientFactor = clamp((((clamp(fogY, m_FogBase, m_FogTop) / fogY) - 1.0) * m_FadeSpeed) + 1.0, m_FogMinDensity, m_FogMaxDensity);
           float fogFactor = exp2( -m_FogDensity * fogGradientFactor * depth *  depth * LOG2 );
           fogFactor = clamp(fogFactor, 0.0, 1.0);
           gl_FragColor = mix(m_FogColor,texVal,fogFactor);
       }
}

I’ll post a screen shot if my ancient laptop cooperates.

3 Likes

Here is how it looks, I’m still playing with the parameters to get the rights feel, but you can see the thick lower layer of fog lapping the base of the hills. I turned up the rate of fog thickening/thinning to make it more visible.

Game1

2 Likes

Very nice!