赞
踩
游戏中大面积的地形不可能全部精密计算加载,不可能一直都以极高频率去采样地形高度,所以需要进行采样的优化处理,其中主要的两个原则是:
最常用的方法仍是四叉树。
优点:
缺点:
四叉树也会遇到T-Junctions问题。解决方案是吸附:让采样密度高的一侧多出来的采样点调整高度,吸附到采样密度低的那条边上
不规则的三角形。
优点:
缺点:
这个步骤处于顶点着色和几何着色之间,分为
具体来说:
hull shader的输入是特殊的patch片元,它是由几个控制点定义的细分曲面,贝塞尔片元或其它曲线元素。hull shader有两个功能,首先配置tessellator及告诉tessellator生成多少个三角形。然后,它在控制点上执行处理(transform等)。hull shader能够修改输入的patch, 根据需要添加或删除控制点。最后,hull shader输出控制点集及tessellator数据到domain shader。
tessellator在管线中是固定功能管线,它的功能是添加新顶点并传送到domain shader。hull shader 发送细分表面类型(如三角形,四边形或等值线)到tessellator。等值线用于头发渲染。hull shader发送的其它重要的数据是细分因子(OpenGL中为细分 levels),有两种类型:内(inner )和外边(outer edge), 内因子决定三角形或四边形内部进行多少次细分,外边因子决定外边切分为多少次。
domain以重心坐标为中心为每个点生成坐标,并在patch的评估方程中使用这些坐标来生成位置(position),法线(normal),纹理坐标(texture coordinates)和其他所需的顶点信息。
引用于https://zhuanlan.zhihu.com/p/391322740
后续又发展出Mesh Shader(DX12以上 win10+),用来替代这个三个步骤。
为什么这种基于GPU的方法很重要呢?主要是其可以实时调整所有顶点的位置和数量。因而实现实时可变地形。这也是许多比如黑神话悟空预告片中雪地场景实现的重要技术。
上述所讲都是基于高度的地形,还有其他类别,比如单纯基于模型。这时候也有很多trick,比如在山体模型上挖个洞做隧道(通过取一个隧道中心点,将其位置设为none,从而几何会退化,去掉所有包含这个点的三角形,最终形成一个洞,后续再利用隧洞模型掩盖锯齿状的边缘)
通过每一个体素(小立方体)的各个顶点在面的上下位置来判断切面是如何与这个体素相交。
真实世界中材质数量很多,所以需要处理大量的材质混合情况
传统情况下渲染地表,使用的都是texture splatting技术,也就是说,地表纹理使用多种不同的纹理混合而来。然后使用一张叫做splat map的权重图来记录这些纹理的权重。
考虑最简单的两种材质的混合问题:
现实世界远不止两种材质,所以在多材质相叠的时候,就引入了texture array。简单来讲就是将每个材质用一个index表示,在实际处理时根据用到的index和其对应的权重来进行混合计算。
【注意】texture array的处理方式不同于3D texture,后者利用八个顶点上下两个面进行七次插值计算出一个最终颜色信息。
当前处理凹凸效果最基础的方法是Bump mapping。
升级版就是Parallax mapping,其特点在于假设地表下的材质和有高度凹凸的,所以当相机看到某个点时,实际上由于上面有凹凸会导致有一个offset,比如实际上看到的点应该高于那个平面上的点,从而让视角效果更好。其缺点一是成本较高,需要走几步更新一下,缺点二是仍未解决只是视觉效果而未改变几何的问题。
更好的解决方法是Displacement mapping。根据前文所述的实时可变地形,切实的改变地形高低。
核心思想是只将需要用的部分放入内存,其他都留在硬盘中。
这里简单阐述下方案:绘制两边,第一遍把需要用的的贴图的tile以及自身的UV等等信息输出到rendertarget上,CPU根据RT的数据将资源送到GPU,第二遍绘制才是真正的渲染
这个概念取自于Virtual Memory,与虚拟内存类似的是,一个很大的Texture将不会全部加载到内存中,而是根据实际需求,将需要的部分加载。与虚拟内存不同的是,它不会阻塞执行,可以使用更高的mipmap来暂时显示,它对基于block的压缩贴图有很好的支持。 基本思路是,会将纹理的mipmap chain分割为相同大小的tile或page,这里的纹理叫虚纹理,然后通过某种映射,映射到一张内存中存在的纹理,这里的纹理是物理纹理,在游戏视野发生变化的时候,一部分物理纹理会被替换出去,一部分物理纹理会被加载。
可以参考https://zhuanlan.zhihu.com/p/138484024和https://www.zhihu.com/question/453803452
VT的另一个好处是可以在加载新的tile时预先bake好材质的融合再放入物理材质中,这样后续调用就更快了。
现在VT基本上一统天下了。
与其相关的两个硬件知识:
因为浮点数精度是有限的,所以当表示大距离的时候就会出现问题,比如当相机和某个点离世界坐标原点越来越远(看月球)时就会出现其精度不够,比如最小精度可能都大于1了,然后就会出现“抖动”,因为物体的坐标精度不够了,已经不准了
解决方案为Camera-Relative Rendering。在任何其他几何变换影响物体之前,通过重设世界空间相机位置来转换物体。其实就是把camera设为世界坐标原点,这样就可以用相对坐标来代替员阿里的绝对坐标了(当然还需要更新所有其他矩阵)
比较琐碎和笼统,没啥好记的。
首先和光线追踪类似,大气渲染也有类似的渲染公式,在实际处理中也有类似 Blinn-Phong的拟合模型。关键参数是当前点到天顶的角度和到太阳的角度
但这种模型换了情况就不适用了马上,比如天气变了,日夜变化,甚至多了PM2.5。
光和介质的接触:
大气中真实存在两种介质:气体分子和气溶胶分子,前者往往小于太阳光中各种光的波长,而后者一般接近这些波长。
因此散射也分为了两种:
当空气中介质尺寸远小于波长的时候(气体分子):
详细来说,其散射公式如下:
其中θ是光散射出去的方向和入射角之间的角度,n是空气折射率。而密度比。
ρ
\rho
ρ 这个数字在海平面上等于1,随
ρ
(
z
)
=
exp
−
h
/
H
\rho(z) = \exp{-h/H}\,
ρ(z)=exp−h/H 呈指数递减
几何部分决定了不同方向光的散射情况不同(但整体差别不太大,而且旋转不变);波长部分表明波长越短,散射越强;密度部分表明了海拔对散射的影响。
这也解释了天空在白天是蓝色在傍晚是偏红的原因:
当空气中介质尺寸接近或大于波长时(气溶胶):
详细来说,其散射公式如下:
对比瑞利散射,多了几何参数g的影响。
其实际生活影响就是雾和太阳光环:
空气中主要是臭氧(
O
3
O_3
O3)和甲烷(
C
H
4
CH_4
CH4)能够吸收波长的光,比如臭氧吸收红橙黄,甲烷吸收红光。比如海王星上大量甲烷导致其显现蓝色。
实际计算过程中往往假设这些气体是均匀分布在整个大气中的(虽然实际上并不是,比如臭氧集中在大气上层)
实际计算时,Ray Marching是最常用的方法。其原理主要是依照路径逐步计算累积,如下图:
其中T就是所谓通透度(密度)
和普通物体的实时渲染类似,预计算也在该领域得到运用,LUT就是一个将许多复杂计算进行预计算保存下来的表格。在通透度方面,一个公式得以提出:
我们注意到,两个点之间的通透度关系借此只由两个参数决定(
h
h
h 和
θ
\theta
θ )由此,我们可以得到一个关于传播通透度的LUT表。
提出这个公式之后,原来的单次散射公式就可以表示为:
这里最重要的是一种参数化思想(和上面一样),利用三个参数
η
\eta
η(太阳顶角)、
θ
\theta
θ (观察顶角)和
ϕ
\phi
ϕ (太阳到观察视角之间水平角度)再加上当前高度
h
h
h 表示站在所有点在所有太阳角度下看任何方向的情况。(这三个角都是方位角并进一步通过cos计算得到相应结果(
μ
s
\mu_s
μs 、
μ
\mu
μ 以及
v
v
v)。我们将这个4D表示存到多个3Dtexture array(其实3D texture的插值更合理)里面方便查询。
因此,我们获得了通透度LUT表和单次散射LUT表,利用这两张表,就可以计算出二次、三次以及更多次散射的LUT表
缺点:
因为上述缺点,一种更简化的多次散射方案被提出,其特点在于认为任何散射都是各向同性的,向所有方向均匀散射,所以对一个介质来说,其所有邻居介质收到来自它的散射能量都是相同的,因而一次散射带来的结果只是整体削减(吸收)了固定百分比。
在这种设定下,多次散射也就单纯变成了一次散射的指数变化(等比数列),而一个介质收到的不同次数的散射总量就是其求和(等比数列求和)。
这样一来,由于极大加快了速度,所以这种方法可以每一帧都进行计算。从而导致原方法LUT参数中的高度
h
h
h 以及太阳顶角
η
\eta
η 都不需要参与预计算(因为都实时更新了),所以新方法的LUT表中只需要计算出观察的天顶角
θ
\theta
θ 和一个水平方向环绕360度的夹角
ϕ
\phi
ϕ (对应原来太阳到观察视角水平方向的夹角)即可。化四维为二维。
再加入相机距离可以进一步获得3D的LUT表来实现ray marching
云渲染从最早学术界的Mesh方法到早起游戏的单纯叠贴图,逐渐发展到了用于3A行业的Volumetric Cloud Modeling。其本身有各种优点:
同时也具有一个明显的缺点:
其具体依赖于一个称为Weather Texture的东西,而它由两个部分组成:
利用这两个部分就可以实现比如云的移动(对1进行平移)以及厚度变化等
但是单单这样做会导致云的形状变成柱状,所以引入了Noise,比如Perlin Noise(棉絮状噪声)和Worley Noise(细胞结构状)等,先利用低频把云的规则边缘模糊化,再加上一些高频来优化细节。
实际如何进行渲染呢?Ray Marching。具体来说分四步:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。