179 lines
8.9 KiB
Java
179 lines
8.9 KiB
Java
/*
|
|
* Decompiled with CFR 0.152.
|
|
*
|
|
* Could not load the following classes:
|
|
* com.google.common.collect.Lists
|
|
* org.joml.Vector4f
|
|
* org.joml.Vector4fc
|
|
* org.lwjgl.system.MemoryStack
|
|
*/
|
|
package net.minecraft.client.renderer.fog;
|
|
|
|
import com.google.common.collect.Lists;
|
|
import com.mojang.blaze3d.buffers.GpuBuffer;
|
|
import com.mojang.blaze3d.buffers.GpuBufferSlice;
|
|
import com.mojang.blaze3d.buffers.Std140Builder;
|
|
import com.mojang.blaze3d.buffers.Std140SizeCalculator;
|
|
import com.mojang.blaze3d.systems.GpuDevice;
|
|
import com.mojang.blaze3d.systems.RenderSystem;
|
|
import java.nio.ByteBuffer;
|
|
import java.util.List;
|
|
import net.minecraft.client.Camera;
|
|
import net.minecraft.client.DeltaTracker;
|
|
import net.minecraft.client.multiplayer.ClientLevel;
|
|
import net.minecraft.client.player.LocalPlayer;
|
|
import net.minecraft.client.renderer.GameRenderer;
|
|
import net.minecraft.client.renderer.MappableRingBuffer;
|
|
import net.minecraft.client.renderer.fog.FogData;
|
|
import net.minecraft.client.renderer.fog.environment.AtmosphericFogEnvironment;
|
|
import net.minecraft.client.renderer.fog.environment.BlindnessFogEnvironment;
|
|
import net.minecraft.client.renderer.fog.environment.DarknessFogEnvironment;
|
|
import net.minecraft.client.renderer.fog.environment.FogEnvironment;
|
|
import net.minecraft.client.renderer.fog.environment.LavaFogEnvironment;
|
|
import net.minecraft.client.renderer.fog.environment.PowderedSnowFogEnvironment;
|
|
import net.minecraft.client.renderer.fog.environment.WaterFogEnvironment;
|
|
import net.minecraft.util.ARGB;
|
|
import net.minecraft.util.Mth;
|
|
import net.minecraft.world.effect.MobEffects;
|
|
import net.minecraft.world.entity.Entity;
|
|
import net.minecraft.world.entity.LivingEntity;
|
|
import net.minecraft.world.level.material.FogType;
|
|
import org.joml.Vector4f;
|
|
import org.joml.Vector4fc;
|
|
import org.lwjgl.system.MemoryStack;
|
|
|
|
public class FogRenderer
|
|
implements AutoCloseable {
|
|
public static final int FOG_UBO_SIZE = new Std140SizeCalculator().putVec4().putFloat().putFloat().putFloat().putFloat().putFloat().putFloat().get();
|
|
private static final List<FogEnvironment> FOG_ENVIRONMENTS = Lists.newArrayList((Object[])new FogEnvironment[]{new LavaFogEnvironment(), new PowderedSnowFogEnvironment(), new BlindnessFogEnvironment(), new DarknessFogEnvironment(), new WaterFogEnvironment(), new AtmosphericFogEnvironment()});
|
|
private static boolean fogEnabled = true;
|
|
private final GpuBuffer emptyBuffer;
|
|
private final MappableRingBuffer regularBuffer;
|
|
|
|
public FogRenderer() {
|
|
GpuDevice device = RenderSystem.getDevice();
|
|
this.regularBuffer = new MappableRingBuffer(() -> "Fog UBO", 130, FOG_UBO_SIZE);
|
|
try (MemoryStack stack = MemoryStack.stackPush();){
|
|
ByteBuffer buffer = stack.malloc(FOG_UBO_SIZE);
|
|
this.updateBuffer(buffer, 0, new Vector4f(0.0f), Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE);
|
|
this.emptyBuffer = device.createBuffer(() -> "Empty fog", 128, buffer.flip());
|
|
}
|
|
RenderSystem.setShaderFog(this.getBuffer(FogMode.NONE));
|
|
}
|
|
|
|
@Override
|
|
public void close() {
|
|
this.emptyBuffer.close();
|
|
this.regularBuffer.close();
|
|
}
|
|
|
|
public void endFrame() {
|
|
this.regularBuffer.rotate();
|
|
}
|
|
|
|
public GpuBufferSlice getBuffer(FogMode mode) {
|
|
if (!fogEnabled) {
|
|
return this.emptyBuffer.slice(0, FOG_UBO_SIZE);
|
|
}
|
|
return switch (mode.ordinal()) {
|
|
default -> throw new MatchException(null, null);
|
|
case 0 -> this.emptyBuffer.slice(0, FOG_UBO_SIZE);
|
|
case 1 -> this.regularBuffer.currentBuffer().slice(0, FOG_UBO_SIZE);
|
|
};
|
|
}
|
|
|
|
private Vector4f computeFogColor(Camera camera, float partialTicks, ClientLevel level, int renderDistance, float darkenWorldAmount) {
|
|
LivingEntity livingEntity;
|
|
FogType fogType = this.getFogType(camera);
|
|
Entity entity = camera.entity();
|
|
FogEnvironment colorSourceEnvironment = null;
|
|
FogEnvironment darknessModifyingEnvironment = null;
|
|
for (FogEnvironment fogEnvironment : FOG_ENVIRONMENTS) {
|
|
if (!fogEnvironment.isApplicable(fogType, entity)) continue;
|
|
if (colorSourceEnvironment == null && fogEnvironment.providesColor()) {
|
|
colorSourceEnvironment = fogEnvironment;
|
|
}
|
|
if (darknessModifyingEnvironment != null || !fogEnvironment.modifiesDarkness()) continue;
|
|
darknessModifyingEnvironment = fogEnvironment;
|
|
}
|
|
if (colorSourceEnvironment == null) {
|
|
throw new IllegalStateException("No color source environment found");
|
|
}
|
|
int color = colorSourceEnvironment.getBaseColor(level, camera, renderDistance, partialTicks);
|
|
float voidDarknessOnsetRange = level.getLevelData().voidDarknessOnsetRange();
|
|
float darkness = Mth.clamp((voidDarknessOnsetRange + (float)level.getMinY() - (float)camera.position().y) / voidDarknessOnsetRange, 0.0f, 1.0f);
|
|
if (darknessModifyingEnvironment != null) {
|
|
LivingEntity livingEntity2 = (LivingEntity)entity;
|
|
darkness = darknessModifyingEnvironment.getModifiedDarkness(livingEntity2, darkness, partialTicks);
|
|
}
|
|
float fogRed = ARGB.redFloat(color);
|
|
float fogGreen = ARGB.greenFloat(color);
|
|
float fogBlue = ARGB.blueFloat(color);
|
|
if (darkness > 0.0f && fogType != FogType.LAVA && fogType != FogType.POWDER_SNOW) {
|
|
float brightness = Mth.square(1.0f - darkness);
|
|
fogRed *= brightness;
|
|
fogGreen *= brightness;
|
|
fogBlue *= brightness;
|
|
}
|
|
if (darkenWorldAmount > 0.0f) {
|
|
fogRed = Mth.lerp(darkenWorldAmount, fogRed, fogRed * 0.7f);
|
|
fogGreen = Mth.lerp(darkenWorldAmount, fogGreen, fogGreen * 0.6f);
|
|
fogBlue = Mth.lerp(darkenWorldAmount, fogBlue, fogBlue * 0.6f);
|
|
}
|
|
float brightenFactor = fogType == FogType.WATER ? (entity instanceof LocalPlayer ? ((LocalPlayer)entity).getWaterVision() : 1.0f) : (entity instanceof LivingEntity && (livingEntity = (LivingEntity)entity).hasEffect(MobEffects.NIGHT_VISION) && !livingEntity.hasEffect(MobEffects.DARKNESS) ? GameRenderer.getNightVisionScale(livingEntity, partialTicks) : 0.0f);
|
|
if (fogRed != 0.0f && fogGreen != 0.0f && fogBlue != 0.0f) {
|
|
float targetScale = 1.0f / Math.max(fogRed, Math.max(fogGreen, fogBlue));
|
|
fogRed = Mth.lerp(brightenFactor, fogRed, fogRed * targetScale);
|
|
fogGreen = Mth.lerp(brightenFactor, fogGreen, fogGreen * targetScale);
|
|
fogBlue = Mth.lerp(brightenFactor, fogBlue, fogBlue * targetScale);
|
|
}
|
|
return new Vector4f(fogRed, fogGreen, fogBlue, 1.0f);
|
|
}
|
|
|
|
public static boolean toggleFog() {
|
|
fogEnabled = !fogEnabled;
|
|
return fogEnabled;
|
|
}
|
|
|
|
public Vector4f setupFog(Camera camera, int renderDistanceInChunks, DeltaTracker deltaTracker, float darkenWorldAmount, ClientLevel level) {
|
|
float partialTickTime = deltaTracker.getGameTimeDeltaPartialTick(false);
|
|
Vector4f fogColor = this.computeFogColor(camera, partialTickTime, level, renderDistanceInChunks, darkenWorldAmount);
|
|
float renderDistanceInBlocks = renderDistanceInChunks * 16;
|
|
FogType fogType = this.getFogType(camera);
|
|
Entity entity = camera.entity();
|
|
FogData fog = new FogData();
|
|
for (FogEnvironment fogEnvironment : FOG_ENVIRONMENTS) {
|
|
if (!fogEnvironment.isApplicable(fogType, entity)) continue;
|
|
fogEnvironment.setupFog(fog, camera, level, renderDistanceInBlocks, deltaTracker);
|
|
break;
|
|
}
|
|
float renderDistanceFogSpan = Mth.clamp(renderDistanceInBlocks / 10.0f, 4.0f, 64.0f);
|
|
fog.renderDistanceStart = renderDistanceInBlocks - renderDistanceFogSpan;
|
|
fog.renderDistanceEnd = renderDistanceInBlocks;
|
|
try (GpuBuffer.MappedView view = RenderSystem.getDevice().createCommandEncoder().mapBuffer(this.regularBuffer.currentBuffer(), false, true);){
|
|
this.updateBuffer(view.data(), 0, fogColor, fog.environmentalStart, fog.environmentalEnd, fog.renderDistanceStart, fog.renderDistanceEnd, fog.skyEnd, fog.cloudEnd);
|
|
}
|
|
return fogColor;
|
|
}
|
|
|
|
private FogType getFogType(Camera camera) {
|
|
FogType blockFogType = camera.getFluidInCamera();
|
|
if (blockFogType == FogType.NONE) {
|
|
return FogType.ATMOSPHERIC;
|
|
}
|
|
return blockFogType;
|
|
}
|
|
|
|
private void updateBuffer(ByteBuffer byteBuffer, int offset, Vector4f fogColor, float environmentalStart, float environmentalEnd, float renderDistanceStart, float renderDistanceEnd, float skyEnd, float endClouds) {
|
|
byteBuffer.position(offset);
|
|
Std140Builder.intoBuffer(byteBuffer).putVec4((Vector4fc)fogColor).putFloat(environmentalStart).putFloat(environmentalEnd).putFloat(renderDistanceStart).putFloat(renderDistanceEnd).putFloat(skyEnd).putFloat(endClouds);
|
|
}
|
|
|
|
public static enum FogMode {
|
|
NONE,
|
|
WORLD;
|
|
|
|
}
|
|
}
|
|
|