Kamujin's picture

Fliping Screen Origin

I am making a lot of progress on my GUI port.

I am somewhat stuck on one issue and I'd like to hear what you all think about it.

In OpenGL, the Y axis is inverse relative to most GUI coordinate systems that I've used. In other words, the Y values get larger as you move from the bottom of the screen to the top.

Most GUI systems use the top left as the origin (0,0) for widget locations.

Obviously, I need to make an adjustment somewhere to account for this. My question is where? My current choices seem to be.

1) Build the whole system with a bottom-left origin. As this is most native, I would think things like mouse picking and gui events would be the simplest and fastest to compute.

2) Build the GUI system with a top-left origin and convert the coordinates when I construct the vertex arrays.

3) Build the GUI system with a top-left origin and convert the coordinates in a shader.

Is there an established "best practice" for this?


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
JTalton's picture

I am also working on a GUI system, and yes that issue exists. It is really up to you.

I use the OpenGL method with the origin being in the bottom-left corner. I like this because I feel that the top of my widget should be greater than the bottom of my widget. If you use the System.Drawing.Rectangle it is the opposite with the top being less than the bottom. I got around this my making my own class called ScreenArea that has top greater than bottom.

Switching between top-left and bottom-left is as simple as changing your projection matrix and possibly subtracting your mouse Y from the window height on mouse input. Of course if you are using the OpenTK text rendering I believe it uses bottom-left so that may also need to be tweaked.

I'd love to hear more about your design and screen shots. :)

Out of town for a week... may have internet access...

Kamujin's picture

I am working on a port of a GUI that I built under MDX1.1 and XNA. Screenshots of the pre-ported version can be seen at www.robotechmmo.com in the screenshots section.

Thanks for the advice.

the Fiddler's picture

OpenTK text rendering uses top-left as (0, 0), as this simplifies text layout (which is done through System.Drawing).

This is a personal preference, but I generally find it easier / more intuitive to setup an ortho projection with (0, 0) as top-left and build the GUI with that.

Inertia's picture

With the texture loaders I've faced a similar problem (decided to flip the image for optimization reasons that require the texture matrix to be identity), but the solution might be interesting.

Think of Matrices as a definition for a coordinate system. How do you have to modify it to flip the Y axis? Mirror the Y axis and translate the origin.

GL.Scale( 1f, -1f, 1f );
GL.Translate( 0f, -height, 0f );

Edit: changed discussion's subject to something more descriptive than "Looking for advice"

Kamujin's picture

I have decided to use an orthographic projection matrix with a top-left origin for the GUI system. This seems to have the lowest cost in terms of complexity and speed. Also, it seems to be consistent with OpenTK's font system.

I use shaders with a worldViewProjection matrix passed as a uniform, so for my app I am calling...

    this.modelViewProjection = Matrix4Helper.CreateOrthographicProjection(0, screenSize.Width, 0, screenSize.Height, 0, 1);

on any screen resize events.

Kamujin's picture

OK, so it seems that Mouse.X and Mouse.Y are in top/left origin format too?

objarni's picture

@Kamujin: yup Windows.Forms have top-left as origin, Y going down X going right.

the Fiddler's picture

True, and OpenTK respects that for consistency.

Inertia's picture

Since the original question has been answered sufficiently, I guess it's ok to go offtopic :P

shaders with a worldViewProjection matrix passed as a uniform

You said that before, but I still don't quite get the advantage of this over using GL built-in uniforms (I assume you are doing this to use GL_EXT_draw_instanced?). How are you retrieving gl_NormalMatrix in the shader? Manually inverting the 3x3 rotation part?

Kamujin's picture

When I port over the rest of my game project, there will be cases where the shaders will need access to the model, view, or projection matrices separately (If I am remembering correctly), so I thought it would be a good idea to get used to passing matrices manually.

I am an intermediate level 3d graphics programmer at best, so forgive me if my technique lacks a certain elegance.