如何有效地渲染大型地形网格?


10

最近,我一直在思考如何在游戏中生成地形的最佳方法。在另一个项目中,我通常使用高度图,因此所有核心工作都基于所使用的引擎,但是现在无法完成,因为地形具有数百万个必须精确绘制的特定多边形。而且,其中许多不能从Y向量进行解析(因为下面隐藏了多边形),也就是说,高度图在这里没有用。在这种情况下,我必须使用COLLADA对象。

有人告诉我要在Blender之类的软件中手动划分模型,但是不幸的是,这也是不可能的,因为这些地形是在另一个软件中成块创建的,然后加载到游戏中(这就是想法)。因此,每次必须手动对其进行切片将是一项巨大的工作。

因此,自从一周以来,我一直在研究如何解决此问题并以程序方式将此网格,地形(对应于相机平​​截头体)加载,以尽可能地节省性能。我遇到了许多有关过程网格生成的文档,我认为可以通过将网格映射到八叉树来解决我的问题。这是一项巨大的工作,至少对我来说是如此,这就是为什么我在这里,因为我不想冒险走错误的道路,而无需经验丰富的人来信。

简而言之,我有数百万个顶点和索引共同构成了地形,但是出于明显的原因,我无法同时绘制它们。它需要某种程序。将大型网格物体视为地形的最佳方法是什么?有没有关于这本书的具体书?有没有最佳的实施方法?

很抱歉出现任何错误,我是这个领域的新手。

Answers:


12

基本分块是开始的好方法。如果需要,您可以在以后移至更复杂的数据结构,如八叉树。现在,从磁盘加载模型时,只需将地形分成给定尺寸的块即可。

根据您的数据,您可能想要将地形拆分为跨越整个高度的平面上的柱子,或者拆分为空间中的立方体。代码不完整(fmod,向量初始化,索引等),但是应该给您一个开始。

// Load vertices from disk
struct point { double x, y, z; };    
vector<point> vertices;

// Create container for chunks
typedef pair<int, int> key;
unordered_map<key, vector<point>> chunks;
const int chunksize = 10;

// For each vertex
for (int i = 0; i < vertices.size(); ++i) {
    // Fetch global coordinates
    int x = vertices[i].x,
        y = vertices[i].y,
        z = vertices[i].z;

    // Find containing chunk
    key k;
    k.first  = x / chunksize;
    k.second = z / chunksize;

    // Calculate local coordinates
    point p;
    p.x = x % chunksize;
    p.y = y;
    p.z = z % chunksize;

    // Add to chunk
    chunks[k].push_back(p);
}

// Create separate buffers for each chunk
// ...

由于您现在已经拆分了网格,因此可以对其执行LOD和剔除技术,以跳过隐藏块的渲染。

  • 观看距离是您的起点。您将只渲染给定距离内的块,例如相机的查看距离。视距距离越小,由于必须绘制较少的地形块,因此可获得的性能越高。

  • 视锥剔除是仅渲染与摄影机的视锥相交的网格的常用技术。这很可能为您带来最大的性能提升。

试验块大小和查看距离以获得最佳结果。块大小是精确剔除与易于计算之间的权衡。为了进一步优化,您可以看一下这些更高级的优化。

  • 遮挡剔除可以通过以非常低的分辨率在CPU上渲染网格来完成。这使您可以及早发现隐藏在其他网格后面的网格。它们不必发送到GPU,因此可以节省很多顶点着色器执行,否则将在拒绝三角形之前执行这些操作。

  • 详细程度意味着您可以计算块的较低分辨率网格。根据与相机的距离,选择要绘制的网格之一。这允许您减少顶点的数量,因为远处的块不需要那么多的细节。这种方法在八叉树上效果很好,因为您可以将多个多维数据集合并为一个低分辨率网格,用于远离相机的区域。但是,无缝合并具有不同分辨率的两个块之间的边缘并非易事。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.