近期热门
粉丝2694
关注 3
获赞 10662
基于unity2018的NPR Toon Shading的一般实现(转)

[U3D] 基于unity2018的NPR Toon Shading的一般实现(转)

 !heats_icon! [复制链接]
3590 1 1 5 5年前 举报



上一期在介绍fur shader之后,一些朋友问如何实现卡通渲染效果。之后打算利用unity简单的介绍一下实现方法,当然这里这是把最核心的视觉效果写出,在明白基本原理后,可以自主的写一些小效果加进去来增强画面表现。

二次元渲染效果,实际上说的是Toon shading。Toon shading在一些Celluloid(赛璐珞)风格游戏中经常被用到,比如游戏行尸走肉、国产游戏崩坏3、凯瑟琳、女神异闻录(日本游戏居多)等等,这种渲染方式接近二次元卡通效果同时十分的Cheap,手机神马的扛得住,而且简化了模型制作流程,游戏趋向轻量级,所以逐渐被应用推广。
1.jpg
2.jpg
3.jpg
4.jpg

Toon shading实际上是一种Non-photorealistic Rendering(非真实性渲染)技术。下面两图,右边的是 Standard Shader下的效果,左边则是toon Shader 的效果。
5.jpg

获得Celluloid效果,用surface function也是可以的,但是开销会很大,surface function只作用于材质的属性,而不是实际光照。 Toon shading要求在应用时可改变光线的反射,所以我们需要创建一个光照模型来达到渲染目的。

一般来说,实现Toon shading需要一张特殊的贴图:Ramp map(如下图所示)。
6.jpg

当正常填充材质颜色时,这张图用于指定着色层次。这里面需要注意,当你导入一张自制的ramp map时,需要在Inspector面板中将ramp map的Wrap Mode调整为Clamp,如果你想让颜色间的交界边缘更加锐利,Filter Mode也要相应调整为Point。
7.jpg

之后还是老套路,创建一个球、一个材质、一个shader,用VS打开shader进行编程。之后来简单介绍一下基本实现原理:
1.添加RampTex贴图
_RampTex ("Ramp", 2D) = "white" {}

2.添加其关联变量
sampler2D _RampTex;

3.改变一下#pragma指令
#pragma surface surf Toon

4.将LightingSimpleLambert函数替换掉,加入下列代码
fixed4 LightingToon (SurfaceOutput s, fixed3 lightDir, fixed atten)
{  
//首先计算光线与表面法线的点积
half NdotL = dot(s.Normal, lightDir);  
//NdotL在ramp图上重映射NdotL
NdotL = tex2D(_RampTex, fixed2(NdotL, 0.5));
//之后确定被返回的颜色
half4 color;

color.rgb = s.Albedo * _LightColor0.rgb * (NdotL * atten );  
color.a = s.Alpha;

//返回计算后的颜色
return color;
}

5.保存shader脚本,打开材质球,开始对相应属性进行调试,如下:
8.jpg

6.Toon shading效果会根据环境光照发生改变,这里为了观测方便,在Window | Lighting | Settings目录下将 Environment | Environment Lighting | Intensity Multiplier属性值调整为0.

7.实现原理
Toon shading实现的这种特殊光线效果仅靠Surface很难完美实现,所以我们需要一张 Ramp map,旨在将Lambertian光照强度NdotL重映射为其他数值。利用非渐变的Ramp map,可以将光照强制渲染为具有梯度特点的效果。原理如下图所示:
9.jpg

8.其实可以用很多方法来实现 Toon shading效果。利用不同的ramp可以在你的模型上产生剧烈的梯度变化。还有一种可以替代ramp map的方法是去强制Snap光线强度NdotL,这样梯度变化可以在0到1之间进行采样来控制,代码如下:

half4 LightingCustomLambert (SurfaceOutput s, half3 lightDir,  half3 viewDir, half atten)
{  
half NdotL = dot (s.Normal, lightDir);
half cel = floor(NdotL * _CelShadingLevels) /(_CelShadingLevels - 0.5);
half4 color;
color.rgb = s.Albedo * _LightColor0.rgb * (cel * atten );
color.a = s.Alpha;
return color;
}

实现效果如下:
10.jpg

虚幻或是其他引擎的实现思路基本一致,各位看官可尝试再开一些属性栏或是绘制不同的Ramp进行制作。今天的分享就到这里,掌柜告辞

转自Thepoly

1
点赞
0
打赏
5
添加到收藏夹

0

点击复制链接

使用微信扫码分享
一次扣10个券
全部评论1
您需要登录后才可以回帖 登录

提示: 作者被禁止或删除 内容自动屏蔽
5年前
回复

使用道具 举报

您当前使用的浏览器IE内核版本过低会导致网站显示错误

请使用高速内核浏览器或其他浏览器