作为第二个顶点着色器的例子,让我们编写两个顶点着色器,它们以卡通风格的绘画方式对网格着色(shade)和轮廓勾勒(outline)。图17.2展示了这一点:



注意:卡通渲染是一种特定类型的非写实渲染(non-photorealistic rendering),有时被称作风格化渲染(stylistic rendering)。
虽然卡通渲染不适用于所有游戏,例如激烈的第一人称射击游戏,但是它仍然可以增强一些希望表现卡通感觉类型游戏的气氛。此外,卡通渲染是漂亮的,并易于实现。让我们好好的演示一个顶点着色器。
我们将卡通渲染分为两步:
1. 卡通绘画的特点是:在一个顶点到下一个顶点的强烈转换时,有少量的阴影强度级别;我们看一下这个卡通阴影(cartoon shading)。在图17.2(a)中,我们看到网络着色使用了三种阴影强度(亮、中、暗),而且其间的过渡是不平滑的——不像图17.2(c),其明暗过渡是平滑的。
2. 卡通绘图的主要特点是:在其外框上勾画轮廓,如图17.2(b)所示。
这两个步骤都需要其各自的顶点着色器。
17.5.1 卡通着色
要实现卡通着色,我们采用Lander在2000年3月发表在Game Developer Magazine的文章“Shades of Disney: Opaquing a 3D World”中所描述的方法。我们创建一个带强度级别的灰度纹理,它包含我们需要的不同的着色强度。图17.3显示了我们在样例程序中使用的这个纹理。

然后在顶点着色器中,我们执行标准漫反射光运算(standard diffuse calculation dot product)来确定顶点法线N和光线向量L之间角度的余弦,用以确定顶点接收到多少光线:s=L·N
如果s<0,就表示光线向量和顶点法线之间的角度大于90度,即该表面接收不到光线。因此,如果s<0,我们就让s=0。所以s∈ [0, 1]。
现在,在通常的散射光照模型中,我们使用s来标记颜色向量。这样,顶点颜色的明暗取决于接收到的光照的数量:diffuseColor = s(r, g, b, a)
但是,这将会导致从亮到暗之间平滑的着色。这是与我们期望的卡通着色相反的。我们想要一种在几个不同着色器间突然转换颜色的效果(对卡通渲染来说,在2至4种着色器工作起来还是挺不错的)。
不使用s来标记颜色向量,我们将使用s作为早先提到的强度纹理的u纹理坐标——如图17.3。
注意:标量(scalar)s必定是一个有效的纹理坐标,因为s∈ [0, 1],这是通常的纹理坐标区间。
按这种方式,顶点不会被平滑着色,而是间断的。例如,强度纹理可能被分成3种着色,如图17.4所示:

由图17.4可以看出:若s∈ [0, 0.33]则使用shader0着色,s∈ [ 0.33,0.66]则使用shader1着色,s∈ [0.66,1]则使用shader2着色。当然,从这些着色的一种到另一种的过渡是不平滑的,这就赋予了我们期望的效果。
注意:我们还为卡通着色关闭了纹理过滤,因为这种过滤会试图使着色过渡变平滑。这对于我们要求的不连续过渡是多余的。