美文网首页
Shader学习——卡通积雪场景(Shader宏控制开关)

Shader学习——卡通积雪场景(Shader宏控制开关)

作者: BacteriumFox | 来源:发表于2019-08-29 16:02 被阅读0次

核心

积雪方向和法线进行点击,如果大于积雪厚度值则改变该片元的输出颜色为雪的颜色

效果图

卡通积雪场景效果图
卡通场景效果图
Shader "Unlit/020"
{
    Properties
    {
        _MainTex ("纹理", 2D) = "white" {}
        _Diffuse("漫反射",Color) = (1,1,1,1)

        _BumpMap("法线贴图",2D) = "while"{}
        _BumpScale("法线强度",float) = 1

        _Outline("轮廓粗细", Range(0,0.2)) = 0.1 
        _OutlineColor("轮廓颜色", Color) = (0,0,0,0)
        _Step("离散化",Range(1,30))=1
        _ToonEffect("卡通效果",Range(0,1))=0.5

        _Snow("积雪厚度",Range(0,1)) = 0.5
        _SnowColor("积雪的颜色",Color) = (1,1,1,1)
        _SnowDir("积雪的方向",Vector) = (0,1,0)
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        //调用上章所用到的描边ShaderPass进行描边
        UsePass "Unlit/019/Outline"

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            
            //宏开关设置
        #pragma multi_compile __ SNOW_ON

            #include "UnityCG.cginc"
            #include "Lighting.cginc"

          
            struct v2f
            {
        float4 vertex : SV_POSITION;
                float4 uv : TEXCOORD0;
                float4 T2W0 : TEXCOORD1;
            float4 T2W1 : TEXCOORD2;
                float4 T2W2 : TEXCOORD3;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
        fixed4 _Diffuse;
            float _Step;
        float _ToonEffect;
        sampler2D _BumpMap;
        float4 _BumpMap_ST;
        float _BumpScale;
        float _Snow;
        float4 _SnowColor;
        float4 _SnowDir;

            v2f vert (appdata_tan v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv.xy = TRANSFORM_TEX(v.texcoord, _MainTex);
        o.uv.zw = TRANSFORM_TEX(v.texcoord, _BumpMap);
                
                //求出世界(坐标\法线\副法线\切线
                fixed3 worldPos = mul (unity_ObjectToWorld,v.vertex);
                fixed3 worldNormal = UnityObjectToWorldNormal(v.normal);
                fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
                fixed3 worldBinormal = cross(worldNormal,worldTangent) * v.tangent.w;
                
                //切线空间转世界空间矩阵
                o.T2W0 = float4(worldTangent.x,worldBinormal.x,worldNormal.x,worldPos.x);
                o.T2W1 = float4(worldTangent.y,worldBinormal.y,worldNormal.y,worldPos.y);
                o.T2W2 = float4(worldTangent.z,worldBinormal.z,worldNormal.z,worldPos.z);

                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT;
                //采样
                fixed4 albedo = tex2D(_MainTex,i.uv);

                //世界坐标
                float3 worldPos = float3(i.T2W0.w,i.T2W1.w,i.T2W2.w);

                //光源方向和视角方向
                fixed3 lightDir = UnityWorldSpaceLightDir(worldPos);
                fixed3 viewDir = normalize(UnityWorldSpaceViewDir(worldPos));

                //法线贴图
                fixed4 packedNormal = tex2D(_BumpMap,i.uv.zw);
                //切线空间法线
                fixed3 tangentNormal = UnpackNormal(packedNormal);
                tangentNormal.xy *= _BumpScale;
                //转换成世界坐标法线
                fixed3 worldNormal = normalize(float3(dot(i.T2W0.xyz, tangentNormal),dot(i.T2W1.xyz, tangentNormal),dot(i.T2W2.xyz, tangentNormal)));


                //半罗伯特模型
                float difLight= dot(lightDir,worldNormal)* 0.5+0.5;
                difLight = smoothstep(0,1,difLight);
                
                //离散化
                float toon = floor(difLight * _Step)/_Step;
                difLight = lerp(difLight, toon, _ToonEffect);

                //光照模型
                fixed3 diffuse = _LightColor0.rgb * albedo * _Diffuse.rgb * difLight;

                fixed4 color = fixed4 (ambient + diffuse,1); 

                //宏开关控制
                #if SNOW_ON
                //积雪
                if(dot(worldNormal,_SnowDir.xyz)>lerp(1,-1,_Snow))
                {
                    color.rgb = _SnowColor.rgb;
                }
                #endif

                return color;
            }
            ENDCG
        }
    }
}
  • 宏控制代码
    该脚本需要放在项目Editor文件夹中
using UnityEditor;
using UnityEngine;

public class Tools : MonoBehaviour
{
    private static string SNOW_ON = "SNOW_ON";

    [MenuItem("Tools/Shader/开启雪景宏")]
    public static void OpenRimlight()
    {
        if (Shader.IsKeywordEnabled(SNOW_ON))
        {
            Shader.DisableKeyword(SNOW_ON);
        }
        else
        {
            Shader.EnableKeyword(SNOW_ON);
        }
    }
}

相关文章

网友评论

      本文标题:Shader学习——卡通积雪场景(Shader宏控制开关)

      本文链接:https://www.haomeiwen.com/subject/jniiectx.html