【问题标题】:3D maps rendering in games [closed]游戏中的 3D 地图渲染 [关闭]
【发布时间】:2015-03-12 19:46:55
【问题描述】:

我对 3D 游戏(即魔兽世界)中的地图以及程序员如何渲染它们有一些疑问:

  1. 是否可以通过某种技术“平滑”山脉的边缘,或者唯一可能的解决方案是在高度图中使用更多顶点?

    我错了吗,并认为他们为此使用了某种技术,因为他们只是为每座山渲染了相当数量的顶点?

  2. 看看这张图片:


    (来源:gamona.de)

    关于如何渲染这种场景的一些问题:

    1. 据我所知,像 WoW 这样的开放世界游戏使用高度图进行地形渲染,他们怎么知道在哪里绘制所有其他内容? (树木、房屋、栅栏、水等)。
    2. 它们如何渲染地下区域? (山内有一座巨大的城堡)
    3. 请注意,每个凹凸都使用大约 2 个纹理进行显示(雪和岩石)。他们用来知道何时对每个纹理进行采样的算法可能是什么?它看起来并不依赖于法线。 (我认为他们甚至不会为其地形生成法线。)
    4. 看起来他们也没有使用天空盒作为地平线。可能是什么技术?
    5. 您能说出您注意到我可以探索的其他有趣技术吗?

我目前正在学习 OpenGL,但我也标记了 DirectX,因为这些问题并不是特定于 API 的。

【问题讨论】:

  • 纹理喷溅可以应用多个纹理。这是来自frostbyte引擎的一篇有趣的文章。 dice.se/wp-content/uploads/…
  • 这个问题太宽泛了,比如你可以在你完成的模型上使用细分曲面en.wikipedia.org/wiki/Subdivision_surface 使其更平滑,或者你可以使用着色器来改变它的几何形状,还有其他方法可以取得相同的结果。

标签: opengl directx textures shader terrain


【解决方案1】:

很难从您的高度图上分辨出来(主要是因为您上面没有任何照明),但我想说几乎可以肯定的是,在您的示例中,他们使用的基本高度图比您使用的更高分辨率。

现在与其他一些海报所暗示的不同,景观不太可能在 3D 建模包中进行建模。他们也极不可能使用 B 样条来渲染景观。

使用更高分辨率的高度图的最大问题是内存要求。为此,有多种不同的解决方案可以“优化”存储在内存中的高度图数据。附近的景观不需要像远处的景观那么多的细节。

geometry clipmaps 是渲染大量高度详细的景观几何图形的非常好的技术。不过这很复杂。另一个我过去取得巨大成功的方案是Geo-Mipmapping。它非常简单而且非常快。如果您将三线性过滤技术应用于您的 Geo-mipmap,它也会产生出色的结果。为这样的景观编写异步块加载器以提供巨大景观的良好流式传输性能也是相当简单的。

不管怎样,我会回答你的其他问题。

  1. 正如 hbdavehb 所建议的,他们将有一个编辑器来加载景观,然后他们可以在地图上放置项目(也很可能,作为编辑景观)。模型将在 3DS Max 或 Maya 中创建,然后加载到编辑器中进行放置。

  2. 它们使用其他形式的渲染器进行渲染。通常是portal renderer 或BSP renderer。

  3. 这种技术被称为texture splatting。

  4. 对我来说就像一个天空盒。我猜它可能是在天空盒上的动态渲染。

  5. 列表很大。但我建议研究各种图像映射技术,例如bump mapping(尤其是normal mapping)、cube mapping、Parallax mapping、Displacement mapping。然后是global illumination、Phong illumination(与Phong shading不同)、bidirectional reflectance distribution functions和precomputed radiance transfer等照明技术。这只是表面问题。我强烈建议好好阅读一下。 Computer Graphics: Principles and Practice by Foley et al. 是一本关于渲染的优秀书籍。 GPU Gems series 也很好。对于 3D 渲染技术的历史,在我看来,这仍然是一本非常有用的书,值得一看 Michael Abrash's Black Book。

祝你好运!

【讨论】:

  • 我不明白答案的逻辑。您声称暴雪没有使用“b样条”,我认为您的意思是NURB。但是众所周知,他们使用的是 Autodesk,而 Autodesk 中有 NURB,而且 WOW 中的山脉看起来就像 NURB,那么你说它们不是 NURB 的理由是什么???
  • @TylerDurden:仅仅因为软件包含一个特性并不意味着它被使用了。 >没有人
  • 另外......当你接近山丘时,很明显他们没有使用 NURBS......细分的进展会很明显......他们在高分辨率基础网格上使用平滑几何...
  • ">没有人
  • 另外,“动态渲染到天空盒”是什么意思?
【解决方案2】:

除了 Tyler Durdens 的回答,我想谈谈你的几点。

  1. 他们可能已经开发了自己的编辑器,然后将其导出并传递给他们的渲染器。因此开发人员可以进入并在该点放置一棵树,然后渲染器知道在该点绘制树模型。或者他们按照以下方式做一些事情:http://mollyrocket.com/casey/stream_0017.html,他们在其中“填充”空白区域,例如草(如本例所示)、树木等。

  2. 它们渲染外部区域的方式相同:p

  3. 可以使用作为回复您帖子的链接 dari 来实现该效果,或者像您提到的那样从高度图中覆盖一些纹理。

  4. 我不太确定天空盒。

  5. 看看已经发布的一些链接,你肯定会花大量时间研究 :)

【讨论】:

  • 关于 2.,您不能(afaik)使用高度图创建洞穴和地下区域。每个 x,z 位置都有一个 y。
【解决方案3】:

我发现平滑地形的最简单方法是在转换为浮点数后,对顶点应用convolution 过滤器。这是一种来自图像处理的技术,但也可以很好地处理来自 8 位高度图的数据。

这是我几年前很好用的 C++ 源代码。

void CGround::CHeightmap::_SmoothTerrain(int passes)
{
   float* NewHeightData;

   while (passes--)
   {
       // Note: m_Size.X and m_Size.Y should be equal and power-of-two values 
       NewHeightData = new float[m_Size.X * m_Size.Y];

       for (int x = 0; x < m_Size.X; x++)
       {
          for (int y = 0; y < m_Size.Y; y++)
          {
              int adjacentSections = 0;
              float sectionsTotal = 0.0f;

              if ((x - 1) > 0) // Check to left
              {
                 sectionsTotal += m_Heights[(x - 1)*m_Size.Y + y];
                 adjacentSections++;

                 if ((y - 1) > 0) // Check up and to the left
                 {
                    sectionsTotal += m_Heights[(x - 1)*m_Size.Y + y - 1];
                    adjacentSections++;
                 }

                 if ((y + 1) < m_Size.Y) // Check down and to the left
                 {
                    sectionsTotal += m_Heights[(x - 1)*m_Size.Y + y + 1];
                    adjacentSections++;
                 }
              }

              if ((x + 1) < m_Size.X) // Check to right
              {
                 sectionsTotal += m_Heights[(x + 1)*m_Size.Y + y];
                 adjacentSections++;

                 if ((y - 1) > 0) // Check up and to the right
                 {
                     sectionsTotal += m_Heights[(x + 1) * m_Size.Y + y - 1];
                     adjacentSections++;
                 }

                 if ((y + 1) < m_Size.Y) // Check down and to the right
                 {
                     sectionsTotal += m_Heights[(x + 1)*m_Size.Y + y + 1];
                     adjacentSections++;
                 }
              }

              if ((y - 1) > 0) // Check above
              {
                 sectionsTotal += m_Heights[x*m_Size.Y + y - 1];
                 adjacentSections++;
              }

              if ((y + 1) < m_Size.Y) // Check below
              {
                 sectionsTotal += m_Heights[x*m_Size.Y + y + 1];
                 adjacentSections++;
              }

              NewHeightData[x*m_Size.Y + y] = (m_Heights[x*m_Size.Y + y] + (sectionsTotal / adjacentSections)) * 0.5f;
           }
       }
       delete m_Heights;
       m_Heights = NewHeightData;
   }
}

增加passes 的值以获得更平滑的效果。

回答你的 1) - 分开。它们有一个对象列表,只需将它们放在高度图的顶部。

2) - 以不同的方式。地下城通常是规则的网格。

3) 您可以使用法线、高度、附加纹理数据以不同方式解释或以上任意组合

【讨论】:

  • 基本上虽然您只是添加更多顶点......对吗?
  • @Goz 不是真的,这更像是一种混合。动态寻找形状并在山坡更陡峭的地方添加更多顶点更难,但当然可行。
  • 顺便说一句,几年前我写了一篇关于图像过滤的非常详细的帖子:stackoverflow.com/questions/1696113/… 也值得研究可分离过滤器,因为它们是一种更有效的盒式过滤器(或甚至更复杂的对称过滤器),就像你在上面做的那样。
【解决方案4】:

暴雪建模者使用Autodesk's 3ds max 来创建模型。如果您研究该软件包的功能和技术,您将了解它们如何实现其效果。请注意,景观模型使用非均匀 b 样条 (NURB),使其具有圆润的外观。

【讨论】:

    猜你喜欢
    • 2014-03-12
    • 1970-01-01
    • 2018-04-10
    • 1970-01-01
    • 1970-01-01
    • 2010-11-04
    • 2014-10-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多