Skip to content

Lighting

This section will go into how lighting data is rendered, not how it is calculated.

Face lighting

Every block has constant directional lighting which is statically assigned based on the angles of the faces. This is the base of all lighting thereafter, no matter whether it's smooth or not.

NOTE

I haven't found a generalized formula to this yet but I'm sure there is one

c
if (normal.y > 0.0f) {
    lighting = 1.0f;
} else if (normal.y < 0.0f) {
    lighting = 0.5f;
} else {
    lighting = (abs(normal.x) * 0.6) + (abs(normal.z) * 0.8);
}

Source: Betrock

The resulting value is then multiplied with the underlying color.

Light levels

Lighting in Minecraft is based on a 4-bit gradient from 0 - 15. As of Indev, this relationship is no longer linear.

If mapped from a range of 0.0 - 1.0, where 1.0 represents a light level of 15, we get the following mapping.

ValueColor
00.035
10.044
20.055
30.069
40.086
50.107
60.134
70.168
80.21
90.262
100.328
110.41
120.512
130.64
140.8
151.0

Or in code form

c
const float lightArray[16] = { 0.035f, 0.044f, 0.055f, 0.069f, 0.086f, 0.107f, 0.134f, 0.168f, 0.21f, 0.262f, 0.328f, 0.41f, 0.512f, 0.64f, 0.8f, 1.0f };

Non-smooth lighting

The illumination of a face is determined by the light level of the block its facing, i.e. the top of a grass block with a torch on it would get the full light level of 14.

Smooth Lighting

Every vertex samples and averages the light level of surrounding blocks along the direction of the face its part of. This provides ambient occlusion without any additional work, since solid blocks have a total light level of 0.

Credits