Unity Shaders and Effects Cookbook (1-2)创建自定义漫反射光照模型

在Unity3d 中,右键创建 一个 Shader ,这个Shader 中会默认包含一些代码。这个默认的代码就为我们创建了 基本的漫反射着色器,并且接收一个 纹理。


上一篇中,为了了解 Shader 最基本的结构,我删掉了 里面的一些代码。

这一次来学习创建自定义的漫反射光照模型。


首先来看下默认的 Shader 内容( 即 基本的漫反射着色器 Lambert 光照模型 )

Shader "Custom/NewShader" {
	Properties {
		_MainTex ("Base (RGB)", 2D) = "white" {}
	}
	SubShader {
		Tags { "RenderType"="Opaque" }
		LOD 200
		
		CGPROGRAM
		#pragma surface surf Lambert // 告诉着色器使用哪个 光照模型来计算,这里默认使用了 Lighting.cginc 中的 Lambert 光照模型

		sampler2D _MainTex;

		struct Input {
			float2 uv_MainTex;
		};

		void surf (Input IN, inout SurfaceOutput o) {
			half4 c = tex2D (_MainTex, IN.uv_MainTex);
			o.Albedo = c.rgb;
			o.Alpha = c.a;
		}
		ENDCG
	} 
	FallBack "Diffuse"
}

Shader 结构解析:

#pragma surface surf Lambert :  告诉着色器使用哪个 光照模型来计算,这里默认使用了 Lighting.cginc 中的 Lambert 光照模型


上一篇中提到,我们的Shader 引用了 \Editor\Data\CGIncludes 目录下面的 Lighting.cginc ,就像在 C 语言中,调用了其它 文件 中的函数。

Lambert 这个光照模型 就位于 Lighting.cginc 文件中。

Unity Shaders and Effects Cookbook (1-2)创建自定义漫反射光照模型_第1张图片


在 Lighting.cginc中找到了 Lambert 光照模型相关的函数,但是发现一个问题:

函数名并不只是 Lambert,而是由  Lighting 开头,加上 Lambert ,再加上 _PrePass 或 _DirLightmap 后缀。


这正是这一次要学习的,创建自定义的光照模型的时候,光照模型的函数名,函数定义 都是有规定的。

以我要创建的 BasicDiffuse 漫反射光照模型来讲, Unity Shader 中规定,光照模型函数名的格式是:

//不需要视角方向的前向着色
inline half4 LightingBasicDiffuse(SurfaceOutput so,half3 lightDir,half atten)
{
	half4 color=(0,0,0,0);

	return color;
}

//需要视角方向的前向着色
inline half4 LightingBasicDiffuseWithViewDir(SurfaceOutput so,half3 lightDir,half3 viewDir,half atten)
{
	half4 color=(0,0,0,0);

	return color;
}

//需要使用延迟着色
inline half4 LightingBasicDiffuse_PrePass(SurfaceOutput so,half4 light)
{
	half4 color=(0,0,0,0);

	return color;
}


编写好对应的光照模型函数之后,需要在 Shader 中指定 它 为当前使用的光照模型。

修改

#pragma surface surf Lambert

#pragma surface surf BasicDiffuse

这样就使用了  不需要视角方向 的 前向着色器

然后完成 光照模型函数。

//不需要视角方向的前向着色
inline half4 LightingBasicDiffuse(SurfaceOutput s,half3 lightDir,half atten)
{
	float difLight = max(0,dot(s.Normal,lightDir) );

	half4 color=(0,0,0,0);
	color.rgb=s.Albedo * _LightColor0.rgb * ( difLight * atten * 2 );
	color.a=s.Alpha;
	return color;
}

从这个 BasicDiffuse 光照模型函数中可以看出,光照模型函数是在 Surf 函数之后执行的。


在 BasicDiffuse 光照模型函数中,使用了 max 点积函数:

点积函数 ( dot product function ) 用来比较 两个向量在 空间里的方向。max ( A , B ) 其实就是求 A 向量 和 B 向量 夹角的 Cos 值。这里就是 法线向量 和 灯光方向向量。

Cos 值 :值越大,两个向量 夹角 越小,

Cos 值 = 1的时候,两个向量 平行并垂直指向你。这时光照垂直照射,就像正午的太阳。

Cos值 =-1时,平行并且背离你。 就像太阳正好照着地球的另一边。

Cos 值 = 0时,表示垂直,这下就没有光照了。就像傍晚,然后黑夜。


Unity Shaders and Effects Cookbook (1-2)创建自定义漫反射光照模型_第2张图片





然后在代码中,将 SurfaceOutput 结构 提供的数据 和 光照数据 相乘 。光照数据来自 Unity ,SurfaceOutput 数据来自我们在编辑器中的设置。

然后再和 上面计算出来的 Cos 值 进行相乘。这样才会随着物体与 光线的角度的差异而表面受光照强度不同。


我发现,这上面的自定义的 漫反射光照模型函数 是和 Lighting.cginc 中的 Lambert 光照模型函数是一样的……

汗。。

不过这一次我就是学习来自定义一个光照模型函数,所以目的达到了哦。后面就能在这一次的基础上修改出自己的光照模型函数了。


例子工程下载:

http://pan.baidu.com/s/1qXtYPre


你可能感兴趣的:(unity3d,shader,漫反射光照模型)