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

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
,它才会对烘焙过的物体产生照明。

时间: 2024-08-29 23:03:31

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

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

第7章 Forward渲染路径 本章的主要目的是让大家在不使用Unity的Surface Shader时,也能够正确地存取Unity的光源数据,从而定制自己的Forward渲染路径的Shader.如果读者没有这个需求,或者己经了解了Unity是如何为Forward渲染路径存放光源数据的,那么就可以跳过本章. 7.1ForwardBase和ForwardAdd ForwardBase和ForwardAdd是专门为在Forward渲染路径下渲染物体而设计的两种Pass,其中ForwardBase会先

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

第7章 Forward渲染路径 本章的主要目的是让大家在不使用Unity的Surface Shader时,也能够正确地存取Unity的光源数据,从而定制自己的Forward渲染路径的Shader.如果读者没有这个需求,或者己经了解了Unity是如何为Forward渲染路径存放光源数据的,那么就可以跳过本章. 7.2Forward渲染路径下的重要光源 7.2.1 设计检测用的材质 其编辑器截图如图所示, _WorldSpaceLightPosO.x.shader文件,其主要代码如下: Shader

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文件夹下的场景,其编

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

6.4顶点照明和Unity存放光源的第三种方式 6.4.1   Unity为Vertex Pass准备的光源 是不是绝望了?世界没有光明怎么能行呢?当然不行,光明马上就来,Unity把它放到了unity_LightPosition[4]数组中. 可以简单地告诉你一个结果:在LightMode = Vertex的Pass内,unity_LightPosition[4]和unity_LightColor[4]是存取光源数据最可靠的第一首选手段,无论在Camera的RenderingPath为何,Ve

untiy 3d ShaderLab_第7章_ Forward渲染路径_4_Forward渲染路径总结

Forward渲染路径总结 现在可以总结一卜适应于Forward渲染路径的ForwardBase和ForwardAdd的情况. 7.4.1   Forward渲染路径下材质的适应性 这两类Pass不能在Camera为VertexLit时被演染,但可以被渲染路径为Forward和Deferred的Camera渲染. 7.4.2  Unity如何为Forward渲染路径设置光源 在ForwardBase的Pass内,_WorldSpaceLightPos0和_LightColor0只会含有第一个Pi

javascript高级程序设计 第十四章--表单脚本

javascript高级程序设计 第十四章--表单脚本 在HTML中表单由<form>元素表示,在js中表单对应的是HTMLFormElement类型,这个类型也有很多属性和方法:取得表单元素的引用还是为它添加id特性,用DOM操作来获取表单元素:提交表单:把<input>或<button>元素的type特性设置为"submit",图像按钮把<input>元素的type特性设置为"image",也可以调用submit(

第10章 表单元素(中)

第 10章表单元素[中]学习要点:1.type属性总汇2.type属性解析 本章主要探讨 HTML5中表单中 input元素的 type属性,根据不同的值来显示不同的输入框.一.type属性总汇input元素可以用来生成一个供用户输入数据的简单文本框.在默认的情况下,什么样的数据均可以输入.而通过不同的属性值,可以限制输入的内容. 属性名称 说明text 一个单行文本框,默认行为password 隐藏字符的密码框search 搜索框,在某些浏览器键入内容会出现叉标记取消submit.reset.

第10章 表单元素(上)

第10章表单元素[上] 学习要点:1.表单元素总汇2.表单元素解析 本章主要探讨 HTML5中表单元素,表单元素用于获取用户的输入数据.一.表单元素总汇在 HTML5的表单中,提供了各种可供用户输入的表单控件.元素名称 说明form 表示 HTML表单input 表示用来收集用户输入数据的控件textarea 表示可以输入多行文本的控件select 表示用来提供一组固定的选项option 表示提供提供一个选项optgroup 表示一组相关的 option元素button 表示可用来提交或重置的表

ASP.NET MVC5 高级编程 第5章 表单和HTML辅助方法

参考资料<ASP.NET MVC5 高级编程>第5版 第5章 表单和HTML辅助方法 5.1 表单的使用 5.1.1 action 和 method 特性 默认情况下,表单发送的是 HTTP Post 请求 EF 对于外键关系,数据库名称等也有约定.这些约定取代了以前需要提供给一个关系对象映射框架的所有映射和配置. GET 方法:GET 请求的所有参数都在URL中,因此可以为GET 请求建立书签. POST 方法:浏览器把输入值放入 HTTP 请求的主体中. 5.2 辅助方法 可以通过视图的H