ShaderLab学习小结(十四)点光源问题
之前在“ShaderLab学习小结(三)漫反射+高光+点光源”中
用了Shade4PointLights()函数来计算点光源的反射。
这个函数定义在unitycg.cginc中,其中用到的前八个参数来自于UnityShaderVariables.cginc。
在这个例子中,只一个pass就实现了平行光、点光源反射,以及高光反射。
后来在学习中,接触到另一种点光源反射的例子,用到两个pass,第一个pass实现平行光的,第二个实现点光源的
Shader "Custom/TestLightColor0" { SubShader { pass{ tags{"LightMode"="ForwardBase"} CGPROGRAM #pragma vertex vert #pragma fragment frag #include "unitycg.cginc" #include "lighting.cginc" struct v2f{ float4 pos:POSITION; float3 normal:NORMAL; float3 wpos:TEXCOORD0; }; v2f vert(appdata_base v) { v2f o; o.pos=mul(UNITY_MATRIX_MVP,v.vertex); o.normal=UnityObjectToWorldNormal(v.normal); o.wpos=mul(unity_ObjectToWorld, v.vertex).xyz; return o; } fixed4 frag(v2f IN):COLOR { float3 N = IN.normal; float3 L = normalize(_WorldSpaceLightPos0).xyz; float ndotl=saturate(dot(N,L)); fixed4 col=_LightColor0*ndotl; col+=UNITY_LIGHTMODEL_AMBIENT; return col; } ENDCG } pass{ tags{"LightMode"="ForwardAdd"} blend one one CGPROGRAM #pragma vertex vert #pragma fragment frag #include "unitycg.cginc" #include "lighting.cginc" struct v2f{ float4 pos:POSITION; float3 normal:NORMAL; float3 wpos:TEXCOORD0; }; v2f vert(appdata_tan v) { v2f o; o.pos=mul(UNITY_MATRIX_MVP,v.vertex); o.normal=UnityObjectToWorldNormal(v.normal); o.wpos=mul(unity_ObjectToWorld, v.vertex).xyz; return o; } fixed4 frag(v2f IN):COLOR { float3 N = IN.normal; float3 L = normalize(_WorldSpaceLightPos0).xyz; float ndotl=saturate(dot(N,L)); float atten=1; if(_WorldSpaceLightPos0.w!=0) { atten = 1.0/length(_WorldSpaceLightPos0.xyz); } fixed4 col=_LightColor0*ndotl*atten; return col; } ENDCG } }}
两个pass几乎一样,叫pass1和pass2吧。pass1是forwardbase,pass2是forwardadd,pass2还要用上blend one one,不然pass1的光照就没了,因为pass1中加了环境光LIGHT_MODEL_AMBIENT,pass2中就不用再加了。
共同点,都用的是_LightColor0。之前学习时,认为_LightColor0就是指的平行光,所以点光源要用Shade4PointLights,但现在看来并不是。在网上搜索的结果之一:
LightMode=ForwardBase: _LightColor0将会是主要的directional light的颜色。
LightMode=ForwardAdd: _LightColor0将是该逐像素光源的颜色。
也就是说在lightmode为forwardadd的pass里,_LightColor0代表不同的光源
pass2中多定义了一个衰减系数atten,且进行判断赋值
float atten=1;if(_WorldSpaceLightPos0.w!=0){ atten = 1.0/length(_WorldSpaceLightPos0.xyz);}
点光源和平行光不同,与物体距离不同反射的强度也不同,所以这个颜色要乘一个衰减系数。
fixed4 col=_LightColor0*ndotl*atten;
当然这个只是简单写的一个衰减系数
这个衰减系数的计算算是抄来的吧,稍做修改
原出处用的是
atten = 1.0/length(IN.LightDir);
显然这个LightDir是在结构体中要定义,float3型
float3 LightDir:TEXCOORD1;
代表光的方向,且在顶点程序中要转化到切线空间
即
v2f vert(appdata_tan v){ ... TANGENT_SPACE_ROTATION; o.LightDir=mul(rotation, ObjSpaceLightDir(v.vertex)); ...}
也就是计算衰减系数时,length()函数中的参数,我为了更加简化,直接用了_WorldSpaceLightPos0.xyz,就省去了上面那一堆。
最后结果如下两图,点光源为×××
把两个球体放在同一个位置,分别单独显示
上边的是两个通道出来的,下边的是一个通道Shade4PointLights出来的
两个球体都反射了平行光和点光源,看上去两个的漫反射的效果基本一样
下面的球体暗部边缘处更黑一些
注:本例只做漫反射
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。