从零开始实现Unity光照模型_01_标准光照模型与漫反射_技术美术基础学习记录

从零开始实现Unity光照模型_01_标准光照模型与漫反射

标准光照模型

标准光照模型是BRDF理论,也就是PBS技术被提出之前游戏领域应用较为广泛的光照模型。
简略来说其大概分为四个经验模型的结合。

  1. 自发光emissive部分。
  2. 环境光ambient部分。
  3. 漫反射diffuse部分。
  4. 高光反射specular部分。

自发光部分和环境光部分属于较为简易的直接叠加,因此不做赘述。

漫反射

漫反射的公式大致如下: C d i f f u s e = ( C l i g h t ⋅ M d i f f u s e ) m a x ( 0 , n ⃗ ⋅ l ⃗ ) \bold C_{diffuse}=(\bold C_{light}\cdot \bold M_{diffuse})max(0,\vec\bold n\cdot \vec\bold l) Cdiffuse=(ClightMdiffuse)max(0,n l )
漫反射模型的颜色结果是光照颜色和本身颜色的叠加结果,当然这里要算上世界坐标下的法向量 n ⃗ \vec\bold n n 和光源方向 l ⃗ \vec\bold l l 的点乘结果,并且为了保证结果大于零,需要用max函数做一个截取。
其中 C l i g h t \bold C_{light} Clight将来还需要考虑光照的衰减。 M d i f f u s e \bold M_{diffuse} Mdiffuse需要考虑到材质本身的采样颜色。但是今天只实现到单一颜色下的漫反射模型。
代码如下:

Shader "Custom/Diffuse"//声明一个shader的名称,格式为 文件夹/文件夹/.../文件夹/shader名称
{
    Properties//声明材质中可选的属性
    {
        _Diffuse ("Diffuse", Color) = (1,1,1,1)//格式为 _PropertyName("Displayed Name",Type)=DefaultValue
	}
		SubShader
		{
			Tags { "RenderType" = "Opaque" }//表明这个着色器的渲染属性,意思是使用不透明渲染模式
			LOD 200
			Pass{
				Tags{"LightMode"="ForwardBase"}//表明这个Pass的渲染属性,这里指定了光照模式,是前向渲染中的Base模式,
												//会考虑最重要光源进行计算
				CGPROGRAM//开始一段CG代码段
			#pragma vertex vert
			#pragma fragment frag
			#include "Lighting.cginc"//Unity自带的光照文件,包含了许多内置变量,例如下文用到的UNITY_LIGHTMODEL_AMBIENT
									//和_WorldSpaceLightPos0
				fixed4 _Diffuse;//声明外部变量,要求一定要是对应的变量类型和变量名,不能有错。
				//(吐槽一下如果定的这么死为什么不干脆直接让引擎处理了省的复制粘贴。)
				
				
		struct a2v {//输入结构体
			float4 vertex:POSITION;//利用语义向变量中填充所需的数据,这里填充的是每个顶点在模型空间下的坐标
			float3 normal:NORMAL;//模型空间下的法向量。一般来说需要转化为世界坐标使用
			
		};
		struct v2f {//顶点着色器的输出结构体,片元着色器的输入结构体
			float4 pos:SV_POSITION;//SV_POSITION这个语义会将pos内的数据输出到屏幕坐标上
			float3 worldNormal:TEXCOORD0;//采用一个寄存器来存储worldNormal变量。
		};
		v2f vert(a2v v) {
			v2f o;
			o.pos = UnityObjectToClipPos(v.vertex);//将模型上的点显示到屏幕上的正确位置
			o.worldNormal = mul(v.normal, unity_WorldToObject);//获得模型上每个点的世界空间下的法向量方向
			return o;//将v2f输出传递到片元着色器中。
		}
		fixed4 frag(v2f i) : SV_TARGET{
			float4 worldLightDir = normalize(_WorldSpaceLightPos0);//在这里使用的是平行光,
			//因此这个系统变量存储的就是光源的方向,
			//如果不是平行光,那么光源方向要用光源坐标减去顶点坐标才行。
			//可以考虑使用ifdef语法进行区分
			float3 ambient = UNITY_LIGHTMODEL_AMBIENT;//利用系统变量直接获得环境光信息。
			//经过一番实验,这个环境光信息是Unity->windows->
			//rendering->lighting settings中Enviroment lighting下的颜色信息,
			//如果采用渐变颜色的话,那么使用的是天空信息。
			float3 diffuse = _Diffuse.rgb * dot(i.worldNormal, worldLightDir);
			return fixed4(diffuse.rgb+ambient,1.0);//返回颜色值
		}
			ENDCG
		}
    }
    FallBack "Diffuse"
}

给自己的提醒备注

  1. 整理记忆属性类型表,哪种属性对应哪种变量类型,方便查阅。
  2. Subshader 的Tags,其常用种类和用途,方便查阅。
  3. 一般的顶点片元着色器的格式框架以及表面着色器的格式框架,防止写代码时脑袋一片空白。
  4. LOD相关细节,其数值的含义。
  5. 光照 衰减 阴影相关的内置变量和矩阵,以及写法归纳总结。

参考文献:

UnityShader入门精要 _ 人民邮电出版社 _ 冯乐乐编著

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值