Unity Shader 学习笔记(6) 漫反射

44 篇文章 5 订阅
36 篇文章 5 订阅

Unity Shader 学习笔记(6) 漫反射

参考书籍:《Unity Shader 入门精要》
3D数学 学习笔记(8) 光照

逐顶点、逐像素、半兰伯特光照模型对比:

在这里插入图片描述


逐顶点光照(Lambert法则)


在这里插入图片描述

Shader "Custom/Chapter 6/DiffuseVertexLevel" {
	Properties {
		_Diffuse ("Diffuse",Color) = (1,1,1,1)
	}

	SubShader {
		Pass {
			Tags {"LightMode" = "ForwardBase"}				// 光照流水线,定义了才能得到一些内置光照变量

			CGPROGRAM
			
			#pragma vertex vert
			#pragma fragment frag
			
			#include "Lighting.cginc"						// 后面用到 _LightColor0

			fixed4 _Diffuse;								// 声明属性变量
			
			struct a2v {
				float4 vertex : POSITION;
				float3 normal : NORMAL;	
			};

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

			v2f vert(a2v v) {
				v2f o;
				o.pos = UnityObjectToClipPos(v.vertex);
				
				fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;							// 获得环境光,Unity内置变量

				// 等价 UnityObjectToWorldNormal(v.normal)
				fixed3 worldNormal = normalize(mul(v.normal,(float3x3)unity_WorldToObject));	// 将法线从模型空间转到世界空间

				fixed3 worldLight = normalize(_WorldSpaceLightPos0.xyz);				// 光源方向(假设场景只有一个光源且为平行光)

				// _LightColor0:光源颜色和强度。saturate:把参数限制在[0,1],CG提供的函数
				fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal,worldLight));

				o.color = ambient + diffuse;

				return o;
			}

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

 			ENDCG
		}
	}
	FallBack "Diffuse"
}


逐像素光照

原理同上,只不过是在片元着色器中计算。计算的法线是像素的法线。

struct v2f {
	float4 pos : SV_POSITION;
	fixed3 worldNormal : TEXCOORD0;				// 获取纹理坐标
};

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

	// 不需要计算光照模型,直接把世界空间法线传给着色器
	o.worldNormal = mul(v.normal,(float3x3)unity_WorldToObject);	

	return o;
}

fixed4 frag(v2f i) : SV_Target {
	fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;					// 获取环境光
	
	fixed3 worldNormal = normalize(i.worldNormal);					// 获取世界坐标的法线

	fixed3 worldLight = normalize(_WorldSpaceLightPos0.xyz);		// 光源方向

	// _LightColor0:光源颜色和强度,saturate:把参数限制在[0,1]
	fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal,worldLight));

	fixed3 color = ambient + diffuse;

	return fixed4(color,1.0);
}

半兰伯特光照

因为上面两种光照在背面都是无法接收光照而显示全黑,所有就有了这个模型。定义如下:


在这里插入图片描述

一般α和β都取0.5,也就是把原来( n · I )的范围从[-1, 1]映射到[0, 1],即法线平行光照的片元才会是全黑的。

在这里插入图片描述

从逐片元光照代码中直接修改公式即可。

// 将原本n·l的[-1,1]映射到[0,1],两个常量可以变,通常都是两个0.5
fixed halfLambert = dot(worldNormal,worldLight) * 0.5 + 0.5;
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * halfLambert;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值