光源類型
- 方向光:Directional
- 點光源:Point
- 聚光燈:Spot
光照模型
每一種類型的光源都可能同時會有以下光照模型:
- Diffuse:漫反射
- Specular:鏡面反射
光照衰減
- 方向光:沒有衰減
- 點光源
- 距離衰減:光源有光照範圍[near,far],在near距離內的光照係數爲1,在far距離外的光照係數爲0,在該兩者之間的頂點會隨距離進行衰減,光照強度與距離的平方成反比。Unity中的計算方式爲:DisAtten = 1/(1 +atten*atten * dis * dis),其中atten是衰減係數,dis是到光源的距離
- 聚光燈
- 距離衰減:與點光源一樣
- 聚光衰減:除了距離衰減,聚光燈還有圓錐內的衰減。聚光燈的光照區域是個圓錐體,該圓錐體有外錐角A和內錐角B,在內錐角內的頂點無聚光衰減,在外錐角外的點無光照效果,光照係數。在內外錐角之間的頂點會進行衰減。假設頂點與光照方向的夾角爲C。則其聚光衰減係數爲:Spot = (cos(C/2) - cos(A/2)) / (cos(B/2) - cos(A/2))
- 最終的衰減係數爲:FinalAtten = DisAtten * SpotAtten。
光照計算
最終光照結果是所有光照成分的總和 = 環境光 + 自發光+ sum(漫反射)+sum(鏡面反射)。
- 環境光:AmbitentColor * AmbientMaterial * AmbientIntensity
- 自發光:EmissionColor * EmissionIntensity
- 漫反射:LightColor * DiffuseMaterial * DiffuseIntensity * dot(N,L) 。N是法線方向,L是指向光源的方向向量。以下方式計算法線N和L的點積(即夾角餘弦)
- 鏡面反射:LightColor * SpecularMaterial * SpecularIntensity * pow(dot(R,V),shininess),其中R是反射光的方向,V是頂點到眼睛的方向。
- 強度intensity默認都是1。SpecularMaterial默認都是1。
- 計算函數
@ lightPostion:平行光(-direction,0) 點光源和聚光燈(position,1)
@ lightColor:燈光顏色
@ eyePos:頂點在相機空間的座標
@ eyeyNormal:頂點在相機空間的法線
@ viewDir:頂點到相機的方向
@ diffuseMaterial:漫反射材質係數
@ specularMaterial:鏡面反射材質係數,unity中不設置,默認爲1
@ shininess:鏡面反射高亮度,[0,1]
@ atten:反射增強係數
@ specColor:鏡面反射結果
@ return:漫反射結果
half computeLighting(float4 lightPostion,half3 lightColor,
float3 eyePos,half3 eyeNormal,half3 viewDir,
half3 diffuseMaterial,half3 specularMaterial,half shininess,
half atten,inout half3 specColor)
{
float3 dirToLight = lightPostion //光照方向的反向
if(lightPostion.w == 1)
{
dirToLight -= eyePos
dirToLight = normalize(dirToLight)
}
half NdotL = max(dot(eyeNormal,dirToLight),0)
half3 diffse = lightColor * diffuseMaterial * atten
if(NdotL > 0)
{
half3 h = normalize(dirToLight + viewDir)
half HdotN = max(dot(eyeNormal,h),0)
half sp = saturate(pow(HdotN,shininess * 128))
half3 specular = atten * lightColor * specularMaterial * sp
specColor += specular
}
return diffse
}