使用硬件加速渲染器时,SDL2 rendercopy不再工作



我正在用SDL2制作一个2D游戏,在将地图渲染到屏幕上时遇到了一些问题。当你四处移动时,地图会滚动,所以我决定分块加载地图,这样我就可以简单地根据玩家的位置剪辑一个SDL_Texture,在屏幕上显示地图的相关部分。问题是,在显示一次地图后,在所有后续帧上,我会得到一个黑屏,或者实际上是一个带有渲染器绘图颜色设置的屏幕。我知道这听起来像是我在错误的地方调用SDL_RenderClear,但请耐心等待,这个问题更复杂。

首先,当我使用软件渲染器时,一切都很好,但这占用了太多渲染时间,无法以60帧/秒的速度运行,所以这就是我创建硬件加速渲染器的原因,它引入了这个问题。

我的SDL相关代码的要点是:

加载映射时,会初始化几个瓦片(或"块")。当你在远处移动时,瓷砖将被释放,新的瓷砖将被初始化。每个瓦片都会根据其位置创建一个图像(纹理)。(我承认,我不知道这是否是最有效的方法,我希望它能节省时间,准备好只需要剪裁的大纹理,而不是动态绘制所有东西)。这会导致在渲染目标之间进行大量切换,因为对于每个瓦片,SDL_RenderSetTarget都会被调用以直接渲染到其纹理,基本上很多纹理都会"粘贴"到较大的一个(瓦片的图像)上。当然,在此之后,渲染目标会更改回屏幕。

渲染过程的其余部分相当简单:

  • SDL_RenderClear
  • 查找相关磁贴
  • SDL_Render用剪辑复制其图像以在屏幕上获得正确的部分,并对相邻的瓦片执行相同操作
  • 更多的SDL_RenderCopys将玩家精灵和其他一些精灵(npc)放在屏幕上
  • SDL_呈现
  • 使用SDL_Delay等待几毫秒

最终结果似乎是有效的,因为正如我之前提到的,对SDL_RenderPresent的第一次调用显示一切都很好。然而,随后的每个调用都会显示一个具有绘图颜色的屏幕,这意味着对RenderClear和RenderPresent的调用之间表面上不再发生任何事情。所以我认为,在第一次SDL_RenderPresent之后,SDL_Rendercopy根本就不起作用了。然而,该程序也没有崩溃,所以几乎就像所有纹理都因为某种原因决定变得完全透明,或者它们只是被渲染到了边缘。

老实说,我甚至不知道问题可能出在哪个领域,但我已经试过了我能想到的一切,不幸的是还没有成功。更糟糕的是,我可以隔离的代码的所有部分都可以单独工作。。。因此,任何关于问题可能是什么的建议甚至怀疑都是非常受欢迎的!也许我看错了方向,使用硬件渲染器进行纹理渲染是不可能的?此外,我还考虑过放弃SDL并学习OpenGL,但由于这意味着要重写大量代码,我想先问一下这里,看看是否真的没有其他解决方案。最后,这里有一些系统规范,我尝试过的东西,我能想到的任何可能相关的东西:

  • 我试图创建一个"屏幕纹理"作为渲染器的中间人,在最终将这个复制到屏幕之前,所有渲染副本都指向该渲染器
  • 这就是我创建渲染器的方式(就像Lazy Foo教程中一样(https://lazyfoo.net/tutorials/SDL/43_render_to_texture/index.php)SDL_CreateRenderer(gWindow,-1,SDL_RENDERER_ACCELERATE|SDL_RENDRER_PRESENTVSYNC);我还尝试添加SDL_RENDERER_TARGETTEXTURE标志。永远不明白为什么教程中没有这样做
  • 我有一个AMD Radeon HD 8330视频卡,Windows 8操作系统
  • 调用SDL_GetRendererInfo显示硬件渲染器称为direct3d,支持的像素格式为ARGB888、YV12和IYUV。每当创建纹理时,我都会使用SDL_CreateTextureFromSurface中的源代码来确定要使用的格式
  • 因为我的大多数bmp都有一个alpha通道,所以我称之为SDL_SetTextureBlendMode,在所有纹理上都带有SDL_BLENDMODE_BLEND标志。以及渲染器上带有此标志的SDL_SetRenderDrawBlendMode

原来我在两帧之间意外地调用了SDL_SetWindowSize,因为我检查了一个类似的布尔指针

if(布尔值)

而不是

if(*boolean)

。。。哇!

尽管我每次都将大小设置为相同的值,但这会使通过硬件渲染器的SDL_CreateTexture创建的所有纹理无效。有趣的是,使用SDL_CreateTextureFromSurface创建的那些不受影响。正如我所说,使用软件渲染器创建的纹理似乎根本不介意调整窗口大小。我会把这个留在这里,希望有一天我的愚蠢能帮助别人。

最新更新