高光反射光照模型分为Phong模型和Blinn-Phong模型:
Phong 模型公式:
高光反射 = 光源颜色 * 反射颜色 ∗ pow( max(0, 视角v与光反射向量r的余弦值) , 光泽度)
如下图:
Blinn-Phong 模型公式:
高光反射 = 光源颜色 * 反射颜色 ∗ pow( max(0, 半角向量h与法线n的余弦值) , 光泽度)
如下图:
逐顶点高光反射:
Shader "Unlit/003"
{
Properties
{
_Specular ("_Specular",Color) = (1,1,1,1)
// 高光反射值
_Gloss ("_Gloss",range(1,100)) = 5
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
float4 _Specular;
half _Gloss;
struct v2v
{
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f
{
float4 vertex : POSITION;
float3 color : Color;
};
v2f vert (v2v v)
{
v2f o;
// 将对象空间中的点变换到齐次坐标中的摄像机裁剪空间
o.vertex = UnityObjectToClipPos(v.vertex);
// 光源方向
float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
// 将法向量转到世界坐标法向量
float3 normal = UnityObjectToWorldNormal(v.normal);
// 视野方向
float3 viewDir = normalize(_WorldSpaceCameraPos.xyz- UnityObjectToWorldDir(v.vertex));
// 反射方向
float3 reflectDir = normalize(mul(normal,2) - lightDir);
// float3 reflectDir = normalize(reflect(-lightDir,normal));
// Phong 模型公式高光反射计算
float3 specular = _LightColor0.rab * _Specular.rgb * pow(max(0,dot(reflectDir,viewDir)),_Gloss);
// 半角向量
float3 _half = normalize(mul(lightDir + viewDir,0.5));
// Blinn-Phong 模型公式高光反射计算
//float3 specular = _LightColor0.rab * _Specular.rgb * pow(max(0,dot(_half,normal)),_Gloss);
o.color = specular;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
float4 color = float4(i.color,1);
return color;
}
ENDCG
}
}
}
逐片元:
Shader "Unlit/004"
{
Properties
{
_Specular ("_Specular",Color) = (1,1,1,1)
// 高光反射值
_Gloss ("_Gloss",range(1,256)) = 5
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
float4 _Specular;
half _Gloss;
struct v2v
{
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f
{
float4 vertex : POSITION;
float3 normal : TEXCOORD0;
float3 worldPos : TEXCOORD1;
};
v2f vert (v2v v)
{
v2f o;
// 将对象空间中的点变换到齐次坐标中的摄像机裁剪空间
o.vertex = UnityObjectToClipPos(v.vertex);
o.normal = UnityObjectToWorldNormal(v.normal);
o.worldPos = UnityObjectToWorldDir(v.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
float3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos);
float3 reflectDir = normalize(mul(i.normal , 2) - _WorldSpaceLightPos0.xyz);
// Phong 模型公式高光反射计算
float3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0,dot(reflectDir,viewDir)),_Gloss);
// 半角向量
float3 _half = normalize(mul(normalize(_WorldSpaceLightPos0.xyz) + viewDir,0.5));
// Blinn-Phong 模型公式高光反射计算
//float3 specular = _LightColor0.rab * _Specular.rgb * pow(max(0,dot(_half,i.normal)),_Gloss);
return float4(specular,1);
}
ENDCG
}
}
}
看下效果 左边是逐顶点,右边是逐片源
phong 模型:
Blinn-Phong 模型:
可以看到逐顶点渲染和逐像素渲染的区别:逐片元更加细腻