Unity Shader 标准光照模型——漫反射

Unity Shader 标准光照模型——漫反射

1. 逐顶点的漫反射

Shader "Unlit/DiffuseReflection"
{
    Properties
    {
        _diffuse("diffuse",Color) = (1,1,1,1)
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"
            #include "Lighting.cginc"
            fixed4 _diffuse;
            struct v2f
            {
                float4 vertex : SV_POSITION;
                fixed3 color : Color;
            };


            v2f vert (appdata_base v)    //appdata_base 为unity Shader自己定义的一个结构体
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
                //将法线转换到世界坐标下的法线
                fixed3 worldNormal = UnityObjectToWorldNormal(v.normal);
                //光源方向
                fixed3 worldLight = normalize(_WorldSpaceLightPos0.xyz);
                //兰伯特公式
                fixed3 diffuse = _LightColor0.rgb * _diffuse.rgb * saturate(dot(worldNormal,worldLight));
                o.color = diffuse + ambient;
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                return fixed4(i.color,1);
            }
            ENDCG
        }
    }
}

2. 逐片元的漫反射

Shader "Unlit/FragmentReflection"
{
    Properties
    {
        _diffuse("diffuse",Color) = (1,1,1,1)
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"
            #include "Lighting.cginc"
            fixed4 _diffuse;
            struct v2f
            {
                float4 vertex : SV_POSITION;
                fixed3 worldNormal : TEXCOORD0;
            };


            v2f vert (appdata_base v)    //appdata_base为unity自己定义的结构体
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);

                //将法线转换到世界坐标下的法线
                fixed3 worldNormal = UnityObjectToWorldNormal(v.normal);
                //光源方向
                o.worldNormal = worldNormal;
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
                fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
                fixed3 diffuse = _LightColor0.rgb * _diffuse.rgb * max(0,dot(worldLightDir,i.worldNormal));
                fixed3 color = ambient + diffuse;
                return fixed4(color,1);
            }
            ENDCG
        }
    }
}

3.半兰伯特漫反射

Shader "Unlit/HalfLambert"
{
     Properties
    {
        _diffuse("diffuse",Color) = (1,1,1,1)
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"
            #include "Lighting.cginc"
            fixed4 _diffuse;
            struct v2f
            {
                float4 vertex : SV_POSITION;
                fixed3 worldNormal : TEXCOORD0;
            };


            v2f vert (appdata_base v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);

                //将法线转换到世界坐标下的法线
                fixed3 worldNormal = UnityObjectToWorldNormal(v.normal);
                //光源方向
                o.worldNormal = worldNormal;
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                //环境光
                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
                //
                fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
                //半兰伯特公式
                fixed3 diffuse = _LightColor0.rgb * _diffuse.rgb * dot(worldLightDir,i.worldNormal) * 0.5 + 0.5;
                fixed3 color = ambient + diffuse;
                return fixed4(color,1);
            }
            ENDCG
        }
    }
}

4. 各自的优缺点

逐顶点的漫反射与逐片元的漫反射的区别在于顶点漫反射在阴影切换处会有明显的锯齿反应,可以看的到明显的顶点。而片元漫反射则相对切换平滑。
以上的逐顶点和逐片元漫反射都是兰伯特漫反射公式,但是兰伯特漫反射公式有个缺点是暗的地方接近全暗,为了解决这个全暗的问题则有半兰伯特公式。半兰伯特公式在兰伯特公式的基础上 result * 0.5 + 0.5 .这就是半兰伯特漫反射。
最终效果如下。(从左至右依次为逐顶点、逐片元、半lambert)
Unity Shader 标准光照模型——漫反射_第1张图片

你可能感兴趣的:(unity,Shader,unity,游戏引擎,图形渲染)