Skip to content

Commit

Permalink
Added biome color cache support for custom color resolver (#2222)
Browse files Browse the repository at this point in the history
  • Loading branch information
CPTProgrammer authored Jan 15, 2024
1 parent 5550393 commit 27aece3
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ public final class WorldSlice implements BlockRenderView, BiomeColorView, Render

// The starting point from which this slice captures blocks
private int originX, originY, originZ;

// The volume that this WorldSlice contains
private BlockBox volume;

Expand Down Expand Up @@ -194,7 +194,7 @@ private void unpackBlockData(BlockState[] blockArray, ChunkRenderContext context
ChunkSectionPos origin = context.getOrigin();
ChunkSectionPos pos = section.getPosition();

if (origin.equals(pos)) {
if (origin.equals(pos)) {
container.sodium$unpack(blockArray);
} else {
var bounds = context.getVolume();
Expand Down Expand Up @@ -330,7 +330,7 @@ public BlockEntity getBlockEntity(int x, int y, int z) {

@Override
public int getColor(BlockPos pos, ColorResolver resolver) {
return this.biomeColors.getColor(BiomeColorSource.from(resolver), pos.getX(), pos.getY(), pos.getZ());
return this.biomeColors.getColor(resolver, pos.getX(), pos.getY(), pos.getZ());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
package me.jellysquid.mods.sodium.client.world.biome;

import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap;
import me.jellysquid.mods.sodium.client.util.color.BoxBlur;
import me.jellysquid.mods.sodium.client.util.color.BoxBlur.ColorBuffer;
import me.jellysquid.mods.sodium.client.world.cloned.ChunkRenderContext;
import net.minecraft.client.color.world.BiomeColors;
import net.minecraft.util.math.MathHelper;
import net.minecraft.world.biome.Biome;

import java.util.Arrays;
import net.minecraft.world.biome.ColorResolver;

public class BiomeColorCache {
private static final int NEIGHBOR_BLOCK_RADIUS = 2;
private final BiomeSlice biomeData;

private final Slice[] slices;
private final boolean[] populatedSlices;
private final Reference2ReferenceOpenHashMap<ColorResolver, Slice[]> slices;
private long populateStamp;

private final int blendRadius;

Expand All @@ -23,21 +23,19 @@ public class BiomeColorCache {
private int minX, minY, minZ;
private int maxX, maxY, maxZ;

private final int sizeXZ, sizeY;

public BiomeColorCache(BiomeSlice biomeData, int blendRadius) {
this.biomeData = biomeData;
this.blendRadius = blendRadius;

int sizeXZ = 16 + ((NEIGHBOR_BLOCK_RADIUS + this.blendRadius) * 2);
int sizeY = 16 + (NEIGHBOR_BLOCK_RADIUS * 2);

this.slices = new Slice[sizeY];
this.populatedSlices = new boolean[sizeY];
this.sizeXZ = 16 + ((NEIGHBOR_BLOCK_RADIUS + this.blendRadius) * 2);
this.sizeY = 16 + (NEIGHBOR_BLOCK_RADIUS * 2);

for (int y = 0; y < sizeY; y++) {
this.slices[y] = new Slice(sizeXZ);
}
this.slices = new Reference2ReferenceOpenHashMap<>();
this.populateStamp = 1;

this.tempColorBuffer = new ColorBuffer(sizeXZ, sizeXZ);
this.tempColorBuffer = new ColorBuffer(this.sizeXZ, this.sizeXZ);
}

public void update(ChunkRenderContext context) {
Expand All @@ -49,27 +47,47 @@ public void update(ChunkRenderContext context) {
this.maxY = (context.getOrigin().getMaxY() + NEIGHBOR_BLOCK_RADIUS);
this.maxZ = (context.getOrigin().getMaxZ() + NEIGHBOR_BLOCK_RADIUS) + this.blendRadius;

Arrays.fill(this.populatedSlices, false);
this.populateStamp++;
}

public int getColor(BiomeColorSource source, int blockX, int blockY, int blockZ) {
return switch (source) {
case GRASS -> getColor(BiomeColors.GRASS_COLOR, blockX, blockY, blockZ);
case FOLIAGE -> getColor(BiomeColors.FOLIAGE_COLOR, blockX, blockY, blockZ);
case WATER -> getColor(BiomeColors.WATER_COLOR, blockX, blockY, blockZ);
};
}

public int getColor(ColorResolver resolver, int blockX, int blockY, int blockZ) {
var relX = MathHelper.clamp(blockX, this.minX, this.maxX) - this.minX;
var relY = MathHelper.clamp(blockY, this.minY, this.maxY) - this.minY;
var relZ = MathHelper.clamp(blockZ, this.minZ, this.maxZ) - this.minZ;

if (!this.populatedSlices[relY]) {
this.updateColorBuffers(relY);
if (!this.slices.containsKey(resolver)) {
this.initializeSlices(resolver);
}

var slice = this.slices[relY];
var buffer = slice.getBuffer(source);
var slice = this.slices.get(resolver)[relY];

if (slice.lastPopulateStamp < this.populateStamp) {
this.updateColorBuffers(relY, resolver, slice);
}

var buffer = slice.getBuffer();

return buffer.get(relX, relZ);
}

private void updateColorBuffers(int relY) {
var slice = this.slices[relY];
private void initializeSlices(ColorResolver resolver) {
var slice = new Slice[this.sizeY];
this.slices.put(resolver, slice);

for (int y = 0; y < this.sizeY; y++) {
slice[y] = new Slice(this.sizeXZ);
}
}

private void updateColorBuffers(int relY, ColorResolver resolver, Slice slice) {
int worldY = this.minY + relY;

for (int worldZ = this.minZ; worldZ <= this.maxZ; worldZ++) {
Expand All @@ -79,38 +97,28 @@ private void updateColorBuffers(int relY) {
int relativeX = worldX - this.minX;
int relativeZ = worldZ - this.minZ;

slice.grass.set(relativeX, relativeZ, BiomeColors.GRASS_COLOR.getColor(biome, worldX, worldZ));
slice.foliage.set(relativeX, relativeZ, BiomeColors.FOLIAGE_COLOR.getColor(biome, worldX, worldZ));
slice.water.set(relativeX, relativeZ, BiomeColors.WATER_COLOR.getColor(biome, worldX, worldZ));
slice.buffer.set(relativeX, relativeZ, resolver.getColor(biome, worldX, worldZ));
}
}

if (this.blendRadius > 0) {
BoxBlur.blur(slice.grass, this.tempColorBuffer, this.blendRadius);
BoxBlur.blur(slice.foliage, this.tempColorBuffer, this.blendRadius);
BoxBlur.blur(slice.water, this.tempColorBuffer, this.blendRadius);
BoxBlur.blur(slice.buffer, this.tempColorBuffer, this.blendRadius);
}

this.populatedSlices[relY] = true;
slice.lastPopulateStamp = this.populateStamp;
}

private static class Slice {
private final ColorBuffer grass;
private final ColorBuffer foliage;
private final ColorBuffer water;
private final ColorBuffer buffer;
private long lastPopulateStamp;

private Slice(int size) {
this.grass = new ColorBuffer(size, size);
this.foliage = new ColorBuffer(size, size);
this.water = new ColorBuffer(size, size);
this.buffer = new ColorBuffer(size, size);
this.lastPopulateStamp = 0;
}

public ColorBuffer getBuffer(BiomeColorSource source) {
return switch (source) {
case GRASS -> this.grass;
case FOLIAGE -> this.foliage;
case WATER -> this.water;
};
public ColorBuffer getBuffer() {
return this.buffer;
}
}
}

0 comments on commit 27aece3

Please sign in to comment.