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) 产生最终的输出颜色

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采用器如下图所示:

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

2006 - 2024,推荐分辨率 1024*768 以上,推荐浏览器 Chrome、Edge 等现代浏览器,截止 2021 年 12 月 5 日的访问次数:1872 万 9823 站长邮箱

沪 ICP 备 18037240 号-1

沪公网安备 31011002002865 号