用于学习《Unity Shader 入门精要》过程记录
定义Shader的光照类型"LightMode"="ForwardBase"
在Shader中加载Unity内置库文件 Lighting.cginc。
1.使用UnityObjectToClipPos将模型坐标转换至空间坐标
2.使用unity_WorldToObject矩阵将模型坐标转换至空间坐标
3.使用UNITY_LIGHTMODEL_AMBIENT获取环境光
4.使用_WorldSpaceLightPos0获取主平行光位置
5.使用_LightColor0获取顶点光源强度信息
相对于顶点光照,片元光照过度更加平滑。
在场景中添加两个球体,将顶点光照和片元光照分别赋值给其Material,具体效果如下图:
对比图
Shader "ShaderStudy/004"
{
//属性
Properties
{
//定义一个颜色属性 Diffuse
_Diffuse ("Diffuse",Color)=(1,1,1,1)
}
SubShader
{
Pass
{
//定义光照模型为 ForwardBase
Tags{"LightMode"="ForwardBase"}
//CG 程序开始
CGPROGRAM
//编译指令 顶点着色器代码在 name(vert)中
#pragma vertex vert
//编译指令 片元着色器代码在 name(frag)中
#pragma fragment frag
//添加Lighting.cginc库文件 包含_LightColor0
#include "Lighting.cginc"
//声明颜色属性变量 _Diffuse
fixed4 _Diffuse;
//定义结构体 用于顶点着色器的输入数据
struct v2a
{
//定义 pos 为模型顶点位置信息
float4 pos:POSITION;
//定义 normal 为模型顶点法线信息
float3 normal:NORMAL;
};
//定义一个结构,用于顶点着色器的输出数据
struct v2f
{
//定义 pos 为空间裁剪位置信息
float4 pos:SV_POSITION;
//定义 worldNormal 为空间法线信息
fixed3 worldNormal:TEXCOORD0;
};
//顶点着色器 输入参数为结构体v2a(name) 输出参数为结构体 v2f(name)
v2f vert(v2a v)
{
v2f o;
//将模型顶点坐标 转换至裁剪空间坐标
o.pos=UnityObjectToClipPos(v.pos);
//获取顶点法线在世界坐标系中的信息
o.worldNormal=mul(v.normal,(float3x3)unity_WorldToObject);
return o;
}
//片元着色器 输入参数为结构体 v2f(name) 输出存贮到渲染目标
fixed4 frag(v2f i) : SV_Target
{
//获取环境光信息
fixed3 ambient=UNITY_LIGHTMODEL_AMBIENT.xyz;
//获取顶点法线在空间坐标系下的单位向量
fixed3 worldNormal=normalize(i.worldNormal);
//获取主平行光在空间坐标系下的单位向量
fixed3 worldLightDir=normalize(_WorldSpaceLightPos0.xyz);
//片元光照强度*自定义颜色属性*saturate(两向量的投影值Float)
//片元向量和平行光之间的关系决定顶点光照的强度,平行时最强,垂直时最弱
fixed3 diffuse=_LightColor0.rgb*_Diffuse.rgb*saturate(dot(worldNormal,worldLightDir));
//环境光的颜色+片元光照颜色
return fixed4(ambient+diffuse,1.0);
}
//CG程序结束
ENDCG
}
}
FallBack "Diffuse"
}