My lighting engine is in these two classes here: https://github.com/chrislo27/ProjectMP/tree/master/core/src/projectmp/client/lighting
It has “diamond lighting” so it’s not exactly the same as yours (yours is more “globular”).
The meat and potaters of my lighting engine are in the recursion method:
private void recursiveLight(int x, int y, byte bright, int color, boolean source) {
lightingUpdateMethodCalls++;
if (bright <= 0) {
return;
}
if (getBrightness(x, y) >= bright && !source) {
return;
}
if (x < 0 || y < 0 || x >= sizex || y >= sizey) {
return;
}
setBrightness(bright, x, y);
bright = (byte) MathUtils.clamp(bright
- (world.getBlock(x, y).lightSubtraction(world, x, y) * 127), 0, 127);
if (bright <= 0) return;
mixColors(x - 1, y, color);
mixColors(x, y - 1, color);
mixColors(x, y + 1, color);
mixColors(x + 1, y, color);
if ((x - 1 >= 0) && !(getBrightness(x - 1, y) >= bright)) {
recursiveLight(x - 1, y, bright, color, false);
}
if ((y - 1 >= 0) && !(getBrightness(x, y - 1) >= bright)) {
recursiveLight(x, y - 1, bright, color, false);
}
if ((x + 1 < sizex) && !(getBrightness(x + 1, y) >= bright)) {
recursiveLight(x + 1, y, bright, color, false);
}
if ((y + 1 < sizey) && !(getBrightness(x, y + 1) >= bright)) {
recursiveLight(x, y + 1, bright, color, false);
}
}
Unlike how CopyableCougar4 said to “add” the lights together, I simply take the highest one (that is, when the method is called at a block, if the light at the block is already brighter to skip setting the light value). I also have checks if the brightness where the recursion will occur is already bright enough, if so don’t call it (because calling a method is much much slower than an if statement).
There’s also a lot of boring code such as copying the lighting data to another array because I found something where as I was looping through the array, light sources that finished recurring would re-do their recursion again as the for loop went through. That ended up with 200k method calls and took 500 milliseconds to process. Now it only takes around 2-10 ms to process. I also only update the lighting around the player. As the player moves near to the edge of the lit area it will re-light the surroundings. I also have coloured light support.
Data wise, lights are stored in bytes (I actually used signed bytes even though I don’t use negative numbers
and the higher the number, the more light it is. When I render, it flips the number around (127 - lightValue) to convert it into an alpha which I can use to draw the “shadows”.
I hope this helps!