【问题标题】:Efficient way to convert a 2D bitmap into a 3D cube model?将 2D 位图转换为 3D 立方体模型的有效方法?
【发布时间】:2011-05-20 00:52:08
【问题描述】:

我想在 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 的顶点网格,然后在适当的位置从这些顶点创建三角形以形成立方体面。我遇到的一个大问题是如何存储面部的颜色和法线。每个面的三角形需要共享一个顶点,并且该共享顶点需要存储该面的颜色和法线。但是,我认为我没有足够的顶点让每个面都具有适当的颜色和法线。我想不出一个优雅的方法来解决这个问题。

【问题讨论】:

  • 这是为了游戏。我想要看起来像这样的敌人。
  • 你确定你在问正确的问题吗?最后你已经告诉了你是怎么做到的,然后问了一个不同的问题。
  • 您可以逐行循环遍历非透明像素,如果该位置已经没有顶点,则每个像素将 4 个顶点推送到您的数组。以类似的方式,您可以为每个像素插入 4 个顶点并在插入所有顶点后,删除重复项。另一种方法是跟踪当前行上方的现有像素,并且仅在它们是新的时插入顶点。这应该为您提供这些正面顶点,您可以在 Z 上克隆和偏移它们以获得背面,然后循环穿过“边缘”顶点以“缝合”顶部、底部、左侧、右侧的面。看看这个:bit.ly/fQuB5H
  • 我正是以这种方式完成了康威的生命游戏……见照片:smoothjazzy.com/image_display.html?img=screensaver/scr_2.jpg - 如果你真的想要我,我可以挖掘代码,这都是 OpenGL。跨度>

标签: c++ c opengl graphics 3d


【解决方案1】:

关于存储面的颜色和法线;我认为你必须接受你需要为不同的面在相同位置复制顶点。如果两个顶点共享某些属性但其他属性不同,则它们本质上是不同的——即使它们共享的一个属性是它们的位置。

因此,您应该构建一些 VBO,并根据需要使用重复的顶点。您可能希望将此作为设计时步骤运行,并将结果保存为方便的格式,以便在运行时节省一些工作。

编辑:这并不意味着您需要为每个立方体的每个面的每个角都有单独的顶点。实际上,通过相当简单的实现来渲染您想要的东西(当块在一起时)的最便宜的方法可能是将正面和背面分别渲染为两个三角形,使用颜色纹理,GL_MAG_FILTER, GL_NEAREST 采样和仔细对齐纹理坐标,使用像素着色器在透明纹素上进行剪辑。

然后您需要做更多的工作(不一定在运行时)来确定哪些面将从侧面可见,并将每个面设为几何体(所有几何体都是单个静态 VBO显示,从而减少了绘图调用的数量和几何成本,例如调用 - 已弃用,尽管仍然通常有用 - 显示每个立方体的列表)。同样,您可以小心地确保这与正面和背面的不可见部分精确连接。

如果你确实想让你的敌人炸毁并让组成的立方体分道扬镳,那么你可以切换到显示每个立方体的更昂贵的版本。

【讨论】:

  • 感谢您的提示。我很难学到这一点......顺便说一句,我正在使用 OpenGL ES 为 iPhone 编写这个。是否有关于多少顶点太多的指导方针?我知道这是一个非常普遍的问题,但是如果我希望我的游戏敌人是,例如,基于 32x32 像素位图,并且我使用 8 个顶点将每个像素表示为一个立方体,那就是 8192 个顶点和几千个三角形。这对我来说听起来很多。我只是想知道这听起来是否效率很低。
  • 我不太了解 iPhone 硬件,但对我来说这听起来并不多。
  • 另外,只要你不想分离你的立方体,而只是像你链接的图像一样渲染,你需要的顶点比这少得多。您可以避免隐藏的内部面并共享出现在同一面上的顶点(特别是如果您使用纹理作为颜色,这样需要由顶点属性指定的唯一信息较少)。
  • d'哦,我刚刚意识到我的建议与已经投票的答案有多么相似,并且您评论说您已经尝试过了。
【解决方案2】:

只是提示您如何找到一些有趣的阅读材料:搜索“voxel”。 http://en.wikipedia.org/wiki/Voxel

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

【讨论】:

    【解决方案3】:

    如果将正面渲染为单个纹理映射的 GL_QUAD,对“透明”部分使用 alpha 和 GL_ALPHA_TEST,您将是最快的。然后,您将边界(即非正面正方形)设置为一个或多个 GL_QUAD_STRIP。

    如果您决定将精灵绘制为一系列实际的立方体,例如,如果您想将精灵炸成单独的立方体,或者如果您在小立方体面上有非常详细的纹理,那么制作一个显示列表对于一个立方体并重复调用该显示列表。

    【讨论】:

    • Quads 已被弃用,您不应再使用它们。硬件只渲染 tris。
    • 感谢您的提示。我最近实际上尝试了这种方法,但我遇到的问题是你可以看到纹理映射四边形中的孔和边界四边形条相交的接缝(即小间隙)。我无法解决这个问题。我通过使用大量小三角形渲染正面和背面来实现它,但这需要更多的渲染能力。
    • @Richard 如果接缝很大,请仔细检查您的数学。如果它们很小(1px 或更小),那么您可以通过绘制边框立方体的正面并移除用于部分透明前四边形的位图边框周围的一些像素来解决它。将前面的四边形稍微放在立方体的前面。节省您绘制立方体的绝大多数正面,即内部立方体。
    • 它们可能仍然有用,但请注意,显示列表现在也已正式弃用...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-25
    • 2011-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-28
    • 1970-01-01
    相关资源
    最近更新 更多