LWJGL 中的瓦片引擎

Tile Engine in LWJGL

我正在重写我一直在使用 LWJGL 开发的游戏(原始引擎是纯 java),我想知道渲染地图的最有效方法到屏幕。我将制作一个 Tiled 地图,并为可行走的瓷砖、碰撞瓷砖和静止物体分别创建一个图层。我将通过解析 XML 文件将所有这些内容读入游戏。

我的问题是我是否应该这样做并将每个图块单独读入游戏并将值存储到二维数组中,将它们分配给精灵并将每个精灵渲染到屏幕上各自的位置?或者,将这些层制作成自己的单个图片文件并渲染层而不是图块会不会减少 CPU/GPU 的负担?我想第二个会更痛苦,但值得吗?

最好将瓦片组合在一起形成一个大的纹理图集。假设您使用 32x32 像素的图块,一个 2k 的纹理可以容纳多达 4096 个不同的图块,对于一个游戏来说可能绰绰有余。原因是您可以一次绑定此纹理并使用它进行(几乎)所有渲染,避免昂贵的纹理切换操作。不要为每个图块使用单独的图片。所有纹理和其他渲染资源都应预先上传,最好在游戏加载或关卡加载时上传。

至于实际的图块和对象,您应该构建一个顶点缓冲区,其中包含所有对象的顶点属性,并在关卡加载期间上传它。这个缓冲区将包含顶点位置、颜色、纹理坐标……绘制瓷砖所需的一切,如果一个缓冲区不够用,它可以分成多个缓冲区。对于每一帧,您使用相机坐标找出哪些瓦片可见,哪些瓦片不可见,然后使用第一个可见瓦片的起始索引和可见瓦片的数量发出绘制调用。简单的 AABB 检查在这里非常好。当然,为了实现这一点,你的顶点缓冲区必须以这样一种方式布局,即它只在一个方向上,例如从左到右,从上到下。

或者,您可以以更多的绘制调用为代价进行更积极的顶点数修剪:将世界分割成块,使每个块都足够大以覆盖整个屏幕。如上所述为每个块创建顶点缓冲区。然后做同样的相机检查,找出哪个块是可见的并绘制它们。在这种情况下,在任何给定时间至少有 1 个块可见,最多有 4 个块可见,这意味着 1 到 4 个绘制调用。这种方法比以前的方法更有优势,因为您不必遍历每个图块,而是可以遍历块,这意味着需要的检查要少得多。

如果操作正确,您可能只需要几次绘制调用即可渲染世界并且仍然能够绘制大量图块。显然,这仅适用于静态对象,您需要以不同方式绘制动态对象。请记住,绘制调用可以上下文切换是昂贵的,应尽可能避免。