Add basic horizontal light spread to fallback sky lighting

This commit is contained in:
Mike Primm 2021-12-26 15:54:57 -06:00
parent 0452ab1dac
commit 833b25615a
2 changed files with 90 additions and 19 deletions

View file

@ -117,33 +117,99 @@ public class GenericChunk {
// Generate simple sky lighting (must be after all sections have been added) // Generate simple sky lighting (must be after all sections have been added)
public Builder generateSky() { public Builder generateSky() {
int sky[] = new int[256]; // ZX array int sky[] = new int[256]; // ZX array
boolean nonOpaque[] = new boolean[256]; // ZX array of non opaque blocks (atten < 15)
Arrays.fill(sky, 15); // Start fully lit at top Arrays.fill(sky, 15); // Start fully lit at top
GenericChunkSection.Builder bld = new GenericChunkSection.Builder(); GenericChunkSection.Builder bld = new GenericChunkSection.Builder();
boolean allzero = false; boolean allzero = false;
// Make light array for each section, start from top // Make light array for each section, start from top
for (int i = (sections.length - 1); i >= 0; i--) { for (int i = (sections.length - 1); i >= 0; i--) {
if (sections[i] == null) continue; GenericChunkSection sect = sections[i];
if (sect == null) continue;
if (allzero) { // Start section with all zero already, just zero it and move on
// Replace section with new all zero light
sections[i] = bld.buildFrom(sect, 0);
continue;
}
byte[] ssky = new byte[2048]; byte[] ssky = new byte[2048];
if (!allzero) { int allfullcnt = 0;
for (int x = 0; x < 16; x++) { // Top to bottom
for (int z = 0; z < 16; z++) { for (int y = 15; (y >= 0) && (!allzero); y--) {
int idx = (z << 4) + x; int totalval = 0; // Use for allzero or allfull
for (int y = 15; y >= 0; y--) { int yidx = y << 7;
DynmapBlockState bs = sections[i].blocks.getBlock(x, y, z); // Get block // Light next layer down
int atten = bs.getLightAttenuation(); for (int x = 0; x < 16; x++) {
sky[idx] = (sky[idx] >= atten) ? (sky[idx] - atten) : 0; for (int z = 0; z < 16; z++) {
ssky[(y << 7) | (z << 3) | (x >> 1)] |= (sky[idx] << (4 * (x & 1))); int idx = (z << 4) + x;
} int val = sky[idx];
} DynmapBlockState bs = sect.blocks.getBlock(x, y, z); // Get block
} int atten = bs.getLightAttenuation();
// Check if we're all dark if ((atten > 0) && (val > 0)) {
allzero = true; val = (val >= atten) ? (val - atten) : 0;
for (int v = 0; v < 256; v++) { sky[idx] = val;
if (sky[v] > 0) { allzero = false; break; } }
} nonOpaque[idx] = atten < 15;
totalval += val;
}
}
allzero = (totalval == 0);
boolean allfull = (totalval == (15 * 256));
if (allfull) allfullcnt++;
// If not all fully lit nor all zero, handle horizontal spread
if (! (allfull || allzero)) {
// Now do horizontal spread
boolean changed;
do {
changed = false;
for (int x = 0; x < 16; x++) {
for (int z = 0; z < 16; z++) {
int idx = (z << 4) + x;
int cur = sky[idx];
boolean curnonopaq = nonOpaque[idx];
if (x < 15) { // If not right edge, check X spread
int right = sky[idx+1];
boolean rightnonopaq = nonOpaque[idx+1];
// If spread right
if (rightnonopaq && ((cur - 1) > right)) {
sky[idx+1] = cur - 1; changed = true;
}
// If spread left
else if (curnonopaq && (cur < (right - 1))) {
sky[idx] = cur = right - 1; changed = true;
}
}
if (z < 15) { // If not bottom edge, check Z spread
int down = sky[idx+16];
boolean downnonopaq = nonOpaque[idx+16];
// If spread down
if (downnonopaq && ((cur - 1) > down)) {
sky[idx+16] = cur - 1; changed = true;
}
// If spread up
else if (curnonopaq && (cur < (down - 1))) {
sky[idx] = down - 1; changed = true;
}
}
}
}
} while (changed);
// Save values
for (int v = 0; v < 128; v++) {
ssky[yidx | v] = (byte)(sky[v << 1] | (sky[(v << 1) + 1] << 4));
}
}
else if (allfull) { // All light, just fill it
for (int v = 0; v < 128; v++) {
ssky[yidx | v] = (byte) 0xFF;
}
}
} }
// Replace section with new one with new lighting // Replace section with new one with new lighting
sections[i] = bld.buildFrom(sections[i], ssky); if (allfullcnt == 16) { // Just full?
sections[i] = bld.buildFrom(sect, 15);
}
else {
sections[i] = bld.buildFrom(sect, ssky);
}
} }
return this; return this;
} }

View file

@ -243,6 +243,11 @@ public class GenericChunkSection {
LightingAccess skyA = new LightingAccess3D(sky); LightingAccess skyA = new LightingAccess3D(sky);
return new GenericChunkSection(s.blocks, s.biomes, skyA, s.emitted, s.isEmpty); return new GenericChunkSection(s.blocks, s.biomes, skyA, s.emitted, s.isEmpty);
} }
// Build copy from existing section with new single value skylight
public GenericChunkSection buildFrom(GenericChunkSection s, int singlesky) {
LightingAccess skyA = new LightingAccessSingle(singlesky);
return new GenericChunkSection(s.blocks, s.biomes, skyA, s.emitted, s.isEmpty);
}
// Build section based on current builder state // Build section based on current builder state
public GenericChunkSection build() { public GenericChunkSection build() {