图形学基础算法介绍

2020-08-13  本文已影响0人  离原春草

本文将着重搜集图形学基础中的一些容易被忽视的细节,从而避免因此导致的效果异常问题。

渲染相关

由于MSAA只能处理几何边缘,因此在MSAA中使用Alpha-Test绘制的物体在Alpha渐变的边缘的锯齿就无法被平滑,这个问题有如下三种解决方案:

  1. 通过增加顶点的方式将alpha边缘转换为几何边缘,这种方案会导致几何数据增加,代价比较高
  2. 使用alpha-blend替换alpha-test,这种方案需要对模型按照从后到前进行排序,费时费力且效果可能还会有问题
  3. 通过硬件辅助实现的A2C进行处理,成本低,效果好。

在MSAA的实现中,硬件会为每个fragment下的每个sample各分配一个bit用作mask(比如4x MSAA的话,每个fragment对应的mask就是4bits的),这个mask可以称之为coverage mask(这个mask是在Rasterization阶段输出的,而在开启了A2C功能后,在PS中会根据alpha值对此值进行修正),在后续进行blend的时候会用于判断当前sample是否需要更新的依据。

在开启A2C的时候,硬件会将当前shading pixel的alpha数值转化为coverage,之后根据coverage对应的mask(比如4x MSAA, coverage 87-100% 的mask为 1111, 62-87% 为 0111, 37-62% 为 0011, 12-37% 为 0001,0-12% 为 0000)对当前像素中的sample进行覆盖写入。这里需要注意的是早期硬件的coverage mask是通过固定函数实现的,但当代显卡却是可以通过PS对coverage mask进行手动处理。

这里需要注意的是,A2C应该只用于Alpha-Test物件,Alpha-Blend以及不透明物件都不应该使用,否则徒增消耗。

使用A2C实现的MSAA其表现比FSAA效果更好,因为不会出现由于贴图缩小导致的闪烁(不过贴图放大器效果可能会更模糊,这是alpha-blend方案的通病)

为了得到正确的渲染效果,半透物件渲染常见的做法是将物件按照从后往前的顺序进行排序,并按顺序进行渲染。

这种做法的缺陷在于排序比较费时,且对于存在深度穿插的物件而言,也不能完美解决问题。为了应对这两个问题,大家纷纷尝试给出一种OIT渲染方案,通过一种顺序无关的权重计算方式来对半透物件进行累加。为了对权重进行归一化,通常需要将权重累加到一个单独的buffer中(也就是需要MRT的支持),之后通过一个单独的pass对半透物件的渲染结果(即需要将半透物件渲染到一个单独的buffer中)进行resolve(其实就是权重归一化)。

OIT有多种实现方式,这里给出一种Weighted Blended Order-Independent Transparency方案作为示例,在这个方案中,权重的计算与当前待写入像素的depth有关(距离相机越近,权重越大,这种做法是可以理解的),在PS计算的时候,根据像素的depth以及opacity计算对应的权重weight,之后将当前待写入的color数据累加到半透color buffer中(float4(color* opacity, opacity) * weight),并将weight写入对应的半透权重buffer中。之后按照OIT的通用逻辑进行resolve之后与不透明buffer结果相叠加得到最终结果。

最近读文章看到说,MSAA Sample Pattern基本已经成为业界标准,即不论何种机型,相同倍率的Sample Pattern基本上都是一致的,突然很好奇,在不同的倍率下的sample pattern到底是怎样的,这个问题MJP的DangerZone已经做了解答。

基本实现原理是通过绘制一个高密度的grid,而gird中的顶点数据存放的是这个顶点的相对于grid的起始位置信息,在MSAA作用下,被grid的quad所覆盖的sample会有数据写入,之后将sample数据逐个输出就能够得到每个sample的位置信息了。原理非常简单,虽然结果不是百分百精确,但是大致够用,如果希望得到更高精度的结果,还可以通过增加grid的尺寸做到,这里就直接借用其工具输出各个倍率下的Sample Pattern:

1x 2x 4x 8x

D3D 10.1以后,API规定了各硬件必须遵循的MSAA sample pattern,其结果与上面给出的结果中接近一致:

贴图相关

贴图采样中,将UV坐标转换到贴图空间(即从[0, 1]浮点数转换成[0, TexWidth/TexHeight]的整数)之后,整数UV(或者说ST)对应的实际是每个texel的中心,以D3D为例,[0, 0]对应的实际上是贴图中左上角的texel的中心位置,而非贴图左上角的原点。如果在实践过程中发现贴图采样的结果距离自己的预期存在轻微的偏移,那么就是这个原因导致了,具体修正方法为将ST坐标减去0.5。[1]

参考文献

1. 图形学底层探秘 - 纹理采样、环绕、过滤与Mipmap的那些事
2. Do Use Mipmapping
3. MSAA and alpha-to-coverage
4. Alpha to coverage - Humus
5. Weighted Blended Order-Independent Transparency
6. 乱弹纪录II:Alpha To Coverage
7. UE426终于实现了Alpha to Coverage

上一篇 下一篇

猜你喜欢

热点阅读