An
AllocBlock refers to a type of texture internal to the GoldSrc engine. If you're familiar with 3D graphics rendering, the term texture atlas might be familiar to you. AllocBlock is that, but for the lightmaps in a map. Each block is 128x128 lighting pixels (henceforth called luxels) in size, and there is a maximum of 64 of them at any one time.
On loading a map, the game engine allocates for every face in a map a small piece of an AllocBlock texture to paint on the lighting from the lightmaps stored in the map file for the face. This gets allocated for qualifying faces [
note 1] no matter the lighting styles attached to it.
To get the size of the lightmap and thus the luxel area to be allocated onto the AllocBlocks, the face extents were first calculated. The face extents is a 2D rectangle that fits all the vertices of the face, projected to the plane of the texture.
Texture projection
Scaling the face's texture changes the face's extents
Then, the face extents are scaled down by a factor of 1/16th, with the resulting value rounded outward. This is the luxel's scale. Finally, a 1 luxel padding is added to both sides.
Example from c1a0.bsp
The example to the left (or above) illustrates the projected face extents (in green) and the lightmap that covers it (in gray). The size of the lightmap is derived as follows:
side = extent/16 + adj + pad
width = 224/16 + a + 1 = 14 + 1 + 1 = 16
height = 116/16 + b + 1 = 7.25 + 0.75 + 1 = 9
Adjustment values
a and
b are fuzzy values from 0 to 1 that tends to round up the dividend to the nearest integer. It's rarely 0 even if the dividends are whole integers (in the above case, it's 1).
The engine does this for every face in the map, filling up up to 64 of such AllocBlocks.
Visualizing AllocBlock allocation
On rendering a frame, the engine applies lightmaps (after modulating animated ones and combining overlapping styles) to the AllocBlocks, then projects the assigned parts to the faces to be combined with the textures and [if supported and available] the detail textures.
The dreaded AllocBlock:Full error occurs when the engine runs out of these 64 AllocBlocks, and there's still faces left over. Simply put, it's because there's too many texture pixelage in your map. It can happen accidentally, like having scale lock on while resizing down brushes, or transforming brushes that result in textures perpendicular to the face, in which case you should go fix it. When accidental tiny scaled faces are eliminated but AllocBlocks are still over budget, then texture scale should start getting budgeted, by increasing the scale on certain faces which reduces the total number of texels (and the corresponding luxels). The brushwork should also be optimized to reduce cutting across diagonals, which creates diagonal edges. [
note 2]
AllocBlocks are purely a construct inside the engine, but the impact is notable enough that modern compile tools like VHLT simulates allocating faces to AllocBlocks to measure the number of AllocBlocks a map would use if the engine loads it.
Notes
- sky, faces of
!liquids
, and faces marked special are discounted. This lead to slight waste of lightmaps on those generated on !liquids
.
- Faces with diagonal edges wastes AllocBlocks as the lightmaps are always rectangular. A rectangle cut diagonally into two triangles (viz. ◩) uses twice the AllocBlock as an intact rectangle. The most waste however happen on thin diagonal faces.
Face polygon (in green) over face extents (rectangular, in red). The areas shaded red are wasted.