untiy 3d ShaderLab_第7章_ Forward渲染路径_3_重要光源在ForwardAdd内的执行

7.3重要光源在ForwardAdd内的执行


    此外我们知道,根据Unity在关于Forward RenderingPath的官方帮助文档的陈述,除了第一个Pixel平行光之外,每个其他Pixel光源都会在个单独的ForwardAdd Pass内被执行,也就是说场景中的Pixel光源数为n,则ForwardAdd Pass会被执行n-1次。下面就来验证每一个其他Pixel光源是在ForwardAdd Pass内被执行的。


7.3.1设计用来检测Pixel光源的材质

          Lab_1c文件夹下的场景,其编辑器截图如下图所示,左下角的小球被赋予一个默认材质,左边的大球使用的是_Indicator/ForwardBase文件夹下的_WorIdSapceLightPos0.shader,该Shader只计算了ForwardBase内的_WorldSapceLightPos0的光照效果。而右边的大球则使用了Lablc/Shader文件夹里的_WorIdSpaceLightPos0.shader,该Shader在ForwardBase内的输出为(0,0, 0,  1),保证了只会输出FowardAdd内的结果,而具体的ForwardAdd Pass则使用了Blend OneOne的混合模式,因此都是在上一个ForwardAdd的基础上叠加的效果。

untiy 3d ShaderLab_第7章_ Forward渲染路径_3_重要光源在ForwardAdd内的执行_第1张图片

    下面是_Indicator/ForwardBase/_WorldSapceLightPos0.shader的代码:
Shader "Tut/Lighting/Forward/Indicator/Base/_WorldSpaceLighPos0" {
	Properties {//这个一个只计算了ForwardBase内的_WorldSpaceLightPos0光照的Shader
		_Color ("Base Color", Color) =(1,1,1,1)
	}
	SubShader {
		pass{
		Tags{ "LightMode"="ForwardBase"}
		CGPROGRAM
		#pragma vertex vert
		#pragma fragment frag
		#pragma multi_compile_fwdbase
		#include "UnityCG.cginc"
		#include "Lighting.cginc"


		uniform float4 _Color;


		struct vertOut{
			float4 pos:SV_POSITION;
			float4 color:COLOR;
		};
		vertOut vert(appdata_base v)
		{
			float3 n=(mul(float4(v.normal,0.0),_World2Object)).xyz;
			n=normalize(n);


			float4 lightDir;
			float dist;
			float4 diffColor=float4(0,0,0,0);
			float diff=0;
			float atten=1;


			float4 worldSpaceVertex=mul(_Object2World,v.vertex);


			//first light 第一个重要光源
			float4 lightPos=_WorldSpaceLightPos0;
			if(lightPos.w==0)//direction 此条件可判断光源是否为平行光
			{
				lightDir=lightPos;
				atten=1.0;
			}else//Point/Spot 否则是点光源
			{
				lightDir=lightPos-worldSpaceVertex;
				atten=1/(1+length(lightDir));
				lightDir=normalize(lightDir);
			}
			
			diff=max(0.0,dot(n,lightDir.xyz));
			diffColor=_LightColor0*_Color*diff*atten;


			vertOut o;
			o.pos=mul(UNITY_MATRIX_MVP,v.vertex);
			o.color=diffColor;
			return o;
		}
		float4 frag(vertOut i):COLOR
		{
			return i.color;
		}
		ENDCG
		}//end pass
	}
}
下面是Lab_1c/_Shader文件夹里_WorldSpaceLightPos0.shader的代码:
Shader "Tut/Lighting/Forward/Lab_1c/_WorldSpaceLighPos0" {


	Properties {
		_Color ("Base Color", Color) =(1,1,1,1)
	}
	SubShader {
		pass{
		Tags{ "LightMode"="ForwardBase"}
		CGPROGRAM
		#pragma vertex vert
		#pragma fragment frag
		#pragma multi_compile_fwdbase
		#include "UnityCG.cginc"
		#include "Lighting.cginc"


		uniform float4 _Color;


		struct vertOut{
			float4 pos:SV_POSITION;
			float4 color:COLOR;
		};
		vertOut vert(appdata_base v)
		{
			vertOut o;
			o.pos=mul(UNITY_MATRIX_MVP,v.vertex);
			o.color=float4(0,0,0,1);//通过输出黑色,去掉ForwardBase的影响
			return o;
		}
		float4 frag(vertOut i):COLOR
		{
			return i.color;
		}
		ENDCG
		}//end pass
		pass{//这个ForwardAdd内的光源才是我们需要检测的
		Tags{ "LightMode"="ForwardAdd"}
		Blend One One
		CGPROGRAM
		#pragma vertex vert
		#pragma fragment frag
		#include "UnityCG.cginc"
		#include "Lighting.cginc"


		uniform float4 _Color;


		struct vertOut{
			float4 pos:SV_POSITION;
			float4 color:COLOR;
		};
		vertOut vert(appdata_base v)
		{
			float3 n=(mul(float4(v.normal,0.0),_World2Object)).xyz;
			n=normalize(n);


			float4 lightDir;
			float dist;
			float4 diffColor=float4(0,0,0,0);
			float diff=0;
			float atten=1;


			float4 worldSpaceVertex=mul(_Object2World,v.vertex);


			//first light 第一个重要光源
			float4 lightPos=_WorldSpaceLightPos0;
			if(lightPos.w==0)//direction 此条件可判断光源是否为平行光
			{
				lightDir=lightPos;
				atten=1.0;
			}else//Point/Spot  否则为点光源
			{
				lightDir=lightPos-worldSpaceVertex;
				atten=1/(1+length(lightDir));
				lightDir=normalize(lightDir);
			}
			
			diff=max(0.0,dot(n,lightDir.xyz));
			diffColor=_LightColor0*_Color*diff*atten;


			vertOut o;
			o.pos=mul(UNITY_MATRIX_MVP,v.vertex);
			o.color=diffColor;
			return o;
		}
		float4 frag(vertOut i):COLOR
		{
			return i.color;
		}
		ENDCG
		}//end pass
	}
}
7.3.2设计检测用的场景
    场景中存在一个足够强大的黄色Pixel平行光,强大到可以保证它一定会被ForwardBase内的 _WorldSpaceLightPos0所捕捉,从而不会让任何其他Pixel光源落到ForwardBase内,而只会被放 到ForwardAdd Pass的_WorIdSpaceLightPos0内。最后,场景中还有5个RenderMode为Not Important,即Vertex光源,其色彩分别为青色、橙色、绿色、红色和蓝色。
7.3.3检测结果:ForwardAdd如何被执行

    编译并运行此场景,然后依次将5个Vertex光源设为Pixel,结果如图7.8所示,右边的大球体依次被染上了青色、橙色、绿色、红色和蓝色(根据你的改变次序,顺序会稍有差异)。现在我可以负责任地告诉大家,针对这5个Pixel光源,模式为Blend One One的ForwardAdd Pass确确实实被执行了5次。

untiy 3d ShaderLab_第7章_ Forward渲染路径_3_重要光源在ForwardAdd内的执行_第2张图片

untiy 3d ShaderLab_第7章_ Forward渲染路径_3_重要光源在ForwardAdd内的执行_第3张图片

untiy 3d ShaderLab_第7章_ Forward渲染路径_3_重要光源在ForwardAdd内的执行_第4张图片

untiy 3d ShaderLab_第7章_ Forward渲染路径_3_重要光源在ForwardAdd内的执行_第5张图片

    返回到上一个场景,即Lab_1下面的那个场景,把光源不停地在Pixel和Vertex模式,以及 Point和Direction模式问切换,可以发现,对于将会被传递到ForwardAdd内的每一个Pixel光源, Unity也是按照强弱的顺序依次让它们在ForwardAdd Pass内执行的。

你可能感兴趣的:(3D,shaderlab,untiy,Forward渲染路径,ForwardAdd)