在 OpenGL 和细分中滚动/缩放场景
我们将在 Android 上的 OpenGL ES 中开发一个滚动/缩放场景,非常类似于《愤怒的小鸟》中的关卡,但更像《粘粘世界》中的关卡。更像是后者,因为世界不会像《愤怒的小鸟》那样由重复的图层组成,而是由一张大图像组成。由于场景需要滚动/缩放,因此很多场景将不可见,我想知道实现渲染的最有效方法,仅关注环境(即不是世界中的对象而是背景层)。
我们将使用正交投影。
首先想到的是创建一个世界大小的 4 个顶点的大矩形,将背景纹理映射到它,并使用 glTranslatef / glScalef 对其进行平移/缩放。然而,我想知道屏幕边界之外的不可见区域是否仍在由 OpenGL 渲染,因为它没有被剔除(您将失去可见区域,并且只有 4 个顶点)。因此,细分这个矩形是否会更有效,以便可以剔除不可见的较小矩形?
另一种选择是创建一个 4 顶点矩形来填充屏幕,然后通过调整其纹理坐标来移动背景。然而,考虑到纹理大小限制,我想我们在构建更大的世界时会遇到问题。对于像 AngryBirds 这样的重复背景来说,这似乎是一个很好的实现。
也许还有另一种方法..?
如果有人知道如何在《愤怒的小鸟》/《粘粘世界》中实现这一点,请分享,我很乐意听到。他们似乎已经实现了一个系统,可以非常顺利地移动和缩放世界(WorldOfGoo = VERY)。
We are to develop a scrolling/zooming scene in OpenGL ES on Android, very much like a level in Angry Birds but more like a level in World Of Goo. More like the latter as the world will not consist of repeated layers as featured in Angry Birds but of a large image. As the scene needs to scroll/zoom and therefore a lot of it will not be visible, I was wondering about the most efficient way to implement the rendering, focusing on the environment only (ie not the objects within the world but background layers).
We will be using an orthographic projection.
The first that comes to mind is creating a large 4 vertices rectangle at world size, which has the background texture mapped to it, and translate/scale this using glTranslatef / glScalef. However, I was wondering if the non visible area outside of the screens boundaries is still being rendered by OpenGL as it is not being culled (you would lose the visible area as well as there are only 4 vertices). Therefore, would it be more efficient to subdivide this rectangle, so non visible smaller rectangles can be culled?
Another option would be creating a 4 vertice rectangle that would fill the screen, then move the background by adjusting its texture coordinates. However, I guess we would run into problems when building bigger worlds, considering the texture size limit. It seems like a nice implementation for repeated backgrounds like AngryBirds has.
Maybe there is another way..?
If someone has an idea on how it might be done in AngryBirds / World of Goo, please share as I'd love to hear. They seem to have implemented a system that allows for the world to be moved and zoomed very (WorldOfGoo = VERY) smoothly.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这可能是您实施的最佳选择。
根据我的经验,在 Android 上,在内存中保留大纹理的成本非常高。在开始平铺之前,我会遇到很多背景纹理的 OutOfMemoryError 异常。
我认为最大的渲染瓶颈是内存传输速度和填充率,而不是任何图形计算。
编辑:查看此演示文稿的 53:28< /a> 来自 Google I/O 2009。
This is probably your best bet for implementation.
In my experience, keeping a large texture in memory is very expensive on Android. I would get quite a few OutOfMemoryError exceptions for the background texture before I moved to tiling.
I think the biggest rendering bottleneck would be with memory transfer speeds and fill rate instead of any graphics computation.
Edit: Check out 53:28 of this presentation from Google I/O 2009.
您可以将背景矩形分割成更小的矩形,以便 OpenGL 只渲染可见矩形。你不会有一个大屁股矩形加载了一个大屁股纹理,但较小的矩形具有较小的纹理,你可以加载/卸载,具体取决于屏幕上可见的内容......
You could split the background rectangle into smaller rectangles, so that OpenGL only renders the visible rectangles. You won't have a big ass rectangle with a big ass texture loaded but smallers rectangles with smaller textures that you could load/unload, depending on what is visible on screen...
据我所知,由于大面积渲染在屏幕外,因此不会导致性能下降,细分和剔除通常只是为了减少顶点数,但您实际上会在此处添加它。
暂时把它放在一边;从你提出问题的方式来看,我不确定你是否有一个大的背景纹理或一个小的重复纹理。如果它很大,那么无论如何,由于纹理大小限制,您都需要细分,所以这个问题没有实际意义!如果它很小,那么我建议第二种方法,将四边形安装到屏幕上并通过更改纹理坐标来移动背景。
不过,我觉得我可能错过了一些东西,因为我不确定你为什么在谈论纹理坐标方法而不是大四边形方法时提到纹理大小限制问题。当然,对于两者来说,这不是重复纹理的问题,因为您可以使用 GL_REPEAT 纹理环绕模式...
但是对于两者来说,对于单个大纹理来说,这都是一个问题,除非您细分,这会使纹理协调战术的方式比必要的更加复杂。在这种情况下,最好沿着纹理细分来细分网格,并剔除屏幕外部分。使用这种技术决定剔除哪些部分应该是微不足道的。
干杯。
Afaik there would be no performance drop due to large areas being rendered off-screen, subdividing and culling is normally done just to reduce vertex count, but you would actually be adding to it here.
Putting that aside for now; from the way you phrased the question I am unsure whether you have a large background texture or a small repeating one. If it is large, then you will need to subdivide because of texture size limitations anyway, so the question is moot! If it is small, then I would suggest the second method, fit a quad to the screen and move the background by changing the texture coordinates.
I feel like I may have missed something, though, as I am unsure why you mentioned the texture size limitation issue when talking about the the texture coordinate method and not the large quad method. Surely for both this is not a problem for repeating textures as you can use GL_REPEAT texture wrap mode...
But for both it is a problem for a single large texture unless you subdivide, which would make the texture coordinate tactic way more complicated than necessary. In this case subdividing the mesh along texture subdivisions would be best, and culling off-screen sections. Deciding which parts to cull should be trivial with this technique.
Cheers.