ShaderLab学习小结(十四)点光源问题
  5WVVrgL6K2nc 2023年11月02日 35 0

之前在“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出来的 两个球体都反射了平行光和点光源,看上去两个的漫反射的效果基本一样 下面的球体暗部边缘处更黑一些 注:本例只做漫反射

【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
  jo5M4GCiOHdG   2023年11月12日   18   0   0 Unity教程Unity
5WVVrgL6K2nc