求知若饥,虚心若愚
尽管游戏渲染一般都是以照相写实主义(photorealism) 作为主要目标,但也有许多游戏使用了非真实感渲染(Non-Photorealistic Rendering, NPR) 的方法来渲染游戏画面。非真实感渲染的一个主要目标是,使用一些渲染方法使得画面达到和某些特殊的绘画风格相似的效果,例如卡通、水彩风格等。
卡通风格的渲染
使用这种风格的游戏画面通常有一些共有的特点,例如物体被黑色的线条描边,分明的明暗变化等。
实现卡通渲染的方法之一是基于色调的着色技术(tone-based shading)
- 使用漫反射系数对一维纹理采样,来控制漫反射的色调
- 高光往往是一块块分界明显的纯色区域
- 通常要在物体边缘部分绘制轮廓(这里使用基于模型的描边而不是后处理,这种更加简单,效果还不错)
游戏《大神》(英文名:Okami)的游戏截图
渲染轮廓线
近20年,有许多绘制模型轮廓线的方法被先后提出来,在《Real Time Rendering, third edition》一书中,作者把这些方法分成了5种类型:
- 基于观察角度和表面法线的轮廓线渲染,使用视角方向和表面法线的点乘结果来得到轮廓线的信息。简单快速,效果不好,只需要一个Pass。
- 过程式几何轮廓线渲染:使用两个Pass渲染,先渲染背面的面片使轮廓可见,再正常渲染正面的面片。快速有效,适合绝大多数表面光滑的模型,不适合类似立方体这样平整的模型
- 基于图像处理的轮廓线渲染:12、13章介绍的边缘检测方法。适用于任何种类的模型,但一些深度和法线变化很小的无法检测,如桌子上的纸张
- 基于轮廓边检测的轮廓线渲染:前面的方法无法控制轮廓线的渲染风格,这种可以检测出精准的轮廓边,然后直接渲染它们。判断相邻两个三角面片,是否一个朝正面一个朝背面,判断是否满足(n0·v>0)≠(n1·v>0),通过几何着色器帮助下完成。缺点是实现相对复杂,而且还有动画连贯性问题,因为是逐帧单独提取,所以帧与帧之间会出现跳跃
- 混合上述几种渲染方法:例如先找到精确的轮廓边,把模型和轮廓边渲染到纹理中,再用图像处理的方法识别出轮廓线,并在图像空间下进行风格化渲染
这里使用过程式几何轮廓线渲染的方法。在第一个Pass中,使用轮廓线颜色渲染整个背面面片,在视角空间下把模型顶点沿着法线方向向外扩展一段距离,让背部轮廓线可见:
1 | viewPos = viewPos + viewNormal * _Outline; |
为了防止内凹模型发生背面面片遮挡正面的情况,扩张之前要对顶点法线的z分量进行处理使它们等于定值,然后法线归一化再扩张顶点。这样的好处是扩张后的背面更加扁平化,降低了遮挡正面的可能性:
1 | viewNormal.z = -0.5; |
添加高光
卡通高光反射光照模型和Blinn-Phong模型类似,同样要计算normal和halfDir的点乘结果,然后和一个阈值进行比较。使用step函数进行比较,第一个参数是参考值,第二个是带比较的数值,如果后者大于前者,就返回1,否则0:
1 | float spec = dot(worldNormal, worldHalfDir); |
但这种方法会在边界造成锯齿,这是因为高光区域的边缘不是平滑渐变的,而是0突变到1。所以需要进行抗锯齿处理,可以在边界处很小的一块区域进行平滑处理。使用了CG的smoothstep函数,w是一个很小的值,当spec-threshold小于-w时返回0,大于w时返回1,否则在0到1之间进行差值。w的值可以通过CG的fwidth函数得到领域像素之间的近似导数值:
1 | float spec = dot(worldNormal, worldHalfDir); |
左图:未对高光区域进行抗锯齿处理。右图:使用fwidth函数对高光区域进行抗锯齿处理
实现
1 | Shader "Unity Shaders Learn/Chapter14/Toon Shading" |
卡通风格的渲染效果
素描风格的渲染
微软研究院的Praun等人在2001年的SIGGRAPH上发表了论文,使用提前生成的素描纹理来实现实时的素描风格渲染,这些纹理组成了一个色调艺术映射(Tonal Art Map, TAM) ,如下图从左到右笔触逐渐增多,用于模拟不同光照下的漫反射效果。下图从上到下对应每张纹理的多级渐远纹理(mipmaps),这些多级渐远纹理的生成并不是简单的对上一层纹理进行降采样,而是需要保持笔触之间的间隔,以便更真实的模拟素描效果:
一个TAM的例子(来源:Praun E, et al. Real-time hatching4)
这里使用简化版,不考虑mipmaps的生成,直接使用6张素描纹理进行渲染。在顶点着色器计算逐顶点的光照,根据光照结果决定6张纹理的混合权重,并传给片元着色器。在片元着色器中根据这些权重来混合6张纹理的采样结果。
1 | Shader "Unity Shaders Learn/Chapter14/Hatching" |
素描风格的渲染效果
扩展阅读
- 国际讨论会NPAR(Non-Photorealistic Animation and Rendering)上有许多关于非真实感渲染的论文
- 浙江大学耿卫东《艺术化绘制的图形学原理与方法》(英文名:The Algorithms and Principles of Non-photorealistic Graphics)
- Unity资源商店一个免费的卡通资源包,实现了包括轮廓线渲染等卡通风格的渲染,ToonShaderFree:https://assetstore.unity.com/packages/vfx/shaders/toon-shader-free-21288
- Unity资源商店一个收费的卡通资源包,包含了更多的卡通风格UnityShader,ToonStylesShaderPack
- 收费资源包,铅笔渲染、蜡笔渲染等多种手绘风格的NPR效果,HandDrawnShaderPack:https://assetstore.unity.com/packages/vfx/shaders/hand-drawn-shader-pack-12465