【发布时间】:2020-05-20 05:06:06
【问题描述】:
我正在使用 SDL2 制作 2D 游戏,但在将地图渲染到屏幕时遇到了一些问题。当您四处移动时地图会滚动,因此我决定以块的形式加载地图,这样我就可以根据玩家的位置简单地剪辑 SDL_Texture 以将地图的相关部分显示到屏幕上。问题是,在显示一次地图后,在所有后续帧上,我都会得到一个黑屏,或者实际上是一个带有渲染器绘制颜色设置的屏幕。我知道这听起来像是我在错误的地方调用 SDL_RenderClear 但请耐心等待,这个问题更复杂。
首先,当我使用软件渲染器时一切都很好,但这会占用太多渲染时间以运行 60 fps,所以这就是我创建硬件加速渲染器的原因,它引入了问题。
我的 SDL 相关代码的要点是:
加载地图时,会初始化几个图块(或“块”)。当您在远处移动时,瓷砖将被释放并初始化新的瓷砖。每个图块根据其位置创建一个图像(纹理)。 (我承认我不知道这是否是最有效的方法,我希望它可以节省时间来准备大纹理,而这些纹理只需要被裁剪而不是动态绘制所有内容)。这会导致渲染目标之间的大量切换,因为对于每个图块 SDL_RendererSetTarget 被调用以直接渲染到其纹理,并且基本上很多纹理都“粘贴”在较大的一个(图块的图像)上。当然,在此之后,渲染目标将更改回屏幕。
渲染过程的其余部分相当简单:
- SDL_RenderClear
- 查找相关磁贴
- SDL_Render 使用剪辑复制其图像以获取屏幕上的正确部分并对相邻的图块执行相同操作
- 更多 SDL_RenderCopys 将播放器精灵和其他一些精灵 (npcs) 放在屏幕上
- SDL_RenderPresent
- 使用 SDL_Delay 等待几毫秒
最终结果似乎是有效的,因为就像我之前提到的,对 SDL_RenderPresent 的第一次调用显示一切都很好。然而,每个后续调用都会显示一个带有绘图颜色的屏幕,这意味着在调用 RenderClear 和 RenderPresent 之间表面上没有发生任何事情。所以我认为在第一次 SDL_RenderPresent SDL_Rendercopy 之后,它就不再起作用了。然而程序也没有崩溃,所以它几乎就像纹理都因为某种原因决定变得完全透明,或者它们只是被渲染到边缘。
老实说,我什至不知道问题可能出在哪个区域,但我已经尝试了所有我能想到的方法,但遗憾的是仍然无济于事。更糟糕的是,我可以隔离代码的所有部分,它们自己可以正常工作......所以任何关于问题可能是什么的建议甚至怀疑都是非常受欢迎的!也许我以错误的方式看待它并且使用硬件渲染器进行纹理渲染之类的事情根本不可能?我也考虑过放弃 SDL 并学习 OpenGL,但因为这意味着要重写很多代码,所以我想先在这里询问,看看是否真的没有其他解决方案。最后是一些系统规格,我尝试过的东西,我能想到的任何可能相关的东西:
- 我尝试创建一个“屏幕纹理”作为渲染器的中间人,所有 RenderCopy 都指向该渲染器,然后最终将其复制到屏幕上。
- 这就是我创建渲染器的方式(就像在 Lazy Foo 教程 (https://lazyfoo.net/tutorials/SDL/43_render_to_texture/index.php) 中一样在教程中。
- 我有一个 AMD Radeon HD 8330 显卡,Windows 8 操作系统
- 调用 SDL_GetRendererInfo 显示硬件渲染器称为 direct3d,支持的像素格式为 ARGB8888、YV12 和 IYUV。每当我创建纹理时,我都会使用 SDL_CreateTextureFromSurface 中的源代码来确定要使用的格式。
- 因为我的大多数 bmp 都有一个 Alpha 通道,所以我调用 SDL_SetTextureBlendMode,并在所有纹理上使用 SDL_BLENDMODE_BLEND 标志。以及在渲染器上带有此标志的 SDL_SetRenderDrawBlendMode。
【问题讨论】:
-
在minimal reproducible example 中编辑。您使用的是哪个版本的 SDL?来自 libsdl.org 的二进制文件还是自编译的?您使用的是哪个编译器?您是否正在做一些奇怪的事情,例如尝试将
SDL_GetWindowSurface()与渲染器系统一起使用?
标签: sdl-2