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
相关产品推荐
相关产品推荐

