图形学基础算法介绍

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

渲染相关

  • Alpha to coverage(A2C)[3,4,7]

由于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方案的通病)

  • Order-Independent Tranparency(OIT)

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

这种做法的缺陷在于排序比较费时,且对于存在深度穿插的物件而言,也不能完美解决问题。为了应对这两个问题,大家纷纷尝试给出一种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

最近读文章看到说,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]

  • Mipmap相关[1][2]

    • mip级别选取的原理:物体距离相机越近,mipmap级别越低(贴图精度越高),相邻像素之间的UV差距应该越小,因此可以根据相邻像素对应的UV差距来判定当前像素所对应的mipmap级别,这个操作通常是通过dx/dy来实现的(这一步通常是硬件自动完成)。
    • 使用mipmap虽然会导致所使用的贴图大小有大约1/3尺寸的增幅,但是其优点完全可以覆盖因此导致的损失:不但有助于减轻采样高精度贴图导致的高频颜色跳变(这其实是采样频率不足导致的重建失败而出现的锯齿感),同时还有助于减轻贴图采样所需要的带宽(贴图访问会有一个cache机制,在访问某个像素时,会同步将周边的像素一并加载到显存。采用合适的mipmap,有助于提升cache的效率,避免频繁的cache miss,从而降低带宽需要)。
    • 不是所有的贴图都应该使用mipmap:
      • 不需要进行filtering的贴图(比如索引、深度等非image信息)不应该使用mipmap
      • 不会因为相机远近而缩放的贴图(比如UI所使用的的贴图等)不应该使用mipmap
  • 贴图过滤
    目前常用的贴图过滤(filtering)方法有以下几种,按照顺序,效果与性能消耗逐渐提升:

    • point filtering,点采样,无任何过滤,相当于直接采取贴图上最近的texel作为输出结果(一次贴图采样)
    • bilinear filtering,双线性采样,会根据uv坐标的小数部分对相邻的四个texel进行采样并加权平均(通常由硬件自动完成),效果相对点采样有极大提升,锯齿感得到较好的抑制,但是图像也会相对模糊。(四次贴图采样)
    • trilinear filtering,三线性采样,对计算得到的mipmap层级保留其小数部分,据此增加一层mipmap级别的过滤处理,即同时对相邻两层mipmap应用bilinear filtering,之后根据mipmap小数部分对结果进行加权平均(八次贴图采样)
    • anisotropic filtering,各向异性采样,直接按照x/y方向上的最大梯度来计算mipmap级别会导致一个狭长的物体在屏幕上的效果较为模糊,为了能同时兼顾两个方向上的梯度变化,通常需要通过各向异性采样来解决。各向异性采样算法稍微复杂一点,需要将屏幕空间的像素按照短轴(而非普通mipmap算法中按照长轴)计算的mipmap层级投影到贴图空间,之后得到多个对应的texel sample,在每个sample上应用trilinear filtering并加权平均得到最终的结果,具体可以参考使用最广的FAST(Footprint Area Sampled Texturing)算法实现。

参考文献

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,635评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,628评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,971评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,986评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,006评论 6 394
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,784评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,475评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,364评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,860评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,008评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,152评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,829评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,490评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,035评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,156评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,428评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,127评论 2 356