Тройная буфферизация density volume
This commit is contained in:
@@ -48,6 +48,8 @@ public class PostProcessingManager {
|
|||||||
private static int rm_inverseProjectionLocation;
|
private static int rm_inverseProjectionLocation;
|
||||||
private static int rm_depthSamplerLocation;
|
private static int rm_depthSamplerLocation;
|
||||||
private static int rm_fogVolumeLocation;
|
private static int rm_fogVolumeLocation;
|
||||||
|
private static int rm_prevFogVolumeLocation;
|
||||||
|
private static int rm_fogInterpolationLocation;
|
||||||
private static int rm_skyLightVolumeLocation;
|
private static int rm_skyLightVolumeLocation;
|
||||||
private static int rm_blockLightVolumeLocation;
|
private static int rm_blockLightVolumeLocation;
|
||||||
private static int rm_fogOriginLocation;
|
private static int rm_fogOriginLocation;
|
||||||
@@ -106,6 +108,8 @@ public class PostProcessingManager {
|
|||||||
rm_inverseProjectionLocation = raymarchProgram.uniform("InverseProjection");
|
rm_inverseProjectionLocation = raymarchProgram.uniform("InverseProjection");
|
||||||
rm_depthSamplerLocation = raymarchProgram.uniform("DepthSampler");
|
rm_depthSamplerLocation = raymarchProgram.uniform("DepthSampler");
|
||||||
rm_fogVolumeLocation = raymarchProgram.uniform("FogVolume");
|
rm_fogVolumeLocation = raymarchProgram.uniform("FogVolume");
|
||||||
|
rm_prevFogVolumeLocation = raymarchProgram.uniform("PrevFogVolume");
|
||||||
|
rm_fogInterpolationLocation = raymarchProgram.uniform("FogInterpolation");
|
||||||
rm_skyLightVolumeLocation = raymarchProgram.uniform("SkyLightVolume");
|
rm_skyLightVolumeLocation = raymarchProgram.uniform("SkyLightVolume");
|
||||||
rm_blockLightVolumeLocation = raymarchProgram.uniform("BlockLightVolume");
|
rm_blockLightVolumeLocation = raymarchProgram.uniform("BlockLightVolume");
|
||||||
rm_fogOriginLocation = raymarchProgram.uniform("FogOrigin");
|
rm_fogOriginLocation = raymarchProgram.uniform("FogOrigin");
|
||||||
@@ -280,14 +284,18 @@ public class PostProcessingManager {
|
|||||||
GL11.glBindTexture(GL12.GL_TEXTURE_3D, FogSimulationManager.getCurrentDensityTexture());
|
GL11.glBindTexture(GL12.GL_TEXTURE_3D, FogSimulationManager.getCurrentDensityTexture());
|
||||||
GL20.glUniform1i(rm_fogVolumeLocation, 1);
|
GL20.glUniform1i(rm_fogVolumeLocation, 1);
|
||||||
|
|
||||||
// Light Volume
|
|
||||||
GL13.glActiveTexture(GL13.GL_TEXTURE2);
|
GL13.glActiveTexture(GL13.GL_TEXTURE2);
|
||||||
GL11.glBindTexture(GL12.GL_TEXTURE_3D, FogLightVolume.getSkyLightTexture());
|
GL11.glBindTexture(GL12.GL_TEXTURE_3D, FogSimulationManager.getPreviousDensityTexture());
|
||||||
GL20.glUniform1i(rm_skyLightVolumeLocation, 2);
|
GL20.glUniform1i(rm_prevFogVolumeLocation, 2);
|
||||||
|
|
||||||
|
// Light Volume
|
||||||
GL13.glActiveTexture(GL13.GL_TEXTURE3);
|
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());
|
GL11.glBindTexture(GL12.GL_TEXTURE_3D, FogLightVolume.getBlockLightTexture());
|
||||||
GL20.glUniform1i(rm_blockLightVolumeLocation, 3);
|
GL20.glUniform1i(rm_blockLightVolumeLocation, 4);
|
||||||
|
|
||||||
GL20.glUniform2i(rm_fogOriginLocation,
|
GL20.glUniform2i(rm_fogOriginLocation,
|
||||||
FogSystem.originChunkX() * FogWorldVolume.CHUNK_SIZE,
|
FogSystem.originChunkX() * FogWorldVolume.CHUNK_SIZE,
|
||||||
@@ -314,6 +322,7 @@ public class PostProcessingManager {
|
|||||||
|
|
||||||
// Цвет тумана
|
// Цвет тумана
|
||||||
GL20.glUniform3f(rm_fogColorLocation, fogR, fogG, fogB);
|
GL20.glUniform3f(rm_fogColorLocation, fogR, fogG, fogB);
|
||||||
|
GL20.glUniform1f(rm_fogInterpolationLocation, FogSimulationManager.getFogInterpolationAlpha());
|
||||||
|
|
||||||
// Яркость неба
|
// Яркость неба
|
||||||
GL20.glUniform1f(rm_skyBrightnessLocation, client.world.getSkyBrightness(tickDelta));
|
GL20.glUniform1f(rm_skyBrightnessLocation, client.world.getSkyBrightness(tickDelta));
|
||||||
|
|||||||
@@ -14,7 +14,11 @@ public final class FogDensityTextures {
|
|||||||
|
|
||||||
private static int textureA = -1;
|
private static int textureA = -1;
|
||||||
private static int textureB = -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 нули)
|
// PBO для быстрой очистки регионов (half float нули)
|
||||||
private static int clearPBO = -1;
|
private static int clearPBO = -1;
|
||||||
@@ -54,6 +58,11 @@ public final class FogDensityTextures {
|
|||||||
|
|
||||||
textureA = createDensityTexture();
|
textureA = createDensityTexture();
|
||||||
textureB = createDensityTexture();
|
textureB = createDensityTexture();
|
||||||
|
textureC = createDensityTexture();
|
||||||
|
currentIndex = 0;
|
||||||
|
previousIndex = 0;
|
||||||
|
writeIndex = 1;
|
||||||
|
hasPreviousState = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int createDensityTexture() {
|
private static int createDensityTexture() {
|
||||||
@@ -87,15 +96,45 @@ public final class FogDensityTextures {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void swap() {
|
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() {
|
public static int getReadTexture() {
|
||||||
return readIndex == 0 ? textureA : textureB;
|
return indexToTexture(currentIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getPreviousTexture() {
|
||||||
|
return indexToTexture(previousIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getWriteTexture() {
|
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(textureA, physX, physZ, widthChunks, depthChunks, count);
|
||||||
clearRegionsInTexture(textureB, physX, physZ, widthChunks, depthChunks, count);
|
clearRegionsInTexture(textureB, physX, physZ, widthChunks, depthChunks, count);
|
||||||
|
clearRegionsInTexture(textureC, physX, physZ, widthChunks, depthChunks, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void clearRegionsInTexture(
|
private static void clearRegionsInTexture(
|
||||||
|
|||||||
@@ -7,8 +7,9 @@ public final class FogSimulationManager {
|
|||||||
|
|
||||||
private static boolean initialized = false;
|
private static boolean initialized = false;
|
||||||
private static long lastSimulationTime = 0;
|
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 SIMULATION_INTERVAL_NS = 300_000_000L;
|
||||||
private static final long TARGET_STEP_DURATION_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;
|
private static final long FRAME_TIME_WINDOW_NS = 100_000_000L;
|
||||||
@@ -119,6 +120,7 @@ public final class FogSimulationManager {
|
|||||||
long stepDuration = System.nanoTime() - simulationStartedAtNs;
|
long stepDuration = System.nanoTime() - simulationStartedAtNs;
|
||||||
recordCompletedStep(stepDuration);
|
recordCompletedStep(stepDuration);
|
||||||
FogDensityTextures.swap();
|
FogDensityTextures.swap();
|
||||||
|
lastSwapTimeNs = System.nanoTime();
|
||||||
simulationActive = false;
|
simulationActive = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -231,6 +233,25 @@ public final class FogSimulationManager {
|
|||||||
return FogDensityTextures.getReadTexture();
|
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) {
|
public static void setGlobalEmissionMultiplier(float value) {
|
||||||
globalEmissionMultiplier = value;
|
globalEmissionMultiplier = value;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
uniform sampler2D DepthSampler;
|
uniform sampler2D DepthSampler;
|
||||||
uniform sampler3D FogVolume;
|
uniform sampler3D FogVolume;
|
||||||
|
uniform sampler3D PrevFogVolume;
|
||||||
uniform sampler3D SkyLightVolume;
|
uniform sampler3D SkyLightVolume;
|
||||||
uniform sampler3D BlockLightVolume;
|
uniform sampler3D BlockLightVolume;
|
||||||
|
|
||||||
@@ -11,6 +12,7 @@ uniform mat4 InverseView;
|
|||||||
uniform vec3 FogColor;
|
uniform vec3 FogColor;
|
||||||
uniform vec3 CameraPosition;
|
uniform vec3 CameraPosition;
|
||||||
|
|
||||||
|
uniform float FogInterpolation;
|
||||||
uniform float SkyBrightness;
|
uniform float SkyBrightness;
|
||||||
|
|
||||||
uniform ivec2 FogOrigin;
|
uniform ivec2 FogOrigin;
|
||||||
@@ -97,7 +99,9 @@ float density(vec3 worldPos)
|
|||||||
{
|
{
|
||||||
vec3 uv = worldToUV(worldPos);
|
vec3 uv = worldToUV(worldPos);
|
||||||
if (uv.x < 0.0) return 0.0;
|
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)
|
vec2 light(vec3 worldPos)
|
||||||
|
|||||||
Reference in New Issue
Block a user