Sampling Lightmap in a Shader

Hey,

I wanted to sample a Unity lightmap in my shader. By experimentation I found out that I need to do something like that:

	half4 lightmap = tex2D(_LightmapTex, IN.lightmapTexCoord); 
	o.Lightmap = 8.0 * lightmap.rgb * lightmap.a;

Generally it works nice on PC (except for the fact that texcoords ae little bit shifted). I noticed problem however when I ran my application on Android Tegra 2 -based device. Everything is completely washed out.

I changed the lightmap mode to a regular texture and noticed that now the lightmap on a PC looks pretty much like the one on Android. When I removed tha magic 8.0 number I noticed that shadowed areas now look very close to the original lightmap format, but the lit areas are clearly darker.

Is there any way I could sample a Unity lightmap (stored in the lightmapped format) on all platforms consistently?

Yep;

o.Lightmap = DecodeLightmap ( tex2D ( _LightmapTex, IN.lightmapTexCoord ) );

That should give you the correct results regardless of platform.

DecodeLightmap is in UnityCG.cginc and has platform dependent checks for correct decoding of the lightmap.
Copy/pasted from UnityCG.cginc;

// Decodes lightmaps:
// - doubleLDR encoded on GLES
// - RGBM encoded with range [0;8] on other platforms using surface shaders
inline fixed3 DecodeLightmap( fixed4 color )
{
#if defined(SHADER_API_GLES)  defined(SHADER_API_MOBILE)
	return 2.0 * color.rgb;
#else
	// potentially faster to do the scalar multiplication
	// in parenthesis for scalar GPUs
	return (8.0 * color.a) * color.rgb;
#endif
}

It works. Thanks a lot! :slight_smile:

There is one more problem I have, which I mentioned in the first post but didn’t think that would be such an issue - I mean the lightmap’s texcoord offset. I have a surface shader where I defined the vertex function. Lightmap’s texcoords are stored in the second texcoord channel. But applying them explicitly causes some sampling offset with respect to what the lightmap looks like with built-in Unity shader. How do I apply this offset?

Bump… anyone? :slight_smile:

Ok, I got this. I had to call my lightmap sampler “unity_Lightmap” (this way I do not need to choose proper lightmap by hand). Having this, I could declare float4 unity_LightmapST which holds scaling and translation, supplied automatically by Unity to the shader.

Can you please post your code? I cannot find a way to access unity_Lightmap and unity_LightmapST in my surface shader.
Thanks!