您的位置:首页 > 其它

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

2016-05-07 18:07 381 查看
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的基础上叠加的效果。



下面是_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次。









返回到上一个场景,即Lab_1下面的那个场景,把光源不停地在Pixel和Vertex模式,以及Point和Direction模式问切换,可以发现,对于将会被传递到ForwardAdd内的每一个Pixel光源,Unity也是按照强弱的顺序依次让它们在ForwardAdd Pass内执行的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: