为什么我无法绘制到 SDL2 中的纹理?

Why am I unable to draw to a texture in SDL2?

在过去的几个月里,我一直在晚上和周末使用 SDL 处理一个项目。我目前正在尝试使菜单系统正常工作。目前,我正在使用 SDL_TTF 绘制文本。至于我的问题,当我尝试将一些纹理绘制到另一个纹理时,我看到了一些奇怪的行为。

奇怪的是,当我绘制它时,在使用 SDL_TEXTUREACCESS_TARGET 创建的目标纹理上(就像它在文档中说的那样)没有绘制任何东西,但是 returns 没有错误。但是,如果我使用 SDL_TEXTUREACCESS_STATICSDL_TEXTUREACCESS_STREAM,由于 access 属性,当我设置渲染目标时它 returns 出错,但绘制得很好。在做了一些挖掘之后,我听说了一些关于 Intel 驱动程序中的错误的消息(我使用的是带有 Intel 图形的 Macbook),所以我想知道这是否是我搞砸的事情,以及我该如何修复它。或者,如果这不是我的错,我仍然想知道发生了什么,它在不同平台上的表现是否会有所不同,以及我该如何解决它。

这是我的代码,删除了不必要的部分后:

我创建渲染器:

renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);

稍后,当我渲染到 canvas:

TTF_Font *fnt = loadFont(fontName.c_str(), fontSize);

在这里我解析了一些属性并使用 TTF_SetFontStyle() 和文本颜色的 clr 设置它们。

SDL_Texture *canvas; 
canvas = SDL_CreateTexture(rendy, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, contentRect.w, contentRect.h)
SDL_SetRenderTarget(rendy, canvas);

int pos = 0;
for (list<string>::iterator itr = lines.begin(); itr != lines.end(); itr++){
    SDL_Surface *temp;
    temp = TTF_RenderText_Blended(fnt, src.c_str(), clr);

    SDL_Texture *line;
    line = SDL_CreateTextureFromSurface(rendy, temp);
    int w,h;
    SDL_QueryTexture(line, NULL, NULL, &w, &h);

    SDL_Rect destR;

    //Assume that we're left justified
    destR.x = 0;
    destR.y = pos;
    destR.w = w;
    destR.h = h;

    SDL_RenderCopy(rendy, line, NULL, &destR);
    SDL_DestroyTexture(line);
    SDL_FreeSurface(temp);
    pos += TTF_FontLineSkip(fnt);
}

//Clean up
SDL_SetRenderTarget(rendy, NULL);

canvas 返回到调用函数,以便在修改此文本框之前可以对其进行缓存。该功能的工作原理是为整个盒子创建一个纹理,在其上绘制背景纹理,然后在其上绘制此图像,并保持整个物体。

该代码如下所示:

(绘制背景的东西,渲染效果很好)

SDL_Texture *sum = SDL_CreateTexture(rendy, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, globalRect.w, globalRect.h);

SDL_SetTextureBlendMode(sum, SDL_BLENDMODE_BLEND);
SDL_SetRenderTarget(rendy, sum);

string lPad = getAttribute(EL_LEFT_PADDING);
string tPad = getAttribute(EL_TOP_PADDING);
int paddingL = strtol(lPad.c_str(), NULL, 10);
int paddingT = strtol(tPad.c_str(), NULL, 10);

SDL_Rect destR;
SDL_Rect srcR;
srcR.x = 0;
srcR.y = 0;
srcR.w = globalRect.w; //globalRect is the size size of the whole button
srcR.h = globalRect.h;
destR.x = 0;
destR.y = 0;
destR.w = globalRect.w;
destR.h = globalRect.h;

SDL_RenderCopy(rendy, bgTexture, NULL, &destR);
int maxX = contentRect.w;
fgTexture = getFGImage(rendy); //The call to the previous part

int w, h;
SDL_QueryTexture(fgTexture, NULL, NULL, &w, &h);

int width, height;
getTextSize(&width, &height, maxX);

srcR.x = 0;
srcR.y = 0;
srcR.w = width;
srcR.h = height;
destR.x = paddingL;
destR.y = paddingT;
destR.w = globalRect.w;
destR.h = globalRect.h;

SDL_RenderCopy(rendy, fgTexture, NULL, &destR);
SDL_DestroyTexture(fgTexture);
SDL_DestroyTexture(bgTexture);


return sum;

Sum 返回给另一个绘制绘图的函数。

提前致谢!

更新 所以我发现它只在我有不正确的访问设置时绘制的原因是,由于函数返回错误值,渲染目标从未设置为纹理,所以它只是在屏幕上绘制。我还通过编写一个函数 AuditTexture 检查了我的所有纹理,该函数检查渲染器是否支持纹理的纹理格式,打印访问属性的字符串描述,并打印尺寸。我现在知道它们的所有纹理格式都受支持,这两行是静态的,canvas 和 sum 是渲染目标,其中 none 的维度为零。

事实证明,我已经将渲染目标设置为复合纹理,然后在绘制文本之前调用我的函数将渲染目标设置为文本纹理。然后当我从函数返回时,渲染目标仍然是文本纹理而不是复合纹理,所以我基本上是在其自身上绘制文本而不是在背景上绘制。

致智者的一句话:永远不要假设有人为您处理好某些事情,尤其是在 C 或 C++ 中。