今天学习_WorldSpaceLightPos0这个cg内置变量的含义的时候,无意中发现了一些有趣的知识点。首先了解到_WorldSpaceLightPos0这个变量的含义是,这是一个表示世界做表中光源的位置矢量或者方向向量,如果_WorldSpaceLightPos0.w为0,则表示该光源为平行光,_WorldSpaceLightPos0.xyz为此平行光的方向向量。反之_WorldSpaceLightPos0.w不为0,则表示光源为点光源,_WorldSpaceLightPos0.xyz为此点光源。
为此,我想尝试在unity场景中设置点光源和平行光源来验证这个效果,于是改了基础shader为:
Shader"Unlit/LightTest{
Properties
{
_MainTex("Texture", 2D) ="white"{}
}
SubShader
{
Tags {"RenderType"="Opaque"}
LOD 100
Pass
{
CGPROGRAM
#pragmavertex vert
#pragmafragment frag
// make fog work
#pragmamulti_compile_fog
#include"UnityCG.cginc"
structappdata
{
float4vertex : POSITION;
float2uv : TEXCOORD0;
};
structv2f
{
float2uv : TEXCOORD0;
UNITY_FOG_COORDS(1)
float4vertex : SV_POSITION;
};
sampler2D_MainTex;
float4_MainTex_ST;
fixed4 _BlackColor;
fixed4 _WhiteColor;
v2f vert(appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
UNITY_TRANSFER_FOG(o,o.vertex);
returno;
}
fixed4 frag(v2f i) : SV_Target
{
// sample the texture
fixed4 col = tex2D(_MainTex, i.uv);
// apply fog
UNITY_APPLY_FOG(i.fogCoord, col);
if(_WorldSpaceLightPos0.w == 0)//平行光源
{
col = fixed4(1, 0, 0, 1.0);
}
else//点光源
{
col = fixed4(0, 1, 0, 1.0);
}
returncol;
}
ENDCG
}
}
}
重点是这几句,如果是平行光源,输出的颜色为红色,如果不是平行光源,输出的颜色为绿色
if(_WorldSpaceLightPos0.w == 0)//平行光源
{
col = fixed4(1, 0, 0, 1.0);
}
else//点光源
{
col = fixed4(0, 1, 0, 1.0);
}
然后在场景上分别创建了一个Directiona light和 Point light,观察结果如下:
1、Directiona light激活,Point light也激活时,金币显示为红色
2、Directiona light激活,Point light不激活时,金币显示为红色
3、Directiona light不激活,Point light激活时,金币显示为红色
4、Directiona light不激活,Point light不激活时,金币显示为红色
这就产生两个问题——
为何Point light存在的时候,没有效果呢?
为何无论平行光有没有存在,_WorldSpaceLightPos0.w一直都是0呢?
后面查找到了这篇文章https://forum.unity.com/threads/_worldspacelightpos0-how-it-works.435673/,一个同学的回答,
如果当前物体的shader设置的光照模式是ForwardBase,那么就总是对平行光有效,即使场景上没有灯光,所以要把LightMode改成"ForwardAdd",Point light才能生效,因此我将Tags标签添加了"LightMode"="ForwardAdd"看下效果:
Tags {"RenderType"="Opaque""LightMode"="ForwardAdd"}
发现:
1、Directiona light激活,Point light也激活时,金币显示为绿色
2、Directional light激活,Point light不激活时,金币不显示了
3、Directiona light不激活,Point light激活时,金币显示为绿色
4、Directiona light不激活,Point light不激活时,金币显示为红色
所以,Shader光照模型要使用Point light,需要在Tag标签上添加"LightMode"="ForwardAdd"
然而,现在又引申出新的知识点,LightMode是什么意思?从字面上的意思是"光照模式",它有多种设置选项,分别是什么含义呢?还有与之相对应的_LightColor0是什么意思?这个我们后面的章节来讲