光照模型
基本光照模型中高光反射部分的计算公式
Mgloss 光泽度,反光度,控制高光区域的大小,值越大,亮点越小
Mspecular 材质的高光反射颜色,它用于控制该材质对于高光反射的强度和颜色
Clight 光源颜色和强度
v 是视角方向
r 是反射方向,可以通过计算反射方向的函数
r = reflect(I,n)
I,入射方向(要求由光源指向交点处)
n 法线方向
r = 2 (n * I)* n - I 菱形
Blinn-Phong 模型的公式
h = normalize(v + I)
实现
逐顶点光照
缺点:高光部分明显不平滑。主要原因是,高光反射部分的计算是非线性的,而在顶点着色器中计算光照再进行插值的过程是线性的,破坏了原计算的非线性关系,就会出现较大的视觉问题,因此,我们需要使用逐像素的方法来计算高光反射。
Shader "Custom/Shader6_1_sepular_v"
{
// 高光反射,逐顶点光照
// 基础高光放射模型 Csepular = (Clight * Msepular)max(0, n*r)Mgloss
Properties
{
_Diffuse("Diffuse",color)=(1,1,1,1)
_Sepular("Sepular",color)=(1,1,1,1)
_Gloss("Gloss",Range(0,256))=128
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 200
Pass
{
Tags{"LightModel"="ForwardBase"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
fixed4 _Diffuse;
fixed4 _Sepular;
float _Gloss;
struct a2v
{
float4 position:POSITION;
float3 normal:NORMAL;
};
struct v2f
{
float4 pos:SV_POSITION;
fixed3 color:COLOR;
};
v2f vert(a2v v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.position);
// 环境光
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
// 漫反射
fixed3 worldNormal = normalize(mul(v.normal, (fixed3x3)unity_WorldToObject));
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
// 半兰伯特公式
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * (0.5 * dot(worldNormal, worldLightDir) + 0.5);
// 高光反射
fixed3 reflectDir = normalize(reflect(-worldLightDir, worldNormal));
fixed3 sepular = _LightColor0.rgb * _Sepular.rgb * pow(saturate(dot(worldLightDir, reflectDir)), _Gloss);
o.color = ambient + diffuse + sepular;
return o;
}
fixed4 frag(v2f v):SV_Target
{
return fixed4(v.color, 1.0);
}
ENDCG
}
}
FallBack "Diffuse"
}
逐像素光照
使用逐像素的方式处理可以得到更加平滑的高光效果。
Shader "Custom/Shader6_1_sepular_f"
{
// 逐像素光照
Properties
{
_Diffuse("Diffuse",color) = (1,1,1,1)
_Sepular("Sepular",color) = (1,1,1,1)
_Gloss("Gloss",Range(0, 8)) = 4
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 200
Pass
{
Tags{"LightModel"="ForwardBase"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
fixed4 _Diffuse;
fixed4 _Sepular;
float _Gloss;
struct a2v
{
float4 position:POSITION;
float3 normal:NORMAL;
};
struct v2f
{
float4 pos:SV_POSITION;
float3 worldNor:TEXCOORD0;
float3 worldPos:TEXCOORD1;
};
v2f vert(a2v v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.position);
o.worldNor = mul(v.normal, (fixed3x3)unity_WorldToObject);
o.worldPos = mul(unity_ObjectToWorld,v.position).xyz;
return o;
}
fixed4 frag(v2f v):SV_Target
{
// 环境光
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
fixed3 worldNormal = normalize(v.worldNor);
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
// 漫反射
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * (0.5 * (dot(worldNormal, worldLightDir)) + 0.5);
// 反射方向
fixed3 reflectDir = normalize(reflect(-worldLightDir, worldNormal));
// 视觉方向
fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - v.worldPos.xyz);
// 高光反色
fixed3 sepular = _LightColor0.rgb * _Sepular.rgb * pow(saturate(dot(reflectDir, viewDir)), _Gloss);
fixed3 c = ambient + diffuse + sepular;
return fixed4(c, 1.0);
}
ENDCG
}
}
FallBack "Diffuse"
}
Blinn-Phong 模型
Blinn-Phong 光照模型的高光反射部分看起来更大、更亮一些。
Shader "Custom/Shader6_2_sep_bp"
{
Properties
{
_Diffuse("Diffuse",color)=(1,1,1,1)
_Specular("Specular",color)=(1,1,1,1)
_Gloss("Gloss",Range(0,20))=10
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 200
Pass
{
Tags{"LightModel"="ForwardBase"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
fixed4 _Diffuse;
fixed4 _Specular;
float _Gloss;
struct a2v
{
float4 position:POSITION;
float3 normal:NORMAL;
};
struct v2f
{
float4 pos:SV_POSITION;
float3 worldNor:TEXCOORD0;
float3 worldPos:TEXCOORD1;
};
v2f vert(a2v v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.position);
o.worldNor = mul(v.normal, (fixed3x3)unity_WorldToObject);
o.worldPos = mul(unity_ObjectToWorld, v.position).xyz;
return o;
}
fixed4 frag(v2f v):SV_Target
{
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
fixed3 worldNor = normalize(v.worldNor);
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNor, worldLightDir));
fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - v.worldPos);
fixed3 h = normalize(viewDir + worldLightDir);
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(worldNor, h)), _Gloss);
return fixed4(ambient + diffuse + specular, 1);
}
ENDCG
}
}
FallBack "Diffuse"
}