您的位置:首页 > 其它

untiy 3d ShaderLab_第5章_第一个被执行的Pass_1_不同LightMode 被选择的顺序

2016-04-29 18:15 288 查看
第5章 第一个被执行的Pass

5.1 不同LightMode 被选择的顺序

5.1.1 渲染路径和Pass的LightMode标签


Unity支持3种RenderingPath,分别是VertexLit, ForwardDeferred Lighting,为此又定义了在Pass中使用的LightMode标签Vertex, ForwardBase, ForwardAdd, PrepassBase, PrepassFinal等,分别表示当前Pass是为在哪一个RenderingPath下设计使用的。

5.1.2设计可以检测渲染路径的材质

现在的问题就是,在Shader中存在多个适应不同渲染路径的Pass时,Unity会怎么做?是按照某种次序全部渲染?还是只是挑选出其中一个最优的Pass在对应的渲染路径下渲染?

首先是Deferred.shader,这是一个被设计为只会在Camera的RenderingPath为Deferred模式下输出红色的Shader,其代码如下:

Shader "Tut/Lighting/FirstLight/Lab_1/Deferred" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
}
SubShader {
Tags { "RenderType"="Opaque" }
Blend One One

CGPROGRAM
#pragma surface surf MyDeferred
half4 LightingMyDeferred_PrePass (SurfaceOutput s, half4 light) {
half4 c;
c.rgb = s.Albedo;
c.a = s.Alpha;
return c;
}

struct Input {
float2 uv_MainTex;
};
sampler2D _MainTex;
void surf (Input IN, inout SurfaceOutput o) {
o.Albedo=float3(1,0,0);
}
ENDCG
}
}
再就是Deferred_Forward.shader,这是一个包含可以适应Deferred以及Forward渲染路径的材质,其中适应Deferred的部分输出(1 ,0, 0, 1)的红色,而适应Forward的部分只会输出的(0,1,
0, 1)绿色;两个部分都使用了Blend One One混合模式,也就是说如果两部分都执行的话,应该会输出(1, 1, 0, 1)的黄色,反之则只会输出被执行的那一个的输出颜色,也就是红色或者绿色。其代码如下:

Shader "Tut/Lighting/FirstLight/Lab_1/Deferred_Forward" {

SubShader {
Blend One One
//.1
pass{
Tags{ "LightMode"="ForwardBase"}
Blend One One
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"

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,1,0,1);
return o;
}
float4 frag(vertOut i):COLOR
{
return i.color;
}
ENDCG
}//end pass
//.2
CGPROGRAM
#pragma surface surf MyDeferred
half4 LightingMyDeferred_PrePass (SurfaceOutput s, half4 light) {
half4 c;
c.rgb = s.Albedo;
c.a = s.Alpha;
return c;
}

struct Input {
float2 uv_MainTex;
};
sampler2D _MainTex;
void surf (Input IN, inout SurfaceOutput o) {
o.Albedo=float3(1,0,0);
}
ENDCG
}
}
然后是Deferred_Forward_Vertex.shader,这个Shader和上面的Deferred_Forward.shader类似,不同的是添加了可以适应VertexLit渲染路径的Pass,会输出蓝色。也就是说,如果3个都执行,则会输出白色(1,1,1,1),否则会输出红、绿、蓝3个颜色的一个或两个的组合。其代码如一下:

Shader "Tut/Lighting/FirstLight/Lab_1/Deferred_Forward_Vertex" {

SubShader {
Blend One One
//.1
pass{
Tags{ "LightMode"="Vertex"}
Blend One Zero
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"

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,1,1);
return o;
}
float4 frag(vertOut i):COLOR
{
return i.color;
}
ENDCG
}//end pass
//.2
pass{
Tags{ "LightMode"="ForwardBase"}
Blend One One
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"

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,1,0,1);
return o;
}
float4 frag(vertOut i):COLOR
{
return i.color;
}
ENDCG
}//end pass
//.3
CGPROGRAM
#pragma surface surf MyDeferred
half4 LightingMyDeferred_PrePass (SurfaceOutput s, half4 light) {
half4 c;
c.rgb = s.Albedo;
c.a = s.Alpha;
return c;
}

struct Input {
float2 uv_MainTex;
};
sampler2D _MainTex;
void surf (Input IN, inout SurfaceOutput o) {
o.Albedo=float3(1,0,0);
}
ENDCG
}
}
最后还有Deferred_Vertex.shader,这是一个含有可以适应Deferred和VertexLit模式的材质。和Deferred_Forward_Vertex.shader类似,只不过去掉了适应Forward渲染路径的部分。还有Forwardes_Vertex.shader,这个Shader去掉了适应Deferred模式的部分,还有单独适应Forward渲染路径的Forward.shader,以及单独适应VertexLit渲染路径的Vertex.shader。其具体实现都很简单,但是所有针对Deferred渲染路径的Pass最终都会输出红色(1,
0, 0, 1),所有针对Forward渲染路径的Pass最终都会输出绿色(0, 1, 1, 1),所有针对VertexLit渲染路径的Pass最终都会输出蓝色(0, 0, 1, 1)。

5.1.3设计便于检测渲染路径的场景

在具体的场景中布置丰富的光源,可以保证任何一个RenderingPath都可以得到想要的光照,将场景的主相机背景色设置为黑色,背景就不会对材质的Blend One One操作造成任何影响,绿色的控制面板上的一系列按钮可以帮我们切换灯光的类型,以及Camera的RenderingPath。现在我们可以根据不同渲染路径下颜色的输出判断不同的渲染路径下哪些Pass被执行,哪些没有。编译并执行此场景。

5.1.4 VertexLit渲染路径下Pass的执行

首先切换Camera到VertexLit模式下,如图所示。可以看到只有含LightMode = Vertex的Pass会被执行,并输出蓝色,其他的都没有被执行。



5.1.5 Forward渲染路径下Pass的执行

切换相机到Forward渲染路径,可以看到如图所示的结果。凡是包含了针对Forward渲染路径的Pass都会被执行,并输出相应的绿色。如果没有包含针对Forward渲染路径的Pass,但是包含了针对VertexLit渲染路径的Pass,则也会被执行,并输出相应的蓝色。但是如果有Forward渲染路径的Pass可执行,就不会执行VertexLit渲染路径的Pass。针对Deferred渲染路径的Pass不会被执行。



5.1.6 Deferred渲染路径下Pass的执行

再切换相机到Deferred渲染路径下,可以看到如图所示的结果。所有材质,凡是包含了针对Deferred的Pass可执行,则执行Deferred的Pass,并输出红色,其他Pass不会被执行。如果不包含针对Deferred的Pass,而且材质包含了Forward的Pass,则执行针对Forward设计的Pass输出相应的绿色。如果材质既没有针对Deferred的Pass,也没有针对Forward的Pass,则会执行Vertex的Pass,并输出蓝色。



5.1.7不同渲染路径下的Pass执行规则总结

我们可以总结出Unity在Deferred渲染路径下,则会寻找可在Deferred渲染模式下的Pass然后返回,并不会执行其他渲染路径下的Pass,但是如果找不到Deferred状态下的Pass,则会再寻找Forward模式下的Pass并执行,然后返回,如果Forward模式下的Pass依然没有找到,则会寻找VertexLit模式下的Pass并执行。在Forward渲染路径下,会优先寻找Forward模式下可渲染的Pass,如果找不到,才会寻找
VertexLit模式下可渲染的Pass。

但是无论如何,Unity在一个时间只会执行一个渲染路径下的Pass,它并不会将全部可执行Pass都渲染
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: