Улучшено поведение дымки

This commit is contained in:
2026-08-09 20:22:36 +04:00
parent 3c04c6259e
commit 9fa0370ad0
3 changed files with 51 additions and 12 deletions
@@ -8,8 +8,9 @@ public final class FogEnvironmentContext {
private static float emissionMultiplier = 1.0f; private static float emissionMultiplier = 1.0f;
private static float targetDensityMultiplier = 0.0f; private static float targetDensityMultiplier = 0.0f;
private static float fogDayRandom = 0.5f; // НОВЫЙ uniform private static float fogDayRandom = 0.5f;
private static float rainMultiplier = 0.0f; private static float rainMultiplier = 0.0f;
private static float heightFadeMax = 90.0f; // НОВОЕ
private static float smoothEmission = 1.0f; private static float smoothEmission = 1.0f;
private static float smoothTargetDensity = 0.0f; private static float smoothTargetDensity = 0.0f;
@@ -43,7 +44,7 @@ public final class FogEnvironmentContext {
double noiseValue = dayNoise.sample(totalDays * 0.05, 0); double noiseValue = dayNoise.sample(totalDays * 0.05, 0);
float dayOffset = (float)(noiseValue * 1000); float dayOffset = (float)(noiseValue * 1000);
float p1 = 16000 + dayOffset; float p1 = 16000 - dayOffset;
float p2 = 20000; float p2 = 20000;
float p3 = 23000; float p3 = 23000;
float p4 = 3000 + dayOffset; float p4 = 3000 + dayOffset;
@@ -65,23 +66,26 @@ public final class FogEnvironmentContext {
float t4 = 6000; // полдень float t4 = 6000; // полдень
float baseTargetDensity = trapezoid(timeOfDay, t1, t2, t3, t4); float baseTargetDensity = trapezoid(timeOfDay, t1, t2, t3, t4);
// В дождь дымка всегда
float rainFactor = rain + thunder * 0.5f; float rainFactor = rain + thunder * 0.5f;
float rawTargetDensity = Math.max(baseTargetDensity, rainFactor); float rawTargetDensity = Math.max(baseTargetDensity, rainFactor);
// === 3. Случайное значение для "туманного дня" === // === 3. Случайное значение для "туманного дня" ===
// Это ОТДЕЛЬНЫЙ uniform, НЕ умноженный на трапецию
double dayNoiseValue = dayNoise.sample(totalDays * 0.1, 100); double dayNoiseValue = dayNoise.sample(totalDays * 0.1, 100);
float rawFogDayRandom = (float)(0.5 + dayNoiseValue * 0.5); // 0..1 float rawFogDayRandom = (float)(0.5 + dayNoiseValue * 0.5);
// === 4. Сглаживание === // === 4. HeightFadeMax (90 ± 10 от дневного шума) ===
double heightNoise = dayNoise.sample(totalDays * 0.1, 200);
float rawHeightFadeMax = 90.0f + (float)(heightNoise * 10.0);
rawHeightFadeMax = Math.max(80.0f, Math.min(100.0f, rawHeightFadeMax));
// === 5. Сглаживание ===
float lerpSpeed = 0.08f; float lerpSpeed = 0.08f;
smoothEmission = lerp(smoothEmission, rawEmission, lerpSpeed); smoothEmission = lerp(smoothEmission, rawEmission, lerpSpeed);
smoothTargetDensity = lerp(smoothTargetDensity, rawTargetDensity, lerpSpeed * 2.0f); smoothTargetDensity = lerp(smoothTargetDensity, rawTargetDensity, lerpSpeed * 2.0f);
smoothRain = lerp(smoothRain, rainFactor, lerpSpeed * 2.0f); smoothRain = lerp(smoothRain, rainFactor, lerpSpeed * 2.0f);
// FogDayRandom НЕ сглаживаем — он постоянен в течение дня
fogDayRandom = rawFogDayRandom; fogDayRandom = rawFogDayRandom;
heightFadeMax = rawHeightFadeMax; // Не сглаживаем, постоянен в течение дня
emissionMultiplier = smoothEmission; emissionMultiplier = smoothEmission;
targetDensityMultiplier = smoothTargetDensity; targetDensityMultiplier = smoothTargetDensity;
@@ -113,4 +117,5 @@ public final class FogEnvironmentContext {
public static float getTargetDensityMultiplier() { return targetDensityMultiplier; } public static float getTargetDensityMultiplier() { return targetDensityMultiplier; }
public static float getFogDayRandom() { return fogDayRandom; } public static float getFogDayRandom() { return fogDayRandom; }
public static float getRainMultiplier() { return rainMultiplier; } public static float getRainMultiplier() { return rainMultiplier; }
public static float getHeightFadeMax() { return heightFadeMax; }
} }
@@ -37,6 +37,8 @@ public final class FogSimulationShader {
private static int biomeParamsSamplerLocation; private static int biomeParamsSamplerLocation;
private static int fogDayRandomLocation; private static int fogDayRandomLocation;
private static int rainMultiplierLocation; private static int rainMultiplierLocation;
private static int heightFadeMaxLocation;
private static int skyLightSamplerLocation;
private FogSimulationShader() { private FogSimulationShader() {
} }
@@ -74,6 +76,8 @@ public final class FogSimulationShader {
targetDensityMultiplierLocation = program.uniform("TargetDensityMultiplier"); targetDensityMultiplierLocation = program.uniform("TargetDensityMultiplier");
fogDayRandomLocation = program.uniform("FogDayRandom"); fogDayRandomLocation = program.uniform("FogDayRandom");
rainMultiplierLocation = program.uniform("RainMultiplier"); rainMultiplierLocation = program.uniform("RainMultiplier");
heightFadeMaxLocation = program.uniform("HeightFadeMax");
skyLightSamplerLocation = program.uniform("SkyLightSampler");
fbo = GL30.glGenFramebuffers(); fbo = GL30.glGenFramebuffers();
@@ -139,7 +143,7 @@ public final class FogSimulationShader {
// Активный текстурный юнит // Активный текстурный юнит
int previousActiveTexture = GL11.glGetInteger(GL13.GL_ACTIVE_TEXTURE); int previousActiveTexture = GL11.glGetInteger(GL13.GL_ACTIVE_TEXTURE);
// Привязки текстур для юнитов 0 и 1 (2D и 3D) // Привязки текстур для юнитов (2D и 3D)
GL13.glActiveTexture(GL13.GL_TEXTURE0); GL13.glActiveTexture(GL13.GL_TEXTURE0);
int previousTex0_2D = GL11.glGetInteger(GL_TEXTURE_BINDING_2D); int previousTex0_2D = GL11.glGetInteger(GL_TEXTURE_BINDING_2D);
int previousTex0_3D = GL11.glGetInteger(GL_TEXTURE_BINDING_3D); int previousTex0_3D = GL11.glGetInteger(GL_TEXTURE_BINDING_3D);
@@ -152,6 +156,10 @@ public final class FogSimulationShader {
int previousTex2_2D = GL11.glGetInteger(GL_TEXTURE_BINDING_2D); int previousTex2_2D = GL11.glGetInteger(GL_TEXTURE_BINDING_2D);
int previousTex2_3D = GL11.glGetInteger(GL_TEXTURE_BINDING_3D); int previousTex2_3D = GL11.glGetInteger(GL_TEXTURE_BINDING_3D);
GL13.glActiveTexture(GL13.GL_TEXTURE3);
int previousTex3_2D = GL11.glGetInteger(GL_TEXTURE_BINDING_2D);
int previousTex3_3D = GL11.glGetInteger(GL_TEXTURE_BINDING_3D);
// Blend state (на всякий случай) // Blend state (на всякий случай)
boolean previousBlend = GL11.glIsEnabled(GL11.GL_BLEND); boolean previousBlend = GL11.glIsEnabled(GL11.GL_BLEND);
boolean previousDepthTest = GL11.glIsEnabled(GL11.GL_DEPTH_TEST); boolean previousDepthTest = GL11.glIsEnabled(GL11.GL_DEPTH_TEST);
@@ -197,6 +205,10 @@ public final class FogSimulationShader {
GL11.glBindTexture(GL11.GL_TEXTURE_2D, FogBiomeTexture.getTexture()); GL11.glBindTexture(GL11.GL_TEXTURE_2D, FogBiomeTexture.getTexture());
GL20.glUniform1i(biomeParamsSamplerLocation, 2); GL20.glUniform1i(biomeParamsSamplerLocation, 2);
GL13.glActiveTexture(GL13.GL_TEXTURE3);
GL11.glBindTexture(GL12.GL_TEXTURE_3D, FogLightVolume.getSkyLightTexture());
GL20.glUniform1i(skyLightSamplerLocation, 3);
// Устанавливаем параметры // Устанавливаем параметры
GL20.glUniform1f(globalEmissionMultiplierLocation, globalEmissionMultiplier); GL20.glUniform1f(globalEmissionMultiplierLocation, globalEmissionMultiplier);
GL20.glUniform1f(globalAbsorptionMultiplierLocation, globalAbsorptionMultiplier); GL20.glUniform1f(globalAbsorptionMultiplierLocation, globalAbsorptionMultiplier);
@@ -209,6 +221,7 @@ public final class FogSimulationShader {
GL20.glUniform1f(targetDensityMultiplierLocation, FogEnvironmentContext.getTargetDensityMultiplier()); GL20.glUniform1f(targetDensityMultiplierLocation, FogEnvironmentContext.getTargetDensityMultiplier());
GL20.glUniform1f(fogDayRandomLocation, FogEnvironmentContext.getFogDayRandom()); GL20.glUniform1f(fogDayRandomLocation, FogEnvironmentContext.getFogDayRandom());
GL20.glUniform1f(rainMultiplierLocation, FogEnvironmentContext.getRainMultiplier()); GL20.glUniform1f(rainMultiplierLocation, FogEnvironmentContext.getRainMultiplier());
GL20.glUniform1f(heightFadeMaxLocation, FogEnvironmentContext.getHeightFadeMax());
GL20.glUniform3f(voxelSizeLocation, GL20.glUniform3f(voxelSizeLocation,
1.0f / FogWorldVolume.SIZE_X, 1.0f / FogWorldVolume.SIZE_X,
@@ -268,6 +281,10 @@ public final class FogSimulationShader {
GL11.glBindTexture(GL11.GL_TEXTURE_2D, previousTex2_2D); GL11.glBindTexture(GL11.GL_TEXTURE_2D, previousTex2_2D);
GL11.glBindTexture(GL12.GL_TEXTURE_3D, previousTex2_3D); GL11.glBindTexture(GL12.GL_TEXTURE_3D, previousTex2_3D);
GL13.glActiveTexture(GL13.GL_TEXTURE3);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, previousTex3_2D);
GL11.glBindTexture(GL12.GL_TEXTURE_3D, previousTex3_3D);
// Восстанавливаем активный текстурный юнит // Восстанавливаем активный текстурный юнит
GL13.glActiveTexture(previousActiveTexture); GL13.glActiveTexture(previousActiveTexture);
@@ -2,6 +2,7 @@
uniform usampler3D WorldInfoSampler; uniform usampler3D WorldInfoSampler;
uniform sampler3D FogReadSampler; uniform sampler3D FogReadSampler;
uniform sampler3D SkyLightSampler;
uniform sampler2D BiomeParamsSampler; uniform sampler2D BiomeParamsSampler;
uniform float GlobalEmissionMultiplier; uniform float GlobalEmissionMultiplier;
@@ -17,12 +18,19 @@ uniform float CurrentZ;
uniform float EmissionMultiplier; uniform float EmissionMultiplier;
uniform float TargetDensityMultiplier; uniform float TargetDensityMultiplier;
uniform float FogDayRandom; // НОВЫЙ: случайное значение [0, 1] uniform float FogDayRandom;
uniform float RainMultiplier; uniform float RainMultiplier;
uniform float HeightFadeMax;
in vec2 texCoord; in vec2 texCoord;
out vec4 FragColor; out vec4 FragColor;
const float HEIGHT_FADE_MIN = 75.0;
const float MIN_Y = -64.0;
const float SIZE_Y = 384.0;
const float UNDERGROUND_TARGET_DENSITY = 0.008; // Подземная дымка (слабее поверхностной)
float getEmission(uint magnitude, bool isAbsorber) { float getEmission(uint magnitude, bool isAbsorber) {
if (isAbsorber || magnitude == 0u) return 0.0; if (isAbsorber || magnitude == 0u) return 0.0;
return float(magnitude) / 63.0 * 0.05; return float(magnitude) / 63.0 * 0.05;
@@ -60,8 +68,17 @@ void main() {
// Для джунглей (timeSensitivity = 0.3): дымка почти всегда // Для джунглей (timeSensitivity = 0.3): дымка почти всегда
float timeFactor = mix(1.0, TargetDensityMultiplier, biomeTimeSensitivity); float timeFactor = mix(1.0, TargetDensityMultiplier, biomeTimeSensitivity);
// 3. Итоговая плотность // 3. Дымка плавно затухает к высоте 80-100
float finalTargetDensity = biomeTargetDensityBase * hasFogToday * timeFactor; float worldY = uv.y * SIZE_Y + MIN_Y;
float heightFade = 1.0 - clamp((worldY - HEIGHT_FADE_MIN) / (HeightFadeMax - HEIGHT_FADE_MIN), 0.0, 1.0);
// 4. Под землёй дымка другая
float skyLight = texture(SkyLightSampler, uv).r;
float skyLightSmooth = smoothstep(0.2, 0.8, skyLight);
// 4. Итоговая плотность
float surfaceTargetDensity = biomeTargetDensityBase * hasFogToday * timeFactor * heightFade;
float finalTargetDensity = mix(UNDERGROUND_TARGET_DENSITY, surfaceTargetDensity, skyLightSmooth);
// Читаем воксель мира // Читаем воксель мира
uint packedSelf = texture(WorldInfoSampler, uv).r; uint packedSelf = texture(WorldInfoSampler, uv).r;