UnityShader实例07:在shader调用unity内置lightmap和light Probes

原创 2015年07月09日 11:37:24

在shader调用unity内置lightmap和Light Probes


在编写unity shader的时候,有时候会有需求,希望写的shader能支持unity内置lightmap或者light probe (灯光探测器)。如果是用surface 编写的话,这些自然不用考虑,unity会自动编译支持,但如果是用vert&frag编写shader,这些需要自己添加相关代码调用了 。


unity内置lightmap的调用


为了使unity内置数据和各种宏定义(如本文的LIGHTMAP_OFF)起作用,需要添加#pragma指令:

#pragma multi_compile LIGHTMAP_OFF LIGHTMAP_ON


在unity5.0之前的版本需要声明一下两个内置参数,unity5.0的话就不需要这两句了:

half4 unity_LightmapST;
sampler2D unity_Lightmap;

Lightmap是使用模型的uv2 ,因此接下来在顶点输入结构体里声明uv2:


float2 texcoord1 : TEXCOORD1;

在另一个顶点结构里面定义用来接收uv2的uv值:

#ifndef LIGHTMAP_OFF
half2 uvLM : TEXCOORD4;
#endif

在vert函数里面给uvLM赋值:

#ifndef LIGHTMAP_OFF
o.uvLM = v.texcoord1.xy * unity_LightmapST.xy + unity_LightmapST.zw;
#endif

然后frag函数里对lightmap贴图采样并叠加给主颜色:

#ifndef LIGHTMAP_OFF
fixed3 lm = DecodeLightmap (UNITY_SAMPLE_TEX2D(unity_Lightmap, i.uvLM.xy));
col.rgb*=lm;
#endif
在上面的代码中使用了DecodeLightmap解码unity的内置光照贴图,这是因为Unity烘焙的LightMap是32bit的HDR图,在桌面端,光照贴图的编码为RGBM,而在移动端,大部分情况下,光照贴图的编码为double-LDR,因此需要针对不同平台提供不同的编码方式。DecodeLightmap作用就在这里,它可以针对不同的平台对光照贴图进行解码


VF版本代码01:

Shader "PengLu/Unlit/TextureLM" {
Properties {
	_MainTex ("Base (RGB)", 2D) = "white" {}
}

SubShader {
	Tags { "RenderType"="Opaque" }
	LOD 100
	
	Pass {  
		CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#pragma multi_compile_fog
			#pragma multi_compile LIGHTMAP_OFF LIGHTMAP_ON
			#include "UnityCG.cginc"

			struct appdata_t {
				float4 vertex : POSITION;
				float2 texcoord : TEXCOORD0;
				float2 texcoord1 : TEXCOORD1;
			};

			struct v2f {
				float4 vertex : SV_POSITION;
				half2 texcoord : TEXCOORD0;
				#ifndef LIGHTMAP_OFF
				half2 uvLM : TEXCOORD1;
				#endif 
				UNITY_FOG_COORDS(1)
			};

			sampler2D _MainTex;
			float4 _MainTex_ST;
			
			v2f vert (appdata_t v)
			{
				v2f o;
				o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
				o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
				#ifndef LIGHTMAP_OFF
				o.uvLM = v.texcoord1.xy * unity_LightmapST.xy + unity_LightmapST.zw;
				#endif
				UNITY_TRANSFER_FOG(o,o.vertex);
				return o;
			}
			
			fixed4 frag (v2f i) : SV_Target
			{
				fixed4 col = tex2D(_MainTex, i.texcoord);
				UNITY_APPLY_FOG(i.fogCoord, col);
				UNITY_OPAQUE_ALPHA(col.a);
				#ifndef LIGHTMAP_OFF
				fixed3 lm = DecodeLightmap (UNITY_SAMPLE_TEX2D(unity_Lightmap, i.uvLM.xy));
				col.rgb*=lm;
				#endif
				return col;
			}
		ENDCG
	}
}

}

VF版本代码01效果:



unity内置Light Probes的调用


在shader中我们是通过unity定义的half3 ShadeSH9(half4 normal)来调用Light Probes的,Light Probes照明使用的是一种叫球谐光照(Sphere Harmonic)的模拟,简称SH,因此在ShadeSH9函数需要一个世界坐标中的Normal来决定物体表面的光照。

首先我们在顶点输出结构定义一个参数SHLighting:

fixed3  SHLighting : COLOR;

然后在顶点函数里为它赋值:

 

float3 worldNormal = mul((float3x3)_Object2World, v.normal);//获得世界坐标中的normal

o.SHLighting= ShadeSH9(float4(worldNormal,1)) ;

VF版本代码02:

Shader "PengLu/Unlit/TextureLM" {
Properties {
	_MainTex ("Base (RGB)", 2D) = "white" {}
	_SHLightingScale("LightProbe influence scale",float) = 1
}

SubShader {
	Tags { "Queue"="Geometry""LightMode"="ForwardBase""RenderType"="Opaque"   }
	LOD 100
	
	Pass {  
		CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#pragma multi_compile_fog
			
			#include "UnityCG.cginc"

		

			struct v2f {
				float4 vertex : SV_POSITION;
				half2 texcoord : TEXCOORD0;
				fixed3  SHLighting : COLOR;
				UNITY_FOG_COORDS(1)
			};

			sampler2D _MainTex;
			float4 _MainTex_ST;
			float _SHLightingScale;
			
			v2f vert (appdata_base v)
			{
				v2f o;
				o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
				o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
				float3 worldNormal = mul((float3x3)_Object2World, v.normal);
				o.SHLighting= ShadeSH9(float4(worldNormal,1)) ;
								UNITY_TRANSFER_FOG(o,o.vertex);
				return o;
			}
			
			fixed4 frag (v2f i) : SV_Target
			{
				fixed4 col = tex2D(_MainTex, i.texcoord);
				col.rgb*=i.SHLighting;
				UNITY_APPLY_FOG(i.fogCoord, col);
				UNITY_OPAQUE_ALPHA(col.a);
				
				return col*_SHLightingScale;
			}
		ENDCG
	}
}

}

VF版本代码02效果




版权声明:本文为博主原创文章,如需转载请指明出处http://blog.csdn.net/u011047171

相关文章推荐

<Shader>LightMap光照Shader的实现

1,按照具体的步骤来生成LightMap文件后我们来写Shader shader "LightMap/LightMapSH"{ Properties{ _MainTex("Main tex"...

LightmapShader改进

最近公司项目中导入了一些自带光照图的场景模型。这些场景的颜色本应严格按照光照图给出的颜色,但场景中的灯光会使得它们更亮。在Unity中也没能找到支持光照图的不打光Shader,于是自己下来做了一个实现...
  • ldghd
  • ldghd
  • 2014年05月08日 14:08
  • 1160

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

和刚刚的Shader不同的是,此Shader多了一个LightMode为VertexLMRGBM的Pass,在这个Pass中,我们读取了Beast的烘焙结果unity_Lightmap,然后将其输出。...

关于如何判断是否接收lightmap、接收lightmap的shader和怎么烘焙更快

判断lightmap接收,如何写shader接收lightmap,如何加快烘焙

Unity5中lightmap的坑

Unity5中光照系统替换为Enlighten是非常大的革新。但是对手游来说,好处还未享受到,坑先踩上了。并且是我研究了两天都没有很好的解决办法的深坑。         我并没有系统的学过图形学...
  • wolf96
  • wolf96
  • 2016年03月13日 14:10
  • 1530

在shader调用unity内置lightmap和Light Probes

顶点shader接收lightmap

【Unity Shaders】初探Surface Shader背后的机制

转载请注明出处!写在前面一直以来,Unity Surface Shader背后的机制一直是初学者为之困惑的地方。Unity Surface Shader在Unity 3.0的时候被开放给公众使用,其宣...

深入理解Unity5中的StandardShader屏幕像素化特效的实现

概要:续接上文,本文进一步讲解与分析了上文未讲完的Unity5中Standard Shader正向基础渲染通道源码的片段着色实现部分,以及对屏幕像素化后期特效进行了实现。   同样需要声明的是。本...
  • hcud024
  • hcud024
  • 2016年05月10日 05:09
  • 4283

Unity LightMap Unlit Shader解读

使用场景:只使用lightmap,不考虑光照
  • cubesky
  • cubesky
  • 2014年09月16日 15:17
  • 3900

Cg入门22:Fragment shader - 2D纹理采样(光照贴图制作和使用)

一、光照贴图制作:实时光照效果:使用光照贴图步骤:1.选择要灯光贴图的模型,然后设置为Lightmap Static2.光源Baking设置为Baked3.选择Windows/Lighting,打开L...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:UnityShader实例07:在shader调用unity内置lightmap和light Probes
举报原因:
原因补充:

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