Understanding Source Engine Lightmap Bleeding and How to Fix It
Source Engine light bleeding at brush seams comes from mismatched lightmap resolution or UV alignment, not shader faults. Learn how to diagnose and fix it with consistent _lightmapscale and proper UVs.
30 Jul 2026, 09:30 UTC

Problem: Light Bleeding at Brush Seams
When compiling a Source Engine map, static lighting is baked into lightmaps that are applied per‑surface through VMT shader definitions. If adjacent brushes use different lightmap resolutions or have misaligned UVs, the sampler picks texels from different parts of the lightmap, producing visible seams or "bleeding" where light appears to leak across the joint.
How the Lightmap System Works
The BSP compiler (vbsp) assigns each face a lightmap scale via the _lightmapscale keyvalue. This value determines how many world units correspond to one lightmap texel. The VMT references the lightmap with $lightmap01 and the base texture with $basetexture. At render time the shader multiplies the base color by the lightmap sample.
Diagnosing the Issue
- Open the map in Hammer and select a face that shows the seam.
- Check the Face Properties dialog for the
_lightmapscalevalue; note any mismatch with neighboring faces. - Inspect the VMT for the material used on those faces; ensure no entity‑level override of
$lightmapscale. - Verify UV alignment: in Hammer’s Texture Application tool, look for stretching or non‑uniform scaling across the seam.
Worked Example: Fixing a Doorway Frame
Suppose a metal door frame shows a bright line where it meets the surrounding wall.
- In Hammer, select the frame faces and the wall faces. Both show
_lightmapscale 16in the Face Properties, but the frame’s UVs are rotated 90 degrees, causing the lightmap to be sampled sideways. - Reset the frame’s UV alignment: with the faces selected, click "Align" -> "To World" and set the scale to 1.0 in both axes.
- Re‑compile the map with consistent lightmap scaling: run
vbsp -lightmapscale 16 -game mymod mapname.vmffrom the SDK tools directory. - After compilation, use
vtex -dump mapname_lightmap.vtfto inspect the generated lightmap. The dump should show smooth gradients across the former seam.
Trade‑offs: Quality vs. Compile Time and Memory
Lower _lightmapscale values increase lightmap resolution, reducing seam visibility but raising memory usage quadratically (halving the scale quadruples the lightmap size) and can extend vbsp times from minutes to hours on large maps. A common compromise for multiplayer maps is _lightmapscale 16, which keeps lightmap budgets manageable while hiding most seams when UVs are properly aligned. Single‑player levels with detailed lighting may drop to 8 or 4, but only if the team can afford the longer compile and higher memory footprint.
Actionable Takeaway
- Ensure all touching static surfaces share the same
_lightmapscalevalue. - Use Hammer’s Face Constraints / Texture Application tools to verify UV alignment across seams.
- After any change, re‑run
vbspwith the chosen scale and verify the output withvtex -dumpon the resulting lightmap.
By treating lightmap resolution as a shared property of connected geometry, you eliminate most bleeding issues and keep the BSP pipeline predictable.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.