场景中建一个plane,一个cube一个cylinder
把场景平行光的强度调低一些,再加一个点光源,设置为绿色吧,俗话说的好:爱是一道光,绿到你发荒……
把点光源的shadowtype设置为hard shadow(默认的是无阴影)
ShaderLab学习小结(十)简单的支持光照贴图的shader_第1张图片
如上图,平行光和点光源都产生了阴影。

要烘焙lightmap,就要把被烘物体设置上lightmap static
ShaderLab学习小结(十)简单的支持光照贴图的shader_第2张图片
平行光和点光源都把Baking设置为Baked
ShaderLab学习小结(十)简单的支持光照贴图的shader_第3张图片
在lighting面板中,把Ambient GI选成Baked
烘出来感觉暗一些,稍微把General GI里的indirect Intensity调高一些到1.5(这个不为追求什么效果)
把底下的auto前面的勾选取消掉,再点击Build
ShaderLab学习小结(十)简单的支持光照贴图的shader_第4张图片
然后烘出来,可以把灯光关了
ShaderLab学习小结(十)简单的支持光照贴图的shader_第5张图片
物体的光照还有阴影还在
ShaderLab学习小结(十)简单的支持光照贴图的shader_第6张图片

Shader代码:

Shader "Custom/TestLightMapShader" {
    Properties{
        _MainTex("Main Tex",2d) = ""{}
    }
    SubShader {
        pass {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "unitycg.cginc"
            sampler2D _MainTex;
            float4 _MainTex_ST;
            struct v2f {
                float4 pos:POSITION;
                float2 uv0:TEXCOORD0;
                float2 uv1:TEXCOORD1;
            };
            v2f vert(appdata_full v)
            {
                v2f o;
                o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
                o.uv0 = TRANSFORM_TEX(v.texcoord, _MainTex);
                o.uv1 = v.texcoord1.xy*unity_LightmapST.xy + unity_LightmapST.zw;
                return o;
            }
            fixed4 frag(v2f IN) :COLOR
            {
                fixed4 col = tex2D(_MainTex,IN.uv0);
                float3 lm = DecodeLightmap(UNITY_SAMPLE_TEX2D(unity_Lightmap, IN.uv1));
                col.rgb *= lm*2;
                return col;
            }
            ENDCG
        }
    }
    FallBack "Diffuse"
}

定义了一个_MainTex,这里并没有赋纹理,为了和光照贴图有区别
结构体里定义:uv0与uv1
uv1对应的是光照贴图的处理

o.uv1 = v.texcoord1.xy*unity_LightmapST.xy + unity_LightmapST.zw;

看这个公式和unitycg.cginc里的TRANSFORM_TEX的定义好像是一样的

// Transforms 2D UV by scale/bias property
#define TRANSFORM_TEX(tex,name) (tex.xy * name##_ST.xy + name##_ST.zw)

为什么不用TRANSFORM_TEX呢
这个unity_Lightmap和unity_LightmapST是内建的直接用
但是注意,unity_Lightmap与ST之间并无下划线,这个和TRANSFORM_TEX定义的不一样,所以得这样写
这里用到了v.texcoord1,查看unitycg.cginc,发现vert的参数得用appdata_full
v.texcoord对应主纹理,v.texcoord1对应的是光照贴图(就这样理解吧)

然后到frag函数中

fixed4 col = tex2D(_MainTex,IN.uv0);
float3 lm = DecodeLightmap(UNITY_SAMPLE_TEX2D(unity_Lightmap, IN.uv1));
col.rgb *= lm*2;
return col;

tex2D主纹理采样 没变
之后对lightmap贴图进行采样

float3 lm = DecodeLightmap(UNITY_SAMPLE_TEX2D(unity_Lightmap, IN.uv1));

这个在unitycg.cginc中定义,返回值是个half3

inline half3 DecodeLightmap( fixed4 color, half4 decodeInstructions)
{
#if defined(UNITY_NO_RGBM)
    return DecodeLightmapDoubleLDR( color );
#else
    return DecodeLightmapRGBM( color, decodeInstructions );
#endif
}

再与主颜色的rgb叠加

col.rgb *= lm*2;

这里lm*2是因为太暗,所以增加亮度
当然,从图上能看出来,lightmap与实时渲染的效果是不一样的,这个就需要调整了,本文不涉及。