minecraft-src/net/minecraft/client/renderer/LightTexture.java
2025-07-04 03:45:38 +03:00

160 lines
5.8 KiB
Java

package net.minecraft.client.renderer;
import com.mojang.blaze3d.buffers.GpuBuffer;
import com.mojang.blaze3d.systems.GpuDevice;
import com.mojang.blaze3d.systems.RenderPass;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.textures.FilterMode;
import com.mojang.blaze3d.textures.GpuTexture;
import com.mojang.blaze3d.textures.TextureFormat;
import com.mojang.blaze3d.vertex.VertexFormat;
import java.util.OptionalInt;
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.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 GpuTexture texture;
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;
GpuDevice gpuDevice = RenderSystem.getDevice();
this.texture = gpuDevice.createTexture("Light Texture", TextureFormat.RGBA8, 16, 16, 1);
this.texture.setTextureFilter(FilterMode.LINEAR, false);
gpuDevice.createCommandEncoder().clearColorTexture(this.texture, -1);
}
public GpuTexture getTarget() {
return this.texture;
}
public void close() {
this.texture.close();
}
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, null);
}
public void turnOnLightLayer() {
RenderSystem.setShaderTexture(2, this.texture);
}
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.minecraft.player.getEffectBlendFactor(MobEffects.DARKNESS, 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();
RenderSystem.AutoStorageIndexBuffer autoStorageIndexBuffer = RenderSystem.getSequentialBuffer(VertexFormat.Mode.QUADS);
GpuBuffer gpuBuffer = autoStorageIndexBuffer.getBuffer(6);
try (RenderPass renderPass = RenderSystem.getDevice().createCommandEncoder().createRenderPass(this.texture, OptionalInt.empty())) {
renderPass.setPipeline(RenderPipelines.LIGHTMAP);
renderPass.setUniform("AmbientLightFactor", n);
renderPass.setUniform("SkyFactor", g);
renderPass.setUniform("BlockFactor", m);
renderPass.setUniform("UseBrightLightmap", bl ? 1 : 0);
renderPass.setUniform("SkyLightColor", vector3f.x, vector3f.y, vector3f.z);
renderPass.setUniform("NightVisionFactor", l);
renderPass.setUniform("DarknessScale", j);
renderPass.setUniform("DarkenWorldFactor", this.renderer.getDarkenWorldAmount(partialTicks));
renderPass.setUniform("BrightnessFactor", Math.max(0.0F, o - i));
renderPass.setVertexBuffer(0, RenderSystem.getQuadVertexBuffer());
renderPass.setIndexBuffer(gpuBuffer, autoStorageIndexBuffer.type());
renderPass.drawIndexed(0, 6);
}
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 emmision) {
if (emmision == 0) {
return packedLight;
} else {
int i = Math.max(sky(packedLight), emmision);
int j = Math.max(block(packedLight), emmision);
return pack(j, i);
}
}
}