【TA】Unity角色二次元风格渲染
NRMToonLitSample
Author : 文若
我的Demo地址 : NRMToonLitSample
學習視頻地址 : Kerry大佬的 技術美術實戰(zhàn)培訓課程——卡通人物渲染方案
文章目錄
- NRMToonLitSample
- 1. 模型貼圖基本信息
- 2. 基礎渲染效果
- 2.1 基礎shader Toon
- 2.2 光照模型效果
- 第一步:光照色階
- 第二步:增加ILM貼圖
- 第三步:頂點信息
- 2.3 當前渲染效果展示
- 3. 卡通高光
- 3.1 增加高光效果
- 3.2 高光顏色優(yōu)化
- 4. 描邊
- 4.1 增加描線效果
- 4.2 使用DetailMap
- 4.3 描線融合與增強
- 5. 色彩校正
- 6. 外描邊
- 6.1 輪廓描邊實現(xiàn)
- 6.2 邊緣顏色融合
- 7. 效果展示
NRM由四張圖構成角色渲染,亮部貼圖,陰影貼圖圖,ilm貼圖和細節(jié)貼圖。
1. 模型貼圖基本信息
原始模型
亮部貼圖RGBA
亮部貼圖Alpha
用于區(qū)分人物的皮膚區(qū)域以及非皮膚區(qū)域。
暗部顏色RGBA
暗部貼圖Alpha
用于做某些mask使用。
LightMap R通道
控制高光強度
LightMap G通道
偏移光照,越黑部分越接近陰影,越白部分越接近亮部。128中度灰不會對原來光線進行偏移。
LightMap B通道
控制高光范圍大小(光滑度)越黑部分高光越小,純黑區(qū)域五高光。
LightMap Alpha通道
一張描線圖,記錄描線,內描線。
DetailMap RGBA
使用第二套UV采樣,也是描線圖。但UV分部并不嚴格。按照第二套UV做點綴使用。
頂點色R通道
遮擋部分顏色較黑,代表環(huán)境光的遮擋。剩余通道控制描邊的粗細,深度偏移等信息。
2. 基礎渲染效果
2.1 基礎shader Toon
Shader "Toon" {Properties{_BaseMap ("Base Map", 2D) = "white" {}_SSSMap ("SSS Map", 2D) = "black" {}}SubShader{Tags{"RenderType"="Opaque"}LOD 100Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#pragma multi_compile_fwdbase#include "UnityCG.cginc"#include "AutoLight.cginc"struct appdata{float4 vertex : POSITION;float2 texcoord0 : TEXCOORD0;float2 texcoord1 : TEXCOORD1;float3 normal : NORMAL;float4 color : COLOR;};struct v2f{float4 pos : SV_POSITION;float4 uv : TEXCOORD0;float3 pos_world : TEXCOORD1;float3 normal_world : TEXCOORD2;};sampler2D _BaseMap;sampler2D _SSSMap;v2f vert(appdata v){v2f o;o.pos = UnityObjectToClipPos(v.vertex);o.pos_world = mul(unity_ObjectToWorld, v.vertex).xyz;o.normal_world = UnityObjectToWorldNormal(v.normal);o.uv = float4(v.texcoord0, v.texcoord1);return o;}half4 frag(v2f i) : SV_Target{half2 uv1 = i.uv.xy;half2 uv2 = i.uv.zw;half4 base_map = tex2D(_BaseMap, uv1);half4 sss_map = tex2D(_SSSMap, uv1);return base_map;}ENDCG}} }2.2 光照模型效果
// 單位向量 float3 normalDir = normalize(i.normal_world); // 光照方向 float3 lightDir = normalize(_WorldSpaceLightPos0.xyz); // light half NdotL = dot(normalDir,lightDir); return NdotL.xxxx;第一步:光照色階
模型色階
half toon_diffuse = step(0.0, NdotL); // 色階化
圖形色階化
加入閾值范圍和硬度
提高陰影面的亮度
1.第一種方法,原有亮度的0.5倍
2.采用陰影面貼圖,拿到陰影面rgb和toondiffuse做插值計算
第二步:增加ILM貼圖
// ILM貼圖 half4 ilm_map = tex2D(_ILMMap,uv1); float spec_intensity = ilm_map.r; // 控制高光的強度 float diffuse_control = ilm_map.g * 2.0 - 1.0; // 控制光照偏移,從0-1轉換成-1~1 float spec_size = ilm_map.b; // 控制高光的大小 float inner_line = ilm_map.a; // 用來控制內描線當前頭發(fā)沒有任何陰影,需要為頭發(fā)末端添加光照陰影。
光照貼圖的g通道,提前預設陰影區(qū)域,給角色頭發(fā)做光照偏移的效果。這是一張灰度圖,以0.5為分界線,灰度值高于128(0.5)的部分提前變亮,等于128的部分不會對光照進行偏移,低于128的部分變暗。
使用光照貼圖優(yōu)化
half lambert_term = half_lambert + diffuse_control; // 做一個偏移控制 half toon_diffuse = saturate((lambert_term - _ToonThreshold) * _ToonHardness);第三步:頂點信息
當前效果中裙子內部應該是暗面,利用ao信息來渲染。
float4 vertex_color : TEXCOORD3; o.vertex_color = v.color; float ao = i.vertex_color.r; half lambert_term = half_lambert * ao + diffuse_control;2.3 當前渲染效果展示
3. 卡通高光
3.1 增加高光效果
一個完整的效果應該有漫反射和高光反射,上一節(jié)完成了漫反射效果。圈中的金屬質感部分需要進行高光處理
ILM圖的B通道控制高光形狀的大小,高光部分越黑越光滑,形狀也越小。
使用NotV進行計算,并且為這個值加上偏移結果
增加高光系數(shù)
對高光和Base顏色進行疊加,金屬部分光線對比之前漫反射渲染效果有了明顯變化。
3.2 高光顏色優(yōu)化
對高光顏色優(yōu)化,增加可自定義的高光顏色。
// 自定義的高光顏色與原來的顏色進行混合 half spec_color = (_SpecColor.xyz + base_color) * 0.5; half3 final_spec = toon_spec * spec_color * spec_intensity;4. 描邊
4.1 增加描線效果
光照貼圖的alpha通道用來控制內描線
float inner_line = ilm_map.a;將描線效果疊加到當前顏色上
half3 final_line = inner_line.xxx; // 描線效果 half3 final_color = (final_diffuse + final_spec) * final_line; return float4(final_color, 1.0);4.2 使用DetailMap
detail map 的uv更加隨意,可以勾勒出一些圓滑的斜線等。但是該貼圖非常的大,只有高清二點情況下才能避免模糊。
half3 detail_color = tex2D(_DetailMap, uv2); // 采樣detail map 使用第二套uv half3 final_line = inner_line.xxx * detail_color; half3 final_color = (final_diffuse + final_spec) * final_line; return float4(final_color, 1.0);4.3 描線融合與增強
使用插值將內描線線條增強并與皮膚顏色融合
half3 detail_color = tex2D(_DetailMap, uv2); // 采樣detail map 使用第二套uv detail_color = lerp(base_color * 0.2, float3(1.0, 1.0, 1.0), detail_color); half3 inner_line_color = lerp(base_color * 0.2, float3(1.0, 1.0, 1.0), inner_line); half3 final_line = inner_line_color * inner_line_color * detail_color; half3 final_color = (final_diffuse + final_spec) * final_line; return float4(final_color, 1.0);5. 色彩校正
類Tone Mapping做法,將色彩進行微細的調整,稍微對比度壓暗了一丟丟
final_color = sqrt(max(exp2(log2(max(final_color, 0.0)) * 2.2), 0.0));6. 外描邊
6.1 輪廓描邊實現(xiàn)
外輪廓的描線做法,使用雙通道,在Pass2中拿到角色在對應空間坐標上的頂點,根據(jù)頂點得到法線,在法線上對頂點進行外拓。
_OutlineWidth ("OutLine Width",Range(0,10)) = 5.0 // 外輪廓寬度世界空間坐標下外拓實現(xiàn)
float3 pos_world = mul(unity_ObjectToWorld, v.vertex).xyz; float3 normal_world = UnityObjectToWorldNormal(v.normal); // 頂點外拓 拿到世界坐標 pos_world += normal_world * _OutlineWidth * 0.001; // 拿到vp矩陣 o.pos = mul(UNITY_MATRIX_VP, float4(pos_world, 1.0)); return float4(0, 0, 0, 1.0); // 黑色描邊觀察空間坐標下外拓實現(xiàn)
float3 pos_view = UnityObjectToViewPos(v.vertex); // 觀察空間下的normal方向 float3 normal_world = UnityObjectToWorldNormal(v.normal); float3 outline_dir = mul((float3x3)UNITY_MATRIX_V, normal_world); pos_view += outline_dir * _OutlineWidth * 0.001; o.pos = mul(UNITY_MATRIX_P, float4(pos_view, 1.0));輪廓描邊效果
6.2 邊緣顏色融合
根據(jù)自定義描邊顏色降低對比度,降低飽和度,使得顏色偏暗
_OutlineColor ("Outline Color",Color) = (1,1,1,1) // 輪廓顏色 half4 frag(v2f i) : SV_Target {float3 baseColor = tex2D(_BaseMap, i.uv.xy).xyz;half maxComponent = max(max(baseColor.r, baseColor.g), baseColor.b) - 0.004;half3 saturatedColor = step(maxComponent.rrr, baseColor) * baseColor;saturatedColor = lerp(baseColor.rgb, saturatedColor, 0.6);half3 outlineColor = 0.8 * saturatedColor * baseColor * _OutlineColor.xyz;return float4(outlineColor, 1.0); }7. 效果展示
全身效果
半身效果
總結
以上是生活随笔為你收集整理的【TA】Unity角色二次元风格渲染的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 内篇
- 下一篇: Unity3d下载大型文件并显示进度