SDL2 - 如何使用一个缓冲区而不是两个进行渲染?

3
在SDL2中,我希望能够绘制对一个缓冲区的更改,而不是像我的设置一样将整个图像重新绘制到两个不同的缓冲区。下面是一个快速测试,展示了不想要的行为:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <SDL.h>

// Compile: gcc test.c -I/usr/local/include/SDL2 -L/usr/local/lib -lSDL2


void putPixel(SDL_Renderer *renderer, int x, int y)
{
    SDL_SetRenderDrawColor(renderer, 255,255,255,255);
    SDL_RenderDrawPoint(renderer, x, y);
}

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

    int width = 640;
    int height = 480;

    SDL_Window *window = SDL_CreateWindow("Test", 0,0,width,height, 0);
    if (window == NULL)
    {
        return -1;
    }
    SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
    if (renderer == NULL)
    {
        return -2;
    }

    SDL_SetRenderDrawBlendMode(renderer,SDL_BLENDMODE_BLEND);

    SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
    SDL_RenderClear(renderer);

    for(int x=0;x<8;x++)
    {
        for(int y=0;y<10;y++)
        {
            putPixel(renderer,40+x*10,50+y);
        }

        SDL_RenderPresent(renderer);
        sleep(1);
    }


    SDL_Quit();
    return 0;
}

这段代码的输出是两个交替显示的屏幕。显然,它使用了双缓冲,这意味着我必须清除并重新绘制才能得到想要的输出。在每个for...loop循环周期后,我想向缓冲区添加一行——程序运行结束时应该有8行。但实际上,在一个缓冲区上只有4行,在另一个缓冲区上只有4行。我也不想重新绘制之前的行,因此需要一个缓冲区。

单缓冲的坏处有很多,离屏渲染目标是你最好的选择。 - keltar
@keltar 出于好奇,那些原因是什么?另外,使用纹理不就是我正在做的吗?我即将更新问题,并提供更多代码和更好的布局。 - Phil_12d3
@Phil_12d3 不是完全一样的。你的纹理就像后备缓冲区。然而,当没有后备缓冲区(按照规范单缓冲,在屏幕上直接绘制),你可能会注意到很多闪烁或其他视觉缺陷。 - keltar
经过更多的准备工作,这似乎是最好的方法。我仍然愿意听取意见,但我已经将我的解决方案移动到答案位置。 - Phil_12d3
在双缓冲中,您绘制到后备缓冲区(屏幕外),然后交换缓冲区。交换后,后备缓冲区变为前缓冲区,反之亦然,因此内容也会交换。这是双缓冲的核心思想,回退到单缓冲将导致直接在屏幕上绘制。还有三重缓冲,但在这里没有太多意义。您的阴影缓冲区只是您需要的副本;这是最合乎逻辑的方法,并且对性能影响最小。 - keltar
显示剩余3条评论
1个回答

8
使用纹理作为缓冲区,并在完成后将其复制到屏幕上。
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <SDL.h>

// Compile: gcc test.c -I/usr/local/include/SDL2 -L/usr/local/lib -lSDL2


void putPixel(SDL_Renderer *renderer, int x, int y)
{
    SDL_SetRenderDrawColor(renderer, 255,255,255,255);
    SDL_RenderDrawPoint(renderer, x, y);
}

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

    int width = 640;
    int height = 480;

    SDL_Window *window = SDL_CreateWindow("Test", 0,0,width,height, 0);
    if (window == NULL)
    {
        return -1;
    }
    SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
    if (renderer == NULL)
    {
        return -2;
    }

    SDL_SetRenderDrawBlendMode(renderer,SDL_BLENDMODE_BLEND);

    /* Create texture for display */
    SDL_Texture *display = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, width, height);

    SDL_SetRenderTarget(renderer, display);

    SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
    SDL_RenderClear(renderer);

    for(int x=0;x<8;x++)
    {
        SDL_SetRenderTarget(renderer, display);

        for(int y=0;y<10;y++)
        {
            putPixel(renderer,40+x*10,50+y);
        }

        SDL_SetRenderTarget(renderer, NULL);
        SDL_RenderCopy(renderer, display, NULL, NULL);
        SDL_RenderPresent(renderer);
        sleep(1);
    }


    SDL_Quit();
    return 0;
}

以下是输出结果:

在此输入图片描述


这段代码的输出如上所示。

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