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

SDL中Surface转Texture返回NULL,求助问题排查思路

解决SDL_CreateTextureFromSurface返回NULL的问题

兄弟,你的问题根源太明显了——你在Game::init方法里只创建了SDL窗口,压根没初始化SDL渲染器(SDL_Renderer)!m_pRenderer一直是个空指针,你拿它去创建纹理,SDL_CreateTextureFromSurface肯定返回NULL啊!

我给你一步步说怎么修复:

1. 补上SDL_Renderer的创建逻辑

在成功创建SDL_Window之后,立刻调用SDL_CreateRenderer初始化渲染器,把它赋值给m_pRenderer。记得检查创建是否成功,避免后续踩坑:

// 在Window创建成功的代码块里添加:
m_pRenderer = SDL_CreateRenderer(m_pWindow, -1, SDL_RENDERER_ACCELERATED);
if (m_pRenderer == nullptr) {
    printf("Renderer creation failed! SDL Error: %s\n", SDL_GetError());
    return false;
}
// 可以顺便设置渲染器的默认颜色,比如黑色
SDL_SetRenderDrawColor(m_pRenderer, 0, 0, 0, 255);

2. 调整渲染逻辑到循环里

你现在在init里只做了一次渲染就Present,但render函数每次循环都会清屏再Present,这样初始渲染的背景会被清掉。把SDL_RenderCopy移到render函数里,保证每次循环都能绘制背景:

void Game::render(){
    SDL_RenderClear(m_pRenderer);
    // 把渲染纹理的代码移到这里
    SDL_RenderCopy(m_pRenderer, m_pTexture, &m_sourceRectangle, &m_destinationRectangle);
    SDL_RenderPresent(m_pRenderer);
}

同时把init里的SDL_RenderCopy和SDL_RenderPresent删掉,只保留纹理的加载和参数初始化。

3. 额外的调试建议

  • 每次调用SDL函数后都检查返回值,比如SDL_CreateRenderer的结果,不要只检查Surface和Texture
  • 确认background.png确实在程序的运行目录下(或者用绝对路径测试),避免因路径问题导致Surface加载异常(虽然你说Surface创建正常,但还是要确认)
  • 清理资源的时候要注意顺序:先销毁Texture,再销毁Renderer,最后销毁Window,你现在的clean方法顺序是对的,保持住

修正后的关键代码片段

Game.cpp里的init方法(核心修改部分)

bool Game::init(const char* title,int xpos,int ypos,int width,int height,int flags){
    if(SDL_Init(SDL_INIT_VIDEO)==0){
        std::cout<<"SDL init success\n";
        m_pWindow = SDL_CreateWindow(title,xpos,ypos,width,height,flags);
        if(m_pWindow!=0) {
            std::cout<<"Window creation success\n";
            // 新增:创建Renderer
            m_pRenderer = SDL_CreateRenderer(m_pWindow, -1, SDL_RENDERER_ACCELERATED);
            if (m_pRenderer == nullptr) {
                printf("Renderer creation failed! SDL Error: %s\n", SDL_GetError());
                return false;
            }
            SDL_SetRenderDrawColor(m_pRenderer, 0, 0, 0, 255);

            int flags=IMG_INIT_JPG|IMG_INIT_PNG;
            int initted=IMG_Init(flags);
            if((initted&flags) != flags){
                printf( "SDL_image could not initialize! SDL_image Error: %s\n", IMG_GetError() );
                return false;
            } else{
                SDL_Surface *m_pSurface;
                m_pSurface = IMG_Load("background.png");
                if(m_pSurface == NULL){
                    printf("Error while trying creating surface! SDL_image Error: %s\n",IMG_GetError());
                    return false; // 这里最好直接返回,避免后续用空Surface操作
                }
                m_pTexture = SDL_CreateTextureFromSurface(m_pRenderer,m_pSurface);
                if(m_pTexture == NULL){
                    printf("Error while trying creating texture! SDL Error: %s\n", SDL_GetError()); // 这里应该用SDL_GetError,因为是SDL的函数
                    SDL_FreeSurface(m_pSurface);
                    return false;
                } else{
                    SDL_FreeSurface(m_pSurface);
                    SDL_QueryTexture(m_pTexture, NULL, NULL,&m_sourceRectangle.w, &m_sourceRectangle.h);
                    m_destinationRectangle.x=m_sourceRectangle.x = 0;
                    m_destinationRectangle.y=m_sourceRectangle.y = 0;
                    m_destinationRectangle.w=m_sourceRectangle.w;
                    m_destinationRectangle.h=m_sourceRectangle.h;
                    // 删掉这里的SDL_RenderCopy和SDL_RenderPresent
                }
            }
        } else{
            std::cout<<"Window creation failed\n";
            return false;
        }
    } else{
        std::cout<<"SDL init fail\n";
        return false;
    }
    std::cout<<"Initialization was a success\n";
    return true;
}

修改后的render方法

void Game::render(){
    SDL_RenderClear(m_pRenderer);
    // 每次循环都绘制纹理
    SDL_RenderCopy(m_pRenderer, m_pTexture, &m_sourceRectangle, &m_destinationRectangle);
    SDL_RenderPresent(m_pRenderer);
}

按照上面的修改,你的纹理应该能正常创建,背景图也能在循环里持续显示了。

内容的提问来源于stack exchange,提问作者Diogo Fernandes

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:35:32