Shader学习曲线异常陡峭,记录一下学习过的shader,欢迎大家一起解读
Properties
{
_Diffuse ("Diffuse", Color) = (1,1,1,1)
// 用于控制高光反射的颜色
_Specular ("Specular", Color) = (1,1,1,1)
// 用于控制高光区域的大小
_Gloss ("Gloss", Range(8.0, 256)) = 20
}
SubShader
{
Pass
{
// 用于定义该Pass在光照流水线中的角色,只有正确定义了LightMode,才能获得Unity内置的光照变量
Tags { "LightMode" = "ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
struct a2v
{
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f
{
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD0;
float3 worldPos : TEXCOORD1;
};
fixed4 _Diffuse;
fixed4 _Specular;
float _Gloss;
v2f vert (a2v v)
{
v2f o;
// 这里等价于 mul(UNITY_MATRIX_MVP, v.vertex);
o.pos = UnityObjectToClipPos(v.vertex);
// 法线转换
//o.worldNormal = normalize(mul(v.normal, (float3x3) unity_WorldToObject));
// * 使用内置函数进行法线转换
o.worldNormal = UnityObjectToWorldNormal(v.normal);
// 使用模型空间到世界空间的变换矩阵对顶点进行变换
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
return o;
}
fixed4 frag(v2f i) : SV_Target
{
// 环境光
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
// 法线归一化
fixed3 worldNormal = normalize(i.worldNormal);
// 光源方向归一化 _WorldSpaceLightPos0来自Unity内置
//fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
// * 使用Unity内置函数计算光源方向
fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
// 计算漫反射
// 漫反射 = 入射光线的颜色和强度 * 材质的漫反射系数 * 表面法线和光源方向的点乘结果
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal, worldLightDir));
// 计算入射光线方向相对于法线的反射方向
// CG提供的reflect函数要求的入射方向是指向光源处的,所以我们需要将向量取反
fixed3 reflectDir = normalize(reflect(-worldLightDir, worldNormal));
// 然后我们通过_WorldSpaceCameraPos得到世界空间中的摄像机位置,再把顶点位置从模型空间变换到世界空间
// 最后再相减, 就可以得到世界空间下的视角方向
//fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);
// * 使用Unity内置函数获取来计算视角方向
fixed3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
// BlinnPhong模型新引入的向量 光源方向+视角方向, 需要确保同一坐标系
fixed3 halfDir = normalize(worldLightDir + viewDir);
// 到此我们已经获得了所有的4个参数,代入公式即可得到高光反射的光照部分。
// 入射光线的颜色和强度 (光源的颜色和强度 _LightColor0 Unity内置,通过设置合适的LightMode获得)
// 材质的高光反射系数 (_Specular 自定义)
// 视角方向 (viewDir 通过摄像机位置减去顶点位置得到)
// BlinnPhong新向量 (halfDir 光源方向+视角方向后归一化 )
// BlinnPhong高光 = 入射光线的颜色和强度 * 材质的高光反射系数 * max(法线 点乘 halfDir)的_Gloss次方
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0,dot(worldNormal, halfDir)), _Gloss);
// 加入环境光和漫反射
fixed3 color = ambient + diffuse +specular;
return fixed4(color,1.0);
}
ENDCG
}
}