【TA】Unity角色二次元风格渲染

NRMToonLitSample


Author: 文若
Demo地址:我的GitHub(欢迎Start) NRMToonLitSample
学习视频教程Kerry大佬的 技术美术实战培训课程—卡通人物渲染方案


文章目录

  • NRMToonLitSample
    • 1. 模型贴图基本信息
      • 1.1 亮度
      • 1.2 阴影
      • 1.3 LightMap
      • 1.4 DetailMap
      • 1.5 顶点色
    • 2. 基础渲染效果
      • 2.1 基础shader Toon
      • 2.2 光照模型效果
        • 第一步:光照色阶
        • 第二步:增加ILM贴图
        • 第三步:顶点信息
      • 2.3 当前渲染效果展示
    • 3. 卡通高光
      • 3.1 增加高光效果
      • 3.2 高光颜色优化
    • 4. 角色描边
      • TODO

NRM由四张图构成角色渲染,亮部贴图,阴影贴图图,ilm贴图和细节贴图。

1. 模型贴图基本信息

原始模型
【TA】Unity角色二次元风格渲染_第1张图片

1.1 亮度

亮部贴图RGBA
【TA】Unity角色二次元风格渲染_第2张图片
亮部贴图Alpha
用于区分人物的皮肤区域以及非皮肤区域。
【TA】Unity角色二次元风格渲染_第3张图片

1.2 阴影

暗部颜色RGBA
【TA】Unity角色二次元风格渲染_第4张图片
暗部贴图Alpha
用于做某些mask使用。
【TA】Unity角色二次元风格渲染_第5张图片

1.3 LightMap

R通道
控制高光强度
【TA】Unity角色二次元风格渲染_第6张图片
G通道
偏移光照,越黑部分越接近阴影,越白部分越接近亮部。128中度灰不会对原来光线进行偏移。
【TA】Unity角色二次元风格渲染_第7张图片
B通道
控制高光范围大小(光滑度)越黑部分高光越小,纯黑区域五高光。
【TA】Unity角色二次元风格渲染_第8张图片
Alpha通道
一张描线图,记录描线,内描线。
【TA】Unity角色二次元风格渲染_第9张图片

1.4 DetailMap

Detail的RGBA
使用第二套UV采样,也是描线图。但UV分部并不严格。按照第二套UV做点缀使用。
【TA】Unity角色二次元风格渲染_第10张图片

1.5 顶点色

顶点色R通道
遮挡部分颜色较黑,代表环境光的遮挡。剩余通道控制描边的粗细,深度偏移等信息。
【TA】Unity角色二次元风格渲染_第11张图片

2. 基础渲染效果

2.1 基础shader Toon

Shader "Toon"
{
    Properties
    {
        _BaseMap ("Base Map", 2D) = "white" {}
        _SSSMap ("SSS Map", 2D) = "black" {}
    }
    SubShader
    {
        Tags
        {
            "RenderType"="Opaque"
        }
        LOD 100

        Pass
        {
            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;

【TA】Unity角色二次元风格渲染_第12张图片

第一步:光照色阶

模型色阶

half toon_diffuse = step(0.0, NdotL); // 色阶化


图形色阶化
加入阈值范围和硬度

_ToonThreshold ("ToonThreshold", Range(0,1)) = 0.6 // 阈值范围
_ToonHardness ("ToonHardness",Float) = 50.0 // 过渡的生硬情况
half4 base_map = tex2D(_BaseMap, uv1);
half3 base_color = base_map.rgb;
half NdotL = dot(normalDir, lightDir); // 结果在(-1~1)
half half_lambert = (NdotL + 1.0) * 0.5; // 缩放到0-1之间
// 偏移光照位置
half toon_diffuse = saturate((half_lambert - _ToonThreshold) * _ToonHardness);
// 颜色*base图片的灰度值
half3 final_diffuse = toon_diffuse * base_color;
return float4(final_diffuse, 1.0);

【TA】Unity角色二次元风格渲染_第13张图片
提高阴影面的亮度
1.第一种方法,原有亮度的0.5倍

toon_diffuse = saturate(toon_diffuse + 0.5); // 提亮光照

【TA】Unity角色二次元风格渲染_第14张图片
2.采用阴影面贴图,拿到阴影面rgb和toondiffuse做插值计算

half4 sss_map = tex2D(_SSSMap, uv1);
half3 sss_color = sss_map.rgb;
half NdotL = dot(normalDir, lightDir); 
half half_lambert = (NdotL + 1.0) * 0.5; 
half toon_diffuse = saturate((half_lambert - _ToonThreshold) * _ToonHardness);
half3 final_diffuse = lerp(sss_color, base_color, toon_diffuse);

【TA】Unity角色二次元风格渲染_第15张图片

第二步:增加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; // 用来控制内描线

当前头发没有任何阴影,需要为头发末端添加光照阴影。
【TA】Unity角色二次元风格渲染_第16张图片
光照贴图的g通道,提前预设阴影区域,给角色头发做光照偏移的效果。这是一张灰度图,以0.5为分界线,灰度值高于128(0.5)的部分提前变亮,等于128的部分不会对光照进行偏移,低于128的部分变暗。

使用光照贴图优化

half lambert_term = half_lambert + diffuse_control; // 做一个偏移控制
half toon_diffuse = saturate((lambert_term - _ToonThreshold) * _ToonHardness);

【TA】Unity角色二次元风格渲染_第17张图片

第三步:顶点信息

当前效果中裙子内部应该是暗面,利用ao信息来渲染。

float4 vertex_color : TEXCOORD3;
o.vertex_color = v.color;
float ao = i.vertex_color.r;
half lambert_term = half_lambert * ao + diffuse_control;

【TA】Unity角色二次元风格渲染_第18张图片

2.3 当前渲染效果展示

3. 卡通高光

3.1 增加高光效果

一个完整的效果应该有漫反射和高光反射,上一节完成了漫反射效果。圈中的金属质感部分需要进行高光处理
【TA】Unity角色二次元风格渲染_第19张图片
ILM图的B通道控制高光形状的大小,高光部分越黑越光滑,形状也越小。
【TA】Unity角色二次元风格渲染_第20张图片
使用NotV进行计算,并且为这个值加上偏移结果

// 视觉方向
float3 viewDir = normalize(_WorldSpaceCameraPos - i.pos_world.xyz); 
// 高光处理
float NdotV = (dot(normalDir, viewDir) + 1.0) * 0.5; //拿到NdotV并进行数值范围缩放
float spec_trem = NdotV * ao + diffuse_control; // 光线偏移

【TA】Unity角色二次元风格渲染_第21张图片
增加高光系数

_SpecSize ("Spec Size",Range(0,1)) = 0.1 // 高光系数
// 高光处理 拿到NdotV并进行数值范围缩放
float NdotV = (dot(normalDir, viewDir) + 1.0) * 0.5;
float spec_trem = NdotV * ao + diffuse_control; // 光线偏移
// 当前高光是基于视角的高光 真正高光收到光照方向的影响
spec_trem = half_lambert * 0.9 + spec_trem * 0.1; // 高光权重分配
// 限制边缘
half toon_spec = saturate((spec_trem - (1.0 - spec_size * _SpecSize)) * 500); // 内部数值越大越光滑


对高光和Base颜色进行叠加,金属部分光线对比之前漫反射渲染效果有了明显变化。

half3 final_spec = toon_spec * base_color * spec_intensity;
half3 final_color = final_diffuse + final_spec;
return float4(final_color, 1.0);

3.2 高光颜色优化

对高光颜色优化,增加可自定义的高光颜色。

// 自定义的高光颜色与原来的颜色进行混合
half spec_color = (_SpecColor.xyz + base_color) * 0.5;
half3 final_spec = toon_spec * spec_color * spec_intensity;

【TA】Unity角色二次元风格渲染_第22张图片

4. 角色描边

TODO

你可能感兴趣的:(我做游研这件事,Shader,渲染,二次元,技术美术,角色)