【GDC2016】The Technical Art of Uncharted 4

军城早秋
[唐代][严武]
昨夜秋风入汉关,朔云边月满西山。
更催飞将追骄虏,莫遣沙场匹马还。

今天来分享一下GDC 2016中顽皮狗工作室的关于《神海4》中的一些效果的实现技术,这里是原文的PPT链接。


开篇有个视频,各位请前往PPT中查看。

这篇文章主要讲述《神海4》制作中TA工作的相关经验,《神海4》是顽皮狗工作室首次尝试使用PBR管线制作的游戏,从制作者的角度来看,PBR管线有助于提升工作效率,降低工作难度,且整个管线的实现流程对于美术来说也更为直观。

先给个效果相关的内容概览

之后会讲述顽皮狗是如何实现对于洗衣机工作时的表现的模拟的(洗衣机45分钟的工作过程。。。)

这里介绍了PBR管线的实现框架,核心算法用的是Disney BRDF PBR,渲染模式采用的是延迟渲染,这里需要注意的是,环境shader的实现并不是通过类似蓝图的节点编辑方式生成的,因为对于复杂shader实现而言,传统的代码控制实现起来会更容易,运行效率也更高。

先看下HDR跟Color Grading相关的工作

用了一个LUT实现冷色调color grading

对比Tonemapping开启前后,可以看到,Tonemapping加深了阴影与非阴影区域之间的对比度,此外在增加云层曝光度的同时保留了场景中黄紫色区域的相关细节不出现banding。

问题来了,为什么要使用Color Grading呢?这是因为我们不希望游戏的输出画面看起来有人为的后处理痕迹,而是希望能够类似镜头之类的滤镜一样自然,这里给出一个极端的例子

对上面的原图做后处理染色处理,通过一个multiply因子给画面加上一层青色,可以看到白色云层部分也被染上了青色,这自然是不符合实际的观察表现的

而在HDR中应用Color Grading,可以保留云层的一抹白色,当然,也有人说在LDR空间中使用一些算法也能做到这种效果,不过这相对于HDR Color Grading的一步到位就有差距啦。

之前的项目中的Tonemapping采用的是John Hable的实现算法,不过既然John Hable的算法的目的也不过是拟合一条曲线,那么为什么不直接手动设计一条曲线,并将相关数据保存下来,在运行时直接使用呢,《神海4》采用的就是手动设计曲线并将结果保存到一张LUT中,运行时直接查表读取的方式完成Tonemapping的。

且考虑到Color Grading也需要使用LUT方法,那么不如合二为一,将Color Grading跟Tonemapping的映射关系合并到一张LUT中。跟传统映射关系的输入范围为0.0 ~ 1.0 sRGB不同,《神海4》的输入范围为0.0~2.0 sRGB,在开发的过程中还尝试过0.0 ~ 4.0的输入范围,虽然应用起来并没有什么问题,但是对于《神海4》而言,这么大的输入范围并没有收到过多的增益,反而降低了主要输入范围对应的数据的精度,因此最终选定的输入范围为0.0 ~ 2.0。(光照如果采用PBR的话,其亮度应该分分钟破千上万才对,为什么这里用2.0就够了?)

这里调整Color Grading跟Tonemapping使用的是一款叫做Fusion的组合工具,Fusion的默认工作模式为HDR,工作流程也是蓝图式的节点拼接方式,其使用方式相对于Photoshop来说更为方便跟直观。这个图中左下方给出的使用户定义的一些处理节点,可以根据需要调整其实现复杂度,而右边给出的是一些预定义的tonemapping曲线,美术同学可以根据需要选用不同的实现曲线。

Fusion的一个强大之处在于,编辑的效果可以实时呈现在游戏中(实际上是每秒保存五次,保存时通过消息通知游戏客户端刷新),因此美术同学在调整好一个效果的时候,可以直接查看周边其他区域的表现是否也如预期一般(恐怕只能局限于局部,不过即使使用程序算法实现,也无法兼顾全局)

美术同学希望在不同的观察视角,得到的雾气的颜色是不一样的,且希望这个颜色能够跟天空盒的颜色匹配起来(距离相机较远的地方,可以理解为与cubemap相距较近,可以直接使用cubemap的采样结果进行叠色,距离相机较近的区域则需要考虑天光效果,可以使用降分辨率后的cubemap来模拟cubemap上多个像素的叠加作用)

普通的固定颜色的雾气表现

这里使用的方法是对天空盒进行处理,为之生成一套mipmap,之后根据像素的深度取用不同层级的像素数据,越近的像素取用的层级越小(模糊层度越低),用于模拟距离天空越远的位置,天光的作用范围越广吗?

这里给出的是使用不带mip层次的fog贴图的实现效果,其问题在于对于前景跟背景而言,其对应的fog颜色可能是相同的,这个问题对于处于室内或者在一堵墙后面更为严重(因为没有层次结构,同一个像素位置采到的贴图坐标是相同的,不过这个对于表现而言到底有什么影响呢,fog对于不同距离,其强度是不同的,之前使用固定颜色的fog也没有很明显的异常呀?)

这里使用的是带层次结构的fog颜色方案,对于近景采样的是低分辨率的fog贴图,对于远景采样的是高分辨率的贴图,从而使得近景的表现看起来就是将整个天空盒对于大气粒子的散射效果累加起来一样。

使用mipmap fog之后的表现如上图所示(感觉还有些内容没有讲到,雾气表现,颜色只是一方面,强度是另一方面,这张图的近景fog强度明显低于最开始的那一张)

Fog采样代码实现
其他大气效果

下面介绍一下由法线贴图计算得来的细节凹凸的阴影实现

对于高模跟低模而言,其diffuse贴图跟specular贴图是没有太大变化的,而二者间的差异通常都是通过法线贴图与AO贴图来存储的。

更丰富的细节如BRDF关系等就是通过粗糙度以及各向异性(这是什么)来表征了

从模型到贴图的每一步简化都有相关的数据丢失,想要通过简化的贴图实现模型的真实效果,就需要改变输入数据的类型比如说通过高度图来模拟几何表面的视差细节。

在将渲染管线替换成PBR之后,美术同学就开始尝试将AO贴图合并到基色中或者希望AO贴图来影响所有光源的输出效果,最终这里找到了一种 “物理可以理解”的方式达到这个目的,这个方式被命名为micro shadowing

注意那些通过法线贴图产生的凸起在挡住光照的时候却并没有产生对应的投影的区域

这里给出的画面是关闭了光源的输出,单独开启Micro Shadow的阴影表现。

这里两个高低错落的面之间有一个凹洞,AO信息会用来模拟上图中左右两条黑边的所夹的椎角,这里θ2用来表示椎角的一半,如果有一束光线射进凹洞,且光线方向与法线方向的夹角θ小于θ2,那么光线落点处就能够被照亮,否则将处于阴影之中(从下图代码来看,像是使用AO来对Shadow进行调制)。

这里给出具体的实现代码(从代码层面看不到任何物理的踪迹。。),不过由于AO贴图的精度较低,因此仅仅使用AO跟法线还是会对实现效果造成一定的误差,这个问题在《神海4》中不是很明显,因此也就听之任之了。这里之所以将microshadow跟shadow相乘,是因为通过microshadow得到的结果比较硬,需要通过具有软影效果的shadow来综合一下

这里有个跟AO相关的概念,叫做AO遮挡,或者AO菲涅尔效应,我们知道,AO表示的是物体表面的几何遮挡关系,其上的黑色区域对应的是几何面片上的沟壑,对于低模而言,是没有这个沟壑的,通常都是通过法线贴图来模拟,而对于通过水平视角观察的几何表面而言,正确的结果应该是无法看到表面的沟壑的(平视的情况下都被遮挡了),因此对于高模而言,这是自然无问题的,对于低模而言,就需要在shader中将法线贴图与AO贴图表示的沟壑去除掉。

效果图

实现的代码非常简单,曲面的表达方式非常简单,或许后面可以优化一下这个地方,注意其中的点乘用的是几何表面的法线而不是法线贴图的法线。另外,这个方法只会用在那些通过烘焙光照实现的模型,对于那些使用probe光照的模型(比如角色),其对应的AO贴图是包含了周边模型的遮挡信息的,因此不需要进行这个处理

AO菲涅尔算法是在所有场景所有物件表面上都默认打开的效果,并不需要美术同学做额外的参数调整

下面来看看一些特殊的材质类型——苔藓——的实现


《神海4》场景中有很多苔藓的应用


苔藓的渲染方程并不符合标准的BRDF模型的规律,因为苔藓的表面孔洞更为丰富密集,其中有着大量的自阴影,AO以及内部光通路。对于苔藓而言,顶端的枝叶颜色相较于根部的枝干颜色要浅一些,而且其颜色表现跟观察角度也有关系,当垂直向下观察时,可以看到苔藓纤维之间的阴影,而如果水平观察时,则只能看到顶部的枝叶。

这里是苔藓的例子,关于苔藓需要兼顾近观跟远看两种情况下的表现。

下面这个图是《神海4》中苔藓最终的材质球效果

而下面这个是微表面材质使用相同的输入贴图的效果,看起来像是一块硬塑料。

苔藓材质球主要的输入贴图有四张:颜色,法线,高度以及AO,其中AO贴图颜色比较深,其原因后面会说。

这里一步步介绍苔藓的shader细节,这个图是微表面BRDF表现

在微表面BRDF上添加了Sheen(光泽)后的效果

这里受Eric Penner的Pre-Integrated Subsurface Scattering工作启发,对光照进行一层Wrap处理,通过对N*L进行修改使得光照能够沿着表面传播更远的距离,从而实现对次表面的模拟,同时可以模拟纤维层法线与光照方向夹角超过90度的情况可能还依然会处于光照之中的特点。

另外,这里还增加了一种毛绒BRDF功能模块,这个模块的名字叫微纤维(microfiber)这个模块是工作在subpixel层面的,美术同学可以为毛绒特征指定一个不同的颜色,之后在运行时会将微纤维层绘制在微表面层的上方

在性能扛得住的时候,还可以给这个材质增加一个视差阴影。

前面说到,苔藓的AO颜色比较深,这是为了模拟苔藓在不同的观察角度呈现的颜色有所不同的特点:在垂直观察时,颜色较深,在水平观察时,看到的只是苔藓上边的枝叶。通过对AO贴图根据观察角度进行过渡处理,在接近水平观察角度时,直接使用阳光的Micro Shadow取代AO

最后在AO较深的位置增加一层颜色,用于模拟光照的bounce以及次表面散射。《神海4》给出的苔藓的实现方式比较hack,想要实现真正物理正确的苔藓的可以参考Jorge Jimenez的talk。

最终的输出效果
BRDF微表面实现效果对比

下面给出了light wrap的代码,这个代码本身是遵循能量守恒定律的,因为这个过程只是扩大了光照的范围,而没有增加能量。这个计算中唯一人为可控的就是输入的颜色数据Lightwrapcolor,当这个值为0的时候,就回归到常规的N*L实现。

Fuzz的代码就不给出了,太黑客了,羞于见人

除了苔藓之外,自然界还有很多物体的形状与之类似,比如说毛织物或者远处的树叶,或者说堆积的尘埃或者桃子的绒毛等,后续可能会尝试将这些物体的表面渲染实现用统一的BRDF特征来表述。

下面介绍一下《神海4》中物体表面潮湿表现的实现方法

下面这个图是美术同学绘制的潮湿贴图数据,虽然绘制的潮湿贴图可能不利于实现动态的潮湿效果,但是实际上大部分场景中静态的物理正确的潮湿效果就已经能够满足需求了。

这里是一些其他的示例效果,注意水洼的四个不同的特征区域:A).水洼的中心区域,水面如镜 B).水面开始与地面相接,由于水面张力的存在使得水面呈现一种皱缩的表现 C).水面浸润地表,加深地表原有基色,却不影响法线跟高光表现 D).完全干燥的不受水面影响的区域

这里给出了具体的实现代码,在这个实现中,美术同学控制的变量只有两个,分别是潮湿度跟疏松度(porosity,表征地表是否疏松多孔,比如突然的疏松度就比大理石地的疏松度要高)。其中潮湿度用于控制实现潮湿表现在四个特征区域之间的过渡,而疏松度(可选项,如果不用这个参数,就会使用粗糙度来代替)则控制着地表受潮湿度影响后的颜色加深程度,疏松度越高,地表颜色越深,这里的加深程度的上限为原有基色的平方(这个结果跟现实世界的表现比较接近)

这里给了一个demo视频,可以看到使用这种方法实现的地表潮湿的表现效果非常好,另外这里有一点需要注意的是,当地表潮湿度超过98%之后,就会强制修正顶点的法线方向为垂直向上(被水面覆盖),以模拟水面镜面表现。实验证明,虽然可能几何形状实际上是不平整的,但是在法线跟潮湿度作用下得到的效果却非常平整。

这种表现方法在几乎所有的场景中都有用到,加上闪电跟特效的作用,就更加的接近真实世界的表现了。

玻璃材质

《神海4》中有很多地方需要用到玻璃材质,这种材质的实现其实比较简单。

最简单的玻璃材质就是窗户的玻璃了,比如这个车窗的玻璃,虽然从仿真的角度来说,应该要为玻璃增加一个折射计算,不过因为直接使用alpha blend实现成本更低且表现上也不会让人觉得不真实,因此就省去折射这一步了。

玻璃作为透明材质,其实真正透明的是diffuse部分(其他的透明材质比如水面是不是应该也适用于这种特性?),而specular部分则是不受alpha影响的,即不论透明度是多少,该有的高光反射都不会少(感觉不是很符合能量守恒定律?毕竟有部分能量穿过材质而流失了,难道这部分都算在diffuse头上,而specular是完全的镜面反射,不受透明度的影响?),在实际计算的时候只需要考虑alpha对diffuse 的影响就够了。另外,表面的透明度有可能是变化的(比如玻璃底部沾了污渍),其对应的specular效果却是在整个表面都是保持一致的。

上面的公式对应的是提前将alpha乘到color中的时候的计算处理,即需要将alpha对specularLight的影响从中剔除掉(除法比乘法消耗高,对于这种材质不做这种预处理反而性能更高)

对于厚度较高的玻璃材质(或者冰块),在渲染的时候就需要考虑折射的影响,跟前面的做法一样,这里只对diffuse部分做处理,而specular部分依然保持不变。在实现的时候,就是根据玻璃材质的透明度来对依据折射规则从材质背后的color buffer中采样得到的color值与材质的diffuse部分进行lerp blend,得到的结果作为diffuse部分的输出,详细的细节可以参考Morgan McGuire的Presentation。

折射计算遵循的公式是斯涅耳定律(shader语言中可能有对应的内置函数refract可供调用),n1*sin(theta1) = n2 * sin(theta2)。

另外,考虑到穿过透明材质的光线也有可能从材质中穿出来,如上图所示,经过一次折射后得到的出射点距离不考虑折射的直接出射点有一个d的距离差,可以将这个距离差转变为屏幕buffer贴图的uv坐标偏移量来对屏幕buffer进行采样。

对于需要考虑折射表现的玻璃材质而言,这里可以将材质的表面简化为一个完美的球体,这种球体又可以细分为两种代表性的球体:
1.空心玻璃球体
2.实心水晶球体

这里有一个水杯,其效果的实现可以分成两个部分来完成,一个是空心的杯壁,另一个是实心的杯底。

此外,对于玻璃材质,这边还提供了一些参数可以用于实现材质的染色效果或者添加不透明的图案效果。

玻璃材质的相关控制参数

这里给出了玻璃的控制参数在渲染中的使用方法,注意,对于实心材质而言,直接使用了材质的厚度作为光线在材质中传播的距离(这个地方是简化处理吗,貌似没有考虑折射角度的变化),而空心材质则需要根据观察角度对传播距离进行处理(pixeldepth是什么,为什么感觉这样处理后在空心材质中传播的距离反而比实心材质更远?)

应用效果

由于这里只支持一层折射实现,因此对于放置在玻璃杯中的酒水来说,其折射的颜色就不是直接从屏幕buffer中读取的,而是根据折射向量从最近的环境cubemap(就是用于实现高光反射的cubemap)中读取,其实现效果如图所示。

虽然这个效果已经非常不错了,但是依然有着改进的空间。目前算法的主要问题在于多个透明物体的排序问题以及如何从环境贴图从采取到正确的color,此外还有如何通过多次采样实现霜玻璃效果等。

这里准备介绍一下《神海4》中用VS来处理通用计算问题的一些思考与实现。

顶点shader除了用在着色渲染之外,还有很多用武之地。

第一个要介绍的就是使用VS来实现植被的动画系统。

对于植被的动画,其目标是提供一套物理正确的实施方案,这里给出的实施方案是基于pivot(支点)的旋转,pivot数据通常会存储在顶点色中。

用VS实现通用功能时,通常会将数据存储在这些结构中。

Maya的顶点色输出功能不是很稳定,因此这个数据的输出通常是用自定义的导出插件实现。

最终通过类似UV-shell的方法,实现对于pivot数据的编辑与导出。

不过由于pivot数据不是那么直观,美术同学可能不太容易理解,对于这种情况可以考虑使用debug工具将数据导出到美术同学所熟悉的编辑工具中来查看。

由于顶点shader中数据处理是有序的,因此不需要存储每一层的动画数据就能够实现分层动画,此外在实现顶点动画的过程中,还发现要想实现对于高频风力作用效果,最好是提供植物枝叶尖端等区域位置的顶点法线。

这里是顶点动画所需要的最小参数系统,其中最主要的两个参数分别是弯曲强度(控制弯曲时的最大旋转角度)以及完全速度(控制动画触发的速度)。Sub-object Bend参数是用于计算timeoffset参数的输入数据,详情后面会说,Variation参数则是每个sub-object的随机乘法因子。

为了用尽可能少的指令得到一个物理正确的动画效果,就需要经过一些迭代计算,并在迭代中应用一些魔法数值作为输入。

timeOffset参数可以控制顶点动画的效果随着时间而产生动态变化,如果将这个参数跟顶点到pivot的距离调制起来,就能得到一个非常自然的植被摆动效果。

基于pivot的旋转算法还可以用来实现顶点法线的更新(这个处理的axis跟angle都跟顶点动画旋转一样,不同的是将原点设定在pivot上),顶点法线的更新对于《神海4》的第一版动画系统来说是可选操作,不过后面可能会进一步优化集成为必选操作。

到目前为止介绍的参数都是针对单个asset(比如一株草)的,除了这些单个asset顶点动画的控制参数之外,这里还提供了一套与之类似的泛场景(指的是对于场景中各个位置的表现都一致呢还是说对于多个不同的场景的控制效果一致?)控制参数用于实现全局顶点动画效果的控制。由于《神海4》中的植被所承受的风力都是设定为neutral级别的,在这个风力级别下如果将所有的不同类型的植物摆在一起的话,得到的摆动效果肯定就是完全一样的,这就太呆板了。

为了避免这种表现,这里还增加了一个全局的2D风力控制函数,用于实现对整个场景的各个位置的风力进行波浪式的调整,这个函数将会作用于各种风力动作类型上(包括植被,衣物,头发等等)以保证各种类型的顶点动画效果能够保持一致。

角色与植被的交互效果可以通过对植株应用顶点动画来驱使最接近角色的sub-object旋转来模拟其受角色触碰而摆开的效果。

在实际应用中,除了旋转效果之外,有时候还需要模拟植株被角色推开的平移效果,对于很多游戏来说,这种效果通常都是可选的,不过《神海4》使用pivot距离实现的受力平移效果表现良好,且实现简单高效。

另外需要注意的是,这些交互效果其实也是可以通过PS来实现,这里给出的例子就是通过在PS中应用UV动画来实现风力与玩家交互作用的模拟的。

为了能够将力的作用保留下来(比如玩家走过,植被被踩倒后伏在地上而不弹起来),《神海4》还实现了一个粒子作用的RT用于存储植被pivot旋转的方向跟强度,这个RT可以通过粒子的渲染来进行改写(为什么要用粒子来改写呢,是因为粒子比较容易控制形状?)。通过增加这样的一个RT,可以实现无限制的角色以及移动物体与场景的交互,不管交互多少次,其最终的消耗都是一个常量,因为对于顶点而言,只需要采样这个RT即可。

《神海4》中有很多车辆与地表交互的需求,有了这个功能之后,与地表的永久交互就不再是问题。

说到特效粒子RT,就得说一句,为特效跟Shader之间构建一条通用的数据流通管线有助于实现各种有用的效果,比如角色留下的脚印以及与材质的交互留痕等效果的实现。

既然pivot顶点动画效果这么好,还这么省,是不是可以考虑将之应用到带蒙皮的模型上呢?实际上这个想法实现并不难。

这里给出一个解决思路,对于每个头发面片,这里会选定一个pivot顶点,并在骨骼蒙皮完成之后,计算出其有效的世界坐标位置,之后在头发shader中将这个数据传入共享给同面片的其他顶点,之后这些顶点根据这个数据来实现对风力或者其他力量交互的模拟。

这里给出了头发随着风力作用而摆动的效果demo。

除了全局的头发交互效果之外,有时候还想实现有一定限制的头发交互效果,比如将风力作用的范围限定在正对着风力方向的这一侧。而这个效果就需要拿到头发的世界坐标系下的方位数据(指的是那一块的区域是正对着风力?),不过目前在这个地方只能够拿到顶点的法线数据,而顶点法线对于所有方位都是一样的,因此其实现的基本条件貌似无法满足。

这里给出的解决思路是,为每个顶点添加一个额外的颜色数据,用于存储通用的方位信息,且这个数据会通过骨骼蒙皮算法进行相应的变换,保证其最终的输出数据是世界坐标系下的正确方位(其实就相当于额外的一套法线数据)。

另一个需要用到这个方位数据的地方就是头发在重力作用下的表现的实现(比如Drake的湿发),输入的数据跟风力模拟的输入完全一致,因此不需要额外的消耗

这里给出了具体的实现代码,可以看到在这个地方并不需要对头发面片进行旋转,而是对那些距离pivot较远的顶点将之沿着重力的方向向下做一个移动(下垂效果),这个算法非常简单,且因此带来的头发面片的拉伸则可以忽略不计。

衣物受风力的作用也需要用到这个方位数据

根据方位数据以及风力的方向,可以推导出可能会产生衣物褶皱的位置,之后将前面所说的全局的2D风力控制函数沿着X以及Z轴进行投影,并用投影后的结果来影响衣物上褶皱的动态效果,这个算法可以给出褶皱的一个轮廓,但是要想得到真实的效果,就需要对衣物上的法线数据进行更新,为此《神海4》在这里还增加了一个波浪状的法线贴图用于在PS中对法线数据进行修正。

《神海4》中的风力系统的另一个特征是能够根据全局的风力作用来调整可形变物体的顶点色,如上图所示。

对于形变物体受风力影响的动画,则是通过对两个极端情况下的关键帧(0风力以及最强风力?)加上pivot风力模拟算法来实现。

此外,《神海4》还针对玩家到可形变物体sub-object的距离来对形变进行控制,以实现玩家与场景物体的交互。

这里给出了具体的实现代码。这里需要说的是,如果想要留下永久的影响,还是需要借助前面说的粒子RT。

《神海4》是通过将蒙皮顶点色作为一个可形变的数据来实现车辆受损时的表现的(即通过调整顶点色来表现受损情况),由于蒙皮变换操作最终会对法线数据进行归一化,因此需要一个额外的浮点数据位用来存储形变的强度。

这里依然借助的是粒子RT来完成这个工作(不是2D的么,怎么表现侧面的形变?)

《神海4》中的Pivot旋转动画还可以用于实现公告板渲染的优化,因为Pivot旋转可以做到绕着任意提前预算好的pivot旋转,而不需要绕着object的根pivot旋转,因此,可以将多个公告板做到 一起,每个公告板对应于一个sub pivot,在渲染的时候可以通过一个dp完成。

另外,《神海4》还实现了一套通用的动作控制管线,美术同学可以对任意的旋转,移动,缩放动作进行组合以实现任意的效果。

比如说前面说到的洗衣机动画的实现过程就是通过这种方式得到的。

而水面上船体的浮动效果就是通过上下的移动加上左右的旋转操作完成的

另外,雨水打在地面上产生的涟漪也是通过这种scale控制显示与消失来实现的,《神海4》这边通过raycast来生成涟漪触发位置的binary matrix数据,之后在渲染的时候读取这个矩阵来产生涟漪,通过这种方式可以控制涟漪产生的位置与密度。

另外,通过VS还可以实现群组的模拟,比如这个视频中的每一只苍蝇都是一个朝向相机的面片(类似于公告板),而这些苍蝇群其实都是一个物体上的顶点(面片?)单元,这些单元根据他们对应的速度调整他们的朝向,从视频可以看到,这些调整都是非常灵活的。

通过顶点shader还可以实现帧动画

这种通过VS实现的帧动画会被用在particle人群(公告板实现的人群)以及远处的particle动物上,此外,这个技术可以通过将法线数据存储到一个单独的关键帧像素中来实现对法线数据的更新操作。

不过这里需要注意,为了避免硬件自动完成的滤波操作,这里需要使用合适的采样指令。

使用关键帧动画还可以节省大量的消耗,比如说上面的这个特效的渲染,在每次特效翻页的时候,都会创建一个关键帧贴图,这个贴图中会带有在每一帧中有效像素的Rect区域,通过这个贴图数据,就可以在渲染的时候对特效进行裁剪,只将那些有效的区域绘制出来,从而降低无效消耗。通过这种方式可以在很小或者基本上没有分辨率损失的情况下降低一半的实现消耗(?一半怎么算出来的)

此外,《神海4》还试验过通过VS来生成assets,这个视频演示的是如果根据玩家的位置到sub-object pivot的距离,为其周边生成对应的植被的效果展示。

性能消耗看起来还好,而且还可以通过将整个过程转移到compute shader中来进一步降低

你可能感兴趣的:(【GDC2016】The Technical Art of Uncharted 4)