Сглажены биомы

This commit is contained in:
2026-08-09 20:35:57 +04:00
parent 9fa0370ad0
commit e7a6e587ff
2 changed files with 60 additions and 40 deletions
@@ -3,7 +3,6 @@ package su.divan2000.veila.client.render.fog;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.registry.entry.RegistryEntry;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.Heightmap;
import net.minecraft.world.biome.Biome; import net.minecraft.world.biome.Biome;
import net.minecraft.world.chunk.WorldChunk; import net.minecraft.world.chunk.WorldChunk;
@@ -15,8 +14,9 @@ public final class FogBiomeStreamer {
FogWorldVolume.CHUNKS_X * FogWorldVolume.CHUNKS_Z; FogWorldVolume.CHUNKS_X * FogWorldVolume.CHUNKS_Z;
private static final int TOTAL_WORDS = (TOTAL_CHUNKS + 63) / 64; private static final int TOTAL_WORDS = (TOTAL_CHUNKS + 63) / 64;
// ИЗМЕНЕНО: 4×4 пикселя на чанк × 4 канала = 64 float
private static final int CHUNK_DATA_FLOATS = private static final int CHUNK_DATA_FLOATS =
FogWorldVolume.CHUNK_SIZE * FogWorldVolume.CHUNK_SIZE * 4; FogBiomeTexture.CHUNK_DATA_FLOATS;
private static final int MAX_CHUNKS_PER_TICK = 8; private static final int MAX_CHUNKS_PER_TICK = 8;
private static volatile int burstFrames = 0; private static volatile int burstFrames = 0;
@@ -171,6 +171,7 @@ public final class FogBiomeStreamer {
} }
} }
// ИЗМЕНЕНО: усреднение параметров биомов
private static boolean fillBiomesIntoArray(int chunkX, int chunkZ, float[] array) { private static boolean fillBiomesIntoArray(int chunkX, int chunkZ, float[] array) {
MinecraftClient client = MinecraftClient.getInstance(); MinecraftClient client = MinecraftClient.getInstance();
if (client.world == null) return false; if (client.world == null) return false;
@@ -179,23 +180,44 @@ public final class FogBiomeStreamer {
.getWorldChunk(chunkX, chunkZ, false); .getWorldChunk(chunkX, chunkZ, false);
if (chunk == null) return false; if (chunk == null) return false;
int topY = client.world.getTopY()-1; int topY = client.world.getTopY() - 1;
int baseWorldX = chunkX << 4; int baseWorldX = chunkX << 4;
int baseWorldZ = chunkZ << 4; int baseWorldZ = chunkZ << 4;
int idx = 0; int idx = 0;
for (int z = 0; z < FogWorldVolume.CHUNK_SIZE; z++) { // 4×4 пикселя на чанк (каждый покрывает 4×4 блока)
int worldZ = baseWorldZ + z; for (int pz = 0; pz < FogBiomeTexture.PIXELS_PER_CHUNK; pz++) {
for (int x = 0; x < FogWorldVolume.CHUNK_SIZE; x++) { for (int px = 0; px < FogBiomeTexture.PIXELS_PER_CHUNK; px++) {
int worldX = baseWorldX + x; // Суммируем параметры всех 16 блоков в этом пикселе
float sumEmission = 0;
float sumTargetDensity = 0;
float sumHumidity = 0;
float sumTimeSensitivity = 0;
for (int dz = 0; dz < FogBiomeTexture.PIXELS_PER_CHUNK; dz++) {
for (int dx = 0; dx < FogBiomeTexture.PIXELS_PER_CHUNK; dx++) {
int localX = px * FogBiomeTexture.PIXELS_PER_CHUNK + dx;
int localZ = pz * FogBiomeTexture.PIXELS_PER_CHUNK + dz;
int worldX = baseWorldX + localX;
int worldZ = baseWorldZ + localZ;
int surfaceY = chunk.getHeightmap(Heightmap.Type.WORLD_SURFACE).get(x, z);
BlockPos samplePos = new BlockPos(worldX, topY, worldZ); BlockPos samplePos = new BlockPos(worldX, topY, worldZ);
RegistryEntry<Biome> biomeEntry = client.world.getBiome(samplePos); RegistryEntry<Biome> biomeEntry = client.world.getBiome(samplePos);
FogBiomeParams params = FogBiomeParams.forBiome(biomeEntry); FogBiomeParams params = FogBiomeParams.forBiome(biomeEntry);
params.pack(array, idx);
sumEmission += params.emissionMultiplier;
sumTargetDensity += params.targetDensityBase;
sumHumidity += params.humidity;
sumTimeSensitivity += params.timeSensitivity;
}
}
// Усредняем
float invCount = 1.0f / (FogBiomeTexture.PIXELS_PER_CHUNK * FogBiomeTexture.PIXELS_PER_CHUNK);
array[idx ] = sumEmission * invCount;
array[idx + 1] = sumTargetDensity * invCount;
array[idx + 2] = sumHumidity * invCount;
array[idx + 3] = sumTimeSensitivity * invCount;
idx += 4; idx += 4;
} }
} }
@@ -7,26 +7,25 @@ import java.nio.FloatBuffer;
public final class FogBiomeTexture { public final class FogBiomeTexture {
public static final int SIZE_X = FogWorldVolume.SIZE_X; // ИЗМЕНЕНО: 64×64 (один пиксель = 4×4 блока)
public static final int SIZE_Z = FogWorldVolume.SIZE_Z; public static final int SIZE_X = FogWorldVolume.SIZE_X / 4; // 64
public static final int SIZE_Z = FogWorldVolume.SIZE_Z / 4; // 64
private static int texture = -1; private static int texture = -1;
private static final int[] uploadPBOs = new int[3]; private static final int[] uploadPBOs = new int[3];
private static int uploadPBOIndex = 0; private static int uploadPBOIndex = 0;
private static final int CHUNK_DATA_FLOATS = // ИЗМЕНЕНО: 4×4 пикселя на чанк × 4 канала = 64 float
FogWorldVolume.CHUNK_SIZE * FogWorldVolume.CHUNK_SIZE * 4; public static final int PIXELS_PER_CHUNK = 4;
private static final int CHUNK_DATA_BYTES = CHUNK_DATA_FLOATS * 4; public static final int CHUNK_DATA_FLOATS =
PIXELS_PER_CHUNK * PIXELS_PER_CHUNK * 4;
public static final int CHUNK_DATA_BYTES = CHUNK_DATA_FLOATS * 4;
// Буфер размером с ОДИН чанк
private static final FloatBuffer CHUNK_BUFFER = private static final FloatBuffer CHUNK_BUFFER =
BufferUtils.createFloatBuffer(CHUNK_DATA_FLOATS); BufferUtils.createFloatBuffer(CHUNK_DATA_FLOATS);
// Данные одного чанка
private static final float[] EMPTY_CHUNK = new float[CHUNK_DATA_FLOATS]; private static final float[] EMPTY_CHUNK = new float[CHUNK_DATA_FLOATS];
// Данные одного пикселя (для clearRegions)
private static final float[] EMPTY_PIXEL = {0.0f, 0.0f, 0.0f, 0.0f}; private static final float[] EMPTY_PIXEL = {0.0f, 0.0f, 0.0f, 0.0f};
private FogBiomeTexture() { private FogBiomeTexture() {
@@ -52,8 +51,9 @@ public final class FogBiomeTexture {
(ByteBuffer) null (ByteBuffer) null
); );
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST); // ИЗМЕНЕНО: GL_LINEAR для плавной интерполяции между биомами
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST); GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL12.GL_REPEAT); GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL12.GL_REPEAT);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL12.GL_REPEAT); GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL12.GL_REPEAT);
@@ -63,7 +63,6 @@ public final class FogBiomeTexture {
} }
public static void clear() { public static void clear() {
// Кладем данные ОДНОГО чанка в буфер один раз
CHUNK_BUFFER.clear(); CHUNK_BUFFER.clear();
CHUNK_BUFFER.put(EMPTY_CHUNK); CHUNK_BUFFER.put(EMPTY_CHUNK);
CHUNK_BUFFER.flip(); CHUNK_BUFFER.flip();
@@ -71,19 +70,19 @@ public final class FogBiomeTexture {
GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture); GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture);
GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1); GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1);
// Для каждого чанка загружаем те же данные из буфера, делая rewind // 16×16 чанков (теперь каждый = 4×4 пикселя)
for (int z = 0; z < FogWorldVolume.CHUNKS_Z; z++) { for (int z = 0; z < FogWorldVolume.CHUNKS_Z; z++) {
for (int x = 0; x < FogWorldVolume.CHUNKS_X; x++) { for (int x = 0; x < FogWorldVolume.CHUNKS_X; x++) {
GL11.glTexSubImage2D( GL11.glTexSubImage2D(
GL11.GL_TEXTURE_2D, 0, GL11.GL_TEXTURE_2D, 0,
x * FogWorldVolume.CHUNK_SIZE, x * PIXELS_PER_CHUNK,
z * FogWorldVolume.CHUNK_SIZE, z * PIXELS_PER_CHUNK,
FogWorldVolume.CHUNK_SIZE, PIXELS_PER_CHUNK,
FogWorldVolume.CHUNK_SIZE, PIXELS_PER_CHUNK,
GL11.GL_RGBA, GL11.GL_FLOAT, GL11.GL_RGBA, GL11.GL_FLOAT,
CHUNK_BUFFER CHUNK_BUFFER
); );
CHUNK_BUFFER.rewind(); // ← важно: возвращаем позицию к началу CHUNK_BUFFER.rewind();
} }
} }
@@ -113,10 +112,10 @@ public final class FogBiomeTexture {
GL11.glTexSubImage2D( GL11.glTexSubImage2D(
GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_2D,
0, 0,
textureChunkX * FogWorldVolume.CHUNK_SIZE, textureChunkX * PIXELS_PER_CHUNK,
textureChunkZ * FogWorldVolume.CHUNK_SIZE, textureChunkZ * PIXELS_PER_CHUNK,
FogWorldVolume.CHUNK_SIZE, PIXELS_PER_CHUNK,
FogWorldVolume.CHUNK_SIZE, PIXELS_PER_CHUNK,
GL11.GL_RGBA, GL11.GL_RGBA,
GL11.GL_FLOAT, GL11.GL_FLOAT,
0L 0L
@@ -136,12 +135,11 @@ public final class FogBiomeTexture {
GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1); GL11.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 1);
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
int w = widthChunks[i] * FogWorldVolume.CHUNK_SIZE; int w = widthChunks[i] * PIXELS_PER_CHUNK;
int d = depthChunks[i] * FogWorldVolume.CHUNK_SIZE; int d = depthChunks[i] * PIXELS_PER_CHUNK;
int totalPixels = w * d; int totalPixels = w * d;
FloatBuffer clearBuf = BufferUtils.createFloatBuffer(totalPixels * 4); FloatBuffer clearBuf = BufferUtils.createFloatBuffer(totalPixels * 4);
// Кладем пустые пиксели (RGBA = 0,0,0,0) по одному
for (int j = 0; j < totalPixels; j++) { for (int j = 0; j < totalPixels; j++) {
clearBuf.put(EMPTY_PIXEL); clearBuf.put(EMPTY_PIXEL);
} }
@@ -149,8 +147,8 @@ public final class FogBiomeTexture {
GL11.glTexSubImage2D( GL11.glTexSubImage2D(
GL11.GL_TEXTURE_2D, 0, GL11.GL_TEXTURE_2D, 0,
physX[i] * FogWorldVolume.CHUNK_SIZE, physX[i] * PIXELS_PER_CHUNK,
physZ[i] * FogWorldVolume.CHUNK_SIZE, physZ[i] * PIXELS_PER_CHUNK,
w, d, w, d,
GL11.GL_RGBA, GL11.GL_FLOAT, GL11.GL_RGBA, GL11.GL_FLOAT,
clearBuf clearBuf