161 lines
6 KiB
Java
161 lines
6 KiB
Java
package net.minecraft.client.renderer;
|
|
|
|
import com.mojang.blaze3d.pipeline.TextureTarget;
|
|
import com.mojang.blaze3d.systems.RenderSystem;
|
|
import com.mojang.blaze3d.vertex.BufferBuilder;
|
|
import com.mojang.blaze3d.vertex.BufferUploader;
|
|
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
|
import com.mojang.blaze3d.vertex.VertexFormat.Mode;
|
|
import java.util.Objects;
|
|
import net.fabricmc.api.EnvType;
|
|
import net.fabricmc.api.Environment;
|
|
import net.minecraft.client.Minecraft;
|
|
import net.minecraft.client.multiplayer.ClientLevel;
|
|
import net.minecraft.util.Mth;
|
|
import net.minecraft.util.profiling.Profiler;
|
|
import net.minecraft.util.profiling.ProfilerFiller;
|
|
import net.minecraft.world.effect.MobEffectInstance;
|
|
import net.minecraft.world.effect.MobEffects;
|
|
import net.minecraft.world.entity.LivingEntity;
|
|
import net.minecraft.world.level.dimension.DimensionType;
|
|
import org.joml.Vector3f;
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
public class LightTexture implements AutoCloseable {
|
|
public static final int FULL_BRIGHT = 15728880;
|
|
public static final int FULL_SKY = 15728640;
|
|
public static final int FULL_BLOCK = 240;
|
|
private static final int TEXTURE_SIZE = 16;
|
|
private final TextureTarget target;
|
|
private boolean updateLightTexture;
|
|
private float blockLightRedFlicker;
|
|
private final GameRenderer renderer;
|
|
private final Minecraft minecraft;
|
|
|
|
public LightTexture(GameRenderer renderer, Minecraft minecraft) {
|
|
this.renderer = renderer;
|
|
this.minecraft = minecraft;
|
|
this.target = new TextureTarget(16, 16, false);
|
|
this.target.setFilterMode(9729);
|
|
this.target.setClearColor(1.0F, 1.0F, 1.0F, 1.0F);
|
|
this.target.clear();
|
|
}
|
|
|
|
public void close() {
|
|
this.target.destroyBuffers();
|
|
}
|
|
|
|
public void tick() {
|
|
this.blockLightRedFlicker = this.blockLightRedFlicker + (float)((Math.random() - Math.random()) * Math.random() * Math.random() * 0.1);
|
|
this.blockLightRedFlicker *= 0.9F;
|
|
this.updateLightTexture = true;
|
|
}
|
|
|
|
public void turnOffLightLayer() {
|
|
RenderSystem.setShaderTexture(2, 0);
|
|
}
|
|
|
|
public void turnOnLightLayer() {
|
|
RenderSystem.setShaderTexture(2, this.target.getColorTextureId());
|
|
}
|
|
|
|
private float getDarknessGamma(float partialTick) {
|
|
MobEffectInstance mobEffectInstance = this.minecraft.player.getEffect(MobEffects.DARKNESS);
|
|
return mobEffectInstance != null ? mobEffectInstance.getBlendFactor(this.minecraft.player, partialTick) : 0.0F;
|
|
}
|
|
|
|
private float calculateDarknessScale(LivingEntity entity, float gamma, float partialTick) {
|
|
float f = 0.45F * gamma;
|
|
return Math.max(0.0F, Mth.cos((entity.tickCount - partialTick) * (float) Math.PI * 0.025F) * f);
|
|
}
|
|
|
|
public void updateLightTexture(float partialTicks) {
|
|
if (this.updateLightTexture) {
|
|
this.updateLightTexture = false;
|
|
ProfilerFiller profilerFiller = Profiler.get();
|
|
profilerFiller.push("lightTex");
|
|
ClientLevel clientLevel = this.minecraft.level;
|
|
if (clientLevel != null) {
|
|
float f = clientLevel.getSkyDarken(1.0F);
|
|
float g;
|
|
if (clientLevel.getSkyFlashTime() > 0) {
|
|
g = 1.0F;
|
|
} else {
|
|
g = f * 0.95F + 0.05F;
|
|
}
|
|
|
|
float h = this.minecraft.options.darknessEffectScale().get().floatValue();
|
|
float i = this.getDarknessGamma(partialTicks) * h;
|
|
float j = this.calculateDarknessScale(this.minecraft.player, i, partialTicks) * h;
|
|
float k = this.minecraft.player.getWaterVision();
|
|
float l;
|
|
if (this.minecraft.player.hasEffect(MobEffects.NIGHT_VISION)) {
|
|
l = GameRenderer.getNightVisionScale(this.minecraft.player, partialTicks);
|
|
} else if (k > 0.0F && this.minecraft.player.hasEffect(MobEffects.CONDUIT_POWER)) {
|
|
l = k;
|
|
} else {
|
|
l = 0.0F;
|
|
}
|
|
|
|
Vector3f vector3f = new Vector3f(f, f, 1.0F).lerp(new Vector3f(1.0F, 1.0F, 1.0F), 0.35F);
|
|
float m = this.blockLightRedFlicker + 1.5F;
|
|
float n = clientLevel.dimensionType().ambientLight();
|
|
boolean bl = clientLevel.effects().forceBrightLightmap();
|
|
float o = this.minecraft.options.gamma().get().floatValue();
|
|
CompiledShaderProgram compiledShaderProgram = (CompiledShaderProgram)Objects.requireNonNull(
|
|
RenderSystem.setShader(CoreShaders.LIGHTMAP), "Lightmap shader not loaded"
|
|
);
|
|
compiledShaderProgram.safeGetUniform("AmbientLightFactor").set(n);
|
|
compiledShaderProgram.safeGetUniform("SkyFactor").set(g);
|
|
compiledShaderProgram.safeGetUniform("BlockFactor").set(m);
|
|
compiledShaderProgram.safeGetUniform("UseBrightLightmap").set(bl ? 1 : 0);
|
|
compiledShaderProgram.safeGetUniform("SkyLightColor").set(vector3f);
|
|
compiledShaderProgram.safeGetUniform("NightVisionFactor").set(l);
|
|
compiledShaderProgram.safeGetUniform("DarknessScale").set(j);
|
|
compiledShaderProgram.safeGetUniform("DarkenWorldFactor").set(this.renderer.getDarkenWorldAmount(partialTicks));
|
|
compiledShaderProgram.safeGetUniform("BrightnessFactor").set(Math.max(0.0F, o - i));
|
|
this.target.bindWrite(true);
|
|
BufferBuilder bufferBuilder = RenderSystem.renderThreadTesselator().begin(Mode.QUADS, DefaultVertexFormat.BLIT_SCREEN);
|
|
bufferBuilder.addVertex(0.0F, 0.0F, 0.0F);
|
|
bufferBuilder.addVertex(1.0F, 0.0F, 0.0F);
|
|
bufferBuilder.addVertex(1.0F, 1.0F, 0.0F);
|
|
bufferBuilder.addVertex(0.0F, 1.0F, 0.0F);
|
|
BufferUploader.drawWithShader(bufferBuilder.buildOrThrow());
|
|
this.target.unbindWrite();
|
|
profilerFiller.pop();
|
|
}
|
|
}
|
|
}
|
|
|
|
public static float getBrightness(DimensionType dimensionType, int lightLevel) {
|
|
return getBrightness(dimensionType.ambientLight(), lightLevel);
|
|
}
|
|
|
|
public static float getBrightness(float ambientLight, int lightLevel) {
|
|
float f = lightLevel / 15.0F;
|
|
float g = f / (4.0F - 3.0F * f);
|
|
return Mth.lerp(ambientLight, g, 1.0F);
|
|
}
|
|
|
|
public static int pack(int blockLight, int skyLight) {
|
|
return blockLight << 4 | skyLight << 20;
|
|
}
|
|
|
|
public static int block(int packedLight) {
|
|
return packedLight >>> 4 & 15;
|
|
}
|
|
|
|
public static int sky(int packedLight) {
|
|
return packedLight >>> 20 & 15;
|
|
}
|
|
|
|
public static int lightCoordsWithEmission(int packedLight, int emission) {
|
|
if (emission == 0) {
|
|
return packedLight;
|
|
} else {
|
|
int i = Math.max(sky(packedLight), emission);
|
|
int j = Math.max(block(packedLight), emission);
|
|
return pack(j, i);
|
|
}
|
|
}
|
|
}
|