Trying to sample the built-in lightmap

I am trying to sample the built-in lightmap. I have found various posts online detailing this, but I do not seem to be able to get it working. I was able to confirm that I am indeed sampling the lightmap texture, but the coordinates appear to be wrong. Any ideas?

// Upgrade NOTE: replaced tex2D unity_Lightmap with UNITY_SAMPLE_TEX2D

Shader "Custom/CustomSpecular"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            Lighting Off
            SeparateSpecular Off
       
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            // make fog work
//            #pragma multi_compile_fog
           
            #include "UnityCG.cginc"
           
            uniform float4x4 loc2World;
            uniform float4x4 rotateOnly;
            uniform float4 uniCol;

            struct vsInput
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
                float2 uv1 : TEXCOORD1;
                float3 normal : NORMAL;
            };

            struct fsInput
            {
                float4 vertex : SV_POSITION;
                float2 uv : TEXCOORD0;
                float2 uv1 : TEXCOORD1;
                float3 normal : NORMAL;
//                float3 worldPos : _WORLDPOS;
//                UNITY_FOG_COORDS(1)
            };

            sampler2D_half _MainTex;
            half4 _MainTex_ST; // Required by TRANSFORM_TEX macro
//            sampler2D_half unity_Lightmap; // Already defined automagically.
            half4 unity_Lightmap_ST; // Required by TRANSFORM_TEX macro
           
            fsInput vert (vsInput v)
            {
                fsInput o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                o.uv1 = TRANSFORM_TEX(v.uv1, unity_Lightmap);
                o.normal = UnityObjectToWorldNormal(v.normal);
//                o.worldPos = mul(unity_ObjectToWorld, v.vertex);
//                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }
           
            fixed4 frag (fsInput i) : SV_Target
            {
                fixed4 col = tex2D(_MainTex, i.uv);
                col.rgb *= DecodeLightmap(UNITY_SAMPLE_TEX2D(unity_Lightmap, i.uv1));
//                UNITY_APPLY_FOG(i.fogCoord, col);
                return col;
            }
            ENDCG
        }
    }
}

Comparison of my shader to the built-in Default Specular shader, showing that the lightmap is indeed built and there:


^ My shader


^ Default Specular

I found the solution in a Russian forum. For unknown reasons, it is required to use unity_LightmapST, when TRANSFORM_TEX uses unity_Lightmap_ST. All I had to do is code it manually with the corrected variable name:

o.uv1 = v.uv1.xy * unity_LightmapST.xy + unity_LightmapST.zw;
1 Like

The xxxxxST are the texture’s Tiling and Offset (which you can see in any texture in any shader).

.xy is the Tiling and zw are the offset. You multiply the UVs with the tiling and then you add the offset.

For the lightmaps, those parameters are used to properly scale and move the UVs, so that they sample the lightmap from the appropriate place.

I do know that. The irritating part is that for the color map you have to append “_ST”, but for the light map you have to append “ST”.

1 Like