Origin
zhuanlan.zhihu.com
Tags
简悦
项目
收藏夹
创建时间
收藏类型
Cubox 深度链接
更新时间
原链接
描述
一、地形概述
二、地形的几何
1. Heightfield:
Heightfield 渲染细节:
先打网格,然后根据数据进行位移:
2. 开放世界地形的 LOD:
如果采用粗糙的 LOD 对远处的地形进行 “简配” 的话,会出现问题。因为地形是连续的。
所以大世界的地形是需要单独设计:
不需要对玩家所在的地形进行 360° 的 “精加工”,我们要考虑到相机的 Fov,所以只需要对相机锥形外进行网格简化,如上图。为什么上图中随着 Fov 越来越窄时,视线范围反而拉长了呢?是因为随着视角缩小,我们对远方的观察是放大的。
3. 网格密度管理:
网格简化的两个基础原则:
- 网格密度参数,是根据距离相机远近以及 Fov 值进行计算。
- 简化后的网格与原版肯定有误差,那么当简化后的网格合并时,误差不能超过给定的阈值。(这个阈值是在视空间上,也就是保证误差在屏幕上不超过一两个像素)
4. 如何处理网格的密度
三角形的剖分:永远在等腰直角三角形最长的边切一刀,得到两个等腰直角三角形。这个结构是二叉树结构。
T-Junctions:如下图右上角显示的,如果右边切了三角形并且上下位移了之后,就和左边的面片合并不上了。
T-Junctions 解决办法:如果发现邻居面数多,那自己这一边也切一刀,直到两边边数一致。
所以用一个二叉树结构和无数等腰三角形就能搞出来地形。
5. 更好的网格划分以及组织方式
现代引擎更多的采用基于四叉树的地形表达:
切成 512m*512m 大小的格子,这样有个好处是纹理的大小也是 512512_。_512 规格的材质以及上面的建筑树木等等,都组织成很规范的磁盘上的一份数据块。
下图中第四张图能看到,红色的是玩家,然后随着玩家的走动颜色会一直变化,因为会把地块根据玩家距离细分的精度一直在变。
这种网格的划分方法也会遇到上面遇到的问题,那就是不同精度之间如何无缝衔接:
如上图,有个很厉害的解决方案:我们不再切精度低的一面,因为这样会改变几何的拓扑结构。我们会让左边精度更高的点 “吸附” 在右边。
如何吸附:如上图右边,多了的中间点往上移动到顶部重合,这样就得到了一个面积为 0 的三角形,也叫退化三角形。
6. 不规则三角形:
7. Hull Shader & Tessellator & Domain Shader
感觉很吊啊
8. Mesh Shader
现在一个 Mesh Shader 就把上面 7 的活都做了,但需要 DX12 才支持,Win10 才支持 DX12。
9. 实时地形
坦克碾地可以实现,履带往下沉,两边往上挤。或者实现雪地效果,人踩上去有痕迹。
三、地形的材质
1. 材质混合:
材质透明度混合的问题:
解决办法:根据 height 做个权重
2. Texture Array
真实项目中材质有几十上百种材质,这样就需要采用 Texture Array,把所有的纹理都编在一起。然后去拿不同的材质根据权重去混合:
3. 视差贴图:
比法线贴图更好的效果,有点费,但也就是有点点,也不是太费。
4. 地形采样性能耗费:
好几张图混合计算,每张图采样 8 次做 7 次插值。最后把每张图的最终结果根据权重混合。并且多次读不同的图,在内存内跳来跳去也很费:
5. Virtual Texture
解决上图中地形采样性能耗费的巧妙办法就是采用 Virtual Texture:
- 建立虚拟索引纹理,代表整个场景中所有混合地形材质。
- 只加载基于视图相关 LOD 的 Tiles 材质数据。
- 预烘焙混合到 Tiles 中的材质,并将其存储到物理纹理中存储到物理纹理中。
能极大的优化显存大小;直接取烘焙好的 tiles,也能节省消耗;
6. 超大地图的浮点数精度溢出
问题描述:假设一面墙,墙上贴一张画报,画报实际上比墙高 0.1,可以避免它们两个的互相扰动。但是随着相机的远离,在几公里时又会出现互相扰动的现象,这是因为在超远距离上 0.1 的精度不够了。
解决办法:Camera-Relative Rendering (相机相对性的渲染)
四、纸杯道路贴花等
1. 树木:
树木的 LOD:近处是 Mesh,远处是十字之类的面片相插:
2. 道路系统和贴花:
▎本文由 简悦 SimpRead 转码。