unity shader卡通场景

Shader "Unlit/卡通场景shader"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _Diffuse("Color",Color) = (1,1,1,1)  //  漫反射
        _Outline("",Range(0,1)) = 0.1  //  描边参数
        _OutlineColor("OutlineColor",Color) = (0,0,0,0)  //  描边颜色
        _Steps("Steps",Range(1,30)) = 1  //  颜色分阶参数
        _ToonEffect("ToonEffect",Range(0,1)) = 0.5  //  卡通影响
        _BumpMap("Normal Map",2D) = "bump" {}  //  法线贴图
        _BumpScale("Bump Scale",float) = 1  //  法线贴图影响度
        _SnowDir("SnowDir",Vector) = (0,1,0)  //  雪方向
        _SnowColor("SnowColor",Color) = (0,0,0,0)  //  雪颜色
        //_SnowLevel("SnowLevel",Range(0,1)) = 0.5  //  雪厚度  想要全局设置时这里需要注释掉,不然无法控制数值变化
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        UsePass "Unlit/shader018/Outline"  //  用shader018的Outline Pass通道,要保证变量数、名一致

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile __ SNOW_ON  //  单个宏  shader的变种  __代表只需要一个  默认都是关闭的,想开启去代码中开
            #include "Lighting.cginc"
            #include "UnityCG.cginc"

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
                fixed3 worldNormal : TEXCOORD1;  //  世界法线向量,计算漫反射  需要世界光向量和世界法线向量点乘
                float3 worldLightDir : TEXCOORD2;
                float3 worldViewDir : TEXCOORD3;
                float3 worldBinormal : TEXCOORD4;
                fixed2 tangentUv : TEXCOORD5;
                float3x3 rotationTanToWorld : TEXCOORD6;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;
            fixed4 _Diffuse;
            float _Steps;
            float _ToonEffect;
            sampler2D _BumpMap;
            float4 _BumpMap_ST;
            float _BumpScale;
            float3 _SnowDir;
            float4 _SnowColor;
            float _SnowLevel;

            v2f vert (appdata_tan v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
                o.tangentUv = TRANSFORM_TEX(v.texcoord, _BumpMap);  //  法线贴图uv
                o.worldNormal = UnityObjectToWorldNormal(v.normal);  //  法线从模型变换到世界坐标  法线是向量所以fixed3  为世界光向量和世界法线向量点乘计算漫反射做准备  所以要计算世界法线向量
                o.worldLightDir = WorldSpaceLightDir(v.vertex);  //  世界光向量  漫反射世界光向量和世界法线向量点乘

                float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;  //  顶点信息从模型转到世界坐标系
                o.worldViewDir = normalize(UnityWorldSpaceViewDir(worldPos));  //  世界视角方向
                TANGENT_SPACE_ROTATION;
                o.worldBinormal = binormal;  //  副切线向量
                o.rotationTanToWorld = rotation;
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {



                //  法线贴图
                fixed4 packedNormal = tex2D(_BumpMap, i.tangentUv);  //  法线贴图采样
                //  法线贴图要设置为normal map
                fixed3 tangentNormal = UnpackNormal(packedNormal);  //  解压缩法线贴图 unity会自动搞到【0,1】范围内  z值也算好了  解压出的是法线贴图的切线空间法线
                tangentNormal.xy = tangentNormal.xy * _BumpScale;  //  解压都做好了,乘上法线贴图控制参数让他可调整即可
                float3 tangentWorldNormal = normalize(mul(i.rotationTanToWorld , tangentNormal));  //  切线空间法线转换到世界坐标系
                
                //  光照模型
                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;  //  环境光
                fixed4 albedo = tex2D(_MainTex, i.uv);  //  图片采样
                float difLight = max(0, dot(i.worldLightDir, tangentWorldNormal)) * 0.5 + 0.5;  //  max不让这个值小于零  *0.5+0.5半兰伯特光照模型  这是漫反射光的值  参数为世界光方向和转过来的法线贴图世界法线来让他有纹理感
                //  卡通颜色
                difLight = smoothstep(0, 1, difLight);  //  颜色平滑在【0,1】之间  
                //  颜色离散化
                float toon = floor(difLight * _Steps) / _Steps;  //  floor参数向下取整  目的:分几块
                difLight = lerp(difLight, toon, _ToonEffect);  //  lerp前两个值插值,第三个是权值  光照模型
                fixed4 color = fixed4(ambient + _LightColor0.rgb * difLight * albedo * _Diffuse.rgb, 1);  //  计算返回值
                //  雪
#if SNOW_ON  //  对应的宏区间
                if (dot(tangentWorldNormal, _SnowDir) > lerp(1, -1, _SnowLevel)) {  //lerp给定权重在两个向量之间执行线性内插
                    color.rgb = _SnowColor.rgb;
                }else{
                    color = color;
                }
#endif          

                return color;
            }
            ENDCG
        }
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值