29

我有点卡在 SDL2 纹理背后的逻辑上。对我来说,它们毫无意义,因为你无法吸引它们。

在我的程序中,我有几个表面(或者在我切换到 SDL2 之前是什么表面),我只是将它们拼凑在一起形成层。现在看来,我必须创建几个渲染器和纹理来创建相同的效果,因为SDL_RenderCopy需要一个纹理指针。

不仅如此,所有渲染器都必须来自一个窗口,这我理解,但仍然让我更加犯规。

这一切似乎都非常庞大和缓慢。我错过了什么吗?有没有办法直接绘制到纹理?纹理的意义何在,我是否可以安全地使用多个(如果不是数百个)渲染器来代替表面?

4

3 回答 3

39

SDL_Texture对象存储在尽可能靠近显卡内存的位置,因此可以很容易地被 GPU 加速。调整大小、alpha 混合、抗锯齿和几乎所有计算繁重的操作都会受到这种性能提升的严重影响。如果您的程序需要在纹理上运行逐像素逻辑,建议您暂时将纹理转换为表面。也可以使用流式纹理实现解决方法。

编辑:由于这个答案得到了相当多的关注,我想详细说明我的建议。

如果您更喜欢使用Texture -> Surface -> Texture工作流来应用每像素操作,请确保缓存最终纹理,除非您需要在每个渲染周期重新计算它。此解决方案中的纹理是使用SDL_TEXTUREACCESS_STATIC标志创建的。

SDL_TEXTUREACCESS_STREAMING对于像素数据源是网络、设备、帧服务器或其他超出 SDL 应用程序完全范围的其他源的用例,以及从源缓存帧显然效率低下的用例,鼓励使用流式纹理(创建标志为)或者不会工作。

如果使用SDL_TEXTUREACCESS_TARGET标志创建纹理,则可以在纹理顶部进行渲染。这将绘制操作的来源限制为其他纹理,尽管这可能已经是您首先需要的。“作为渲染目标的纹理”是 SDL2 最新且最不广泛支持的功能之一。

好奇读者的书呆子信息:

由于 SDL 实现的性质,前两种方法依赖于应用程序级别的读取和复制操作,尽管它们针对建议的场景进行了优化,并且对于实时应用程序来说足够快。

与 GPU 上的后处理相比,从应用程序级别复制数据几乎总是很慢。如果您的要求比 SDL 可以提供的更严格,并且您的逻辑不依赖于某些外部像素数据源,那么分配从您的 SDL 表面绘制的原始 OpenGL 纹理并将着色器(GPU 逻辑)应用到它们是明智的。

着色器是用 GLSL 编写的,GLSL 是一种编译成 GPU 程序集的语言。硬件/GPU 加速实际上是指在 GPU 内核上并行化的代码,并且使用着色器是实现渲染目的的首选方法。

注意力!将原始 OpenGL 纹理和着色器与 SDL 渲染函数和结构结合使用可能会导致一些意外冲突或库提供的灵活性损失。

TLDR; 尽管修改它们有时会很麻烦,但在纹理上渲染和操作比在表面上更快。

于 2012-11-26T16:33:38.610 回答
8

通过将 SDL2 纹理创建为 STREAMING 类型,可以锁定和解锁整个纹理或仅一个像素区域以执行直接像素操作。必须先创建一个 SDL2 Surface,并与 lock-unlock 链接,如下所示:

SDL_Surface surface = SDL_CreateSurface(..);
SDL_LockTexture(texture, &rect, &surface->pixels, &surface->pitch);
// paint into surface pixels
SDL_UnlockTexture(texture);

关键是,如果您绘制到更大尺寸的纹理,并且绘制是增量的(例如实时数据图),请确保只锁定和解锁实际区域以进行更新。否则操作会很慢,内存复制量很大。

我体验过合理的性能,使用模型也不是太难理解。

于 2013-05-22T09:44:29.520 回答
7

在 SDL2 中,可以在屏幕外渲染/直接渲染到纹理。要使用的功能是:

int SDL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture);

这仅在渲染器启用 SDL_RENDERER_TARGETTEXTURE 时才有效。

于 2013-09-22T11:23:58.883 回答