Skip to content

Commit

Permalink
fix: Use 3D biome color blending
Browse files Browse the repository at this point in the history
This causes a bit of a slowdown (especially now that the
biome cache is gone) but it shouldn't be too bad...
  • Loading branch information
jellysquid3 committed Nov 24, 2021
1 parent af01bef commit cfc36ac
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,59 +34,69 @@ public <T> int[] getColors(BlockRenderView world, BlockPos origin, ModelQuadView
private <T> int getVertexColor(ModelQuadColorProvider<T> colorizer, BlockRenderView world, T state, BlockPos origin,
ModelQuadView quad, int vertexIdx) {
final int x = origin.getX() + (int) quad.getX(vertexIdx);
final int y = origin.getY() + (int) quad.getY(vertexIdx);
final int z = origin.getZ() + (int) quad.getZ(vertexIdx);

final int color = this.getBlockColor(colorizer, world, state, origin, x, z, quad.getColorIndex());
final int color = this.getBlockColor(colorizer, world, state, x, y, z, quad.getColorIndex());

return ColorARGB.toABGR(color);
}

private <T> int getBlockColor(ModelQuadColorProvider<T> colorizer, BlockRenderView world, T state, BlockPos origin,
int x, int z, int colorIdx) {
return colorizer.getColor(state, world, this.mpos.set(x, origin.getY(), z), colorIdx);
private <T> int getBlockColor(ModelQuadColorProvider<T> colorizer, BlockRenderView world, T state,
int x, int y, int z, int colorIdx) {
return colorizer.getColor(state, world, this.mpos.set(x, y, z), colorIdx);
}

private <T> int getInterpolatedVertexColor(ModelQuadColorProvider<T> colorizer, BlockRenderView world, T state,
BlockPos origin, ModelQuadView quad, int vertexIdx) {
final float x = quad.getX(vertexIdx);
final float y = quad.getY(vertexIdx);
final float z = quad.getZ(vertexIdx);

final int intX = (int) x;
final int intY = (int) y;
final int intZ = (int) z;

// Integer component of position vector
final int originX = origin.getX() + intX;
final int originY = origin.getY() + intY;
final int originZ = origin.getZ() + intZ;

// Retrieve the color values for each neighbor
final int c1 = this.getBlockColor(colorizer, world, state, origin, originX, originZ, quad.getColorIndex());
final int c2 = this.getBlockColor(colorizer, world, state, origin, originX, originZ + 1, quad.getColorIndex());
final int c3 = this.getBlockColor(colorizer, world, state, origin, originX + 1, originZ, quad.getColorIndex());
final int c4 = this.getBlockColor(colorizer, world, state, origin, originX + 1, originZ + 1, quad.getColorIndex());
final int c000 = this.getBlockColor(colorizer, world, state, originX, originY, originZ, quad.getColorIndex());
final int c001 = this.getBlockColor(colorizer, world, state, originX, originY, originZ + 1, quad.getColorIndex());
final int c100 = this.getBlockColor(colorizer, world, state, originX + 1, originY, originZ, quad.getColorIndex());
final int c101 = this.getBlockColor(colorizer, world, state, originX + 1, originY, originZ + 1, quad.getColorIndex());

final int result;
final int c010 = this.getBlockColor(colorizer, world, state, originX, originY + 1, originZ, quad.getColorIndex());
final int c011 = this.getBlockColor(colorizer, world, state, originX, originY + 1, originZ + 1, quad.getColorIndex());
final int c110 = this.getBlockColor(colorizer, world, state, originX + 1, originY + 1, originZ, quad.getColorIndex());
final int c111 = this.getBlockColor(colorizer, world, state, originX + 1, originY + 1, originZ + 1, quad.getColorIndex());

// All the colors are the same, so the results of interpolation will be useless.
if (c1 == c2 && c2 == c3 && c3 == c4) {
result = c1;
} else {
// Fraction component of position vector
final float fracX = x - intX;
final float fracZ = z - intZ;
// Fraction component of position vector
final float fracX = x - intX;
final float fracY = y - intY;
final float fracZ = z - intZ;

int z1 = ColorMixer.getStartRatio(fracZ);
int z2 = ColorMixer.getEndRatio(fracZ);
int dx1 = ColorMixer.getStartRatio(fracX);
int dx2 = ColorMixer.getEndRatio(fracX);

int r1 = ColorMixer.mixARGB(c1, c2, z1, z2);
int r2 = ColorMixer.mixARGB(c3, c4, z1, z2);
int dy1 = ColorMixer.getStartRatio(fracY);
int dy2 = ColorMixer.getEndRatio(fracY);

int x1 = ColorMixer.getStartRatio(fracX);
int x2 = ColorMixer.getEndRatio(fracX);
int dz1 = ColorMixer.getStartRatio(fracZ);
int dz2 = ColorMixer.getEndRatio(fracZ);

result = ColorMixer.mixARGB(r1, r2, x1, x2);
}
int c00 = ColorMixer.mixARGB(c000, c001, dz1, dz2);
int c01 = ColorMixer.mixARGB(c100, c101, dz1, dz2);
int c10 = ColorMixer.mixARGB(c010, c011, dz1, dz2);
int c11 = ColorMixer.mixARGB(c110, c111, dz1, dz2);

return ColorARGB.toABGR(result);
}
int c0 = ColorMixer.mixARGB(c00, c01, dy1, dy2);
int c1 = ColorMixer.mixARGB(c10, c11, dy1, dy2);

int c = ColorMixer.mixARGB(c0, c1, dx1, dx2);

return ColorARGB.toABGR(c);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ public class BiomeColorCache {

private final int radius;
private final int dim;
private final int minX, minZ;

private final int height;
private final int minX, minY, minZ;

private final int blendedColorsMinX;
private final int blendedColorsMinY;
private final int blendedColorsMinZ;

public BiomeColorCache(ColorResolver resolver, WorldSlice slice) {
Expand All @@ -35,78 +35,84 @@ public BiomeColorCache(ColorResolver resolver, WorldSlice slice) {
ChunkSectionPos origin = this.slice.getOrigin();

this.minX = origin.getMinX() - (this.radius + 2);
this.minY = origin.getMinY() - (this.radius + 2);
this.minZ = origin.getMinZ() - (this.radius + 2);

this.height = origin.getMinY();
this.dim = 16 + ((this.radius + 2) * 2);

this.blendedColorsMinX = origin.getMinX() - 2;
this.blendedColorsMinY = origin.getMinY() - 2;
this.blendedColorsMinZ = origin.getMinZ() - 2;

this.cache = new int[this.dim * this.dim];
this.blendedColors = new int[BLENDED_COLORS_DIM * BLENDED_COLORS_DIM];
this.cache = new int[this.dim * this.dim * this.dim];
this.blendedColors = new int[BLENDED_COLORS_DIM * BLENDED_COLORS_DIM * BLENDED_COLORS_DIM];

Arrays.fill(this.cache, -1);
Arrays.fill(this.blendedColors, -1);
}

public int getBlendedColor(BlockPos pos) {
int x2 = pos.getX() - this.blendedColorsMinX;
int y2 = pos.getY() - this.blendedColorsMinY;
int z2 = pos.getZ() - this.blendedColorsMinZ;

int index = (x2 * BLENDED_COLORS_DIM) + z2;
int index = (y2 * BLENDED_COLORS_DIM * BLENDED_COLORS_DIM) + (x2 * BLENDED_COLORS_DIM) + z2;
int color = this.blendedColors[index];

if (color == -1) {
this.blendedColors[index] = color = this.calculateBlendedColor(pos.getX(), pos.getZ());
this.blendedColors[index] = color = this.calculateBlendedColor(pos.getX(), pos.getY(), pos.getZ());
}

return color;
}

private int calculateBlendedColor(int posX, int posZ) {
private int calculateBlendedColor(int posX, int posY, int posZ) {
if (this.radius == 0) {
return this.getColor(posX, posZ);
return this.getColor(posX, posY, posZ);
}

int diameter = (this.radius * 2) + 1;
int area = diameter * diameter;
int area = diameter * diameter * diameter;

int r = 0;
int g = 0;
int b = 0;

int minX = posX - this.radius;
int minY = posY - this.radius;
int minZ = posZ - this.radius;

int maxX = posX + this.radius;
int maxY = posY + this.radius;
int maxZ = posZ + this.radius;

for (int x2 = minX; x2 <= maxX; x2++) {
for (int z2 = minZ; z2 <= maxZ; z2++) {
int color = this.getColor(x2, z2);

r += ColorARGB.unpackRed(color);
g += ColorARGB.unpackGreen(color);
b += ColorARGB.unpackBlue(color);
for (int y2 = minY; y2 <= maxY; y2++) {
for (int z2 = minZ; z2 <= maxZ; z2++) {
int color = this.getColor(x2, y2, z2);

r += ColorARGB.unpackRed(color);
g += ColorARGB.unpackGreen(color);
b += ColorARGB.unpackBlue(color);
}
}
}

return ColorARGB.pack(r / area, g / area, b / area, 255);
}

private int getColor(int x, int z) {
int index = ((x - this.minX) * this.dim) + (z - this.minZ);
private int getColor(int x, int y, int z) {
int index = ((y - this.minY) * this.dim * this.dim) + ((x - this.minX) * this.dim) + (z - this.minZ);
int color = this.cache[index];

if (color == -1) {
this.cache[index] = color = this.calculateColor(x, z);
this.cache[index] = color = this.calculateColor(x, y, z);
}

return color;
}

private int calculateColor(int x, int z) {
return this.resolver.getColor(this.slice.getBiome(x, this.height, z), x, z);
private int calculateColor(int x, int y, int z) {
return this.resolver.getColor(this.slice.getBiome(x, y, z), x, z);
}
}

0 comments on commit cfc36ac

Please sign in to comment.