Тройная буфферизация density volume

This commit is contained in:
2026-08-09 19:10:50 +04:00
parent f08dee2677
commit 3c04c6259e
4 changed files with 84 additions and 10 deletions
@@ -48,6 +48,8 @@ public class PostProcessingManager {
private static int rm_inverseProjectionLocation;
private static int rm_depthSamplerLocation;
private static int rm_fogVolumeLocation;
private static int rm_prevFogVolumeLocation;
private static int rm_fogInterpolationLocation;
private static int rm_skyLightVolumeLocation;
private static int rm_blockLightVolumeLocation;
private static int rm_fogOriginLocation;
@@ -106,6 +108,8 @@ public class PostProcessingManager {
rm_inverseProjectionLocation = raymarchProgram.uniform("InverseProjection");
rm_depthSamplerLocation = raymarchProgram.uniform("DepthSampler");
rm_fogVolumeLocation = raymarchProgram.uniform("FogVolume");
rm_prevFogVolumeLocation = raymarchProgram.uniform("PrevFogVolume");
rm_fogInterpolationLocation = raymarchProgram.uniform("FogInterpolation");
rm_skyLightVolumeLocation = raymarchProgram.uniform("SkyLightVolume");
rm_blockLightVolumeLocation = raymarchProgram.uniform("BlockLightVolume");
rm_fogOriginLocation = raymarchProgram.uniform("FogOrigin");
@@ -280,14 +284,18 @@ public class PostProcessingManager {
GL11.glBindTexture(GL12.GL_TEXTURE_3D, FogSimulationManager.getCurrentDensityTexture());
GL20.glUniform1i(rm_fogVolumeLocation, 1);
// Light Volume
GL13.glActiveTexture(GL13.GL_TEXTURE2);
GL11.glBindTexture(GL12.GL_TEXTURE_3D, FogLightVolume.getSkyLightTexture());
GL20.glUniform1i(rm_skyLightVolumeLocation, 2);
GL11.glBindTexture(GL12.GL_TEXTURE_3D, FogSimulationManager.getPreviousDensityTexture());
GL20.glUniform1i(rm_prevFogVolumeLocation, 2);
// Light Volume
GL13.glActiveTexture(GL13.GL_TEXTURE3);
GL11.glBindTexture(GL12.GL_TEXTURE_3D, FogLightVolume.getSkyLightTexture());
GL20.glUniform1i(rm_skyLightVolumeLocation, 3);
GL13.glActiveTexture(GL13.GL_TEXTURE4);
GL11.glBindTexture(GL12.GL_TEXTURE_3D, FogLightVolume.getBlockLightTexture());
GL20.glUniform1i(rm_blockLightVolumeLocation, 3);
GL20.glUniform1i(rm_blockLightVolumeLocation, 4);
GL20.glUniform2i(rm_fogOriginLocation,
FogSystem.originChunkX() * FogWorldVolume.CHUNK_SIZE,
@@ -314,6 +322,7 @@ public class PostProcessingManager {
// Цвет тумана
GL20.glUniform3f(rm_fogColorLocation, fogR, fogG, fogB);
GL20.glUniform1f(rm_fogInterpolationLocation, FogSimulationManager.getFogInterpolationAlpha());
// Яркость неба
GL20.glUniform1f(rm_skyBrightnessLocation, client.world.getSkyBrightness(tickDelta));
@@ -14,7 +14,11 @@ public final class FogDensityTextures {
private static int textureA = -1;
private static int textureB = -1;
private static int readIndex = 0;
private static int textureC = -1;
private static int currentIndex = 0;
private static int previousIndex = 0;
private static int writeIndex = 1;
private static boolean hasPreviousState = false;
// PBO для быстрой очистки регионов (half float нули)
private static int clearPBO = -1;
@@ -54,6 +58,11 @@ public final class FogDensityTextures {
textureA = createDensityTexture();
textureB = createDensityTexture();
textureC = createDensityTexture();
currentIndex = 0;
previousIndex = 0;
writeIndex = 1;
hasPreviousState = false;
}
private static int createDensityTexture() {
@@ -87,15 +96,45 @@ public final class FogDensityTextures {
}
public static void swap() {
readIndex = 1 - readIndex;
previousIndex = currentIndex;
currentIndex = writeIndex;
// Выбираем свободный буфер для следующей записи
writeIndex = 0;
while (writeIndex == currentIndex || writeIndex == previousIndex) {
writeIndex++;
}
hasPreviousState = true;
}
public static int getReadTexture() {
return readIndex == 0 ? textureA : textureB;
return indexToTexture(currentIndex);
}
public static int getPreviousTexture() {
return indexToTexture(previousIndex);
}
public static int getWriteTexture() {
return readIndex == 0 ? textureB : textureA;
return indexToTexture(writeIndex);
}
public static boolean hasPreviousState() {
return hasPreviousState;
}
private static int indexToTexture(int index) {
switch (index) {
case 0:
return textureA;
case 1:
return textureB;
case 2:
return textureC;
default:
throw new IllegalStateException("Unexpected fog density texture index: " + index);
}
}
/**
@@ -108,6 +147,7 @@ public final class FogDensityTextures {
) {
clearRegionsInTexture(textureA, physX, physZ, widthChunks, depthChunks, count);
clearRegionsInTexture(textureB, physX, physZ, widthChunks, depthChunks, count);
clearRegionsInTexture(textureC, physX, physZ, widthChunks, depthChunks, count);
}
private static void clearRegionsInTexture(
@@ -7,8 +7,9 @@ public final class FogSimulationManager {
private static boolean initialized = false;
private static long lastSimulationTime = 0;
private static long lastSwapTimeNs = 0;
// Симулируем каждые 100 мс (10 раз в секунду)
// Симулируем каждые 300 мс (~3.3 раз в секунду)
private static final long SIMULATION_INTERVAL_NS = 300_000_000L;
private static final long TARGET_STEP_DURATION_NS = 300_000_000L;
private static final long FRAME_TIME_WINDOW_NS = 100_000_000L;
@@ -119,6 +120,7 @@ public final class FogSimulationManager {
long stepDuration = System.nanoTime() - simulationStartedAtNs;
recordCompletedStep(stepDuration);
FogDensityTextures.swap();
lastSwapTimeNs = System.nanoTime();
simulationActive = false;
}
}
@@ -231,6 +233,25 @@ public final class FogSimulationManager {
return FogDensityTextures.getReadTexture();
}
public static int getPreviousDensityTexture() {
return FogDensityTextures.getPreviousTexture();
}
public static float getFogInterpolationAlpha() {
if (!FogDensityTextures.hasPreviousState()) {
return 1.0f;
}
long currentTime = System.nanoTime();
long elapsed = currentTime - lastSwapTimeNs;
if (elapsed <= 0) {
return 0.0f;
}
float alpha = (float) elapsed / (float) SIMULATION_INTERVAL_NS;
return Math.min(alpha, 1.0f);
}
public static void setGlobalEmissionMultiplier(float value) {
globalEmissionMultiplier = value;
}
@@ -2,6 +2,7 @@
uniform sampler2D DepthSampler;
uniform sampler3D FogVolume;
uniform sampler3D PrevFogVolume;
uniform sampler3D SkyLightVolume;
uniform sampler3D BlockLightVolume;
@@ -11,6 +12,7 @@ uniform mat4 InverseView;
uniform vec3 FogColor;
uniform vec3 CameraPosition;
uniform float FogInterpolation;
uniform float SkyBrightness;
uniform ivec2 FogOrigin;
@@ -97,7 +99,9 @@ float density(vec3 worldPos)
{
vec3 uv = worldToUV(worldPos);
if (uv.x < 0.0) return 0.0;
return texture(FogVolume, uv).r;
float currentDensity = texture(FogVolume, uv).r;
float prevDensity = texture(PrevFogVolume, uv).r;
return mix(prevDensity, currentDensity, FogInterpolation);
}
vec2 light(vec3 worldPos)