欢迎光临散文网 会员登陆 & 注册

原神卡通渲染shader

2023-07-10 16:40 作者:NEW世界  | 我要投稿

Shader "Unlit/Yuanshen"

{

    Properties

    {

        _BaseMap("BaseMap", 2D) = "white" {}

        _LightMap("Light Map",2D) = "white" {}

        _RampTex("Ramp Tex",2D) = "white" {}

        _MetalMap("Metal Map",2D) = "white"{}

        _SDF("SDF",2D) = "white"{}

        [Header(BaseColor)]

        [Toggle]_Day("Day",int) = 1

        //去控制横向采样的长度与Ramp偏移

        _RampShadowRange("RampShadowRange",Range(0,1)) = 0

        //_RampMapRangStart("RampMapRangStart",float) = 0

        //_RampMapFields("RampMapFields",float) = 0

        _ShadowRampLerp("ShadowRampLerp",Range(0,1)) = 0

        //控制明暗的分布

        _RampAOLerp("RampAOLerp",Range(0,1)) = 0

        _DarkIntensity("暗部亮度 ",Range(0,5)) = 0

        _DarkShadowMultColor("暗部颜色",Color) = (1,1,1,1)

        _ShadowMultColor("亮部颜色",Color) = (1,1,1,1)

        _BrightIntensity("亮部强度",Range(0,5)) = 0

        _CharacterIntensity("整体亮度",Range(0,5)) = 0

        _RampIntensity("Ramp图亮度",Range(0,5)) = 0

        [Header(SpecularColor)]

        [Toggle]_EnableHair("是否为头发",int) = 0

        _SpecularPow("高光幂次数",float) = 5

        _SpecularIntensity("高光强度",float) = 1

        _SpecularExp("Specular Exp",float) = 1

        _StepSpecularWidth("第一层高光范围",Range(0,1)) = 1

        _StepSpecularWidth2("第二层高光范围",Range(0,1)) = 1

        _StepSpecularWidth3("第三层高光范围",Range(0,1)) = 1

        _StepSpecularWidth4("第四层高光范围(头发)",Range(0,1)) = 1

        _StepSpecularIntensity("第一层高光强度",float) = 1

        _StepSpecularIntensity2("第二层高光强度",float) = 1

        _StepSpecularIntensity3("第三层高光强度",float) = 1

        _StepSpecularIntensity4("第四层高光强度(头发)",float) = 1

        _MetalMapV("MetalMapV",Range(0,1)) = 1

        _MetalMapIntensity("MetalMapIntensity",float) = 1

        _HairSpecularRange("头发高光范围",Range(0,1)) = 1

        _HairSpecularViewRange("高光视角范围",Range(0,1)) = 1

        _HairSpecularIntensity("头发高光强度",float) = 1

        _HairSpecularColor("高光颜色",color) = (1,1,1,1)

        [Header(RimLight)]

        _Lightcolor("边缘光颜色",Color) = (1,1,1,1)

        _RimOffect ("偏移量(xy)",vector) = (1.25,0.2,0,0)

        _Threshold("Threshold",Range(-1,1)) = 0.2

        _FresnelPow("菲涅尔强度",Range(0,10)) = 4

        _RimIntensity("边缘光强度",Range(0,10)) =1

        [Header(Faceshadow)]

        [Toggle]_FaceShadow("是否启用脸部阴影",int) = 0

        _ShadowColor("ShadowColor",Color) = (0,0,0,0)

        [Header(OutLine)]

        _Outline ("Outline", Range(0, 1)) = 0.003

        _OutlineColor ("Outline Color", Color) = (0, 0, 0, 1)

    }

    SubShader

    {

        Tags { "Queue" = "Geometry" "RenderType" = "Opaque" "IgnoreProjector" = "True"  }


        Pass

        {

            Cull Off


            CGPROGRAM

            #pragma vertex vert

            #pragma fragment frag

            #pragma multi_compile_fog

            #pragma shader_feature _ _DAY_ON

            #pragma shader_feature _ _ENABLEHAIR_ON _FACESHADOW_ON

            #include "UnityCG.cginc"

            #include "Lighting.cginc"


            struct appdata

            {

                float4 vertex       : POSITION;

                float2 uv               : TEXCOORD0;

                float3 normal           : NORMAL;

            };


            struct v2f

            {

                float4 vertex       : SV_POSITION;

                float2 uv               : TEXCOORD0;

                float3 normalWS         : TEXCOORD1;

                float4 worldPos          : TEXCOORD2;

                float3 normalVS         : TEXCOORD5;

                float2 ScreenPos01      : TEXCOORD3;

                float  srcposW          : TEXCOORD4;

            };


            float4 _BaseMap_ST;

            half _RampShadowRange;

            half _Day;

            half _ShadowRampLerp;

            half _RampAOLerp;

            half _DarkIntensity;

            half4 _DarkShadowMultColor;

            half _BrightIntensity;

            half4 _ShadowMultColor;

            half _CharacterIntensity;

            half _RampIntensity;

            half _SpecularPow;

            half _SpecularExp;

            half _SpecularIntensity;

            half _StepSpecularWidth;

            half _StepSpecularWidth2;

            half _StepSpecularWidth3;

            half _StepSpecularWidth4;

            half _StepSpecularIntensity;

            half _StepSpecularIntensity2;

            half _StepSpecularIntensity3;

            half _StepSpecularIntensity4;

            half _MetalMapV;

            half _MetalMapIntensity;

            half _HairSpecularRange;

            half _HairSpecularViewRange;

            half _HairSpecularIntensity;

            half4 _HairSpecularColor;

            half4 _Lightcolor;

            half4 _RimOffect;

            half _Threshold;

            half _FresnelPow;

            half _RimIntensity;

            fixed4 _ShadowColor;

            sampler2D  _CameraDepthTexture;  

            sampler2D _BaseMap;

            sampler2D _LightMap;

            sampler2D _RampTex;

            sampler2D _MetalMap;

            sampler2D _SDF;

            //float4 _BaseMap_ST;

            float4 _LightMap_ST;

            float4 _RampTex_ST;

            float4 _MetalMap_ST;

           


            v2f vert (appdata v)

            {

                v2f o;


                o.vertex = UnityObjectToClipPos(v.vertex);

                //o.uv = TRANSFORM_TEX(v.uv, _BaseMap);

                o.uv = v.uv;

                o.normalWS = UnityObjectToWorldNormal(v.normal);

                o.worldPos = mul(unity_ObjectToWorld,v.vertex);

                o.srcposW = o.vertex.w;

                o.normalVS = mul((float3x3)UNITY_MATRIX_V , o.normalWS);

                o.ScreenPos01 = float2(v.vertex.x / _ScreenParams.x , v.vertex.y / _ScreenParams.y);

                return o;

            }


            half4 frag (v2f i) : SV_Target

            {


                fixed4 baseMap = tex2D(_BaseMap, i.uv);

                float4 LightColor = float4( _LightColor0.rgb,1);     //获取主光源颜色

                half3 N = normalize(i.normalWS);

                half3 L = normalize(_WorldSpaceLightPos0.xyz);

                float3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);

                half3 V = normalize(viewDir);

                half3 H = normalize(V + L);

                half3 ShadowColor = baseMap.rgb * _ShadowMultColor.rgb; //亮部颜色

                half3 DarkShadowColor = baseMap.rgb * _DarkShadowMultColor.rgb;  //暗部颜色


                //Lightmap

                half4 lightmap = tex2D(_LightMap, i.uv);

                half ao = lightmap.g;

                //Ramp

                half lambert = saturate(dot(N, L));

                half halfLambert = lambert * 0.5 + 0.5;

                float rampvmove = 0.0;  //如果是夜晚,采样ramp图下面

                float rampvalue = halfLambert * lerp(0.5, 1.0, ao) * (1.0 / _RampShadowRange - 0.0003);


                //ramp图前5行为暖色调阴影,后5行为冷色调阴影,对应着夜晚与⽩天。

                #if _DAY_ON

                    rampvmove += 0.5; //如果是白天,采样ramp图上面

                #endif

                half3 ShadowRamp1 = tex2D(_RampTex, float2(rampvalue, 0.4 + rampvmove)).rgb;

                half3 ShadowRamp2 = tex2D(_RampTex, float2(rampvalue, 0.3 + rampvmove)).rgb;

                half3 ShadowRamp3 = tex2D(_RampTex, float2(rampvalue, 0.2 + rampvmove)).rgb;

                half3 ShadowRamp4 = tex2D(_RampTex, float2(rampvalue, 0.1 + rampvmove)).rgb;

                half3 ShadowRamp5 = tex2D(_RampTex, float2(rampvalue, 0.0 + rampvmove)).rgb;

                //将所有的Ramp加起来

                half3 skinRamp = step(abs(lightmap.a - 1),     0.05) * ShadowRamp1;  //皮肤ramp

                float3 tightsRamp = step(abs(lightmap.a - 0.7),     0.05) * ShadowRamp2;    //皮肤与衣服的交界    

                float3 softCommonRamp = step(abs(lightmap.a  - 0.5), 0.05 ) * ShadowRamp3;      //衣服ramp      

                half3 hardSilkRamp = step(abs(lightmap.a  - 0.3),   0.05) * ShadowRamp4;      //衣服边缘

                half3 metalRamp = step(abs(lightmap.a - 0),       0.05) * ShadowRamp5;    

                // 组合5个Ramp,得到最终的Ramp阴影,并根据rampValue与BaseColor结合。

                half3 finalRamp = skinRamp + tightsRamp + metalRamp  + hardSilkRamp + softCommonRamp;

                //return half4(finalRamp,1);

                //因为和阴影同时 出现

                rampvalue =  step(_RampShadowRange, halfLambert) ;

                half3 RampShadowColor = lerp(finalRamp * baseMap.rgb, baseMap.rgb,  rampvalue);

                //return half4(RampShadowColor,1);

                //用_ShadowRampLerp控制lerp的强度,随之控制AO区域的明暗程度

                float3 BaseMapShadowed = lerp(baseMap.rgb * finalRamp , baseMap.rgb, ao);  

                BaseMapShadowed = lerp(baseMap.rgb, BaseMapShadowed, _ShadowRampLerp);  

                float IsBrightSide = ao * step(_RampShadowRange, halfLambert);  //辨别是否为亮部


                float3 Diffuse = lerp(lerp(BaseMapShadowed, baseMap.rgb * finalRamp, _RampAOLerp)

                * _DarkIntensity * DarkShadowColor, _BrightIntensity * BaseMapShadowed * ShadowColor,  

                IsBrightSide * _RampIntensity ) * _CharacterIntensity  * LightColor.rgb;

               

                //return half4(Diffuse,1);


                //高光部分

                float4 MetalMap = tex2D(_MetalMap, mul((float3x3)UNITY_MATRIX_V, N).xy).r;

                MetalMap = saturate(MetalMap);

                MetalMap = step(_MetalMapV, MetalMap) * _MetalMapIntensity;

                float3 Specular = 0;

                float3 StepSpecular = 0;

                float3 StepSpecular2 = 0;


                float LinearMask = pow(lightmap.r, 1 / 2.2);            //图⽚格式全部去掉勾选SRGB ⾼光类型Layer

                float SpecularIntensityMask = pow(saturate(dot(N, V)), _SpecularPow) * _SpecularIntensity;

                float SpecularLayer = lightmap.r * 255;            //高光类型,不同的⾼光层 LightMap.b ⽤途不⼀样

                float StepSpecularMask = step(200, pow(SpecularIntensityMask, 1 / 2.2) * 255); //高光强度遮罩,加伽马校正

                if (SpecularLayer > 0 && SpecularLayer < 50)               //丝袜与包包

                {


                    //step x<=y返回1,否则返回0


                    StepSpecular = step(1 - _StepSpecularWidth, saturate(dot(N, V))) * _StepSpecularIntensity; //可做修改* SpecularIntensityMask

                    StepSpecular *= baseMap;


                }

                // 裁边⾼光 (⾼光在暗部消失)

                if (SpecularLayer > 50 && SpecularLayer < 150)               //布料边缘高光

                {

                    StepSpecular = step(1 - _StepSpecularWidth2, saturate(dot(N, V))) * 1 * _StepSpecularIntensity2;//* SpecularIntensityMask

                    StepSpecular *= baseMap;

                }


                if (SpecularLayer > 150 && SpecularLayer < 250)//头发高光

                {

                    #if _ENABLEHAIR_ON  //如果是头发 ,取代高光,如果不是保持

                        StepSpecular = step(1 - _StepSpecularWidth3, saturate(dot(N, V)))  * _StepSpecularIntensity3;

                        //StepSpecular = lerp(StepSpecular, 0, SpecularIntensityMask);           //反向失去头发高光控制


                        StepSpecular2 = step(1 - _StepSpecularWidth4 * 5, saturate(dot(N, V))) * SpecularIntensityMask * _StepSpecularIntensity4;

                        StepSpecular2 *= baseMap;

                        StepSpecular *= baseMap;

                    #else

                        StepSpecular = step(1 - _StepSpecularWidth3, saturate(dot(N, V))) * _StepSpecularIntensity3;

                        StepSpecular *= baseMap;

                    #endif

                }

                if (SpecularLayer >= 250 && SpecularLayer < 260)     //金属高光

                {

                    Specular = pow(saturate(dot(N, H)), 1 * _SpecularExp) * SpecularIntensityMask * _SpecularIntensity;

                    Specular = max(0, Specular);

                    Specular += MetalMap;

                    Specular *= baseMap;

                }

                float SpecularRange = step(1 - _HairSpecularRange, saturate(dot(N, H)));

                float ViewRange = step(1 - _HairSpecularViewRange, saturate(dot(N, V)));

                float3 HairSpecular = 0;

                HairSpecular = SpecularIntensityMask * _HairSpecularIntensity * SpecularRange * ViewRange;

                HairSpecular = max(0, HairSpecular);

                HairSpecular *= baseMap * LightColor.rgb;

                HairSpecular *=  _HairSpecularColor.rgb;

                //return half4(HairSpecular,1);


                //高光融合

                Specular = lerp(StepSpecular, Specular, LinearMask);     // //⾼光类型Layer 截断分布

                Specular = lerp(0, Specular, LinearMask);

                Specular = lerp(0, Specular, rampvalue);                 //亮暗分布rampValue 加上AO暗部影响

                Specular += HairSpecular;

                //float3 FinalColor = Specular + RampShadowColor;         //Diffuse + Specular;

                float3 FinalColor = Specular  + Diffuse;

                //边缘光

                float fresnel = pow(1 - saturate(dot(N,V)),_FresnelPow);

                float2 ScreenPosOffset = i.ScreenPos01 + i.normalVS.xy * _RimOffect.xy;

                //float2 ScreenPosOffset = i.ScreenPos01 + i.normalVS.xy * float2(_RimOffect.xy / i.srcposW) / _ScreenParams.x ;

                float depth   = UNITY_SAMPLE_DEPTH(tex2D(_CameraDepthTexture, i.ScreenPos01));

                float depth01 = UNITY_SAMPLE_DEPTH(tex2D(_CameraDepthTexture, ScreenPosOffset));//偏移后的深度

                float linearDepth = Linear01Depth(depth);

                float linear01Depth = Linear01Depth(depth01);


                float findepth = linear01Depth - linearDepth;

                //return fresnel;

                float rim = step(_Threshold,findepth);

                rim = lerp(fresnel,rim,_Threshold);

                //fixed4 col = fixed4(_Lightcolor.rgb * rim ,1);

                //return rim;

                FinalColor += rim *_Lightcolor.rgb *1.2 * _RimIntensity ;

                //脸部阴影

                half3 faceshadow = 0;

                #if _FACESHADOW_ON

                    half3 LightDir = normalize(_WorldSpaceLightPos0.xyz);

                    float shadow = tex2D(_SDF, i.uv);//采样右脸阴影

                    float shadow01 = tex2D(_SDF, float2(-i.uv.x,i.uv.y));//采样左脸阴影


                    float3 FrontDir = normalize(UnityObjectToWorldDir(float3(0.0,0.0,1.0)));//拿到模型的向前方向z

                    float3 rightDir = normalize(UnityObjectToWorldDir(float3(1.0,0.0,0.0)));//拿到模型的向右方向x

                    float HalfLambert = dot(LightDir.xz,FrontDir.xz)* 0.5 + 0.5;

                    float Lambert = dot(LightDir.xz,rightDir.xz);

                    float Faceshadow = lerp(shadow,shadow01,step(Lambert,0));//判断该采样哪边的阴影

                    float face = HalfLambert>Faceshadow?1.0:0.0;


                    //return face;

                    faceshadow = lerp(_ShadowColor.rgb * FinalColor*1.2,FinalColor,face);

                    return half4(faceshadow,1);

                #endif

               

                return half4(FinalColor, 1);

            }

            ENDCG

        }

        Pass

        {

            Cull Front


            CGPROGRAM


            #pragma vertex vert

            #pragma fragment frag


            float _Outline;

            fixed4 _OutlineColor;


            struct a2v

            {

                float4 vertex : POSITION;

                float3 normal : NORMAL;

            };


            struct v2f

            {

                float4 pos : SV_POSITION;

            };


            v2f vert (a2v v)

            {

                v2f o;


                float4 pos = mul(UNITY_MATRIX_MV, v.vertex);

                float3 normal = mul((float3x3)UNITY_MATRIX_IT_MV, v.normal);  

                normal.z = -0.5;

                pos = pos + float4(normalize(normal), 0) * _Outline;

                o.pos = mul(UNITY_MATRIX_P, pos);


                return o;

            }


            float4 frag(v2f i) : SV_Target

            {

                return float4(_OutlineColor.rgb, 1);              

            }


            ENDCG

        }

    }

    Fallback "Diffuse"

}


原神卡通渲染shader的评论 (共 条)

分享到微博请遵守国家法律