将2D位图转换为3D立方体模型的高效方法?

4
我希望在OpenGL中创建一个32x32位图的立方体模型。例如,给定超级马里奥中Bob-omb的2D位图,结果应该看起来像这样:http://fc02.deviantart.net/fs49/f/2009/186/f/a/Bob_omb_in_Minecraft_by_Luafox.png。想法是将每个2D像素表示为3D立方体。
每个模型将代表游戏中的一个敌人,因此我需要能够快速渲染它们。有什么好方法可以做到这一点吗?
我尝试从位图生成静态3D模型,首先创建一个32x32x2的顶点网格,然后在适当的位置从这些顶点创建三角形以形成立方体面。然而,我遇到的一个大问题是如何存储面的颜色和法线。每个面的三角形需要共享一个顶点,并且该共享顶点需要存储该面的颜色和法线。但是,我认为我没有足够的顶点使每个面具有适当的颜色和法线。我想不出一个优雅的解决方法。

这是为了一个游戏。我想要长成这样的敌人。 - RichardNewton
你确定你正在问正确的问题吗?最后你已经说出了你是如何做到的,然后又问了一个不同的问题。 - Arne
你可以逐行遍历非透明像素,对于每个像素,如果该位置没有顶点,则将4个顶点推入数组。类似地,您可以每个像素插入4个顶点,并在插入所有顶点后删除重复项。另一种方法是跟踪当前行上方的现有像素,并仅在它们是新的时插入顶点。这应该给你这些前面的顶点,你可以克隆并在Z轴上偏移它们以获得背面,然后遍历“边缘”顶点以“缝合”顶部、底部、左侧和右侧的面。请查看此链接:http://bit.ly/fQuB5H - George Profenza
我用完全相同的方式完成了康威生命游戏...请看照片:http://www.smoothjazzy.com/image_display.html?img=screensaver/scr_2.jpg - 如果你真的想要,我可以找出那段代码,它全部都是OpenGL。 - Jasmine
3个回答

2
您可以通过将正面渲染为单个纹理映射的GL_QUAD,使用alpha和GL_ALPHA_TEST来处理“透明”部分,以实现最快速度。然后,您可以将边界(即非正面朝向的正方形)制作为一个或多个GL_QUAD_STRIP。
如果您决定将精灵绘制为一系列实际的立方体,例如如果您想将精灵炸成单独的立方体,或者如果您在小立方体面上有非常详细的纹理,则可以为一个立方体创建一个显示列表,并重复调用该显示列表。

四边形已经过时了,你不应该再使用它们了。硬件只渲染三角形。 - Axel Gneiting
谢谢你的建议。 最近我实际尝试了这种方法,但我遇到的问题是,在纹理映射的四边形和边界四边形带相遇的地方可以看到接缝(即小间隙)。 我无法解决这个问题。 我通过使用大量的小三角形渲染前面和后面来使其工作,但这会使用更多的渲染能力。 - RichardNewton
如果接缝很大,请仔细检查您的数学计算。 如果它们很小(1像素或更少),则可以通过同时绘制边框立方体的前面并在部分透明的前部四边形位图的边框周围去除一些像素来解决这个问题。将前部四边形放置在立方体的非常稍微前面。 这样可以避免绘制大多数前面的立方体,其中包括内部立方体。 - James Crook
它们可能仍然有用,但请注意,显示列表现在也已正式弃用... - PeterT

0
关于存储面的颜色和法线; 我认为你必须接受需要在相同位置为不同的面复制顶点的事实。如果两个顶点共享某些属性但在其他方面不同,它们本质上是不同的 - 即使它们共享的一个属性是它们的位置。
因此,您应该构建一些VBO,必要时使用重复的顶点。您可能希望将其作为设计时间步骤运行,并将结果保存到方便的格式中以节省运行时的工作量。
编辑:这并不意味着您需要为每个立方体的每个面的每个角落都有单独的顶点。实际上,渲染您想要的内容(当块在一起时)的最便宜的方法,同时具有合理易于实现的实现,可能是将前面和后面各渲染为两个三角形,使用纹理进行着色,GL_MAG_FILTER,GL_NEAREST采样和纹理坐标的仔细对齐,使用像素着色器在透明像素上剪辑。

接下来,您需要做更多的工作(不一定是在运行时),以确定哪些面将从侧面可见,并将每个面作为几何体(所有这些几何体都是单个静态VBO,用于显示,从而降低了绘制调用和几何成本的数量,例如对于每个立方体调用已弃用但仍然常用的显示列表)。再次小心,您可以确保它与前面和后面面的不可见部分精确连接。

如果您想让敌人爆炸并使组成部分的立方体分开,那么您可以切换到更昂贵的版本,显示每个单独的立方体。


谢谢你的建议。我是吃了亏才学到的...顺便说一下,我正在使用OpenGL ES为iPhone编写代码。有没有关于顶点数过多的指导方针?我知道这是一个非常普遍的问题,但如果我想让我的游戏敌人基于32x32像素位图,并且我使用8个顶点来表示每个像素作为一个立方体,那就是8192个顶点和几千个三角形。这听起来对我来说很多。我只是想知道这是否听起来非常低效。 - RichardNewton
我对iPhone的硬件不是很了解,但这听起来对我来说并不像很多verts。 - PeterT
另外,只要您不想分离立方体,而是希望呈现类似于您链接的图像,那么您需要的顶点数量要少得多。您可以避免隐藏的内部面,并共享出现在同一面上的顶点(特别是如果您使用纹理进行着色,这样就需要通过顶点属性指定较少的唯一信息)。 - PeterT
哎呀,我刚意识到我的建议和已经得到赞同的答案非常相似,而且你还评论说你已经尝试过了。 - PeterT

0

关于如何找到一些有趣的阅读材料,这里有一个提示:搜索“体素”。 http://en.wikipedia.org/wiki/Voxel

也许你想看看开源游戏引擎Cube/Sauerbraten的源代码,它们基于立方体细分来创建地图,并配有一个不错的游戏内编辑器: http://sauerbraten.org/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接