untiy 3d ShaderLab_第8章_3_ 单光贴图和Forward 渲染路径

原创 2016年06月01日 21:14:27
8.3 单光贴图和Forward 渲染路径
8.3.1单光照贴图在VertexLit和Forward下面的不同表现
    在单光照贴图的情况下,Camera的RenderingPathVertexLit时,有一个不理想的地方就是被烘焙过的静态物体,默认的材质不会受到实时光照的影响。当然,可以通过提供自定义的材质改变这一行为,但是很麻烦RenderingPathForward时,这种麻烦就不会存在了,经过烘焙物体,Unity的默认材质会继续受到实时Pixel光源的影响
8.3.2 准备可应用于烘培的自发光材质
    如图所示。与前两个场景类似,不同之处在于我们会在这里演示Forward模式下如何让材质正确地被烘焙,以及正确地应用光照贴图。

    首先是绿色的自发光材质。与VertexLit模式下的自发光类似,这里只是提供了_EmissionLM属性,以及材质名前缀为Self-Illumin的Unity规范。ForwardEmission.shader的代码如下:
Shader "Self-Illumin/Lighting/LightMapping/Lab_3/ForwardEmission" {
	Properties {
		_MainTex("MainTexture",2d)="white"{}
		_Color ("Base Color", Color) =(1,1,1,1)
		_EmissionLM ("Emission (Lightmapper)", Float) = 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;
			float3 litDir:TEXCOORD0;
			float3 worldN:TEXCOORD1;
		};
		vertOut vert(appdata_base v)
		{
			float4 worldV=mul(_Object2World,v.vertex);
			float3 worldN=mul(_Object2World,float4(SCALED_NORMAL,0)).xyz;
			float3 c=Shade4PointLights(unity_4LightPosX0,unity_4LightPosY0,unity_4LightPosZ0,unity_LightColor[0],unity_LightColor[1],unity_LightColor[2],unity_LightColor[3],unity_4LightAtten0,worldV.xyz,worldN);

			vertOut o;
			o.pos=mul(UNITY_MATRIX_MVP,v.vertex);
			o.litDir=WorldSpaceLightDir(v.vertex);
			o.worldN=worldN;
			o.color=float4(c,1.0)*_Color;
			return o;
		}
		float4 frag(vertOut i):COLOR
		{
			float4 c=max(0.0,dot(i.worldN,normalize(i.litDir)))*_LightColor0*_Color;
			return c+i.color+_Color;
		}
		ENDCG
		}//end pass
		pass{
		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;
			float3 litDir:TEXCOORD0;
			float3 worldN:TEXCOORD1;
			float atten:TEXCOORD2;
		};
		vertOut vert(appdata_base v)
		{
			float3 worldN=mul(_Object2World,float4(SCALED_NORMAL,0)).xyz;
			vertOut o;
			o.pos=mul(UNITY_MATRIX_MVP,v.vertex);
			o.litDir=WorldSpaceLightDir(v.vertex);
			float dist=length(o.litDir);
			o.atten=1/(1+dist*dist*_WorldSpaceLightPos0.w);
			o.worldN=worldN;
			return o;
		}
		float4 frag(vertOut i):COLOR
		{
			float4 c=_LightColor0*_Color*max(0.0,dot(i.worldN,normalize(i.litDir)))*i.atten;
			return c;
		}
		ENDCG
		}//end pass
	}
}
    再就是一个myForward.shader,在这个自定义Shader中,我们计算了实时光,但是并没有计算光照贴图的影响。
8.3.3 在ForwardBase内计算光照贴图
    然后就是myForwardLM.shader。在此Shader的ForwardBase Pass内,我们计算了unity_Lightmap的影响,这也是Unity默认的计算光照贴图的地方。之所以在ForwardBase内计算,而不是在ForwardAdd内计算,是因为在有多个Pixel光源的情况下ForwardAdd会分别被执行多次。myForwardLM.shader的代码如下:
Shader "Tut/Lighting/LightMapping/Lab_3/myForwardLM" {
	Properties {
		_MainTex("MainTexture",2d)="white"{}
		_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;
		 sampler2D _MainTex;
        float4 _MainTex_ST; //scale & position of _MainTex
        #ifndef LIGHTMAP_OFF
        // sampler2D unity_Lightmap;//Beast lightmap
        // float4 unity_LightmapST; //scale & position of Beast lightmap
		#endif
		struct vertOut{
			float4 pos:SV_POSITION;
			float4 color:COLOR;
			float3 litDir:TEXCOORD0;
			float3 worldN:TEXCOORD1;
			float2 uv:TEXCOORD2;
			#ifndef LIGHTMAP_OFF
			float2 uvLM:TEXCOORD3;
			#endif
		};
		vertOut vert(appdata_full v)
		{
			float4 worldV=mul(_Object2World,v.vertex);
			float3 worldN=mul(_Object2World,float4(SCALED_NORMAL,0)).xyz;
			float3 c=Shade4PointLights(unity_4LightPosX0,unity_4LightPosY0,unity_4LightPosZ0,unity_LightColor[0],unity_LightColor[1],unity_LightColor[2],unity_LightColor[3],unity_4LightAtten0,worldV.xyz,worldN);

			vertOut o;
			o.pos=mul(UNITY_MATRIX_MVP,v.vertex);
			o.litDir=WorldSpaceLightDir(v.vertex);
			o.worldN=worldN;
			o.uv=v.texcoord.xy;
			#ifndef LIGHTMAP_OFF
			o.uvLM=v.texcoord1.xy;
			#endif
			o.color=float4(c,1.0)*_Color;
			return o;
		}
		float4 frag(vertOut i):COLOR
		{
			float4 c=max(0.0,dot(i.worldN,normalize(i.litDir)))*_LightColor0*_Color;
			#ifndef LIGHTMAP_OFF
			float3 clm=tex2D(_MainTex,i.uv).rgb*DecodeLightmap(UNITY_SAMPLE_TEX2D(unity_Lightmap,i.uvLM));
			c+=float4(clm,1.0);
			#endif
			return (c+i.color);
		}
		ENDCG
		}//end pass
		pass{
		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;
			float3 litDir:TEXCOORD0;
			float3 worldN:TEXCOORD1;
			float atten:TEXCOORD2;
		};
		vertOut vert(appdata_base v)
		{
			float3 worldN=mul(_Object2World,float4(SCALED_NORMAL,0)).xyz;
			vertOut o;
			o.pos=mul(UNITY_MATRIX_MVP,v.vertex);
			o.litDir=WorldSpaceLightDir(v.vertex);
			float dist=length(o.litDir);
			o.atten=1/(1+dist*dist*_WorldSpaceLightPos0.w);
			o.worldN=worldN;
			return o;
		}
		float4 frag(vertOut i):COLOR
		{
			float4 c=_LightColor0*_Color*max(0.0,dot(i.worldN,normalize(i.litDir)))*i.atten;
			return c;
		}
		ENDCG
		}//end pass
	}
}
8.3.4Forward渲染路径下烘焙之后的实时照明

    现在可以烘焙一下了,其结果如图下所示。首先我们可以注意到,相比于VertexLit模式下,烘焙过的物体,默认材质不再受到实时光源的影响,我们在Forward模式下的黄色实时Pixel光源仍对烘焙过的物体有着照明作用。但是可以尝试,在CameraForward模式时,将实时光源改为Not Important Vertex光源是不会对已烘焙过的物体产生照明影响的其次,被烘焙过的光源不再对烘焙过的物体产生照明,比如场景中的自色光源(光源1)和绿色光源(光源2),我们可以通过GUI移动或者改变颜色,但是对于烘焙过的物体,它不再产生照明。除非我们将光源Lightmapping模式改为RealTime Only,它才会对烘焙过的物体产生照明。




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

场景中存在一个足够强大的黄色Pixel平行光,强大到可以保证它一定会被ForwardBase内的_WorldSpaceLightPos0所捕捉,从而不会让任何其他Pixel光源落到ForwardBas...
  • heyuchang666
  • heyuchang666
  • 2016年05月07日 18:07
  • 1720

untiy 3d ShaderLab_第7章_ Forward渲染路径_2_Forward渲染路径下的重要光源

这种情形的存在原因,是Unity为FowardAdd Pass准备的光源数据在再次轮回到为FowardBase准备数据时Unity未及时清除的结果。Unity出于性能方面的考虑,因为毕竟在CPU和GP...
  • heyuchang666
  • heyuchang666
  • 2016年05月04日 21:15
  • 4154

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

场景中存在一个足够强大的黄色Pixel平行光,强大到可以保证它一定会被ForwardBase内的_WorldSpaceLightPos0所捕捉,从而不会让任何其他Pixel光源落到ForwardBas...
  • heyuchang666
  • heyuchang666
  • 2016年05月07日 18:07
  • 1720

untiy 3d ShaderLab_第8章_ 基于光照贴图的烘焙照明

转载出处:http://blog.csdn.net/heyuchang666/article/details/51366116 第8章 基于光照贴图的烘焙照明     Lightmap即光...
  • u010779707
  • u010779707
  • 2016年10月07日 10:38
  • 344

untiy 3d ShaderLab_第8章_ 基于光照贴图的烘焙照明

和刚刚的Shader不同的是,此Shader多了一个LightMode为VertexLMRGBM的Pass,在这个Pass中,我们读取了Beast的烘焙结果unity_Lightmap,然后将其输出。...
  • heyuchang666
  • heyuchang666
  • 2016年05月10日 20:08
  • 2234

untiy 3d ShaderLab_第7章_ Forward渲染路径_1_ForwardBase和ForwardAdd

我们编译运行一下,根据上面图中所示的结果,在VertexLit渲染模式下, ForwardBase和FowardAdd的LightMode都不被支持。另外,FwdAddX.shader在3个渲染路径...
  • heyuchang666
  • heyuchang666
  • 2016年05月04日 14:59
  • 3933

untiy 3d ShaderLab_第7章_ Forward渲染路径_2_Forward渲染路径下的重要光源

这种情形的存在原因,是Unity为FowardAdd Pass准备的光源数据在再次轮回到为FowardBase准备数据时Unity未及时清除的结果。Unity出于性能方面的考虑,因为毕竟在CPU和GP...
  • heyuchang666
  • heyuchang666
  • 2016年05月04日 21:15
  • 4154

untiy 3d ShaderLab_第6章_VertexLit渲染路径_3_顶点照明和Unity存放光源的第二种方式

同样,如果你乐意,可以打开Lab 2chaos场景,就像刚刚检测unity 4LightPos[X,Y,Z]0时一样,你会看到默认材质中最后一个Forward Pass执行过后的未清除的光源数据,如图...
  • heyuchang666
  • heyuchang666
  • 2016年05月03日 19:47
  • 4467

untiy 3d ShaderLab_第6章_VertexLit渲染路径_2_顶点照明和Unity存放光源的第一种方式

我们在unity 4LightPos[X,Y,Z]0中看到了数据,而且如果是在Forward的渲染路径下,如果我们改变光源的状态,比如从Pixel光源变为Vertex光源,即从点光源变为平行光,uni...
  • heyuchang666
  • heyuchang666
  • 2016年05月03日 19:26
  • 4146

untiy 3d ShaderLab_第6章_VertexLit渲染路径_1_顶点照明

顾名思义,逐顶点计算的Vertex Light就是基于物体的每一个顶点进行光的照明计算,然后根据顶点的光照信息对面片土的像素光照进行线性插值,这个线性插值操作是通过GPU的硬件来完成的,速度不是一般的...
  • heyuchang666
  • heyuchang666
  • 2016年05月03日 16:53
  • 2881
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:untiy 3d ShaderLab_第8章_3_ 单光贴图和Forward 渲染路径
举报原因:
原因补充:

(最多只允许输入30个字)