3D游戏几何

3D Game Geometry

本文关键字:游戏 3D      更新时间:2023-10-16

我有一个使用3D网格表示的简单游戏,类似于:

Blocks grid[10][10][10];

游戏中的人由一个点和一个视觉向量表示:

double x,y,z, dx,dy,dz;

我画了3个嵌套循环的网格:

for(...) for(...) for(...)
   draw(grid[i][j][k]);

显而易见的问题是,当网格的大小增长到数百以内时,fps会急剧下降。凭直觉,我意识到:

  • 被网格中其他块隐藏的块不需要渲染
  • 不在人视野内的块也不需要渲染(即人身后的块)

我的问题是,给定一个grid[][][]、一个人的x,y,z和一个视觉向量dx,dy,dz,我如何计算出哪些块需要渲染,哪些块不需要渲染?

我研究了使用3D游戏引擎JMonkeyEngine,并研究了他们使用的一些技术。据我记忆所及,他们使用一种叫做剔除的东西。他们构建了一个"世界"中存在的一切事物的树状结构。这样做的想法是,你有一个子集的这个树,表示在任何给定的时间可见的对象。换句话说,这些都是需要呈现的东西。比如说,我有一个房间,里面有一些东西。房间在树上,房间中的对象是树的子对象。如果我在房间外,我会修剪(移除)这棵树的树枝,这意味着我不渲染它。之所以效果如此好,是因为我不必评估世界上的每个对象来判断它是否应该渲染,而是我会快速修剪世界上我知道不应该渲染的整个部分。

更好的是,当我走进房间时,我会从树上修剪世界的其他部分,然后只渲染房间及其所有后代。

我认为JMonkeyEngine团队做出的许多设计决策都是基于David Eberly的书《3D游戏引擎设计》中的内容。我不知道如何实现这样一种方法的技术细节,但我敢打赌这本书对你来说将是一个很好的起点。

这里有一篇关于一些不同剔除算法的有趣文章:

  • 查看Frustum Culling
  • 背面消隐
  • 基于细胞的遮挡剔除
  • 基于PVS的任意几何体遮挡剔除
  • 其他

首先,您需要一个空间分区结构,如果您使用统一的块大小,那么最有效的结构可能是八叉树。然后你需要写一个算法,可以计算盒子是否在平面的特定一侧(或相交)。一旦你有了这些,你就可以计算出八叉树的哪些叶节点在视图截头体的六个边内——这就是视图剔除。此外,使用八叉树,您可以确定哪些块遮挡其他块(有时称为截头体遮罩),但首先要使第一部分工作。

听起来你要做的是minecraft-y类型的东西。看看这个android minecraft级别的渲染器。需要注意的是:

  • 您只需要绘制与透明块共享的块的面。例如:不要麻烦在两个不透明的方块之间画人脸——玩家永远看不到它们
  • 你可能想把你的可见块几何图形批量到chunklet中(并把它粘贴到VBO中),并在每个chunklet的基础上确定可见性。准确地找到可以看到的块可能需要比在gpu上抛出VBO并接受透支更长的时间
  • 整体填充可以很好地确定哪些小块是可见的-使用视锥体、视图方向(如果你面向+ve x方向,不要在-ve方向上整体填充)和小块数据的简单分析来限制填充(例如:如果小块的整个面是不透明的,不要通过该面整体填充)