Shader实现漫反射

漫反射的原理:漫反射是投射在粗糙表面上的光向各个方向反射的现象,根据入射光线与此点的法线来决定此点的反射强度,用ShaderLab书上的公式表达就是:

Lum = C * max(0,cos<L,N>)

C : 到达此点光线的强度和颜色

N : 法线

L : 单位长度(标准化)的入射光向量。

再顶点函数实现漫反射代码:

Shader "Custom/Diffuse" {
	Properties
	{
		_Color("Color",Color) = (1,1,1,1)	//控制漫反射的颜色
	}
		SubShader
	{
		Pass
	{
		Tags{ "LightMode" = "ForwardBase" }

		CGPROGRAM
#pragma vertex vert
#pragma fragment frag
		//引入需要使用灯光的内置变量
#include "Lighting.cginc"

		fixed4 _Color;

	struct a2v
	{
		float4 vertex :POSITION;
		float3 normal:NORMAL;
	};

	struct v2f
	{
		float4 pos:SV_POSITION;
		fixed3 color : COLOR;
	};

	v2f vert(a2v v)
	{
		v2f o;
		//将顶点由模型空间转换到剪裁空间
		o.pos = mul(UNITY_MATRIX_MVP,v.vertex);
		//得到环境光
		fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
		//内置函数,将法线从模型空间转换到世界空间,用的是右乘矩阵
		fixed3 worldNormal = normalize(mul(v.normal,(float3x3)unity_WorldToObject));
		//将灯光归一化
		fixed3 worldLight = normalize(_WorldSpaceLightPos0.xyz);
		//漫反射公式:光照颜色 * 漫反射颜色 * max(0,法向量*光照方向)
		//saturate():将范围控制在0-1之间
		fixed3 diffuse = _LightColor0.rgb * _Color.rgb * saturate(dot(worldNormal,worldLight));

		//添加本行代码为半兰伯特模型
		//diffuse = diffuse * 0.5 + 0.5;

		//返回的颜色为环境光加漫反射的光
		o.color = ambient + diffuse;

		return o;
	}

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

		ENDCG
	}
	}
		Fallback "Diffuse"
}

再片元函数实现漫反射代码:

Shader "Custom/Diffuse2" {
		Properties
		{
			_Color("_Color",Color) = (1,1,1,1)
		}
			SubShader
		{
			Pass
		{
			CGPROGRAM

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

#pragma vertex vert
#pragma fragment frag 

			fixed4 _Color;

		struct a2v
		{
			float4 position:POSITION;
			float3 normal:NORMAL;
		};

		struct v2f
		{
			float4 position:SV_POSITION;
			float3 color:COLOR;
		};


		v2f vert(a2v v)
		{
			v2f f;
			f.position = mul(UNITY_MATRIX_MVP,v.position);
			f.color = v.normal;

			return f;
		}

		float4 frag(v2f f) :SV_Target
		{
			//得到世界空间下的法线
			float3 normalDir = normalize(mul(f.color,(float3x3)_World2Object));
			float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);

			//获得漫反射
			float3 diffuse = _LightColor0.rgb*max(dot(normalDir,lightDir),0)*_Color;
			//半兰伯特模型
			diffuse = diffuse * 0.5 + 0.5;

			//获取环境光
			float3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;

			return float4(diffuse + ambient,1);
		}
			ENDCG
		}
		}
	Fallback "Diffuse"			
}

效果图:

适合用在地形,岩石,墙壁等粗糙的物体上。

猜你喜欢

转载自blog.csdn.net/qq_38721111/article/details/84885359