Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rotating display is fine, but clipping is an issue (SDL2+OpenGL ES - No X server) #3972

Open
hippyau opened this issue Mar 26, 2021 · 6 comments

Comments

@hippyau
Copy link

hippyau commented Mar 26, 2021

Version/Branch of Dear ImGui:

Version: 1.82
Branch: master

Back-end/Renderer/Compiler/OS

Back-ends: imgui_impl_SDL.cpp + Open GL ES on Raspberry Pi4 (SDL2 kmsdrm driver, without X11)
Compiler: gcc
Operating System: Linux / Raspbian

My Issue/Question:

Is there a way to have Dear ImGui globally swap X and Y coordinates, that is, to draw the whole UI in a rotated orientation?

I have a "1920x480 LCD Panel" letterbox HDMI display, however it is really a 480x1920 LCD Panel, and I cannot find driver support or a method of using SDL to rotate the display for me. I am not using X11.

I believe swapping X and Y would do the trick, is this achievable?

@ocornut
Copy link
Owner

ocornut commented Mar 26, 2021

You will need to rotate the projection matrix in the renderer. This will need modifying the renderer. You may need to rotate the mouse position as well.

@hippyau
Copy link
Author

hippyau commented Mar 26, 2021

Great success...

image

I modified the ortho_projection[4][4] to...

        { 0.0f,         2.0f/(R-L),   0.0f,   0.0f },
        { 2.0f/(T-B),   0.0f,         0.0f,   0.0f },
        { 0.0f,         0.0f,         1.0f,   0.0f },
        { (T+B)/(B-T),  (R+L)/(L-R),  0.0f,   1.0f },

I had to comment out because of some weird clipping issues.

//                    glScissor((int)clip_rect.x, (int)(fb_height - clip_rect.w), (int)(clip_rect.z - clip_rect.x), (int)(clip_rect.w - clip_rect.y));

And in SDL2_NewFrame(), I hardcoded my screen dimensions...

    display_w = 480; display_h = 1920;  // real screen
    w = 1920; h = 480; // we want

and swapped X & Y in the mouse input :)

@hippyau hippyau closed this as completed Mar 26, 2021
@hippyau
Copy link
Author

hippyau commented May 3, 2021

As @ocornut explained, I needed to rotate the projection matrix so modified ortho_projection[4][4] as previous comment,

  { 0.0f,         2.0f/(R-L),   0.0f,   0.0f },
  { 2.0f/(T-B),   0.0f,         0.0f,   0.0f },
  { 0.0f,         0.0f,         1.0f,   0.0f },
  { (T+B)/(B-T),  (R+L)/(L-R),  0.0f,   1.0f },

I then have display in correct orientation working nicely, except.... I had to comment out glScissor((int)clip_rect.x, (int)(fb_height - clip_rect.w), (int)(clip_rect.z - clip_rect.x), (int)(clip_rect.w - clip_rect.y)); because it was messing it all up.

Now I need to get glScissor working with the rotated projection matrix because the mess is terrible.

I am not very smart when it comes to OpenGL and projection matrices etc... I have tried a few permutations, I thought swapping x and y would be sufficient, but I am doing something very wrong and not really understanding.

Should I be changing the clip_rect, or the order of the input arguments to glScissor ?

In normal orientation, I think clip_rect.x and .y are top-left x,y of a rectangle, .z and .w are bottom-right x,y so why is swapping them not rotating the rectangle properly?

[original from impl_opengl3.cpp]

[...]
                clip_rect.x = (pcmd->ClipRect.x - clip_off.x) * clip_scale.x;
                clip_rect.y = (pcmd->ClipRect.y - clip_off.y) * clip_scale.y;
                clip_rect.z = (pcmd->ClipRect.z - clip_off.x) * clip_scale.x;
                clip_rect.w = (pcmd->ClipRect.w - clip_off.y) * clip_scale.y; 

                if (clip_rect.x < fb_width && clip_rect.y < fb_height && clip_rect.z >= 0.0f && clip_rect.w >= 0.0f)
                {
                    // Apply scissor/clipping rectangle
                    glScissor(
                      (int)clip_rect.x, 
                      (int)(fb_height - clip_rect.w), 
                      (int)(clip_rect.z - clip_rect.x), 
                      (int)(clip_rect.w - clip_rect.y)
                    ); 
[...]                   

@hippyau hippyau reopened this May 3, 2021
@hippyau hippyau changed the title Can ImGui be told to rotate its display? Swap X and Y coordinates? Rotating display is fine, but clipping is an issue (SDL2+OpenGL ES - No X server) Mar 6, 2023
@hippyau
Copy link
Author

hippyau commented Mar 6, 2023

I have tried several permutations of swapping and offsetting x, y, z, w to get clipping to work, but I can't translate the rectangle that glScissor needs to account for the rotated projection matrix, there is clipping present but in the wrong places.

@ocornut ocornut added the opengl label Mar 6, 2023
@schoolpost
Copy link

schoolpost commented Nov 29, 2023

I have tried several permutations of swapping and offsetting x, y, z, w to get clipping to work, but I can't translate the rectangle that glScissor needs to account for the rotated projection matrix, there is clipping present but in the wrong places.

Did you get a work around for this? I have a waveshare display that is 1080x1920, but I need my fullscreen Imgui app to display as 1920x1080 I need everything rotated 90 degrees, I'm trying to avoid the overhead of X11 or Wayland with my Raspberry Pi 5 / Debian Bookworm setup.

@jgeskens
Copy link

jgeskens commented Feb 6, 2024

I have found a solution for the clipping when rotating the screen 180 degrees. This is the correct way:

// Apply scissor/clipping rectangle (Y is inverted in OpenGL)
GL_CALL(glScissor((int)clip_max.x, (int)((float)fb_height - clip_min.y), (int)(clip_min.x - clip_max.x), (int)(clip_min.y - clip_max.y)));

So basically you just replace min with max and vice versa. For 90 degrees I think you also have to swap and/or negate x/y. But this will hopefully make finding the right permutation easier.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants