grimfang4 / sdl-gpu

A library for high-performance, modern 2D graphics with SDL written in C.
MIT License
1.18k stars 123 forks source link

Textures off by one pixel on the Y axis when rendering to texture with a Y position ending in exactly .5 #204

Open albertvaka opened 4 years ago

albertvaka commented 4 years ago

I managed to track this down quite a lot, but I don't know how to make any further progress debugging this. This is the C++ code that reproduces the problem:

#include <stdio.h>
#include "SDL_gpu.h"

int main(int argc, char* argv[])
{
    GPU_SetDebugLevel(GPU_DEBUG_LEVEL_MAX);

    GPU_Target* screen = GPU_Init(256, 256, 0);

    GPU_SetDefaultAnchor(0.f, 0.f);

    GPU_Image* intermediate = GPU_CreateImage(256, 256, GPU_FORMAT_RGBA);
    GPU_Target* intermediateTarget = GPU_LoadTarget(intermediate);

    GPU_Image* texture = GPU_LoadImage("redsquare.png");
    if (!texture) {
        printf("Unable to load image\n");
        return 1;
    }

    GPU_SetImageFilter(texture, GPU_FILTER_NEAREST);
    GPU_SetSnapMode(texture, GPU_SNAP_NONE);

    while (true) {
        // Render three squares onto intermediateTarget
        GPU_ClearRGB(intermediateTarget, 0, 0, 0);
        GPU_Rect textureSrc = { 32, 32, 32, 32 };
        GPU_Blit(texture, &textureSrc, intermediateTarget, 50.f,  50.45f); // displays OK
        GPU_Blit(texture, &textureSrc, intermediateTarget, 100.f, 50.50f); // displays incorrectly
        GPU_Blit(texture, &textureSrc, intermediateTarget, 150.f, 50.55f); // displays OK
        GPU_Flip(intermediateTarget);

        // Render intermediateTarget onto screen        
        GPU_ClearRGB(screen, 100, 100, 100);
        GPU_Rect screenSrc = { 0, 0, 256, 256 };
        GPU_Blit(intermediate, &screenSrc, screen, 0, 0);
        GPU_Flip(screen);

        SDL_Event event;
        while(SDL_PollEvent(&event)) {
            if(event.type == SDL_QUIT) {
                return 0;

            }
        }
    }
}

Where redsquare.png is the following image:

redsquare

And it renders like this on my Mac with Intel UHD Graphics 630:

Screen Shot 2020-08-24 at 19 38 23

Note the second square has the topmost row of pixels cut (yellow) and it displays a bottom row of pixels (cyan) that is outside of the 32x32 region specified as src coordinates. This only happens when the blitting to a position ending in .50, so it looks like a rounding problem somewhere.

This DOES NOT happen in the X axis, doesn't happen if rendering directly to the screen (without an intermediate render-to-texture) and doesn't happen if the dest position is any number not ending in exactly .50...

Can anyone try the above code and let me know if this is a problem with my hardware, or an actual bug in SDL_gpu? I'm quite lost here.

NODESPLIT commented 3 years ago

Hey @albertvaka, it's happening for me too. I'm on a 2019 Macbook Pro with Catalina 10.15.3 and it has two GPUs, but it's set to always use the AMD Radeon Pro 5500M.

Screenshot 2021-01-31 at 21 42 47