我有点坚持SDL2纹理背后的逻辑。对我来说,它们毫无意义,因为你无法吸引他们。
在我的程序中,我有几个表面(或者在切换到SDL2之前是表面),我只是将它们组合在一起形成图层。现在,似乎我必须创建几个渲染器和纹理以创建相同的效果,因为SDL_RenderCopy
采用纹理指针。
不仅如此,但所有渲染器都必须来自一个窗口,我明白这一点,但仍然会让我更多。
这一切看起来都非常笨重而且很慢。我错过了什么吗?有没有办法直接绘制纹理?纹理有什么意义,我可以安全地使用多个(如果不是数百个)渲染器代替表面吗?
答案 0 :(得分:35)
SDL_Texture
个对象尽可能靠近视频卡内存存储,因此可以通过GPU轻松加速。调整大小,alpha混合,消除锯齿以及几乎任何计算繁重的操作都会受到这种性能提升的严重影响。如果您的程序需要在纹理上运行逐像素逻辑,则建议您暂时将纹理转换为曲面。也可以使用流式纹理实现变通方法。
修改强>: 由于这个答案得到了很多关注,我想详细说明我的建议。
如果您希望使用Texture -> Surface -> Texture
工作流来应用每像素操作,请确保缓存最终纹理,除非您需要在每个渲染周期重新计算它。此解决方案中的纹理使用SDL_TEXTUREACCESS_STATIC
标志创建。
对于像素数据的来源是网络,设备,帧服务器或超出SDL应用程序完全覆盖范围的其他来源的用例,鼓励使用流式纹理(创建标志为SDL_TEXTUREACCESS_STREAMING
)很明显,从源缓存帧效率低或不起作用。
如果使用SDL_TEXTUREACCESS_TARGET
标志创建纹理,则可以在纹理顶部进行渲染。这将绘制操作的来源限制为其他纹理,尽管这可能已经是您首先需要的。 “纹理作为渲染目标”是SDL2最新和最不受支持的功能之一。
好奇读者的书呆子信息:
由于SDL实现的性质,前两种方法依赖于应用程序级别的读取和复制操作,尽管它们针对建议的方案进行了优化,并且对于实时应用程序来说足够快。
与GPU上的后处理相比,从应用程序级复制数据几乎总是很慢。如果您的要求比SDL提供的要求更严格且您的逻辑不依赖于某些外部像素数据源,那么分配从您的SDL表面绘制的原始OpenGL纹理并应用着色器(GPU)将是明智的逻辑)给他们。
着色器是用GLSL编写的,GLSL是一种编译成GPU程序集的语言。 硬件/ GPU加速实际上是指在GPU核心上并行化的代码,并且使用着色器是实现渲染目的的首选方法。
<强>注意!将原始OpenGL纹理和着色器与SDL渲染函数和结构结合使用可能会导致库提供一些意外冲突或失去灵活性。
<强> TLDR; 强> 纹理渲染和操作比表面更快,尽管修改它们有时会很麻烦。
答案 1 :(得分: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);
关键是,如果您绘制到较大尺寸的纹理,并且绘图是增量的(例如实时数据图),请确保仅锁定和解锁要更新的实际区域。否则操作会很慢,重复内存复制。
我经历了合理的表现,使用模式也不难理解。
答案 2 :(得分:6)
在SDL2中,可以直接渲染屏幕/渲染到纹理。使用的功能是:
int SDL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture);
仅当渲染器启用SDL_RENDERER_TARGETTEXTURE时才有效。