🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Need help understanding orthographic projection for UI rendering

Started by
11 comments, last by EBZ 4 years, 1 month ago

I'm trying to create an orthographic projection using GLM for rendering UI elements. I have a window that's 1280x720 and I'm creating the projection like so:

float aspect = (float) height / (float) width;
// args: left, right, bottom, top, ...
glm::mat4 projection = glm::ortho(-1.0, 1.0, -aspect, aspect , near, far); // near: -2.0, far: 2.0

If I create square mesh like this:

auto geometry = Geometry::Primitive::Plane(1.0f, 1.0f * aspect); // (width, height)

Then the square would look too wide, UNLESS I do this:

auto geometry = Geometry::Primitive::Plane(1.0f * aspect, 1.0f * aspect);

What do you all think I'm doing wrong, and what's the best way to construct an orthographic projection for rendering UI elements?

Oh and one last thing: If my height is larger than my width, I'm guessing I would have to switch the division for my aspect ratio?

Thanks all!

Advertisement

Have you looked at the parameters for ortho?

Why do you think a rectangle of the dimensions 1, aspect should be a square?

You're not doing anything wrong - that is a decent way to create an ortographic projection.
- But you're onto something irt. getting the inverse of the aspect ratio! ?

@SuperVGA Hey thanks for the answer, I appreciate it ? I was definitely wrong about my square like you said. My projection's left and right are 1, so I guess my square's width at 1 would take up the whole screen (width-wise).

One question though, when you say I got the inverse of the aspect, what did you mean? Sorry about the dumb question. I switched from height/width to width/height, but then the height of my UI element didn't work as well anymore.

Thanks again for the reply

EBZ said:

@SuperVGA Hey thanks for the answer, I appreciate it ? I was definitely wrong about my square like you said. My projection's left and right are 1, so I guess my square's width at 1 would take up the whole screen (width-wise).

One question though, when you say I got the inverse of the aspect, what did you mean? Sorry about the dumb question. I switched from height/width to width/height, but then the height of my UI element didn't work as well anymore.

Thanks again for the reply

@ebz no problem - by inverse, I meant that you could use 1.0 / aspect to your advantage, in one or perhaps two of your ortho() arguments.

Say for instance that you provided -1, 1, -1, 1 as the arguments; then you'd expect the rectangle going from -1,-1 to 1,1 to cover the screen exactly.

Now if you were to compensate for the aspect ratio, you could divide by aspect in two of your arguments, and the -1,-1 to 1,1 would render as a square.

I admit to not investing enough thought to tell which two those are. Trial and error is a quick way to settle it. :-)

Ortho's parameters are left, right, bottom, top, near, far. Aspect is not used here, or will be interpreted as bottom and top respectively.

Exact values depend on use case, on what you want to display.

Try making the plane 0.5f, 0.5f in size in both axes and leave the projection alone.
The aspect in the projection is to compensate for the screen not being a square. So if you also compensate when making the plane you'll have done it twice, making it show up squished.

An alternative is to make the projection go from 0,0 to your resolution.
then you make your planes in pixels.

Video Game Programmer.
5 years in industry.

Green_Baron said:

Ortho's parameters are left, right, bottom, top, near, far. Aspect is not used here

I'm not sure I follow. Aspect ratio is typically compensated for when creating an orthographic projection, just as aspect can be compensated for when deciding on FOV in a perspective projection.

Perhaps your point was something else, and I just missed it.

For rendering UI, a convenient ortho matrix is:

0, width, height, 0, -1, 1

Using that matrix you can lay out your UI elements using actual screen co-ordinates and you don't need to worry about aspect, scaling, etc.

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

@supervga : it's simply from the documentation of the glm::orthos.

Since orthographic projection has no perspective distortion, it only needs a size, not a ratio.

As @21st century moose suggested, you can start off with the viewport size and a depth range that includes what you want to render. You can also use the 4-parameter version of glm::ortho() if unsure or oblivious to where your stuff lies on the z axis. That'll render everything in the view range and save a few operations.

Note that, if you render a unit thing (size 1), it'll be very tiny on a viewport defined by the screen size. But a UI can calculate screen coordinates directly, thus choosing the size like that is convenient.

Green_Baron said:

@supervga : it's simply from the documentation of the glm::orthos.

Since orthographic projection has no perspective distortion, it only needs a size, not a ratio.

As @21st century moose suggested, you can start off with the viewport size and a depth range that includes what you want to render. You can also use the 4-parameter version of glm::ortho() if unsure or oblivious to where your stuff lies on the z axis. That'll render everything in the view range and save a few operations.

Note that, if you render a unit thing (size 1), it'll be very tiny on a viewport defined by the screen size. But a UI can calculate screen coordinates directly, thus choosing the size like that is convenient.

That's right - but the ratio is implied if you give it an absolute resolution - it's the same proportions you'll end up with.

As you stated previously, it depends on what you want from it, and it just seemed like OP wanted something to take up a big part of the screen. But I agree that the other approach makes it clearer somehow.

This topic is closed to new replies.

Advertisement