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); } } }