World coordinate of fragment, in Filter Shader (Solved)

I’m implementing fog of war (WC3, age of empires) with a filter, using custom vert and frag shaders.

Question is, I need to know the world position of the fragment. How can this be done?

Wondering if a filter is even the right way to go here. Do you just use Lighting.j3md for your game or do you have many matdefs?

If you just use lighting then another approach would be to fork Lighting.vert/Lighting.frag to incorporate your fog of war. (This would also have the added benefit of potentially selectively turning the effect off if you ever need to… where as a filter is always going to be the whole screen.)

Hi pspeed, I guess that approach would allow for more customized behavior. But as of right now, I’m pretty confident that the fog of war will obscure basically everything (units, buildings, trees, terrain etc).

I did some reading on this thread: World coordinates in shader

He says he was able to get the world position of a fragment by passing in a Mat4 to the shader like in the WaterFilter, I looked it up and implemented that.

Like this:

protected void preFrame(float tpf) {
    Camera sceneCam = viewPort.getCamera();
    material.setMatrix4("ViewProjectionMatrixInverse", sceneCam.getViewProjectionMatrix().invert());

I added this in the MaterialParameters block of my j3md:

Matrix4 ViewProjectionMatrixInverse

Then, in the fragment shader, he imports MultiSample.glsllib from ShaderLib plugin and does this:

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.w;

float sceneDepth = fetchTextureSample(m_DepthTexture, texCoord, sampleNum).r;

vec3 pos = getPosition(sceneDepth, texCoord);    

But I don’t know what the m_DepthTexture and sampleNum variables are :frowning:

They are the depth texture and the number of samples. They are uniforms that should be available to the filters. I’ve presumed up until now that you looked at other filters to see how they work… if not then you should.

Yes, of course it will obscure everything… you can be 100% confident about that. It’s the one aspect of the filter approach that could never be changed in fact… it will always apply to everything whether you want it to or not.

The thing is, if you are only using Lighting.j3md then putting the fog of war in a forked version would by like three lines of shader code and WAY less complicated than a filter. If it were me and I were using a even a handful of matdefs, I’d still do it in the shaders instead of doing a post processing filter.

You might even find that the world coordinates are kind of spotty in a filter with odd artifacts at the edges of your fog. Though I guess a really wide area of fade could hide it. To me, a filter is just the most complicated way to do this.

Alright. Well, yes atm I’m just using a single matdef. I guess I’ll heed your advice then.

So, how do I get the world position of the fragment then?

Easiest way is to pass it as a varying from the .vert to the .frag… since the .vert already knows.

Indeed, I think I figured it out. I added a varying vec3 worldPos, then in the .vert, I do this:

worldPos = vec4(inPosition, 1.0) * g_WorldViewMatrix;

And in the .frag:

  #ifdef FOWMAP
    //take the world position, divide it by FOWSize
    //to get the texture coordinate of the fowMap
    vec2 fowTexCoord = vec2(worldPos.x / m_FOWSize, worldPos.z / m_FOWSize);
    //get fog of war amount from alpha
    vec4 fowColor = texture2D(m_FOWMap, fowTexCoord);

    diffuseColor = mix(diffuseColor, vec4(0.0, 0.0, 0.0, 1.0), fowColor.a);

So, I got some fog of war at least. But it’s following the camera. Is my calculation correct as far as the worldPos?

You need to use just the world matrix. g_WorldMatrix… which should already be in the WorldParameters for the shader so you just may need to declare it in the .vert.

Edit: also note you should multiply matrix * pos and not the other way around.

YAY! It works, thanks again you’re the best :smiley:

Now I just to make a fork of the TerrainLighting and implement it there too!

Glad you got it working.