我正在使用SDL 2和SDL_TEXTUREACCESS_STREAMING
,而没有OpenGL,我想将一些纹理从我的函数转移/组合到我的主循环中。因此,我决定将我的访问类型从STREAMING
更改为TARGET
,使用SDL_SetRenderTarget
和SDL_RenderCopy
,并再次将访问类型设置为STREAMING
,但当我使用SDL_RenderPresent
预览时,没有显示发送的纹理。
下面是我打开纹理的函数:
TUserFunc(
void, OpenTTF, Reference font, int32_t align, int32_t x, int32_t y, Reference txt, int32_t scl)
{
int tgt_w = g_w;
int tgt_h = g_h;
TTF_Font * ttfFont = TTF_OpenFont(pu->refToAstr(CP_THREAD_ACP, font).c_str(), scl);
if(ttfFont == nullptr) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "SDL ERROR", "Error cargando la direccion de las fuentes", NULL);
quitGame();
}
SDL_Surface * surfaceText = TTF_RenderText_Blended(ttfFont, (pu->refToAstr(CP_THREAD_ACP, txt).c_str()), color);
if(surfaceText == nullptr){
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "SDL ERROR", "Error creando Superficie", NULL);
quitGame();
}
textureText = SDL_CreateTextureFromSurface(g_renderer,surfaceText);
if(textureText == nullptr){
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "SDL ERROR", "Error creando Texturas", NULL);
quitGame();
}
SDL_Rect rectangle;
rectangle.x = x;
rectangle.y = y;
rectangle.w = surfaceText->w;
rectangle.h = surfaceText->h;
//The Problem Start from here
unlockTarget();
g_target = SDL_CreateTexture(g_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, tgt_w, tgt_h);
SDL_SetRenderTarget(g_renderer, g_target);
SDL_RenderCopy(g_renderer, textureText, NULL, &rectangle);
SDL_SetRenderTarget(g_renderer, NULL);
g_target = SDL_CreateTexture(g_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, tgt_w, tgt_h);
lockTarget();
}
字符串lockTarget()
和unlockTarget()
这是一个简单的方法来锁定和解锁纹理,你可以看到,我使用CreateTexture
更改为TARGET
,把我的SetRenderTarget
和RenderCopy
,并再次使用CreateTexture
更改回STREAMING
这是我的主要循环来显示图形:
TUserFunc(void, Flip)
{
if(g_target){
unlockTarget();
SDL_RenderCopy(g_renderer, g_target, nullptr, nullptr);
lockTarget();
}
SDL_RenderPresent(g_renderer);
}
型
但是如果我加上这个,纹理会显示出来,但不是相同的纹理,我的意思是,不是和g_target
结合在一起
TUserFunc(void, Flip)
{
if(g_target){
unlockTarget();
SDL_RenderCopy(g_renderer, g_target, nullptr, nullptr);
lockTarget();
}
if(textureText){
unlockTarget();
SDL_RenderCopy(g_renderer, textureText, nullptr, nullptr);
lockTarget();
}
SDL_RenderPresent(g_renderer);
}
型
在这里,您可以看到其他函数,以便更好地了解问题:
TUserFunc(bool, Init...)
{
...
// This is the main and unique call to g_target
g_target = SDL_CreateTexture(g_renderer, SDL_PIXELFORMAT_ARGB8888,
SDL_TEXTUREACCESS_STREAMING, w, h);
SDL_SetTextureBlendMode(g_target, SDL_BLENDMODE_NONE);
...
}
void lockTarget()
{
if(g_target) SDL_LockTexture(g_target, nullptr, (void**)&g_pix, &g_pitch);
if(textureText) SDL_LockTexture(textureText, nullptr, (void**)&g_pix, &g_pitch);
}
void unlockTarget()
{
if(g_target) SDL_UnlockTexture(g_target);
if(textureText) SDL_UnlockTexture(textureText);
}
型
1条答案
按热度按时间eqoofvh91#
问题是
这行不通:
字符串
创建一个纹理,在其上渲染另一个纹理,然后继续删除其指针并创建一个新的纹理。
SDL_CreateTexture
,顾名思义,创建纹理。使用这一行:
型
你实际上是扔掉了
g_target
所持有的任何东西,并用一个新的、空的、具有STREAMING
访问权限的纹理来替换它。我使用
CreateTexture
更改为TARGET
,将我的SetRenderTarget
和RenderCopy
放在一起,然后再次使用CreateTexture
更改回STREAMING
这根本不是它的工作方式。一旦创建纹理,就不能更改其访问模式。
SDL_CreateTexture
所做的只是创建另一个纹理。因此,您所做的一切就是泄漏内存并获得无法工作的代码。
clean解决方案
根据the documentation(archive),
SDL_Texture
是:一种结构,它包含像素数据的有效的、驱动程序特定的表示形式。
你不应该做任何事情
SDL_Texture
s除了渲染他们或渲染其他纹理到它。无法真实的更改其访问模式。如果你真的需要在其他纹理之上渲染纹理,然后访问它们的像素数据,那么使用
SDL_Surface
s(archive):一种包含用于软件位块传送的像素集合的结构。
您也可以使用
SDL_BlitSurface
将它们blit在其他对象之上。此外,您还可以访问SDL_Surface
s的像素数据以进行进一步编辑。只有当你接触到像素数据时,才能使用
SDL_CreateTextureFromSurface
将其转换为纹理并渲染它。这可能比直接处理纹理要慢,但至少它是有效的,而且应该这样做。
当然,
STREAMING
模式存在于纹理上是有原因的,但是你所能做的就是用它来做一些不好的事情,而使用表面会更好。除此之外,你不能像我已经说过的那样将纹理的访问模式从
TARGET
更改为STREAMING
,所以你在这里没有选择。你需要使用曲面。