c++windowsdlviewportcentering

SDL2/C++: I'm confused about centering the viewport in SDL2


When trying to center my renderer's viewport, it seems like adding half of the difference between the window-size and viewport-size to the viewport's x and y coords isn't correct. Instead you need to divide this difference by 3? I'm so confused on this and hope someone has some clarification.

The goal is to render a 4:3 viewport on a 16:9 window.

Aside of this, the viewport's aspect ratio starts skewing completely when I resize the window around manually.

SDL_Rect windowRect{ };
SDL_GetWindowSize(m_pWindow, &windowRect.w, &windowRect.h);
SDL_Rect newViewport{ };
float aspectRatio{ 4 / 3.f };
if (static_cast<float>(windowRect.w) / windowRect.h >= aspectRatio)
{
    newViewport.h = windowRect.h;
    newViewport.w = windowRect.h * aspectRatio;
    newViewport.x = (windowRect.w - newViewport.w) / 2; // interchange this between 2 and 3
}
else
{
    newViewport.w = windowRect.w;
    newViewport.h = windowRect.w / aspectRatio;
    newViewport.y = (windowRect.h - newViewport.h) / 2; // interchange this between 2 and 3
}
SDL_RenderSetViewport(m_pRenderer, &newViewport);

Result when divided by 2

Result when divided by 3

Example of skewed viewport after resizing window

Regarding the funky centering, I tried looking around on the internet on why SDL2 does this, to obviously no avail.

And about the skewing, I tried applying a couple of changes to the calculations and looked if the numbers I got were actually correct, and they were.

I was expecting something to change with these adaptations but all I could do was break it some more or change nothing.


Solution

  • The code snippet was right, as in it does make the viewport the largest centered 4:3 rectangle that fits the viewport. The problem was in my rendering method, which passed an SDL_Rect, filled using SDL_GetViewport(), as parameter. Instead you need to pass NULL or any kind of value of zero for it to fill the viewport correctly.

    Correct

    void RenderViewport() const
    {
        SDL_RenderFillRect(m_pRenderer, NULL);
    }
    

    Incorrect

    void RenderViewport() const
    {
        SDL_Rect viewport{};
        SDL_RenderGetViewport(m_pRenderer, &viewport);
        SDL_RenderFillRect(m_pRenderer, &viewport);
    }