Unity制作二次元卡通渲染角色材质

您所在的位置:网站首页 3D怎么换材质 Unity制作二次元卡通渲染角色材质

Unity制作二次元卡通渲染角色材质

2023-06-06 13:39| 来源: 网络整理| 查看: 265

Unity制作二次元材质角色

回到目录

大家好,我是阿赵。 这里继续来讲二次元角色的材质。上次讲了光影的色阶化问题,这次继续讲光照模型效果的问题。 之前我们说过,光照模型的最后效果是: 环境色+漫反射+高光+反射。 这里我们可以先忽略环境光,然后之前做了漫反射,用的是HalfLambert,剩下的就是高光和反射了

一、高光

继续套用之前学过的高光光照模型,习惯上是使用BlinnPhong。

//获取BlinnPhong高光 float GetBlinnPhongSpec(float3 worldPos, float3 worldNormal) { float3 viewDir = normalize(UnityWorldSpaceViewDir(worldPos)); float3 halfDir = normalize((viewDir + _WorldSpaceLightPos0.xyz)); float specDir = max(dot(normalize(worldNormal), halfDir), 0); float specVal = pow(specDir, _shininess); return specVal; } half4 frag (v2f i) : SV_Target { half4 col = tex2D(_BaseMap, i.uv); half4 sssCol = tex2D(_SSSMap, i.uv); //色阶化 half halfLambert = GetHalfLambertDiffuse(i.worldPos, i.worldNormal); half toonVal = smoothstep(_GradationMin, _GradationMax, halfLambert); //高光 half specVal = GetBlinnPhongSpec(i.worldPos, i.worldNormal); half3 finalRGB = col.rgb*toonVal + sssCol * (1 - toonVal) + _specColor * specVal; half alpha = col.a; return half4(finalRGB,alpha); }

在这里插入图片描述

加上高光之后,模型就变成这样了,高光有点强过头了。先不管,把效果都加上,最后再调。

二、反射

熟悉我的朋友都知道了,加反射效果,阿赵一般是推荐Matcap的,特别是这种不需要真反射,只是要一点环境假反射的情况。 于是又找到Matcap的代码,加上去。

float2 GetMatCapUV(float3 normalWorld) { float3 normalView = mul(UNITY_MATRIX_IT_MV, normalWorld); return normalView.xy*0.5 + 0.5; } half4 frag (v2f i) : SV_Target { // sample the texture half4 col = tex2D(_BaseMap, i.uv); half4 sssCol = tex2D(_SSSMap, i.uv); //色阶化 half halfLambert = GetHalfLambertDiffuse(i.worldPos, i.worldNormal); half toonVal = smoothstep(_GradationMin, _GradationMax, halfLambert); //高光 half specVal = GetBlinnPhongSpec(i.worldPos, i.worldNormal); //matcap float2 MatCapUV = GetMatCapUV(i.worldNormal)*_MatCapUVScale; float4 MatCapCol = tex2D(_MatCapTex, MatCapUV)*_MatCapIntensity; MatCapCol = pow(MatCapCol, _MatCapPow); half3 finalRGB = col.rgb*toonVal + sssCol * (1 - toonVal)+_specColor* specVal; finalRGB = finalRGB * MatCapCol.rgb; half alpha = col.a; return half4(finalRGB,alpha); }

在这里插入图片描述

这个效果,已经加上了BlinnPhong高光、Matcap反射。但明显效果是不对的,角色像一个少林寺十八铜人似的。

三、ILM贴图

上面把高光和反射加上去之后,发现效果不对。那么需要怎样去修正呢? 我们可以分析一下,效果不对的原因是什么: 1、某些部位的反射强度不对,比如皮肤,不应该反射这么强烈 2、高光的范围不对,有些部位的高光范围应该被控制在一个局部 3、反射的范围不对,反射不应该所有地方都一样的强度,应该根据实际的材质来显示,比如皮肤是不会反射的,皮衣可能有一点,吉他的金属漆部分应该有比较强的反射。 那么,我们应该怎样去控制这些强度和范围呢?这里我们需要回顾一下,之前分析资源时,得到的ILM贴图的实际情况: 由于已经知道ILM贴图的A通道是内描线,所以这里先忽略,只看RGB三个通道: 首先是R通道: 在这里插入图片描述

然后是G通道: 在这里插入图片描述

然后是B通道: 在这里插入图片描述

这里可以猜测一下,三个通道的作用了。 比较明显的是R通道,他明显是控制高光强弱的。 G通道的作用不是很明显,只有脸部和身上某些部位是比较白,其他的颜色都一样。这样应该是控制影子强度的, B通道只有某些局部亮起来,大部分都是黑的,可以理解成,是用来控制高光和反射的形状范围的。 于是我们可以把ILM贴图对应的通道的值,加在之前的高光和反射上面。 首先来看高光部分:

half4 frag (v2f i) : SV_Target { // sample the texture half4 col = tex2D(_BaseMap, i.uv); half4 sssCol = tex2D(_SSSMap, i.uv); half4 ilmCol = tex2D(_ILMMap, i.uv); //色阶化 half halfLambert = GetHalfLambertDiffuse(i.worldPos, i.worldNormal); half toonVal = smoothstep(_GradationMin, _GradationMax, halfLambert); //高光 half specVal = GetBlinnPhongSpec(i.worldPos, i.worldNormal); half3 finalRGB = col.rgb*toonVal + sssCol * (1 - toonVal)+_specColor* specVal*ilmCol.r+ _specColor * specVal*ilmCol.b*_SpecAdd; half alpha = col.a; return half4(finalRGB,alpha); }

使用ILM贴图的R通道控制高光强度,本来ILM贴图的B通道是控制形状的,我这里修改了一下用法,变成了在R通道控制完强度之后,使用B通道把某些区域的高光加强一下,比如胸部的光点,衣服上的金属边的高光点等。于是就得到了这样的效果: 在这里插入图片描述

再来看Matcap部分,直接用B通道控制范围,为了看得更清楚一些,所以暂时把高光去掉:

half4 frag (v2f i) : SV_Target { // sample the texture half4 col = tex2D(_BaseMap, i.uv); half4 sssCol = tex2D(_SSSMap, i.uv); half4 ilmCol = tex2D(_ILMMap, i.uv); //色阶化 half halfLambert = GetHalfLambertDiffuse(i.worldPos, i.worldNormal); half toonVal = smoothstep(_GradationMin, _GradationMax, halfLambert); float2 MatCapUV = GetMatCapUV(i.worldNormal)*_MatCapUVScale; float4 MatCapCol = tex2D(_MatCapTex, MatCapUV)*_MatCapIntensity; MatCapCol = pow(MatCapCol, _MatCapPow); half3 finalRGB = col.rgb*toonVal + sssCol * (1 - toonVal); finalRGB = finalRGB * (1-ilmCol.b) +MatCapCol.rgb*ilmCol.b; half alpha = col.a; return half4(finalRGB,alpha); }

在这里插入图片描述

这时候可以看到,之前十八铜人一般的全身反射已经没有了,变成了只有指定的部位出现了反射效果。 最后,把ILM对高光和反射的影响一起加上,就得到了:

在这里插入图片描述

四、完整Shader Shader "azhao/ToonBodyLight" { Properties { _BaseMap ("BaseMap", 2D) = "white" {} _SSSMap("SSSMap", 2D) = "white" {} _ILMMap("ILMMap", 2D) = "white" {} _specColor("specColor",Color) = (1,1,1,1) _shininess("shininess", Range(1 , 100)) = 1 _SpecAdd("SpecAdd",float) = 1.0 _GradationMin("GradationMin",Range(0.0,1.0)) = 0.0 _GradationMax("GradationMax",Range(0.0,1.0)) = 1.0 _MatCapTex("MatCapTex", 2D) = "white" {} _MatCapIntensity("MatCapIntensity",Range(0,2)) = 1 _MatCapPow("MatCapPow",Range(0,5)) = 1 _MatCapUVScale("MatCapUVScale",Range(0,1)) = 1 } SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" #pragma multi_compile_fwdbase #include "AutoLight.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; float2 uv2 : TEXCOORD1; float3 normal:NORMAL; }; struct v2f { float4 pos : SV_POSITION; float2 uv : TEXCOORD0; float2 uv2 : TEXCOORD1; float3 worldPos :TEXCOORD2; float3 worldNormal :TEXCOORD3; }; sampler2D _BaseMap; float4 _BaseMap_ST; sampler2D _SSSMap; sampler2D _ILMMap; float4 _specColor; float _shininess; float _SpecAdd; float _GradationMin; float _GradationMax; sampler2D _MatCapTex; float _MatCapIntensity; float _MatCapPow; float _MatCapUVScale; //获取HalfLambert漫反射值 float GetHalfLambertDiffuse(float3 worldPos, float3 worldNormal) { float3 lightDir = UnityWorldSpaceLightDir(worldPos); float NDotL = saturate(dot(worldNormal, lightDir)); float halfVal = NDotL * 0.5 + 0.5; return halfVal; } //获取BlinnPhong高光 float GetBlinnPhongSpec(float3 worldPos, float3 worldNormal) { float3 viewDir = normalize(UnityWorldSpaceViewDir(worldPos)); float3 halfDir = normalize((viewDir + _WorldSpaceLightPos0.xyz)); float specDir = max(dot(normalize(worldNormal), halfDir), 0); float specVal = pow(specDir, _shininess); return specVal; } float2 GetMatCapUV(float3 normalWorld) { float3 normalView = mul(UNITY_MATRIX_IT_MV, normalWorld); return normalView.xy*0.5 + 0.5; } v2f vert (appdata v) { v2f o; o.pos = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _BaseMap); o.uv2 = TRANSFORM_TEX(v.uv2, _BaseMap); o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz; o.worldNormal = UnityObjectToWorldNormal(v.normal); return o; } half4 frag (v2f i) : SV_Target { // sample the texture half4 col = tex2D(_BaseMap, i.uv); half4 sssCol = tex2D(_SSSMap, i.uv); half4 ilmCol = tex2D(_ILMMap, i.uv); //色阶化 half halfLambert = GetHalfLambertDiffuse(i.worldPos, i.worldNormal); half toonVal = smoothstep(_GradationMin, _GradationMax, halfLambert); //高光 half specVal = GetBlinnPhongSpec(i.worldPos, i.worldNormal); //matcap float2 MatCapUV = GetMatCapUV(i.worldNormal)*_MatCapUVScale; float4 MatCapCol = tex2D(_MatCapTex, MatCapUV)*_MatCapIntensity; MatCapCol = pow(MatCapCol, _MatCapPow); half3 finalRGB = col.rgb*toonVal + sssCol * (1 - toonVal)+_specColor* specVal*ilmCol.r+ _specColor * specVal*ilmCol.b*_SpecAdd; finalRGB = finalRGB * (1-ilmCol.b) +MatCapCol.rgb*ilmCol.b; half alpha = col.a; return half4(finalRGB,alpha); } ENDCG } } }


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3