XNA Shader编程教程7-卡通渲染
今天,我将讨论一个简单的算法,可以通过使用Cel shading/Toon shading渲染一个非真实感的场景。
要实现这个效果,你需要两个shaders:
(a)Toon shader会根据纹理添加光线,使用的是教程2讨论国的过的漫反射算法。
(b)一个post process edge detection(离屏边缘检测)算法。
首先,我们使用Toon shader将场景渲染到渲染目标(render target),然后将这个纹理在shader(b)中检测边缘,最后将场景和边缘组合起来:
Shader (a) + (b) 产生最终的输出颜色。
Cel/Toon shader
要创建cel/toon shader我们需要计算漫反射光 ( N点乘L )并将它作为纹理的x坐标:
Tex.y = 0.0f; Tex.x = saturate(dot(L, N)); float4 CelColor = tex2D(CelMapSampler, Tex);
而2D纹理(分辨率32x1)的CelMapSampler采用器如下图所示:
如果L和N垂直(点乘=0),那么将使用坐标为(0.0,0.0)的纹理像素。如果N和L平行(点乘=1),那么将使用坐标为(1.0,0.0)的纹理像素,其他像素在0.0~1.0的范围内。如你所见,纹理只有3种不同的颜色。要从pixel shader返回CelColor,output将使用指定纹理作为漫反射shader:
但是我们仍需要纹理,这可以通过在教程2中同样的方法实现,只不过不是用纹理的颜色乘以漫反射颜色,而是用toon-shaded漫反射映射的CelColor乘以纹理颜色:
return (Ai*Ac*Color)+(Color*Di*CelColor);
最终结果如下图所示:
不是很难吧?:)看起来不错,但在某些情况下,我们可能还希望在图像边缘有黑边。要实现这一点:
一个办法是第一次绘制对象的全黑的图像,然后绘制对象的cel-shaded图像,但小一点点;
另一个办法是将场景渲染到一个纹理,然后对这个纹理应用边缘检测shader,这也是本教程的做法。
后屏边缘检测(Post process Edge Detection)
边缘检测shader使用下列矩阵作为核心过滤器:
核心过滤器的工作原理是将该矩阵作用到图像中的每个像素。核心包含乘法因子应用于像素和它的临近像素。当所有的值相乘后,像素就会被替换成乘积的总和。选择不同的核心,可应用不同的过滤。
使用这个shader可以创建一个黑白纹理,其边缘是黑色的,其余是白色的。这使得创建一个具有边缘的普通场景很容易:
Color*result.xxxx;
Color是场景纹理,而result.xxxx是边缘检测纹理。当Color乘以result,不是边缘部分的像素是白色的即1.0,而边缘是黑色的即0.0。将Color乘以1.0颜色不变,而乘以黑色边缘( 0.0 )则变成0.0(黑色)。
如你所见,toon-shaders不难,通过几行代码就能实现。
发布时间:2009/4/7 下午1:40:45 阅读次数:12554