什么是SDL渲染器?

133

我刚开始学习SDL2,对于SDL_Renderer不太理解。

它是什么?它有什么作用?SDL_Renderer、SDL_Window、SDL_Surface和SDL_Texture之间的区别是什么,它们之间的关系是什么?

我在尝试理解这段入门代码时遇到了问题:

#include <iostream>
#include <SDL2/SDL.h>

int main()
{
    /* Starting SDL */
    if (SDL_Init(SDL_INIT_EVERYTHING) != 0) {
        std::cout << "SDL_Init Error: " << SDL_GetError() << std::endl;
        return 1;
    }

    /* Create a Window */
    SDL_Window *window = SDL_CreateWindow("Hello World!", 100, 100, 640, 480, SDL_WINDOW_SHOWN);
    if (window == nullptr) {
        std::cout << "SDL_CreateWindow Error: " << SDL_GetError() << std::endl;
        return 1;
    }

    /* Create a Render */
    SDL_Renderer *render = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
    if (render == nullptr) {
        std::cout << "SDL_CreateRenderer Error: " << SDL_GetError() << std::endl;
        return 1;
    }

    /* Load bitmap image */
    SDL_Surface *bmp = SDL_LoadBMP("./Tutorial/res/Lesson1/hello.bmp");
    if (bmp == nullptr) {
        std::cout << "SDL_LoadBMP Error: " << SDL_GetError() << std::endl;
        return 1;
    }

    /* Upload surface to render, and then, free the surface */
    SDL_Texture *texture = SDL_CreateTextureFromSurface(render, bmp);
    SDL_FreeSurface(bmp);
    if (texture == nullptr){
        std::cout << "SDL_CreateTextureFromSurface Error: " << SDL_GetError() << std::endl;
        return 1;
    }

    /* Draw the render on window */
    SDL_RenderClear(render); // Fill render with color
    SDL_RenderCopy(render, texture, NULL, NULL); // Copy the texture into render
    SDL_RenderPresent(render); // Show render on window

    /* Wait 2 seconds */
    SDL_Delay(5000);

    /* Free all objects*/
    SDL_DestroyTexture(texture);
    SDL_DestroyRenderer(render);
    SDL_DestroyWindow(window);

    /* Quit program */
    SDL_Quit();
    return 0;
}

我使用了SDL Wiki上推荐的Twinklebear教程,并查看了SDL Wiki文档和一些书籍。但是它们都假定我知道这些定义。


/* 等待2秒 */ SDL_Delay(5000); 代码与注释不匹配... ;-) - Jarod42
2个回答

251

SDL_Window

SDL_Window是一个结构体,包含有关窗口本身的所有信息: 大小,位置,全屏,边框等。


SDL_Renderer

SDL_Renderer是一个处理所有渲染操作的结构体。它与一个SDL_Window相关联,因此只能在该SDL_Window内进行渲染。它还记录与渲染相关的设置。有几个重要的函数与SDL_Renderer相关:

  • SDL_SetRenderDrawColor(renderer, r, g, b, a);
    这将设置您清除屏幕时使用的颜色(请参见下文)

  • SDL_RenderClear(renderer);
    这将使用上面设置的绘制颜色清除渲染目标

  • SDL_RenderCopy(
    这可能是您最常使用的功能,用于呈现SDL_Texture,并具有以下参数:

    • SDL_Renderer* renderer,
      您要用于渲染的渲染器。
    • SDL_Texture* texture,
      您要呈现的纹理。
    • const SDL_Rect* srcrect, 您要呈现的纹理部分,如果要呈现整个纹理,则为NULL。
    • const SDL_Rect* dstrect)
      您要在窗口中呈现纹理的位置。如果此SDL_Rect的宽度和高度小于或大于纹理本身的尺寸,则纹理将根据此SDL_Rect进行拉伸。
  • SDL_RenderPresent(renderer);
    其他SDL_Render*函数绘制到隐藏目标。此函数将获取所有内容,并在与渲染器相关联的窗口中进行绘制。

SDL_Textures和SDL_Surface

SDL_Renderer呈现SDL_Texture,后者存储一个元素的像素信息。这是SDL_Surface的新版本,两者基本相同。主要区别在于SDL_Surface只是包含像素信息的struct,而SDL_Texture是表示像素数据的高效,特定于驱动程序的表示形式。

您可以使用以下方法将SDL_Surface*转换为SDL_Texture

SDL_Texture* SDL_CreateTextureFromSurface(SDL_Renderer* renderer,
                                          SDL_Surface*  surface)

完成后,应使用以下方式释放SDL_Surface:

SDL_FreeSurface( SDL_Surface* surface )

另一个重要的区别是,SDL_Surface 使用软件渲染(通过 CPU),而 SDL_Texture 使用硬件渲染(通过 GPU)。


SDL_Rect

SDL 中最简单的结构。它仅包含四个 shorts。其中 x, y 保存位置,w, h 保存宽度和高度。

需要注意的是,在 SDL 中,0, 0 是左上角。因此,更高的 y 值意味着更低,右下角将具有坐标 x + w,y + h


您可以在我的博客上了解有关 SDL2 的更多信息。


1
当您调用SDL_RenderPresent时,所做的是将具有所有设置和已上传纹理的渲染器,并使其在其绑定到的窗口上呈现这些信息。 - prcastro
5
@olevegard,非常好的答案。为了澄清SDL_Texture和SDL_Surface之间的区别,我要强调一下:SDL_Texture使用GPU进行渲染,而SDL_Surface使用软件渲染,虽然效率较低但可以自由操作像素信息。此外,你的博客也很棒,我肯定会阅读的 :) - Fabio Picchi
2
顶部答案有一些不准确,SDL_Renderer 也可以绑定到 surface 上,而不仅仅是窗口,请查看链接:https://wiki.libsdl.org/SDL_CreateSoftwareRenderer - dmitro
1
很多文章现在在你的博客上不可用 =( - Eugen Konkov
渲染上下文是唯一的吗?还是可以有多个渲染器。例如:在游戏类中有renderer,在玩家类中有playerRenderer。或者我必须将游戏类*render传递给其他类以从表面制作不同的纹理? - Hernán Garcia
显示剩余2条评论

11

SDL_Window看作是物理像素,而SDL_Renderer则是存储设置/上下文的地方。

因此,您需要创建大量资源,并将它们与渲染器相关联;然后当一切准备就绪时,您会告诉渲染器将其组合在一起并将结果发送到窗口。


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