SDL2 绘制到纹理与直接绘制到屏幕不同

问题描述 投票:0回答:1

我在 Windows 11 上使用 SDL2 版本 2.28.3,该问题发生在所有后端(DirectX、opengl、软件)上,与先绘制到纹理相比,当我直接绘制到屏幕时得到不同的结果。

我编写了以下抗锯齿圆算法,该算法本身并不重要,只是它使用了 alpha 混合,所以我怀疑存在问题,当我禁用 alpha 混合并仅对背景进行着色时,该问题也会消失白色,但实际使用时需要进行alpha混合。

enter image description here

enter image description here

致电

SDL_SetTextureBlendMode(stored_arc_texture, SDL_BLENDMODE_BLEND)
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND)
没有帮助。

#include <SDL2/SDL.h>
#include <array>

void DrawFilledArcAA3(SDL_Renderer* renderer, SDL_Point midpoint, int radius, const SDL_Color color)
{
    SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
    int y = 0;
    int max_y = radius + 1;
    int raidus_squared = radius * radius;
    while (y <= max_y)
    {
        double x = sqrt(raidus_squared - y * y);
        {
            int max_x = static_cast<int>(floor(x));
            if (floor(x) < y)
            {
                break;
            }
            SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, 255);
            std::array<SDL_Point, 4> points{
            SDL_Point{midpoint.x, midpoint.y + y}, SDL_Point{midpoint.x + max_x, midpoint.y + y},
            SDL_Point{midpoint.x + y, midpoint.y}, SDL_Point{midpoint.x + y, midpoint.y + max_x},
            };
            SDL_RenderDrawLines(renderer, points.data(), points.size());
        }

        {
            double overflow = x - floor(x);
            int color_value = 255 * overflow;
            SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, color_value);
            int max_x = static_cast<int>(floor(x + 1));
            std::array<SDL_Point, 2> points{
                SDL_Point{midpoint.x + max_x, midpoint.y + y},
                SDL_Point{midpoint.x + y, midpoint.y + max_x},
            };

            SDL_RenderDrawPoints(renderer, points.data(), points.size());
        }

        y++;
    }
}

int main(int argc, char** argv) 
{

    SDL_Window* pWindow = NULL;
    pWindow = SDL_CreateWindow("test AA circle", SDL_WINDOWPOS_UNDEFINED,
        SDL_WINDOWPOS_UNDEFINED,
        640,
        480,
        SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);

    SDL_Renderer* renderer = SDL_CreateRenderer(pWindow, -1, 
        SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE);

    bool is_running = true;
    while (is_running)
    {

        SDL_Event e;
        while (SDL_PollEvent(&e))
        {
            if (e.type == SDL_QUIT)
            {
                is_running = false;
                break;
            }
        }

        SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);

        SDL_RenderClear(renderer);
        
        {
            // render directly to screen
            DrawFilledArcAA3(renderer, SDL_Point{ 10,4 }, 100, SDL_Color{ 180,180,180,255 });

        }

        // render to texture first
        {
            int stored_radius = 100;
            SDL_Texture* old_texture = SDL_GetRenderTarget(renderer);
            SDL_Texture* stored_arc_texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_TARGET, stored_radius, stored_radius);
            SDL_SetRenderTarget(renderer, stored_arc_texture);
            SDL_SetTextureBlendMode(stored_arc_texture, SDL_BLENDMODE_BLEND);
            DrawFilledArcAA3(renderer, { 0,0 }, stored_radius, SDL_Color{ 180,180,180,255 });
            SDL_SetRenderTarget(renderer, old_texture);
            SDL_Rect dst{ 120 + 10, 4, stored_radius, stored_radius};
            SDL_RenderCopy(renderer, stored_arc_texture, 0, &dst);
            SDL_DestroyTexture(stored_arc_texture);
        }

        SDL_RenderPresent(renderer);

    }

    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(pWindow);
    SDL_Quit();
    return 0;
}

如何修复此问题以使两者看起来相同?

c++ sdl sdl-2
1个回答
0
投票

我找到了一个修复,虽然不直观,如果我在绘制之前在纹理上使用带有颜色

SDL_RenderClear
(是的,透明白色)的
255, 255, 255, 0
,那么即使在黑色背景上,它也会正确绘制......文档中没有提到我需要在使用它之前清除纹理,也没有在任何地方的示例中完成。

{
    int stored_radius = 100;
    SDL_Texture* old_texture = SDL_GetRenderTarget(renderer);
    SDL_Texture* stored_arc_texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_TARGET, stored_radius + 20, stored_radius + 20);
    SDL_SetRenderTarget(renderer, stored_arc_texture); // target the texture
    SDL_SetRenderDrawColor(renderer, 255, 255, 255, 0); // set color to transparent white
    SDL_RenderClear(renderer); // clear renderer
    DrawFilledArcAA3(renderer, { 0,0 }, stored_radius, SDL_Color{ 180,180,180,255 }); // draw the things
    SDL_SetRenderTarget(renderer, old_texture); // set it back to sceen
    SDL_SetTextureBlendMode(stored_arc_texture, SDL_BLENDMODE_BLEND);
    SDL_Rect dst{ 120 + 10, 4, stored_radius + 20, stored_radius + 20 };
    SDL_RenderCopy(renderer, stored_arc_texture, 0, &dst);
    SDL_DestroyTexture(stored_arc_texture);
}
© www.soinside.com 2019 - 2024. All rights reserved.