我在 Windows 11 上使用 SDL2 版本 2.28.3,该问题发生在所有后端(DirectX、opengl、软件)上,与先绘制到纹理相比,当我直接绘制到屏幕时得到不同的结果。
我编写了以下抗锯齿圆算法,该算法本身并不重要,只是它使用了 alpha 混合,所以我怀疑存在问题,当我禁用 alpha 混合并仅对背景进行着色时,该问题也会消失白色,但实际使用时需要进行alpha混合。
致电
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;
}
如何修复此问题以使两者看起来相同?
我找到了一个修复,虽然不直观,如果我在绘制之前在纹理上使用带有颜色
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);
}