Unity shader学习(二)漫反射光照模型

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010476348/article/details/84260760

正常的漫反射公式(Lambert)是这样的:

C(diffuse) = C(light) * M(diffuse)max(0,n*I)

C(light):入射光的颜色和强度

M(diffuse):材质的漫反射系数

n:世界坐标系下的表面法线

I:世界坐标系下的光源方向(反射点指向光源的矢量)

max函数:,将结果截取到0,防止法线与光源方向的点乘为负值,被背后的光源照亮的错误效果

然后是毫无依据的半兰伯特公式:C(diffuse) = (C(light) * M(diffuse))(0.5(n*l)+0.5)

最后是代码(unity5.5.4):

Shader "Custom/DiffuseVertexLevel3" {
	Properties {
		_Color("color",Color)=(1,1,1,1)
	}
	SubShader {
		Pass{
			//定义光照模式
			Tags{"LightMode"="ForwardBase"}
			CGPROGRAM
			//顶点着色器
			#pragma vertex vert
			//片元着色器
			#pragma fragment frag
			//引入unity的Lighting库
			#include "Lighting.cginc"
			//衔接Properties的_Color属性
			fixed4 _Color;
			//定义顶点着色器的输入和输出结构体
			struct a2v{
				float4 vertex:POSITION;
				float3 normal:NORMAL;
			};
			//顶点着色器的输出结构体也是片元着色器的输入结构体
			struct v2f{
				float4 pos:SV_POSITION;
				float3 worldNoraml:TEXCOORD0;
			};

			v2f vert(a2v v){
			//顶点着色器不需要计算光照模型,只需要把世界空间下的法线传递给片元着色器即可
				v2f o;
				o.pos=UnityObjectToClipPos(v.vertex);
				o.worldNoraml=mul(v.normal,(float3x3)unity_WorldToObject);
				return o;
			}

			fixed4 frag(v2f f):SV_Target{
			//在片元着色器中计算漫反射光照模型
				fixed3 ambient=UNITY_LIGHTMODEL_AMBIENT.xyz;
				fixed3 worldNoraml=normalize(f.worldNoraml);
				fixed3 worldLightDir=normalize(_WorldSpaceLightPos0.xyz);
				//使用半兰伯特公式
				fixed halfLambert=dot(worldNoraml,worldLightDir)*0.5+0.5;
				fixed3 diffuse=_LightColor0.rgb*_Color.rgb*halfLambert;
				float3 color=ambient+diffuse;
				return fixed4(color,1.0);
			}
			ENDCG
		}
	}
	//设置回调shader
	FallBack "Diffuse"
}

另外还有一个据说是加强版,原谅我眼拙没有看出太大区别....也放在这里记录一下吧

Shader "Custom/DiffuseVertexLevel4" {
	 Properties
    {
        _MainTex("Main Tex",2D) = "white"{}
        _DiffuseColor("Diffuse Color",Color) = (1,1,1,1)
    }
        SubShader
        {
            Tags{"Queque" = "Opaque"}
            Pass
            {
                Tags{"LightMode" = "ForwardBase"}
                CGPROGRAM
                #pragma vertex vert
                #pragma fragment frag
                #include "UnityCG.cginc"
                #include "Lighting.cginc"

                sampler2D _MainTex;
                float4 _MainTex_ST;
                float4 _DiffuseColor;

                struct a2v
                {
                    float4 vertex : POSITION;
                    float4 texcoord : TEXCOORD0;
                    float3 normal :NORMAL;
                };
                struct v2f
                {
                    float4 pos : SV_POSITION;
                    //float3 color : COLOR;
                    float halfLambert : TEXCOORD0;
                    float2 uv : TEXCOORD1;
                };

                v2f vert(a2v v)
                {
                    v2f o;
                    o.pos = UnityObjectToClipPos(v.vertex);
                    o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
                    float3 worldNormal = normalize(UnityObjectToWorldNormal(v.normal));
                    float3 worldPos = mul(unity_ObjectToWorld, o.pos);
                    float3 worldLightDir = normalize(UnityWorldSpaceLightDir(worldPos));
                    o.halfLambert = dot(worldNormal, worldLightDir)*0.5 + 0.5;
                    
                    
                    return o;
                }

                float4 frag(v2f f) : SV_Target
                {
                    float3 col = tex2D(_MainTex, f.uv).rgb;
                    float3 diffuse = col * _DiffuseColor.rgb;
                    float3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb * col;
                    float3 color = ambient + _LightColor0.rgb * diffuse * f.halfLambert;
                    return float4(color,1);
                }

                ENDCG
        }
    }
}

 

展开阅读全文

没有更多推荐了,返回首页