Understanding The LightGrid
What Is The LightGrid?
The lightgrid is a 3D array of evenly spaced sample points across the BSP’s world bounds, this value can be set in the worldspawn of the map and is information compiled into the .BSP from q3map2.
The lightgrid is the engine’s way of storing precomputed lighting information in an array formation in world-space, so that dynamic or moving objects (like players, weapons, and some visual effects) can appear correctly lit, even though they can’t use static lightmaps.
Lightmaps (baked 2D textures for lighting) work great for static brush geometry but can’t be applied to moving entities, because their position relative to the lightmap changes every frame. This is why the lightGrid exists, the lightgrid samples lighting at fixed 3D points in the map, so anything in the map can query the lighting at its position.
This is a visualization of the lightgrid I made with AI, thankfull AI didn't make this image to scale and instead portrays the 3D array as cubes, when typically there are less sample points along the Z axis. The default unit value of LightGrid sample points is 128 128 256 (XYZ).
What Do LightGrid Sample Points Do?
Each point stores:
- Ambient RGB - soft background light color.
- Directional RGB - light color coming from a specific direction.
- Direction vector - the normalized vector of the main light source.
Every frame, each dynamic entity’s origin is used to interpolate between the nearest 8 lightgrid points (using trilinear interpolation).The resulting color + direction is used to either tint the model (with rgbGen lightingDiffuse or rgbGen vertex) OR compute per-vertex diffuse lighting if the shader uses directional lighting.
When a map is compiled, the light stage computes lighting for the lightgrid points using the same radiosity and light entity data that’s used for lightmaps. The grid density is controlled by the lightgrid BSP structure resolution, which is set in the worldspawn of the .map - by default gridSize is 128 128 256 units per grid cell (but can be smaller for more accurate lighting at a cost of memory).
Does a smaller LightGrid setting mean better lighting?
No. q3map2 computes lightmaps and the lightgrid as two separate outputs during the -light phase. Lightmaps are baked textures for world surfaces while the lightgrid is a 3D lattice used at runtime to light dynamic entities.
The lightgrid isn’t consulted to build the lightmaps, nor are lightmaps sampled to build the lightgrid. So while they are both influenced by the same lights and compile options, the lightgrid data is not used to calculate lightmaps.
Why is this useful for a Level Designer?
While it does not affect lightmaps, I have found that it tends to make indoor/outdoor lighting more noticeable on playermodels as they interpolate between more accurate points on the lightgrid.
At the same time lightJunior entities are much more accurate on playermodels when this value is reduced. The lightJunior light is not often used alone, but is great when paired with other lights if you want to ramp up the contrast on players under a spotlight or office light.
I tend to enjoy the smooth results on playermodels from going smaller to 64 64 128 and have never encountered any issues with this value, just be sure to remain using powers of 2. Noting that you won't need as many vertical splits along the Z axis as you would prefer along the X and Y axis.
Values as low as 32 32 64 cause entities to fail to render lightGrid data in certain parts of the map, normally close to walls or low ceilings. In those spots, entities would turn black with 0 lightGrid info. (both first person models and 3rd person models).
Regardless, I doubt there is much to gain from such low granularity.
