Unity的光源類(lèi)型
Unity一共支持4種光源類(lèi)型:平行光(directional light)貌虾、點(diǎn)光源(point light)限煞、聚光燈(spot light)撮抓、面光源(area light)棋电。而面光源僅在烘焙時(shí)才可以發(fā)揮作用
1、光源類(lèi)型有什么影響
一般經(jīng)常使用的光源屬性有:位置椎组、方向油狂、顏色、強(qiáng)度寸癌,衰減
(1)平行光专筷,只有方向,顏色灵份,強(qiáng)度仁堪,沒(méi)有衰減
(2)點(diǎn)光源,位置、方向带欢、顏色黄娘、強(qiáng)度,衰減全有
(3)聚光燈朴上,位置、方向、顏色枪眉、強(qiáng)度,衰減全有
2再层、在Unity中使用前向渲染處理多光源
Shader "Unlit/ForwardRenderingMat"
{
Properties
{
_Diffuse("Diffuse",Color)=(1,1,1,1)
_Specular("Specular",Color)=(1,1,1,1)
_Gloss("Gloss",Range(8.0,256))=20
}
SubShader
{
Pass //第一個(gè)Pass使用Base用來(lái)逐像素平行光光照
{
Tags{"LightModel"="ForwardBase"}
CGPROGRAM
#include "Lighting.cginc"
#pragma vertex vert
#pragma fragment frag
fixed4 _Diffuse;
fixed4 _Specular;
float _Gloss;
struct a2v
{
float4 vertex:POSITION;
float3 normal:NORMAL;
};
struct v2f
{
float4 pos:SV_POSITION;
float3 worldPos:TEXCOORD0;
float3 worldNormal:TEXCOORD1;
};
v2f vert(a2v v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.worldPos = mul(unity_ObjectToWorld,v.vertex).xyz;
o.worldNormal = UnityObjectToWorldNormal(v.normal);
return o;
}
fixed4 frag(v2f i):SV_TARGET
{
float3 worldPos = i.worldPos;
float3 worldNormal = normalize(i.worldNormal);
float3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
float3 worldViewDir = normalize(_WorldSpaceCameraPos.xyz-i.worldPos.xyz);
float3 halfNormal = normalize(worldLightDir+worldViewDir);
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
//_LightColor0已經(jīng)是顏色和強(qiáng)度相乘之后的結(jié)果了
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal,worldLightDir));
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(worldNormal,halfNormal)),_Gloss);
fixed atten = 1.0; //光的衰減贸铜,平行光是沒(méi)有衰減的
return fixed4(ambient+(diffuse+specular)*atten,1.0);
}
ENDCG
}
Pass //第二個(gè)Pass用來(lái)計(jì)算其他光源的逐像素光照,可能是平行光聂受,也可能是點(diǎn)光源蒿秦,聚光燈
{
Tags{"LightModel"="ForwardAdd"}
Blend One One
CGPROGRAM
#include "Lighting.cginc"
#include "AutoLight.cginc"
//為了得到正確的衰減因子
// #pragma multi_compile_fwadd
#pragma multi_compile_fwadd_fullshadows
#pragma vertex vert
#pragma fragment frag
fixed4 _Diffuse;
fixed4 _Specular;
float _Gloss;
struct a2v
{
float4 vertex:POSITION;
float3 normal:NORMAL;
};
struct v2f
{
float4 pos:SV_POSITION;
float3 worldPos:TEXCOORD0;
float3 worldNormal:TEXCOORD1;
};
v2f vert(a2v v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.worldPos = mul(unity_ObjectToWorld,v.vertex).xyz;
o.worldNormal = UnityObjectToWorldNormal(v.normal);
return o;
}
fixed4 frag(v2f i):SV_TARGET
{
fixed3 worldPos = i.worldPos;
fixed3 worldNormal = normalize(i.worldNormal);
#ifdef USING_DIRECTIONAL_LIGHT
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
#else
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz-i.worldPos);
#endif
fixed3 worldViewDir = normalize(_WorldSpaceCameraPos.xyz-i.worldPos);
fixed3 halfNormal = normalize(worldViewDir+worldLightDir);
//因?yàn)橐呀?jīng)在第一個(gè)Pass中計(jì)算了環(huán)境光,所以這里就不需要再次計(jì)算了
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal,worldLightDir));
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(worldNormal,halfNormal)),_Gloss);
#ifdef USING_DIRECTIONAL_LIGHT
fixed atten = 1.0;
#else
//Unity提供了衰減因子的查找表蛋济,并存在了一個(gè)圖片中棍鳖,我們只要采樣就可以
//但這樣也會(huì)有精度的問(wèn)題
#if defined(POINT)
float3 lightCoord = mul(unity_WorldToLight,float4(i.worldPos,1)).xyz;
//A.rr操作相當(dāng)于是取了兩個(gè)一樣的值(A,A)
fixed atten = tex2D(_LightTexture0,dot(lightCoord,lightCoord).rr).UNITY_ATTEN_CHANNEL;
#elif defined(SPOT)
float4 lightCoord = mul(unity_WorldToLight, float4(i.worldPos, 1));
fixed atten = (lightCoord.z > 0) * tex2D(_LightTexture0, lightCoord.xy / lightCoord.w + 0.5).w * tex2D(_LightTextureB0, dot(lightCoord, lightCoord).rr).UNITY_ATTEN_CHANNEL;
#else
fixed atten = 1.0;
#endif
#endif
return fixed4((diffuse+specular)*atten,1.0);
}
ENDCG
}
}
}
從Frame Debug中可以看出第一個(gè)Pass使用了BasePass并執(zhí)行了一次,而第二個(gè)Pass使用了Addtional Pass執(zhí)行了4次碗旅,因?yàn)閳?chǎng)景中除了一個(gè)平行光之外還有一個(gè)4個(gè)其他可以逐像素的光源渡处。