1、原理
物体表面反射光线是由三部分组成:环境光 + 漫反射光 + 镜面反射光(高光反射光)
2、Shader 中的环境光
环境光变量其实是可以在Unity中进行设置的
Window——> Rendering——> Lighting
Environment(环境)页签中的Environment Lighting(环境光)
这里可以设置环境光来源
当是Skybox和Color时,我们可以通过 UNITY_LIGHTMODEL_AMBIENT 获取到对应环境光颜色
当是Gradient(渐变)时,通过以下3个成员可以得到对应的环境光
- unity_AmbientSky(周围的天空环境光)
- unity_AmbientEquator(周围的赤道环境光)
- unity_AmbientGround(周围的地面环境光)
3、Phong光照模型的公式
物体表面光照颜色 = 环境光颜色 + 漫反射光颜色 + 高光反射光颜色
其中:
- 环境光颜色 = UNITY_LIGHTMODEL_AMBIENT(unity_AmbientSky、unity_AmbientEquator、unity_AmbientGround)
- 漫反射光颜色 = 兰伯特光照模型 计算得到的颜色
- 高光反射光颜色 = Phong式高光反射光照模型 计算得到的颜色
PS:两个颜色相乘和相加的区别
相乘: 颜色相乘时,最终颜色会往黑色靠拢,计算两个颜色混合时一般用颜色相乘,因为真实世界中多个颜色混在一起最终会变成黑色
相加: 颜色相加时,最终颜色会往白色靠拢,计算光照反射时一般用颜色相加,因为向白色靠拢能带来 更亮的感觉,复合光的表现
4、逐顶点光照
Shader "ShaderProj/1/Phong_vertex"
{
Properties
{
_MainColor("_MainColor", Color)=(1,1,1,1)
_SpecularColor("_SpecularColor", Color)=(1,1,1,1)
_SpecularNum("_SpecularNum", Range(0,30)) = 0.5
}
SubShader
{
Tags { "LightMode"="ForwardBase" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
struct v2f
{
float4 pos:SV_POSITION;
fixed3 color:COLOR;
};
fixed3 _MainColor;
fixed3 _SpecularColor;
float _SpecularNum;
// lambert function
fixed3 getLambertColor(in float3 objNormal)
{
float3 normal = UnityObjectToWorldNormal(objNormal);
float3 lightDir = normalize(_WorldSpaceLightPos0);
fixed3 color = _LightColor0.rgb * _MainColor.rgb * max(0, dot(normal, lightDir));
return color;
}
// phong specular function
fixed3 getSpecularColor(in float4 pos, in float3 objNormal)
{
float3 worldPos = mul(unity_ObjectToWorld, pos);
float3 normal = UnityObjectToWorldNormal(objNormal);
float3 viewDir = normalize(_WorldSpaceCameraPos.xyz - worldPos);
float3 lightDir = normalize(_WorldSpaceLightPos0);
float3 reflectDir = reflect(-lightDir, normal);
fixed3 color = _LightColor0.rgb * _SpecularColor.rgb * pow(max(0, dot(viewDir, reflectDir)), _SpecularNum);
return color;
}
v2f vert (appdata_base v)
{
v2f data;
data.pos = UnityObjectToClipPos(v.vertex);
fixed3 lambertColor = getLambertColor(v.normal);
fixed3 specularColor = getSpecularColor(v.vertex, v.normal);
data.color = lambertColor + specularColor + UNITY_LIGHTMODEL_AMBIENT;
return data;
}
fixed4 frag (v2f i) : SV_Target
{
return fixed4(i.color, 1);
}
ENDCG
}
}
}
5、逐片元光照
Shader "ShaderProj/1/Phong_frag"
{
Properties
{
_MainColor("_MainColor", Color)=(1,1,1,1)
_SpecularColor("_SpecularColor", Color)=(1,1,1,1)
_SpecularNum("_SpecularNum", Range(0, 30))=0.5
}
SubShader
{
Tags {"LightMode"="ForwardBase" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
struct v2f
{
float4 pos:SV_POSITION;
float3 normal:NORMAL;
float4 wPos:TEXCOORD0;
};
fixed3 _MainColor;
fixed3 _SpecularColor;
float _SpecularNum;
fixed3 getLambertColor(in float3 normal)
{
float3 lightDir = normalize(_WorldSpaceLightPos0);
fixed3 color = _LightColor0.rgb * _MainColor.rgb * max(0, dot(normal, lightDir));
return color;
}
fixed3 getSpecularColor(in float3 worldPos, in float3 normal)
{
float3 viewDir = normalize(_WorldSpaceCameraPos - worldPos);
float3 lightDir = normalize(_WorldSpaceLightPos0);
float3 reflectDir = reflect(-lightDir, normal);
fixed3 color = _LightColor0.rgb * _SpecularColor.rgb * pow(max(0, dot(viewDir, reflectDir)), _SpecularNum);
return color;
}
v2f vert (appdata_base v)
{
v2f data;
data.pos = UnityObjectToClipPos(v.vertex);
data.wPos = mul(unity_ObjectToWorld, v.vertex);
data.normal = UnityObjectToWorldNormal(v.normal);
return data;
}
fixed4 frag (v2f i) : SV_Target
{
fixed3 lambertColor = getLambertColor(i.normal);
fixed3 specularColor = getSpecularColor(i.wPos, i.normal);
fixed3 color = lambertColor + specularColor + UNITY_LIGHTMODEL_AMBIENT;
return fixed4(color, 1);
}
ENDCG
}
}
}