2025-11-24 22:52:51 +03:00

156 lines
7.0 KiB
Java

/*
* Decompiled with CFR 0.152.
*/
package net.minecraft.client.renderer.texture;
import com.mojang.blaze3d.platform.NativeImage;
import com.mojang.blaze3d.platform.TextureUtil;
import net.minecraft.client.renderer.texture.MipmapStrategy;
import net.minecraft.resources.Identifier;
import net.minecraft.util.ARGB;
public class MipmapGenerator {
private static final String ITEM_PREFIX = "item/";
private static final float ALPHA_CUTOFF = 0.2f;
private static final float STRICT_ALPHA_CUTOFF = 0.6f;
private static final int ALPHA_CUTOUT_CUTOFF = 96;
private MipmapGenerator() {
}
public static NativeImage[] generateMipLevels(Identifier name, NativeImage[] currentMips, int newMipLevel, MipmapStrategy mipmapStrategy) {
if (newMipLevel + 1 <= currentMips.length) {
return currentMips;
}
NativeImage[] result = new NativeImage[newMipLevel + 1];
if (mipmapStrategy == MipmapStrategy.AUTO) {
if (name.getPath().startsWith(ITEM_PREFIX)) {
mipmapStrategy = MipmapStrategy.STRICT_CUTOUT;
} else {
MipmapStrategy mipmapStrategy2 = mipmapStrategy = MipmapGenerator.hasTransparentPixel(currentMips[0]) ? MipmapStrategy.CUTOUT : MipmapStrategy.MEAN;
}
}
if (currentMips.length == 1 && (mipmapStrategy == MipmapStrategy.CUTOUT || mipmapStrategy == MipmapStrategy.STRICT_CUTOUT)) {
TextureUtil.solidify(currentMips[0]);
}
result[0] = currentMips[0];
for (int level = 1; level <= newMipLevel; ++level) {
if (level < currentMips.length) {
result[level] = currentMips[level];
continue;
}
NativeImage lastData = result[level - 1];
NativeImage data = new NativeImage(lastData.getWidth() >> 1, lastData.getHeight() >> 1, false);
int width = data.getWidth();
int height = data.getHeight();
for (int x = 0; x < width; ++x) {
for (int y = 0; y < height; ++y) {
int color;
if (mipmapStrategy == MipmapStrategy.MEAN || mipmapStrategy == MipmapStrategy.DARK_CUTOUT) {
int color1 = lastData.getPixel(x * 2 + 0, y * 2 + 0);
int color2 = lastData.getPixel(x * 2 + 1, y * 2 + 0);
int color3 = lastData.getPixel(x * 2 + 0, y * 2 + 1);
int color4 = lastData.getPixel(x * 2 + 1, y * 2 + 1);
color = mipmapStrategy == MipmapStrategy.DARK_CUTOUT ? MipmapGenerator.darkenedAlphaBlend(color1, color2, color3, color4) : ARGB.meanLinear(color1, color2, color3, color4);
} else {
color = MipmapGenerator.alphaBlend(x, y, result[0], level, mipmapStrategy);
}
data.setPixel(x, y, color);
}
}
result[level] = data;
}
return result;
}
private static boolean hasTransparentPixel(NativeImage image) {
for (int x = 0; x < image.getWidth(); ++x) {
for (int y = 0; y < image.getHeight(); ++y) {
if (ARGB.alpha(image.getPixel(x, y)) != 0) continue;
return true;
}
}
return false;
}
private static int darkenedAlphaBlend(int color1, int color2, int color3, int color4) {
float aTotal = 0.0f;
float rTotal = 0.0f;
float gTotal = 0.0f;
float bTotal = 0.0f;
if (ARGB.alpha(color1) != 0) {
aTotal += ARGB.srgbToLinearChannel(ARGB.alpha(color1));
rTotal += ARGB.srgbToLinearChannel(ARGB.red(color1));
gTotal += ARGB.srgbToLinearChannel(ARGB.green(color1));
bTotal += ARGB.srgbToLinearChannel(ARGB.blue(color1));
}
if (ARGB.alpha(color2) != 0) {
aTotal += ARGB.srgbToLinearChannel(ARGB.alpha(color2));
rTotal += ARGB.srgbToLinearChannel(ARGB.red(color2));
gTotal += ARGB.srgbToLinearChannel(ARGB.green(color2));
bTotal += ARGB.srgbToLinearChannel(ARGB.blue(color2));
}
if (ARGB.alpha(color3) != 0) {
aTotal += ARGB.srgbToLinearChannel(ARGB.alpha(color3));
rTotal += ARGB.srgbToLinearChannel(ARGB.red(color3));
gTotal += ARGB.srgbToLinearChannel(ARGB.green(color3));
bTotal += ARGB.srgbToLinearChannel(ARGB.blue(color3));
}
if (ARGB.alpha(color4) != 0) {
aTotal += ARGB.srgbToLinearChannel(ARGB.alpha(color4));
rTotal += ARGB.srgbToLinearChannel(ARGB.red(color4));
gTotal += ARGB.srgbToLinearChannel(ARGB.green(color4));
bTotal += ARGB.srgbToLinearChannel(ARGB.blue(color4));
}
rTotal /= 4.0f;
gTotal /= 4.0f;
bTotal /= 4.0f;
int finalAlpha = ARGB.linearToSrgbChannel(aTotal /= 4.0f);
if (finalAlpha < 96) {
finalAlpha = 0;
}
return ARGB.color(finalAlpha, ARGB.linearToSrgbChannel(rTotal), ARGB.linearToSrgbChannel(gTotal), ARGB.linearToSrgbChannel(bTotal));
}
private static int alphaBlend(int x, int y, NativeImage originalImage, int level, MipmapStrategy mipmapStrategy) {
float resultAlpha;
float[] accumulated = new float[7];
int size = 1 << level;
for (int xOrig = x * size; xOrig < x * size + size; ++xOrig) {
for (int yOrig = y * size; yOrig < y * size + size; ++yOrig) {
MipmapGenerator.accumulate(originalImage.getPixel(xOrig, yOrig), accumulated);
}
}
float alphaTotal = accumulated[0];
float resultRed = accumulated[1] / alphaTotal;
float resultGreen = accumulated[2] / alphaTotal;
float resultBlue = accumulated[3] / alphaTotal;
alphaTotal /= (float)(size * size);
float f = mipmapStrategy == MipmapStrategy.STRICT_CUTOUT ? 0.6f : 0.2f;
if (alphaTotal < f) {
resultAlpha = 0.0f;
resultRed = accumulated[4] / (float)(size * size);
resultGreen = accumulated[5] / (float)(size * size);
resultBlue = accumulated[6] / (float)(size * size);
} else {
resultAlpha = 1.0f;
}
return ARGB.color(resultAlpha, ARGB.color(ARGB.linearToSrgbChannel(resultRed), ARGB.linearToSrgbChannel(resultGreen), ARGB.linearToSrgbChannel(resultBlue)));
}
private static void accumulate(int color, float[] accumulated) {
float alpha = ARGB.alphaFloat(color);
accumulated[0] = accumulated[0] + alpha;
float red = ARGB.srgbToLinearChannel(ARGB.red(color));
accumulated[1] = accumulated[1] + red * alpha;
accumulated[4] = accumulated[4] + red;
float green = ARGB.srgbToLinearChannel(ARGB.green(color));
accumulated[2] = accumulated[2] + green * alpha;
accumulated[5] = accumulated[5] + green;
float blue = ARGB.srgbToLinearChannel(ARGB.blue(color));
accumulated[3] = accumulated[3] + blue * alpha;
accumulated[6] = accumulated[6] + blue;
}
}