You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SDL2中SDL_TEXTUREACCESS_STREAMING纹理合并显示异常求助

问题分析与解决方案

核心问题

  1. 纹理数据完全丢失:你每次重建g_target时都是创建全新的空纹理,既没有继承原有STREAMING纹理的像素数据,也没有保留刚绘制的文字内容,最终渲染的是空白纹理。
  2. lockTarget函数指针冲突:g_pix被连续两次赋值,原g_target的像素指针会被textureText的指针覆盖,导致无法正确操作目标纹理的像素,还可能引发内存泄漏。
  3. 不必要的纹理重建:SDL纹理的访问类型是创建时确定的,不需要反复销毁重建,通过中间纹理或直接像素复制即可完成合并。

解决方案1:用临时目标纹理合并后复制回STREAMING纹理

保留原g_target的STREAMING类型,通过临时TARGET纹理完成文字与原纹理的合并,再将结果复制回g_target:

修改OpenTTF函数的问题代码段:

// 问题从此处开始
unlockTarget(); 

// 1. 创建临时目标纹理
SDL_Texture* temp_target = SDL_CreateTexture(g_renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_TARGET, tgt_w, tgt_h);
if (!temp_target) {
    SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "SDL ERROR", "Error creating temp target", NULL);
    quitGame();
}

// 2. 将原g_target内容复制到临时目标
SDL_SetRenderTarget(g_renderer, temp_target);
SDL_RenderCopy(g_renderer, g_target, nullptr, nullptr);
// 3. 绘制文字到临时目标
SDL_RenderCopy(g_renderer, textureText, NULL, &rectangle);
SDL_SetRenderTarget(g_renderer, NULL);

// 4. 把临时目标的像素复制回g_target
void* temp_pixels;
int temp_pitch;
SDL_LockTexture(temp_target, nullptr, &temp_pixels, &temp_pitch);
SDL_LockTexture(g_target, nullptr, (void**)&g_pix, &g_pitch);

// 像素格式匹配(ARGB8888),直接内存复制
memcpy(g_pix, temp_pixels, tgt_w * tgt_h * 4);

SDL_UnlockTexture(g_target);
SDL_UnlockTexture(temp_target);

// 清理临时资源
SDL_DestroyTexture(temp_target);
lockTarget();

同时修正lockTarget函数,避免指针覆盖:

// 新增全局变量存储各自的像素指针和行距
void* g_pix_target = nullptr;
int g_pitch_target = 0;
void* g_pix_text = nullptr;
int g_pitch_text = 0;

void lockTarget()
{
    if(g_target) SDL_LockTexture(g_target, nullptr, (void**)&g_pix_target, &g_pitch_target);
    if(textureText) SDL_LockTexture(textureText, nullptr, (void**)&g_pix_text, &g_pitch_text);
}

void unlockTarget()
{
    if(g_target) SDL_UnlockTexture(g_target);
    if(textureText) SDL_UnlockTexture(textureText);
}

解决方案2:直接将文字Surface像素复制到STREAMING纹理

跳过渲染目标,直接操作像素缓冲区完成合并,效率更高:

修改OpenTTF函数的问题代码段:

// 问题从此处开始
unlockTarget(); 

// 锁定g_target获取像素指针
void* target_pixels;
int target_pitch;
SDL_LockTexture(g_target, nullptr, &target_pixels, &target_pitch);

// 转换为像素数组(ARGB8888格式)
uint32_t* src_pixels = (uint32_t*)surfaceText->pixels;
uint32_t* dst_pixels = (uint32_t*)target_pixels;
int src_pitch_div = surfaceText->pitch / 4;
int dst_pitch_div = target_pitch / 4;

// 逐像素复制文字到目标纹理对应位置
for (int y = 0; y < surfaceText->h; y++) {
    for (int x = 0; x < surfaceText->w; x++) {
        int dst_x = x + rectangle.x;
        int dst_y = y + rectangle.y;
        // 确保坐标不越界
        if (dst_x >= 0 && dst_x < tgt_w && dst_y >= 0 && dst_y < tgt_h) {
            dst_pixels[dst_y * dst_pitch_div + dst_x] = src_pixels[y * src_pitch_div + x];
        }
    }
}

SDL_UnlockTexture(g_target);
lockTarget();

// 清理临时资源(避免内存泄漏)
SDL_FreeSurface(surfaceText);
SDL_DestroyTexture(textureText);
textureText = nullptr;

额外注意事项

  • 每次创建textureText后,记得在不需要时销毁,避免内存泄漏。
  • 确保所有纹理/表面的像素格式一致(此处为ARGB8888),否则需要添加格式转换逻辑。
  • 如果需要alpha混合效果,需设置正确的纹理混合模式,或手动处理像素的alpha通道。

内容的提问来源于stack exchange,提问作者Strong FS - MUGEN Studio

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 07:27:03