Pixel-Perfect Outline Shaders for Unity
请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com
原文地址
How outline shaders work 我第一次在电子游戏中看到3D物体的 轮廓线(outline) 是2003年育碧的《XIII》。这是我听说过的第一个具有 cel-shaded风格的 3D 游戏。(它基于一本图画小说。)
一旦我看到它,我必须知道它是如何完成的。《XIII》是一款使用虚幻2引擎的研发的游戏,我能够打开我信赖的 UnrealEd 并四处看看。
虚幻2引擎使用了固定功能的图形管道,这意味着XIII厚实的 墨水状轮廓(thick, ink-like outlines) 没有涉及着色器魔法。轮廓实际上是每个网格的一部分:外壳,悬停在角色的表面,具有倒置的面法线,因此只有内部可见,覆盖着黑色纹理。
自 2003 年和固定功能的图形管道以来,我们已经取得了长足的进步,但我们处理轮廓的方式几乎没有改变。最大的变化是轮廓不再需要成为网格的一部分;我们可以在单独的通道中使用顶点着色器来渲染网格的略微肥大的版本,并剔除正面(front face culled)。
换句话说,在我们的outline pass中,我们将取顶点的法线,乘以一个小数(我们不想增肥一个完整的单位!)得到一个偏移值,并将在变换顶点到裁剪空间之前,其此偏移值添加到顶点之前的位置。
这正是XIII在 2003 年在没有任何着色器的情况下完成的结果,但现在我们使用GPU自动地执行轮廓线绘制操作,来简化我们的创作工作流程。但我们可以做得更好。
Limitations of the classic technique 对于XIII受图形小说启发的美学而言,这些墨色轮廓恰到好处。但就像任何 15 年前的预着色技术一样,它们也有局限性,这使得它们作为通用轮廓解决方案的用处不大:
根据形状和视角,轮廓在对象表面上的厚度会有所不同。 当物体远离相机时,轮廓会被缩短(使用透视投影时) 轮廓宽度以对象空间单位指定,而不是以像素为单位。 请注意,这些是限制(limition),不一定是问题(problems)。在某些情况下,它们中的一些或全部可能是可取的。但他们每个人都应该在我们的控制之下。
我专注于技术,电脑艺术的。当我们作为艺术家以高水平的技术进行操作时,我们正在对我们制作的艺术——即我们代码的输出——施加精确的控制。
例如,我们可能希望将物体轮廓作为用户界面的一部分,以表明该物体已被选中。我们可能希望这些元素具有稳定的屏幕空间宽度。
或者我们可能正在模仿矢量或像素艺术风格,或者将 3D 网格与矢量或像素艺术精灵混合。我们需要能够以像素为单位匹配我们的轮廓宽度。
在本教程的过程中,我们将探索经典技术,然后对其进行改进,特别关注我们如何变换顶点位置,以更适应我们的需求,并为我们提供对最终外观的更多艺术控制。
Building the classic outline shader 下面是作为现代 Unity 着色器的经典XIII风格轮廓的代码。
Shader "Tutorial/Outline" { Properties { _Color ("Color", Color) = (1, 1, 1, 1) _Glossiness ("Smoothness", Range(0, 1)) = 0.