SDL2没有延迟就无法渲染。

4

这个简单的SDL2程序在我的系统上打开一个空窗口(即它不渲染任何内容),除非我取消注释SDL_Delay行。

#include <SDL.h>

int main(int argc, char** argv) {

    constexpr unsigned width = 256, height = 256;

    if (SDL_Init(SDL_INIT_EVERYTHING) < 0) {
        SDL_Log("Failed to initialize SDL: %s", SDL_GetError());
        return 1;
    }

    SDL_Window* window = SDL_CreateWindow("Test",
                                          SDL_WINDOWPOS_UNDEFINED,
                                          SDL_WINDOWPOS_UNDEFINED,
                                          width, height,
                                          0);
    SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0);

    SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255);
    SDL_RenderClear(renderer);
    // SDL_Delay(20);
    SDL_RenderPresent(renderer);

    bool quit{};
    SDL_Event event;
    while (!quit) {
        SDL_WaitEvent(&event);

        switch (event.type) {
        case SDL_QUIT:
            quit = true;
            break;
        }
    }

    SDL_Quit();

    return 0;
}

延迟必须大约是10-20ms,否则不会显示任何内容,但它并不一致 - 如果设置为10ms,则只有一半的时间有效。

在阅读这个答案之后,我添加了事件循环,但在没有它的情况下我得到了相同的行为。在IRC上的#sdl用户从相同的代码中获得了预期的蓝屏。

这里有什么问题/我做错了什么?


1
尝试将清除和现有的调用放在循环中,以查看是否能够重现问题。 - Lasoloz
2
无法重现(在Linux上),但对此行为不感到惊讶。在窗口创建后进行事件泵,然后在呈现渲染后再次进行泵。 - keltar
1
玩了一下事件推送。在渲染呈现后调用没有效果,但在清除渲染之前调用可以奏效。或者,在清除之前增加一个SetRenderDrawColor的调用也许会奏效——可能包括对事件推送的调用。关键是要在RenderClear之前调用它。 - scry
1
什么操作系统?窗口管理器合成是否启用?使用了哪个SDL渲染后端(https://wiki.libsdl.org/SDL_GetRendererInfo)?它是否与`SDL_RENDERER_PRESENTVSYNC`相同?使用软件渲染后端是否有相同的结果?从未在主循环之外进行过SDL绘图,但很可能每次出现`SDL_WINDOWEVENT_EXPOSED`事件时都必须重新绘制。 - keltar
我使用没有合成的Arch Linux。渲染器是OpenGL,但使用软件渲染也会得到相同的结果。然而,SDL_RENDERER_PRESENTVSYNC似乎可以解决这个问题。不过,我不太确定SDL_WINDOWEVENT_EXPOSED是什么意思——它是在窗口聚焦时发送还是每次更新时发送?我似乎找不到相关文档。 - scry
显示剩余2条评论
1个回答

1

为避免阻塞绘图线程,您应该调用SDL_PollEvent()。

尝试以下操作:

while (!quit) {
    SDL_Delay(1000/25);
    SDL_RenderClear(renderer);
    SDL_RenderPresent(renderer);
    if(!SDL_PollEvent(&event)) continue;

    switch (event.type) {
    case SDL_QUIT:
        quit = true;
        break;
    }
}

或者,如果您需要键盘和游戏手柄轮询的完整示例,请编译并运行GPL游戏Rock Dodger SDL2 Compact Edition,然后查看其源代码(仅为单个小文件)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接