几种卡通渲染方法的解析
来源:互联网 发布:淘宝网现在卖多少钱 编辑:程序博客网 时间:2024/05/01 05:49
代码全部出自RenderMonkey的样例文件NPR.rfx,下载地址:
http://developer.amd.com/tools-and-sdks/archive/games-cgi/rendermonkey-toolsuite/
龙书上讲的卡通渲染的方法一直没有看懂,两个faceNormal一直不明白是怎么算出来的 =_=||| ,看了其他DX sample,只看到有计算切法线之类的,也并没有看到能计算“临近边”的法线的。。。而且也想不通如果一个顶点被很多人公用的话怎么想都没法算的啊。。。如果有大神看到我的这段话还望不吝赐教 T_T
以下是对RenderMonkey中所展示的几种卡通渲染的总结:
1. Silhouette
关键:先将所有物体所在的像素置为白色而其他区域置为黑色;再遍历屏幕每一个像素的顶点,亦即遍历上一个pass得到的结果,并据它计算出图像的导数。从而得到轮廓。其求导的方法使用的是Sobel滤波器的方法。
流程
pass0:
使用茶壶模型,
在vs中,(Positon->Position),根据Positon,将顶点位置进行观察变换和投影变换,输出屏幕位置Positon;
在ps中,(Color->Color),将物体所在的位置都为白色;
pass1:
使用一个特殊的网格(ScreenAlignedQuad.3ds),这个网格的顶点坐标的xy分别遍历0到1范围。也因此,在vs中,不对其进行观察变换及投影变换。
在vs中,(Position,TexCoord->Position,TexCoord),根据输入Position的xy,将其转换到0到1之间,作为输出TexCoord;
在ps中,(TexCoord->Color),使用pass0渲染出的结果,通过tex2D对该像素点进行八个采样并分别计算xy方向的导数,如果两个方向的导数平方和大于0.07*0.07那么输出黑色,否则输出白色。
疑问
0.07*0.07不知道是从何得来的。。。
而且这个只能描最外边的轮廓额~
2. ToonWithDynamicSpecular
将物体的diffuse通过一个映射贴图映射到少数几个颜色中。
流程
pass0
在vs中,(Position,Normal->Position,TexCoord),输出Position为输入Position变换后的结果;输出的uv的u为diffuse值,v为0;
在ps中,(TexCoord->Color),使用上述uv对阶梯状的颜色映射纹理采样输出颜色。
3. ToonWithSilhouetteRendering
将 ToonWithDynamicSpecular 和 Silhouette 结合起来。
流程
pass0
与 ToonWithDynamicSpecular 一致;
多加了一步:其w分量置为1.0,相当于 Silhouette 中的 pass0,从而为下一步节省了一个pass。
pass1
与Silhouette的pass1一致。
pass2
将上两个pass所得的结果,比较如果有 Silhouette 的值的话,就置为0.0(黑线),否则使用 ToonWithDynamicSpecular 的结果。
疑问
明明与Silhouette是一样的流程,为什么这个的锯齿这么严重?放大时尤其明显。。
貌似不是纹理采样时的走样造成的。。。把mipmap开大之后确实好了一些,但是还是远远不及Silhouette。。
纹理反走样前:纹理反走样后:Silhouette:
赶脚就像,Silhouette的pass0是根据分辨率调整的一样。。。
4. Hatch
使用密度逐渐增大的几张铅笔纹理(本例是6张),依据Diffuse值来决定每张纹理的比重,最终生成这种铅笔画风格。
流程
pass0
关键在如何对diffuse进行映射,来得到每张纹理的比重。
首先使用 f(x)=x^4 * 6 这个变换,将diffuse变换到[0.0, 6.0]范围内;
在[0.0,6.0]的范围内,6个整数处分别代表渐进的6张纹理,将新的diffuse值,看做是对离散的整数节点,进行的三角形插值。亦即实际上所采用的纹理只有至多2个。
疑问
在uv突变的地方(例如壶嘴和壶身的连接处),会显得露馅儿。
5. HatchWithSilhouetteRendering
又是组合大法2333
6. MetallicCartoon
金属色的卡通。。。好奇怪的画风 0 0 它的关键在于,对diffuse值映射到一个特殊的轮廓贴图中。
流程
pass0
计算diffuse,然后将其映射到一个轮廓贴图中。(本例使用了3个光源)
轮廓贴图左白右黑,只在中间有一个陡峭渐变。
7. DilateErode
直译是……扩大……腐蚀?总之就是,先把模型晕开一圈,再缩小一圈,最后将两个渲染结果相减。
流程
pass0
同Silhouette,不过多加了一步,不明白是为啥。。。
float pixelSize: register(c0);
Out.texCoord.x = 0.5 * (1 + Pos.x + pixelSize);
Out.texCoord.y = 0.5 * (1 - Pos.y + pixelSize);
pass1
使用遍历屏幕的那个模型ScreenAlignedQuad.3ds;
对当前像素及其附近的8个点,映射到pass0生成的纹理中,取所有值中最大值;算是放大了一圈;
pass2
使用遍历屏幕的那个模型ScreenAlignedQuad.3ds;
对当前像素及其附近的8个点,映射到pass0生成的纹理中,取所有值中的最小值;算是缩小了一圈;
然后!!重点来了!!!
这一步打开了Alpha混合,将混合操作符变为 rev_substract,将src和dest的混合系数都变为1,亦即,这一步实际上执行的是,源像素值-目标像素值;
亦即,pass1中放大的那一圈和pass2中缩小的那一圈之差。
疑问
不太懂为什么在vs做了一个这个。。。
float pixelSize: register(c0);
Out.texCoord.x = 0.5 * (1 + Pos.x + pixelSize);
Out.texCoord.y = 0.5 * (1 - Pos.y + pixelSize);
8. WhiteBoard
看上去和上边那个很像但是非常不同,因为这个终于不再是只能描边最外侧轮廓了!这是一个使用depth来进行Sobel滤波,来确定边缘的方案。
流程
pass0
将模型的点变换到投影空间,然后输出其z值到每个颜色通道;
pass1
使用Sobel滤波,导数平方大于0.07*0.07的点为1其他为0;
pass2
这一步进行一个简单的反走样,具体而言,先定义一个12个点的固定的sample pattern,然后对其平均。
9. ShowerDoor
浴室门23333。总体而言就是正常的渲染,然后在最后一步,使用噪声贴图来增加一个扰动,然后用扰动后的结果重新采样。
流程
pass0
使用3d纹理渲染环境背景
Out.Pos = mul(view_proj_matrix, float4(In.Pos.xyz + view_position, 1));
Out.TexCoord = In.Pos.xyz;
pass1
将整个大象渲染为红色
pass2
遍历屏幕上的每一个点,对输入值使用噪声纹理进行映射,增加一个扰动;
使用扰动后的值来对上边得到的结果进行采样。
9. Silhouette With Normal
使用normal值来进行Sobel滤波找边缘。比上边那个用depth值来查找边缘,要更加……锋利一点的样子?
流程
pass0
计算深度、法线;
茶壶像素全都输出红色;
pass1
计算深度、法线;
把法线变换到0到1上,获得法线的xy值的一个纹理;
pass2
使用Sobel计算pass0所得的图的轮廓;
pass3
将四周的8个像素的法线值,分别于当前像素的法线值进行点乘,减去一个阈值后钳位到大于0,作为该点的“值”;
将上述值求导,取其平方和大于 0.07 * 0.07 的点。
疑问
不太清楚上述阈值是怎么设定的。。以及为什么又出现了 0.07*0.07?
完。
是时候去补充shader的理论知识了~
- 几种卡通渲染方法的解析
- 卡通渲染的另类勾边方法
- 卡通渲染的另类勾边方法 (续)
- 一种简单实现卡通勾边渲染的方法
- 卡通渲染的一点心得
- 关于卡通渲染的一些思考
- 在DirectX9.0中渲染文字的几种方法
- AE中栅格数据的几种渲染方法
- 几首喜欢的卡通歌曲
- 卡通渲染最新进展汇报
- ShaderSimpler(3) : 卡通渲染
- 卡通渲染效果脚本
- NPR-卡通渲染
- 【NPR】卡通渲染
- 卡通渲染简报
- 日式卡通渲染的效果的unity实现
- Vertex Shader 支持的卡通描边渲染
- 卡通渲染的3D电影《苹果核战记》
- 关于log4j2在windows和ubuntu上的部分使用经验
- MySQL数据库的增删改查
- VC----小结
- 动态规划----硬币问题
- C语言atof()函数:将字符串转换为double(双精度浮点数)
- 几种卡通渲染方法的解析
- Hive 点滴
- google最新开源的tensorFlow
- POJ 3268 Silver Cow Party
- 不容错过的华为5G十二大DEMO
- 李开复给大学生的第4封信:大学四年应是这样度过
- 数据结构实验之排序五:归并求逆序数(归并排序)
- HDU 1780 Fibonacci String
- JavaScript数组合并几种方法