Search code examples
directxshaderrenderinghlsl

Screen-space to clip-space conversion problems


I'm drawing a GUI in Direct3D 11, and currently I'm managing it by drawing a load of 3D quads near the screen. I've decided to instance the screen quads to improve speed a little.

When I draw I quad I provide it with an input position (input.pos), which is a set of coordinates that define a quad as follows:

0,0
0,1
1,0
1,1

I also pass in an instance position, which is a position, in screen space, of the quad, e.g.

456,700

And finally I pass in the scale of the quad, which is in pixels. So a 50x30 pixel quad will have the following scale value:

50,40

In order to convert these coordinates into clip-space for my pixel shader I use the following math (which I intent to do on the CPU eventually, but for now is done in the vertex shader):

output.pos = float4((input.pos*2* input.instanceScale) / winSize+input.instancePos*2/winSize -1,0.25,1);

This mostly works and everything appears near everything else, but the y axis is inverted. This is because clip space runs from -1 to 1, but 1 is the top of the screen in clip-space - contrary to the normal way of doing things. As such, the solution should be:

output.pos.x = 2*(input.pos.x * input.instanceScale.x + input.instancePos.x)/winSize.x -1;
output.pos.y = 1 - 2*(input.pos.y * input.instanceScale.y + input.instancePos.y)/winSize.y;

However when I run this, my quads just disappear. I assume they're still rendering, but off screen somewhere.

Does anybody have any idea what might be going wrong?

Also, if I keep the new output.pos.x calculation but use the old calculation for the y coordinate, it still works. So the problem must be in that second line of this new code.

Thanks very much

EDIT1: I've now followed TomMcTwattyPants' advice and lerped the finalized y position between 1 and -1. What happens is the GUI elements move vertically towards the centre and also shrink. As they reach the centre they shrink out of existence and then it loops.

There is a delay before the loop, so I believe between the 0 and -1 portion of the multiplication the quads are invisible. I'm not sure why though, perhaps the order of the vertices has changed so the normal is now pointing away from the screen and is being culled? I'll try turning off backface culling to see if that changes anything. It's not needed for a GUI pass anyway.

EDIT2: The problem was backface culling. Disabling that fixed everything


Solution

  • The simplest way to invert the y axis would be to multiply it by minus one:

    output.pos.y *= -1;