Skip to content

Commit

Permalink
Rename useBiomeTint to isBiomeDependant. Make 2D biome benefit from t…
Browse files Browse the repository at this point in the history
…racking whether biome is used int the chunk or not
  • Loading branch information
aTom3333 committed Oct 14, 2023
1 parent 01d7f53 commit 62b1587
Show file tree
Hide file tree
Showing 9 changed files with 134 additions and 130 deletions.
6 changes: 2 additions & 4 deletions chunky/src/java/se/llbit/chunky/block/AbstractModelBlock.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package se.llbit.chunky.block;

import se.llbit.chunky.model.AABBModel;
import se.llbit.chunky.model.BlockModel;
import se.llbit.chunky.model.Tint;
import se.llbit.chunky.plugin.PluginApi;
import se.llbit.chunky.renderer.scene.Scene;
import se.llbit.chunky.resources.Texture;
Expand Down Expand Up @@ -49,7 +47,7 @@ public boolean intersect(Ray ray, Scene scene) {
}

@Override
public boolean useBiomeTint() {
return super.useBiomeTint() || model.useBiomeTint();
public boolean isBiomeDependant() {
return super.isBiomeDependant() || model.isBiomeDependant();
}
}
2 changes: 1 addition & 1 deletion chunky/src/java/se/llbit/chunky/block/Block.java
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ public Tag getNewTagWithBlockEntity(Tag blockTag, CompoundTag entityTag) {
/**
* Does this block use biome tint for its rendering
*/
public boolean useBiomeTint() {
public boolean isBiomeDependant() {
return isWaterFilled();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public Tag getNewTagWithBlockEntity(Tag blockTag, CompoundTag entityTag) {
}

@Override
public boolean useBiomeTint() {
public boolean isBiomeDependant() {
return true; // (in reality it is only used for fern)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public void finalizeBlock(FinalizationState state) {
}

@Override
public boolean useBiomeTint() {
public boolean isBiomeDependant() {
return true;
}
}
2 changes: 1 addition & 1 deletion chunky/src/java/se/llbit/chunky/model/AABBModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ private boolean intersectFace(Ray ray, Scene scene, Texture texture, UVMapping m
}

@Override
public boolean useBiomeTint() {
public boolean isBiomeDependant() {
Tint[][] tints = getTints();
if(tints == null)
return false;
Expand Down
2 changes: 1 addition & 1 deletion chunky/src/java/se/llbit/chunky/model/BlockModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@ public interface BlockModel {

double faceSurfaceArea(int face);

boolean useBiomeTint();
boolean isBiomeDependant();
}
2 changes: 1 addition & 1 deletion chunky/src/java/se/llbit/chunky/model/QuadModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ public boolean intersect(Ray ray, Scene scene) {
}

@Override
public boolean useBiomeTint() {
public boolean isBiomeDependant() {
Tint[] tints = getTints();
if(tints == null)
return false;
Expand Down
241 changes: 121 additions & 120 deletions chunky/src/java/se/llbit/chunky/renderer/scene/Scene.java
Original file line number Diff line number Diff line change
Expand Up @@ -934,9 +934,9 @@ public synchronized void loadChunks(TaskTracker taskTracker, World world, Collec
int wz0 = cp.z * 16;
BiomeData biomeData = chunkData.getBiomeData();
ChunkBiomeBlendingHelper chunkBiomeHelper = new ChunkBiomeBlendingHelper();
biomeBlendingHelper.put(cp, chunkBiomeHelper);

if (use3dBiomes) {
biomeBlendingHelper.put(cp, chunkBiomeHelper);
// We need to load biome data for the full height of the chunk
// and not only limited to the sections where there are blocks
// because it is possible that a neighboring chunks has blocks
Expand Down Expand Up @@ -1003,7 +1003,7 @@ public synchronized void loadChunks(TaskTracker taskTracker, World world, Collec
int octNode = currentBlock;
Block block = palette.get(currentBlock);

if(block.useBiomeTint())
if(block.isBiomeDependant())
chunkBiomeHelper.makeBiomeRelevant(y);

if(block.isEntity()) {
Expand Down Expand Up @@ -1243,151 +1243,152 @@ public synchronized void loadChunks(TaskTracker taskTracker, World world, Collec

// Finalize grass and foliage textures.
// 3x3 box blur.
if (biomeBlendingRadius > 0) {
if (use3dBiomes) {
ChunkBiomeBlendingHelper chunkBiomeHelper = biomeBlendingHelper.get(cp);
ChunkBiomeBlendingHelper[] neighboringChunks = new ChunkBiomeBlendingHelper[] {
biomeBlendingHelper.get(new ChunkPosition(cp.x - 1, cp.z - 1)),
biomeBlendingHelper.get(new ChunkPosition(cp.x - 1, cp.z)),
biomeBlendingHelper.get(new ChunkPosition(cp.x - 1, cp.z + 1)),
biomeBlendingHelper.get(new ChunkPosition(cp.x, cp.z - 1)),
biomeBlendingHelper.get(new ChunkPosition(cp.x, cp.z + 1)),
biomeBlendingHelper.get(new ChunkPosition(cp.x + 1, cp.z - 1)),
biomeBlendingHelper.get(new ChunkPosition(cp.x + 1, cp.z)),
biomeBlendingHelper.get(new ChunkPosition(cp.x + 1, cp.z + 1))
};

int[] combinedBiomeTransitions = chunkBiomeHelper.combineAndTrimTransitions(neighboringChunks, biomeBlendingRadius);

// When doing 3D blur we use the list of (vertical) biome transition
// in the chunk or in neighboring ones
// If there is no transition, a 2D blur is enough, otherwise we only
// need to compute the colors around the transitions

// For example, if loading from y=0 to y=200 with a biome transition at y=20
// and another one at y=50 and with a blur radius of 2 (5*5*5 box)
// We can compute a 2D blur at y=0 and use those color for up to y=17
// For y in [18, 21] we need to compute the real 3D blur (because of the biome transition
// at y=20 and the blur radius of 2)
// Then we can compute the 2D blur at y=22 and use those colors for up to y=47
// And so on, 3D blur for y in [48, 51] and 2D blur for y in [52,200]

// As such, in spirit every transition make us compute an additional 16*16*(2*biomeBlendingRadius) 3D blur
// and a 16*16 2D blur (that can be combined in a 16*16*(2*biomeBlendingRadius+1) 3D blur)
// (ignoring cases where transition are close to one another which are handled by the code)

// Note that having a single (x, y) column that effectively has a biome transition
// in the chunk are a neighboring chunk causes us to compute the 3D blur for the whole 16*16
// vertical slice of the chunk. Because vertical biome transition are pretty rare,
// that's probably ok.
int nextY = chunkBiomeHelper.getyMinBiomeRelevant();

for(int i = 0; i < combinedBiomeTransitions.length; ++i) {
int transition = combinedBiomeTransitions[i];
if(nextY < transition - biomeBlendingRadius) {
// Do a 2d blur to fill up to the height affected by the transition
BiomeBlendingUtility.chunk2DBlur(
ChunkBiomeBlendingHelper chunkBiomeHelper = biomeBlendingHelper.get(cp);
if(chunkBiomeHelper.isBiomeUsed()) {
if(biomeBlendingRadius > 0) {
if(use3dBiomes) {
ChunkBiomeBlendingHelper[] neighboringChunks = new ChunkBiomeBlendingHelper[]{
biomeBlendingHelper.get(new ChunkPosition(cp.x - 1, cp.z - 1)),
biomeBlendingHelper.get(new ChunkPosition(cp.x - 1, cp.z)),
biomeBlendingHelper.get(new ChunkPosition(cp.x - 1, cp.z + 1)),
biomeBlendingHelper.get(new ChunkPosition(cp.x, cp.z - 1)),
biomeBlendingHelper.get(new ChunkPosition(cp.x, cp.z + 1)),
biomeBlendingHelper.get(new ChunkPosition(cp.x + 1, cp.z - 1)),
biomeBlendingHelper.get(new ChunkPosition(cp.x + 1, cp.z)),
biomeBlendingHelper.get(new ChunkPosition(cp.x + 1, cp.z + 1))
};

int[] combinedBiomeTransitions = chunkBiomeHelper.combineAndTrimTransitions(neighboringChunks, biomeBlendingRadius);

// When doing 3D blur we use the list of (vertical) biome transition
// in the chunk or in neighboring ones
// If there is no transition, a 2D blur is enough, otherwise we only
// need to compute the colors around the transitions

// For example, if loading from y=0 to y=200 with a biome transition at y=20
// and another one at y=50 and with a blur radius of 2 (5*5*5 box)
// We can compute a 2D blur at y=0 and use those color for up to y=17
// For y in [18, 21] we need to compute the real 3D blur (because of the biome transition
// at y=20 and the blur radius of 2)
// Then we can compute the 2D blur at y=22 and use those colors for up to y=47
// And so on, 3D blur for y in [48, 51] and 2D blur for y in [52,200]

// As such, in spirit every transition make us compute an additional 16*16*(2*biomeBlendingRadius) 3D blur
// and a 16*16 2D blur (that can be combined in a 16*16*(2*biomeBlendingRadius+1) 3D blur)
// (ignoring cases where transition are close to one another which are handled by the code)

// Note that having a single (x, y) column that effectively has a biome transition
// in the chunk are a neighboring chunk causes us to compute the 3D blur for the whole 16*16
// vertical slice of the chunk. Because vertical biome transition are pretty rare,
// that's probably ok.
int nextY = chunkBiomeHelper.getyMinBiomeRelevant();

for(int i = 0; i < combinedBiomeTransitions.length; ++i) {
int transition = combinedBiomeTransitions[i];
if(nextY < transition - biomeBlendingRadius) {
// Do a 2d blur to fill up to the height affected by the transition
BiomeBlendingUtility.chunk2DBlur(
cp,
biomeBlendingRadius,
nextY,
transition - biomeBlendingRadius,
origin,
biomePaletteIdxStructure,
biomePalette,
nonEmptyChunks,
grassTexture,
foliageTexture,
waterTexture);
nextY = transition - biomeBlendingRadius;
}

// Do a 3D blur to fill the next 2*biomeBlendingRadius layers
// or more if the next transition is close by, in which case
// both transition (or even more) are handled by a bigger 3D blur
int maxYWorkedOn = transition + biomeBlendingRadius;
while(i < combinedBiomeTransitions.length - 1 && maxYWorkedOn >= combinedBiomeTransitions[i + 1] - biomeBlendingRadius) {
// Extends the 3D blur to enclose the next transition as well
maxYWorkedOn = combinedBiomeTransitions[i + 1] + biomeBlendingRadius;
++i;
}
int maxYWorkedOnClamped = Math.min(maxYWorkedOn, chunkBiomeHelper.getyMaxBiomeRelevant());
BiomeBlendingUtility.chunk3DBlur(
cp,
biomeBlendingRadius,
nextY,
transition - biomeBlendingRadius,
maxYWorkedOnClamped + 1,
origin,
biomePaletteIdxStructure,
biomePalette,
nonEmptyChunks,
grassTexture,
foliageTexture,
waterTexture);
nextY = transition - biomeBlendingRadius;
nextY = maxYWorkedOnClamped + 1;
}

// Do a 3D blur to fill the next 2*biomeBlendingRadius layers
// or more if the next transition is close by, in which case
// both transition (or even more) are handled by a bigger 3D blur
int maxYWorkedOn = transition + biomeBlendingRadius;
while(i < combinedBiomeTransitions.length - 1 && maxYWorkedOn >= combinedBiomeTransitions[i+1] - biomeBlendingRadius)
{
// Extends the 3D blur to enclose the next transition as well
maxYWorkedOn = combinedBiomeTransitions[i+1] + biomeBlendingRadius;
++i;
// Last 2D blur that extent up to the top
if(nextY <= chunkBiomeHelper.getyMaxBiomeRelevant()) {
BiomeBlendingUtility.chunk2DBlur(
cp,
biomeBlendingRadius,
nextY,
chunkBiomeHelper.getyMaxBiomeRelevant() + 1,
origin,
biomePaletteIdxStructure,
biomePalette,
nonEmptyChunks,
grassTexture,
foliageTexture,
waterTexture);
}
int maxYWorkedOnClamped = Math.min(maxYWorkedOn, chunkBiomeHelper.getyMaxBiomeRelevant());
BiomeBlendingUtility.chunk3DBlur(
cp,
biomeBlendingRadius,
nextY,
maxYWorkedOnClamped + 1,
origin,
biomePaletteIdxStructure,
biomePalette,
nonEmptyChunks,
grassTexture,
foliageTexture,
waterTexture);
nextY = maxYWorkedOnClamped + 1;
}

// Last 2D blur that extent up to the top
if(nextY <= chunkBiomeHelper.getyMaxBiomeRelevant()) {
BiomeBlendingUtility.chunk2DBlur(
cp,
biomeBlendingRadius,
nextY,
chunkBiomeHelper.getyMaxBiomeRelevant() + 1,
origin,
biomePaletteIdxStructure,
biomePalette,
nonEmptyChunks,
grassTexture,
foliageTexture,
waterTexture);
} else {
BiomeBlendingUtility.chunk2DBlur(cp, biomeBlendingRadius, 0, 1, origin, biomePaletteIdxStructure, biomePalette, nonEmptyChunks, grassTexture, foliageTexture, waterTexture);
}
} else {
BiomeBlendingUtility.chunk2DBlur(cp, biomeBlendingRadius, 0, 1, origin, biomePaletteIdxStructure, biomePalette, nonEmptyChunks, grassTexture, foliageTexture, waterTexture);
}
} else {
if (use3dBiomes) {
for (int sectionY = yMin >> 4; sectionY < (yMax - 1 >> 4) + 1; sectionY++) {
for (int y = 0; y < 16; y++) {
int wy = sectionY * 16 + y;
for (int x = 0; x < 16; ++x) {
int wx = cp.x * Chunk.X_MAX + x;
for (int z = 0; z < 16; ++z) {
int wz = cp.z * Chunk.Z_MAX + z;

int id = biomePaletteIdxStructure.get(wx, wy, wz);

Biome biome = biomePalette.get(id);
grassTexture.set(cp.x * 16 + x - origin.x, sectionY * 16 + y - origin.y, cp.z * 16 + z - origin.z, biome.grassColorLinear);
foliageTexture.set(cp.x * 16 + x - origin.x, sectionY * 16 + y - origin.y, cp.z * 16 + z - origin.z, biome.foliageColorLinear);
waterTexture.set(cp.x * 16 + x - origin.x, sectionY * 16 + y - origin.y, cp.z * 16 + z - origin.z, biome.waterColorLinear);
if(use3dBiomes) {
for(int sectionY = yMin >> 4; sectionY < (yMax - 1 >> 4) + 1; sectionY++) {
for(int y = 0; y < 16; y++) {
int wy = sectionY * 16 + y;
for(int x = 0; x < 16; ++x) {
int wx = cp.x * Chunk.X_MAX + x;
for(int z = 0; z < 16; ++z) {
int wz = cp.z * Chunk.Z_MAX + z;

int id = biomePaletteIdxStructure.get(wx, wy, wz);

Biome biome = biomePalette.get(id);
grassTexture.set(cp.x * 16 + x - origin.x, sectionY * 16 + y - origin.y, cp.z * 16 + z - origin.z, biome.grassColorLinear);
foliageTexture.set(cp.x * 16 + x - origin.x, sectionY * 16 + y - origin.y, cp.z * 16 + z - origin.z, biome.foliageColorLinear);
waterTexture.set(cp.x * 16 + x - origin.x, sectionY * 16 + y - origin.y, cp.z * 16 + z - origin.z, biome.waterColorLinear);
}
}
}
}
}
} else {
for (int x = 0; x < 16; ++x) {
int wx = cp.x * 16 + x;
for (int z = 0; z < 16; ++z) {
int wz = cp.z * 16 + z;

int id = biomePaletteIdxStructure.get(wx, 0, wz);
Biome biome = biomePalette.get(id);

grassTexture.set(cp.x * 16 + x - origin.x, 0, cp.z * 16 + z - origin.z, biome.grassColorLinear);
foliageTexture.set(cp.x * 16 + x - origin.x, 0, cp.z * 16 + z - origin.z, biome.foliageColorLinear);
waterTexture.set(cp.x * 16 + x - origin.x, 0, cp.z * 16 + z - origin.z, biome.waterColorLinear);
} else {
for(int x = 0; x < 16; ++x) {
int wx = cp.x * 16 + x;
for(int z = 0; z < 16; ++z) {
int wz = cp.z * 16 + z;

int id = biomePaletteIdxStructure.get(wx, 0, wz);
Biome biome = biomePalette.get(id);

grassTexture.set(cp.x * 16 + x - origin.x, 0, cp.z * 16 + z - origin.z, biome.grassColorLinear);
foliageTexture.set(cp.x * 16 + x - origin.x, 0, cp.z * 16 + z - origin.z, biome.foliageColorLinear);
waterTexture.set(cp.x * 16 + x - origin.x, 0, cp.z * 16 + z - origin.z, biome.waterColorLinear);
}
}
}
}
}
task.updateEta(target, done);
done += 1;
OctreeFinalizer.finalizeChunk(worldOctree, waterOctree, palette, origin, cp, yMin, yMax);
if (legacyChunks.contains(cp)) {
LegacyBlocksFinalizer
.finalizeChunk(worldOctree, waterOctree, palette, origin, cp, yMin, yMax);
}
task.updateEta(target, done);
done += 1;
}

worldOctree.endFinalization();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,9 @@ public int getyMinBiomeRelevant() {
public int getyMaxBiomeRelevant() {
return yMaxBiomeRelevant;
}

public boolean isBiomeUsed() {
// Has makeBiomeRelevant been called at least once
return yMaxBiomeRelevant >= yMinBiomeRelevant;
}
}

0 comments on commit 62b1587

Please sign in to comment.