SDL2不清空渲染器更新屏幕:仅第二个矩形显示问题求助
SDL_RenderPresent后渲染元素丢失的问题解决
问题原因
SDL默认使用双缓冲渲染机制,SDL_RenderPresent()的作用是交换前台显示缓冲区和后台渲染缓冲区:
- 第一次调用
SDL_RenderPresent()时,后台缓冲区(已绘制rect)被交换到前台显示,此时后台缓冲区会被重置为SDL_RenderClear()后的初始状态(通常是黑色)。 - 之后你在后台缓冲区绘制nice,再次调用
SDL_RenderPresent()时,只会把后台的nice内容交换到前台,覆盖了之前显示的rect,所以最终只能看到第二个矩形。
解决方案
方案1:一次性渲染所有元素(标准流程)
将所有需要显示的元素绘制完成后,再调用一次SDL_RenderPresent(),这是SDL最常用的渲染模式:
SDL_Event event; SDL_RenderClear(renderer); SDL_Rect rect = {10, 10, 100, 100}; SDL_Rect nice = {130, 123, 100, 100}; SDL_SetRenderDrawColor(renderer, 255, 255, 255, SDL_ALPHA_OPAQUE); // 先画第一个矩形 SDL_RenderFillRect(renderer, &rect); // 再画第二个矩形 SDL_RenderFillRect(renderer, &nice); // 一次性提交所有渲染内容 SDL_RenderPresent(renderer); while (SDL_WaitEvent(&event)) { if (event.type == SDL_QUIT) break; }
方案2:维护元素列表,动态重绘(适合交互场景)
如果需要动态添加元素(比如用户操作后新增图形),可以维护一个所有需要显示元素的列表,每次渲染循环都重新绘制全部元素:
#include <SDL2/SDL.h> #include <stdio.h> #include <stdlib.h> // 定义可绘制矩形的结构体 typedef struct { SDL_Rect rect; SDL_Color color; } DrawableRect; int main(int argc, char* argv[]) { SDL_Init(SDL_INIT_VIDEO); SDL_Window* window = SDL_CreateWindow("Incremental Render", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 400, 300, 0); SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); DrawableRect* rectList = NULL; int rectCount = 0; // 添加第一个矩形 rectList = realloc(rectList, sizeof(DrawableRect) * (rectCount + 1)); rectList[rectCount].rect = (SDL_Rect){10, 10, 100, 100}; rectList[rectCount].color = (SDL_Color){255, 255, 255, 255}; rectCount++; SDL_Event event; int running = 1; while (running) { // 处理事件 while (SDL_PollEvent(&event)) { if (event.type == SDL_QUIT) { running = 0; } // 按下空格键添加第二个矩形 if (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_SPACE) { rectList = realloc(rectList, sizeof(DrawableRect) * (rectCount + 1)); rectList[rectCount].rect = (SDL_Rect){130, 123, 100, 100}; rectList[rectCount].color = (SDL_Color){255, 255, 255, 255}; rectCount++; } } // 清屏后重绘所有元素 SDL_RenderClear(renderer); for (int i = 0; i < rectCount; i++) { SDL_SetRenderDrawColor(renderer, rectList[i].color.r, rectList[i].color.g, rectList[i].color.b, rectList[i].color.a); SDL_RenderFillRect(renderer, &rectList[i].rect); } SDL_RenderPresent(renderer); } // 释放资源 free(rectList); SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_Quit(); return 0; }
方案3:使用离屏纹理实现增量渲染
如果必须保留之前的渲染内容而不重绘全部元素,可以创建一个离屏纹理作为缓冲区,所有渲染操作都在这个纹理上进行,每次将纹理整体渲染到屏幕:
SDL_Event event; // 创建与窗口同尺寸的离屏纹理 SDL_Texture* offscreen = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, 400, 300); // 将渲染目标切换到离屏纹理 SDL_SetRenderTarget(renderer, offscreen); // 初始化离屏纹理为黑色 SDL_RenderClear(renderer); // 绘制第一个矩形 SDL_Rect rect = {10, 10, 100, 100}; SDL_SetRenderDrawColor(renderer, 255, 255, 255, SDL_ALPHA_OPAQUE); SDL_RenderFillRect(renderer, &rect); // 切换回屏幕渲染目标,将离屏纹理渲染到屏幕并显示 SDL_SetRenderTarget(renderer, NULL); SDL_RenderCopy(renderer, offscreen, NULL, NULL); SDL_RenderPresent(renderer); // 绘制第二个矩形(直接在离屏纹理上叠加) SDL_SetRenderTarget(renderer, offscreen); SDL_Rect nice = {130, 123, 100, 100}; SDL_RenderFillRect(renderer, &nice); // 再次将离屏纹理渲染到屏幕并显示 SDL_SetRenderTarget(renderer, NULL); SDL_RenderCopy(renderer, offscreen, NULL, NULL); SDL_RenderPresent(renderer); while (SDL_WaitEvent(&event)) { if (event.type == SDL_QUIT) break; } // 释放离屏纹理 SDL_DestroyTexture(offscreen);
内容的提问来源于stack exchange,提问作者Sachin Vijaykumar
相关产品推荐
相关产品推荐

