minecraft-src/net/minecraft/client/renderer/LightTexture.java
2025-07-04 01:41:11 +03:00

194 lines
6.6 KiB
Java

package net.minecraft.client.renderer;
import com.mojang.blaze3d.platform.NativeImage;
import com.mojang.blaze3d.systems.RenderSystem;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.renderer.texture.DynamicTexture;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.Mth;
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 final DynamicTexture lightTexture;
private final NativeImage lightPixels;
private final ResourceLocation lightTextureLocation;
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.lightTexture = new DynamicTexture(16, 16, false);
this.lightTextureLocation = this.minecraft.getTextureManager().register("light_map", this.lightTexture);
this.lightPixels = this.lightTexture.getPixels();
for (int i = 0; i < 16; i++) {
for (int j = 0; j < 16; j++) {
this.lightPixels.setPixelRGBA(j, i, -1);
}
}
this.lightTexture.upload();
}
public void close() {
this.lightTexture.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, 0);
}
public void turnOnLightLayer() {
RenderSystem.setShaderTexture(2, this.lightTextureLocation);
this.minecraft.getTextureManager().bindForSetup(this.lightTextureLocation);
RenderSystem.texParameter(3553, 10241, 9729);
RenderSystem.texParameter(3553, 10240, 9729);
}
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;
this.minecraft.getProfiler().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;
Vector3f vector3f2 = new Vector3f();
for (int n = 0; n < 16; n++) {
for (int o = 0; o < 16; o++) {
float p = getBrightness(clientLevel.dimensionType(), n) * g;
float q = getBrightness(clientLevel.dimensionType(), o) * m;
float s = q * ((q * 0.6F + 0.4F) * 0.6F + 0.4F);
float t = q * (q * q * 0.6F + 0.4F);
vector3f2.set(q, s, t);
boolean bl = clientLevel.effects().forceBrightLightmap();
if (bl) {
vector3f2.lerp(new Vector3f(0.99F, 1.12F, 1.0F), 0.25F);
clampColor(vector3f2);
} else {
Vector3f vector3f3 = new Vector3f(vector3f).mul(p);
vector3f2.add(vector3f3);
vector3f2.lerp(new Vector3f(0.75F, 0.75F, 0.75F), 0.04F);
if (this.renderer.getDarkenWorldAmount(partialTicks) > 0.0F) {
float u = this.renderer.getDarkenWorldAmount(partialTicks);
Vector3f vector3f4 = new Vector3f(vector3f2).mul(0.7F, 0.6F, 0.6F);
vector3f2.lerp(vector3f4, u);
}
}
if (l > 0.0F) {
float v = Math.max(vector3f2.x(), Math.max(vector3f2.y(), vector3f2.z()));
if (v < 1.0F) {
float u = 1.0F / v;
Vector3f vector3f4 = new Vector3f(vector3f2).mul(u);
vector3f2.lerp(vector3f4, l);
}
}
if (!bl) {
if (j > 0.0F) {
vector3f2.add(-j, -j, -j);
}
clampColor(vector3f2);
}
float v = this.minecraft.options.gamma().get().floatValue();
Vector3f vector3f5 = new Vector3f(this.notGamma(vector3f2.x), this.notGamma(vector3f2.y), this.notGamma(vector3f2.z));
vector3f2.lerp(vector3f5, Math.max(0.0F, v - i));
vector3f2.lerp(new Vector3f(0.75F, 0.75F, 0.75F), 0.04F);
clampColor(vector3f2);
vector3f2.mul(255.0F);
int w = 255;
int x = (int)vector3f2.x();
int y = (int)vector3f2.y();
int z = (int)vector3f2.z();
this.lightPixels.setPixelRGBA(o, n, 0xFF000000 | z << 16 | y << 8 | x);
}
}
this.lightTexture.upload();
this.minecraft.getProfiler().pop();
}
}
}
private static void clampColor(Vector3f color) {
color.set(Mth.clamp(color.x, 0.0F, 1.0F), Mth.clamp(color.y, 0.0F, 1.0F), Mth.clamp(color.z, 0.0F, 1.0F));
}
private float notGamma(float value) {
float f = 1.0F - value;
return 1.0F - f * f * f * f;
}
public static float getBrightness(DimensionType dimensionType, int lightLevel) {
float f = lightLevel / 15.0F;
float g = f / (4.0F - 3.0F * f);
return Mth.lerp(dimensionType.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 & 65535;
}
public static int sky(int packedLight) {
return packedLight >> 20 & 65535;
}
}