Shader Depth to WorldPosition problem

I’m currently trying to create a mist shader that renders fog from below a certain height.

I’ve spent the afternoon learning from scratch about sharers and have found many

discussions online that supposedly solve the problem of calculating World Position of a

fragment from its depth but none of them seem to have worked properly so far.

Below is the closest I have got so far to something working - this is from the Frag15 file

main method. I’ve used Fog15.frag as a template, and the shader works fine if I set weight

to another value.

The problem seems to stem from the multiplication of the screenPosition and the ViewProjectionMatrixInverse value, which is included also in the j3md under

WorldParameters. Incidentally the screenPos matrix appears to work as expected.

The resulting worldPos has 0’s meaning when it is normalized with it’s w component it

presumably becomes NaN-valued and the render fails.

Could anyone possibly shed some light on this, or suggest an alternative solution if there’s

a better one?

Thanks! Hugh


vec4 texVal = getColor(m_Texture, texCoord);

float depthVal = getDepth(m_DepthTexture, texCoord).r;

vec4 screenPos = vec4(texCoord.x * 2 - 1, -texCoord.y * 2 - 1, depthVal, 1);

vec4 D = screenPos * g_ViewProjectionMatrixInverse;

vec4 worldPos = D / D.w;

vec4 color = texVal;

color.r = 1.0;

float weight = worldPos.z;

gl_FragColor = mix(color, texVal, weight);


Look in DepthOfField.frag (or whatever the name is) to see how I calculated Z in that. I also had trouble with the fog method so I looked up the approach on the internet. I commented it as best I could.

Ok, I looked it up:

It’s right near the top.

Sorry if I’ve misunderstood the code but I can’t see anything that calculates

the height above the (0, 0) plane in world coordinates as opposed to the

distance from the camera.

I’m looking for a feature similar to the water.frag code

That calculates the position vector so I can call position.y and test for it

below/above a particular value. However, when I copy in this code (which is

almost identical to what I posted above) it still draws a black screen.

Perhaps it’s something to do with initializing g_ViewProjectionMatrixInverse?

Do I need to do this myself? I’ve assumed its automatic…

Sorry… you mentioned looked at Fog15.frag and I got confused.

Given the screen x,y and the real z it should be pretty easy to find the world y… but I’ve never done it.

The g_ parameters are set by the engine if you specify them in the j3md file. You never need to set them yourself.

The maths seems relatively simple re. what I found on the web and Water15.frag file,

it just seems to produce a zero vec4 worldPos when I try it.

this is incorrect :

vec4 screenPos = vec4(texCoord.x * 2 - 1, -texCoord.y * 2 - 1, depthVal, 1);

the depth value is from 0 to 1 too you need to transform it in clip space from -1 to 1 like you do with tex coords. Also you don’t have to invert the Y value of tex coord. You probably translated this from a HLSL code right? because directX second uv attribute is inverted compared to opengl.

this should work

vec4 screenPos = vec4(texCoord.xy, depthVal, 1.0) * 2.0 - 1.0;

In the water shader the getPosition() method transform a position in projection space to WorldSpace, that’s what you need.

If you want more details on this method ask, but be assured that this method works.