我们在做手机游戏开发过程中经常使用 Diffuse shader,并对场景进行烘培,这样能用很低的消耗达到不错的效果。 DiffuseShader 不能设置Alpha通道,在实际开发过程中遇到需要透明,或者实现渐隐效果。
全部Shader代码如下
Shader "Mobile/Diffuse_Aplha" {
Properties{
_Color("Color",Color) = (1,1,1,1)
_MainTex("MainTex",2D) = "white"{}
_AlphaScale("AlphaScale",Range(0,1)) = 1
}
SubShader{
Tags{"Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent"}
//"RenderType"="Transparent"指明该shader为使用了透明度混合的shader
//开启深度写入的Pass是为了将模型的深度信息写入深度缓冲中,从而剔除模型中被自身遮挡的片元
Pass{
ZWrite On
ColorMask 0
}
Pass{
//Tags{"LightMode" = "ForwardBase"}
Zwrite Off //关闭深度写入
Blend SrcAlpha OneMinusSrcAlpha //设置混合因子为源的透明度
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile LIGHTMAP_OFF LIGHTMAP_ON
#include "Lighting.cginc"
fixed4 _Color;
sampler2D _MainTex;
float4 _MainTex_ST;
fixed _AlphaScale;
struct a2v {
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float2 uv1 : TEXCOORD1;
};
struct v2f {
float4 vertex:SV_POSITION;
float2 uv:TEXCOORD0;
#ifdef LIGHTMAP_ON
float2 uvLM : TEXCOORD1;
#endif
};
v2f vert(a2v v) {
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
#ifdef LIGHTMAP_ON
o.uvLM = v.uv1.xy * unity_LightmapST.xy + unity_LightmapST.zw;
#endif
return o;
}
fixed4 frag(v2f i) :SV_Target{
fixed4 col = tex2D(_MainTex, i.uv);
col = col * _Color;
#ifdef LIGHTMAP_ON
fixed3 lm = DecodeLightmap(UNITY_SAMPLE_TEX2D(unity_Lightmap, i.uvLM));
col.rgb *= lm;
#endif
return fixed4(col.rgb, _AlphaScale);
}
ENDCG
}
}
FallBack "Transparent/VertexLit"
}
首先我们需要透明,我们需要渲染队列 "Queue" = "Transparent"
接受场景烘培贴图 加入编辑指令 #pragma multi_compile LIGHTMAP_OFF LIGHTMAP_ON
(#ifdef LIGHTMAP_ON ) 处理LightMap 代码
这里为什么要用DecodeLightmap又要用UNITY_SAMPLE_TEX2D来解读ligtmap呢?
实际上unity生成的lightmap的有两种编码格式:doubleLDR和RGBM
Unity使用了两种编码方式来存储lightmap:
1、doubleLDR,需要一张rgb24贴图 2、RGBM,需要一张rgba32贴图
在移动设备上使用doubleLDR格式,可以获得更快的计算速度。它只用到了lightmap的RGB通道。
PC上则使用RGBM格式,可以获得更广的亮度范围,而牺牲一点速度。它使用了贴图的RGBA通道,而A通道是用来做乘法,所以称为RGBM格式。
这两种格式的差异就是导致不同平台下lightmap表现不同的原因,当然Unity会在切换平台时帮我们对贴图进行转换,而不需要太关心这个差异。