Keep Primative shape same pixel size regardless of distance and elevation in World Space


I’m trying to figure out the best route to draw a simple shape, like a square, but keep its size constant on the screen (like one would do orthographically). But it has to be drawn in world space.

So if at location (X1, Y1, Z1) the square is 10px by 10px, changing to location (X2, Y2, Z1), the square would still be 10px by 10px on the screen.

Any suggestions on a starting point. Searching the web hasn’t been as helpful as I thought, or (most likely) I’m searching for the wrong keywords.


So pass the shape down in world space but render it with an orthographic projection.

Or by “it has to be drawn in world space”, do you really mean it has to be rendered with a perspective projection active? If so, why?


Yes, perspective projection.

Why? Short Answer: Because I was told to look into the feasibility of doing it by someone higher up than me. It’s more of a “let’s see how much more work it would be to do it this way than the other way (orthographically), and can we make it more efficient”. This is on an embedded system (using a minimum port of OpenGL) which is starting to hit resource limitations.


Ok. That’s fine. Sometimes there’s a need. For instance, generating a 2D screen-space billboard around a real-world point’s screen-space location (which was computed with a perspective projection).

You can do this pretty easily. In your vertex shader, just figure out what screen space coords you want, map that back through NDC to clip-space, and set it on gl_Position.

More detail: gl_Position = (x_c,y_c,z_c,w_c) (i.e. the position in clip-space). That becomes NDC (x_c/w_c, y_c/w_c, z_c/w_c) after the perspective divide. NDC is just simple -1…1 for the whole viewport. Also note that with a perspective projection, w_c = -z_e (i.e. clip-space w == negative of eye-space z).

So compute the screen space position that you “really” want, map that to NDC -1…1 (x_n, y_n, z_n,1), multiply this by your clip-space w value (w_c), and set this on gl_Position.