GitXplorerGitXplorer
d

lighting-algorithm-spec

public
13 stars
0 forks
0 issues

Commits

List of commits on branch master.
Verified
861353f8626fab44352031e2a16c53a9f2c63d07

Attempt to describe newer 4-square pass 2 algorithm (significantly easier to implement, but harder to describe)

ddktapps committed 3 years ago
Verified
c7ea313e94a0059c06ac8569bf2ce76b571b5ce1

Update README.md

ddktapps committed 4 years ago
Verified
d9ba455fe83974fe0ccaab07ae65bc5447febc63

Update README.md

ddktapps committed 4 years ago
Verified
cda5e65cbec78a6016577a88b1a7482aa25b76d8

Update README.md

ddktapps committed 4 years ago
Verified
feaeb2a4b7f6db8513dd5b45bc73933e2bf4b3b7

README.md

ddktapps committed 4 years ago

README

The README file for this repository.

Minecraft block lighting

Why do we care about light on the server?

On the server side, light is used for a variety of vanilla logic, including (but not limited to):

  • Grass growth (and death)
  • Crop growth
  • Sapling growth
  • Ice melting
  • Bamboo growth
  • Mob spawning (for example, undead mobs won't usually spawn in bright light)

So why are we calculating light for every single chunk?

No idea. In theory, we don't need to calculate lighting for anything other than chunks currently in ticking areas (usually a few chunks' radius around the player where crops are expected to grow and so on).

Algorithm

We propose a 3-pass algorithm for relighting chunks, starting from zero light.

Special cases

If an arbitrary chunk is replaced, its light must be invalidated, and also the light of the surrounding 8 chunks. This is because a chunk's lighting may have affected any of these adjacent chunks (due to propagation).

Pass 0: Discover light nodes

Sky light

For sky light, this involves calculating the "height map" of the chunk. For each X/Z column in the chunk, the heightmap contains the Y coordinate of the highest block that doesn't affect light, NOT the highest block.

Blocks pointed to by the heightmap should be treated as light sources for sky light propagation. In addition, account for the difference between the current column and the highest immediately adjacent heightmap, to account for cases where sideways propagation is needed.

Block Ignored by heightmap Reason
Glass Yes Fully transparent
Air Yes Fully transparent
Leaves No Diffuses sky light (doesn't reduce light propagation, but triggers heightmap)
Cobweb No Diffuses sky light (doesn't reduce light propagation, but triggers heightmap)
Water No Light is reduced by 3 levels when propagating through (instead of usual 1)
Stone No Fully opaque

Block light

For block light, you just need to scan the whole chunk and look for blocks with a non-zero light emission. These blocks are your source nodes.

Tip: You can optimise these kinds of scans using the block palette. If a subchunk's block palette doesn't contain any light-emitting blockstates, you can avoid scanning the entire 4096 blocks of that subchunk.

Pass 1: Propagate light inside the bounds of a single chunk column

This pass must not influence any other chunks except the source chunk. It's possible, probably practical, to do pass 0 and 1 directly in series.

Requirements

  • Pass 0 must have been completed.

Pass 2: Propagate light across chunk borders

For this pass, we take square groups of 4 chunks, and propagate light across their shared borders. No chunk is special; all 4 chunks in each group are treated the same way.

Each chunk belongs to 4 groups of 4 chunks:

  • one where it is the top-left chunk
  • one where it is the top-right chunk
  • one where it is the bottom-left chunk
  • one where it is the bottom-right chunk

Once a chunk has been involved in a pass 2 calculation in all of these positions, it is then fully light-populated.

Why not groups of 9?

Groups of 4, while harder to explain, are significantly more parallel-friendly, easier to code, and in the case of PocketMine-MP, require significantly fewer chunk copies (4 instead of 9), due to the fact that a pass2 using groups of 4 only needs to lock a chunk 4 times.

Example

  • A torch is placed in chunk (0,0) at x=14,z=14
  • A tunnel crosses into chunk (0,1), turns right, crosses into chunk (1,1), then upwards, and crosses into chunk (1,0).
  • The light from the torch must be propagated to all three chunks.

Requirements for each part of the pass

  • All chunks involved must be available.
  • All chunks involved must have had pass 1 completed.

Notes

  • Block and sky light are independent and can be calculated in parallel.
  • If pass 1 did nothing for any of the 4 adjacent chunks, pass 2 can be skipped for the current chunk, since it guarantees that none of the adjacent chunks have any border light that can be received by the current chunk.
  • It's possible to record whether light reached chunk borders during pass 1, to allow adjacent chunks to quickly decide whether they want to do pass 2 with that chunk or not.
  • Pass 0 and 1 can be embarassingly parallel, since they only require a single chunk to execute.