Arch Linux下SDL2窗口透明或渲染后方内容异常求助
问题根因
窗口透明、透传桌面的问题由两处代码错误直接导致,与SDL 2.0.22版本、Arch Linux系统环境无关:
- 渲染逻辑位置错误:
SDL_RenderClear()、SDL_RenderPresent()两个核心渲染接口被写在了事件循环外部,程序整个运行周期内,事件循环执行时没有任何绘制操作,窗口始终没有提交有效像素内容。等用户触发退出、循环结束后才会执行一次渲染,此时程序马上进入资源释放流程,渲染结果根本不会被用户看到。 - 窗口标志使用错误:创建窗口时传入了
SDL_WINDOW_OPENGL标志,该标志仅用于手动编写原生OpenGL渲染逻辑、自行管理OpenGL上下文的场景;当前代码使用SDL自带的SDL_Renderer做2D渲染,不需要该标志,传入后会干扰SDL渲染后端的上下文初始化,加剧渲染异常。
注:Linux下的X11/Wayland合成器不会给无内容的窗口填充默认底色,程序不提交绘制内容时窗口就会呈现透明、显示后方桌面的状态,属于合成器的正常行为。
修正方案
修改main.c的两处错误即可,头文件、Makefile、项目结构均无问题:
- 创建窗口时移除
SDL_WINDOW_OPENGL标志 - 将清屏、呈现的渲染逻辑移动到事件循环内部,保证每帧都执行绘制
修正后的完整main.c代码:
#include"global.h" static const int width = 800; static const int height = 600; int main (int argc, char **argv) { SDL_Init(SDL_INIT_VIDEO); // 移除SDL_WINDOW_OPENGL标志,使用SDL_Renderer时无需该参数 SDL_Window *window = SDL_CreateWindow("Ferengine", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, 0); SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255); SDL_SetWindowOpacity(window, 1.0f); bool running = true; SDL_Event event; while(running) { while(SDL_PollEvent(&event)) { if(event.type == SDL_QUIT) { running = false; } } // 渲染逻辑移至循环内,每帧执行 SDL_RenderClear(renderer); // 后续所有图形、图片绘制操作都要写在Clear和Present之间 SDL_RenderPresent(renderer); } SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_Quit(); return 0; }
编译运行
修改完成后在项目根目录执行以下命令重新编译即可看到正常的纯红色窗口:
make clean && make ./Build/Ferengine
后续开发注意事项
- 所有绘制相关的接口调用,都必须放在对应帧的
SDL_RenderClear()和SDL_RenderPresent()之间,否则内容不会被提交到窗口。 - 只有当你完全放弃SDL_Renderer、打算手动编写原生OpenGL渲染逻辑时,才需要给窗口添加
SDL_WINDOW_OPENGL标志,此时需要自行创建OpenGL上下文、编写着色器处理渲染流程。
内容的提问来源于stack exchange,提问作者wij
相关产品推荐
相关产品推荐

