OpenGL ES 中的大滚动背景
我正在为 iPhone 开发一款 2D 卷轴游戏。 我有一个大图像背景,比如 480×6000 像素,只有一部分可见(正好一个屏幕的大小,480×320 像素)。 在屏幕上获得这样的背景的最佳方法是什么?
目前,我将背景分成几个纹理(以绕过最大纹理大小限制),并将每个帧中的整个背景绘制为纹理三角形条。 滚动是通过平移模型视图矩阵来完成的。 剪刀框设置为窗口大小,480×320像素。 这并不意味着要快,我只是想要在优化之前有一个工作代码。
我认为 OpenGL 实现可能足够聪明,可以丢弃背景的不可见部分,但根据我编写的一些测量代码,背景绘制平均需要 7 毫秒,最多需要 84 毫秒。 (这是在模拟器中测量的。)这大约是整个渲染循环的一半,即。 对我来说相当慢。
绘制背景应该像将一些 480×320 像素从 VRAM 的一个部分复制到另一部分一样简单,或者换句话说,速度非常快。 接近这样的性能的最佳方法是什么?
I am working on a 2D scrolling game for iPhone. I have a large image background, say 480×6000 pixels, of only a part is visible (exactly one screen’s worth, 480×320 pixels). What is the best way to get such a background on the screen?
Currently I have the background split into several textures (to get around the maximum texture size limit) and draw the whole background in each frame as a textured triangle strip. The scrolling is done by translating the modelview matrix. The scissor box is set to the window size, 480×320 pixels. This is not meant to be fast, I just wanted a working code before I get to optimizing.
I thought that maybe the OpenGL implementation would be smart enough to discard the invisible portion of the background, but according to some measuring code I wrote it looks like background takes 7 ms to draw on average and 84 ms at maximum. (This is measured in the simulator.) This is about a half of the whole render loop, ie. quite slow for me.
Drawing the background should be as easy as copying some 480×320 pixels from one part of the VRAM to another, or, in other words, blazing fast. What is the best way to get closer to such performance?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这是最快的方法。 您可以采取以下措施来提高性能:
我假设您正在以 1:1 的缩放级别进行绘制; 是这样吗?
编辑:哎呀。 更仔细地阅读了您的问题后,我必须提供另一条建议:在模拟器上进行的计时毫无价值。
That's the fast way of doing it. Things you can do to improve performance:
I'm assuming you're drawing at a 1:1 zoom-level; is that the case?
Edit: Oops. Having read your question more carefully, I have to offer another piece of advice: Timings made on the simulator are worthless.
快速解决方案:
创建图块的几何矩阵(最好是四边形),以便在可视区域的所有侧面至少有一行/列的离屏图块。
将纹理映射到所有这些图块。
一旦一个图块超出了可视区域,您就可以释放该纹理并绑定一个新纹理。
一旦一个图块超出了可视区域,
使用图块宽度和图块高度的模数作为位置来移动图块(这样,当图块移动了恰好一个图块长度时,它会将自身重新定位在其起始位置)。 还要记住在该操作期间重新映射纹理。 这允许您在任何给定时间加载非常小的网格/非常小的纹理内存。 我认为这在 GL ES 中尤其重要。
如果您有空闲内存并且仍然受到加载速度慢的困扰(尽管您不应该使用那么多纹理)。 您可以构建一个纹理流引擎,当您到达新区域时,该引擎将纹理预加载到更快的内存中(无论目标设备上有什么内存)。 在这种情况下,纹理映射将在需要时从更快的内存中进行。 只需确保您能够在不耗尽所有内存的情况下预加载它,并记住在不需要时动态释放它。
这是 GL(非 ES)图块引擎的链接。 我自己没有使用过它,所以我不能保证它的功能,但它可能可以帮助你: http://www.mesa3d.org/brianp/TR.html
The quick solution:
Create a geometry matrix of tiles (quads preferably) so that there is at least one row/column of off-screen tiles on all sides of the viewable area.
Map textures to all those tiles.
As soon as one tile is outside the viewable area you can release this texture and bind a new one.
Move the tiles using a modulo of the tile width and tile height as position (so that the tile will reposition itself at its starting pos when it have moved exactly one tile in length). Also remember to remap the textures during that operation. This allows you to have a very small grid/very little texture memory loaded at any given time. Which I guess is especially important in GL ES.
If you have memory to spare and are still plagued with slow load speed (although you shouldn't for that amount of textures). You could build a texture streaming engine that preloads textures into faster memory (whatever that may be on your target device) when you reach a new area. Mapping as textures will in that case go from that faster memory when needed. Just be sure that you are able to preload it without using up all memory and remember to release it dynamically when not needed.
Here is a link to a GL (not ES) tile engine. I haven't used it myself so I cannot vouch for its functionality but it might be able to help you: http://www.mesa3d.org/brianp/TR.html