I am currently trying to understand the following wierd result. This is basically from deferred shading in monogame/XNA. For Comparison I also write the ViewSpace Position in a Buffer and the ViewSpace Depth in another buffer like so:

float4 viewPosition = mul(input.Position, WorldView);
depth = viewPosition.z;

(the depth value is sent to a rendertarget with surfaceformat vector2 = 2x32bit float), the position-buffer now looks like so:

original position buffer contents (this is basically just a quad with a cube in the middle and some elevation in top left)

What I do now is I calculate the CornerFrustum on the CPU:

Vector3 cfrust = Vector3.Zero;
cfrust.Y = camera.FarClip * (float)Math.Tan(camera.FOV * 0.5f);
cfrust.X = cfrust.Y * camera.AspectRatio;
cfrust.Z = camera.FarClip;

The Fullscreen-quad is aligned with that frustum in mind:

new VertexPositionTexture(new Vector3(1, -1, 0), new Vector2(1, 1)),
new VertexPositionTexture(new Vector3(-1, -1, 0), new Vector2(0, 1)),
new VertexPositionTexture(new Vector3(-1, 1, 0), new Vector2(0, 0)),
new VertexPositionTexture(new Vector3(1, 1, 0), new Vector2(1, 0))

now in the VS I get the ViewRay / ViewDirection like this

output.ViewDirection = float3(-CornerFrustum.x * input.Position.x, CornerFrustum.y * input.Position.y, CornerFrustum.z);

in PS I now try to reconstruct the ViewPosition from ViewRay/Depth

float3 ViewRay = normalize(input.ViewDirection);
float Depth = tex2D(sampler_depth, input.UV).r;
float3 ViewPosition = Depth * ViewRay;

I should now have the ViewPosition of that pixel, right?

I am now converting this back to screen by

float4 ScreenPosition = mul(float4(ViewPosition, 1.0),Projection);
float2 ScreenUV = 0.5 * (ScreenPosition.xy / ScreenPosition.w) + float2(0.5,0.5);

if I now output that position to the screen I get this:

inverted y

as the colors suggests, the Y-Axis is inverted? (It's negative now, so the corresponding channel is clamped to 0 in the output, basically inverting the colors)

This gives me trouble now, because as a consequence (this is used in a SSAO shader) the SSAO samples (hemisphere) are moved along the inverted y-axis as well.

I fear I am missing something, because the generated UVs are actually correct. As they sample the correct piece. If I use those "ScreenUV" to sample from the PositionBuffer I do get the correct result (the exact same as the first image). I just cannot understand, why the position is inverted in the y-axis (it's now pointing down instead of up.


1 Answer 1


There is a coordinate system change between DX and GL since monogame can use either under the hood. This is normally taken care of internally however there are some things that the user must deal with such as passing static or global shader variables. Any thing that monogame cannot know the intended use of, so they fall thru the cracks into the default behavior.

That can result in what is seen in your example.

The positional realignment is as follows and will not be required on the converse platform gl vs dx.

y = GraphicsDevice.Viewport.Height - y;

  • \$\begingroup\$ You should or probably already have asked this on the monogame site but i need 50 quick points i think to comment else were. \$\endgroup\$
    – will_m
    Feb 8, 2020 at 13:23

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .