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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 23:05:46