minecraft-src/net/minecraft/client/renderer/texture/MipmapGenerator.java
2025-07-04 02:00:41 +03:00

142 lines
3.7 KiB
Java

package net.minecraft.client.renderer.texture;
import com.mojang.blaze3d.platform.NativeImage;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.Util;
import net.minecraft.util.ARGB;
@Environment(EnvType.CLIENT)
public class MipmapGenerator {
private static final int ALPHA_CUTOUT_CUTOFF = 96;
private static final float[] POW22 = Util.make(new float[256], fs -> {
for (int i = 0; i < fs.length; i++) {
fs[i] = (float)Math.pow(i / 255.0F, 2.2);
}
});
private MipmapGenerator() {
}
public static NativeImage[] generateMipLevels(NativeImage[] images, int mipLevel) {
if (mipLevel + 1 <= images.length) {
return images;
} else {
NativeImage[] nativeImages = new NativeImage[mipLevel + 1];
nativeImages[0] = images[0];
boolean bl = hasTransparentPixel(nativeImages[0]);
for (int i = 1; i <= mipLevel; i++) {
if (i < images.length) {
nativeImages[i] = images[i];
} else {
NativeImage nativeImage = nativeImages[i - 1];
NativeImage nativeImage2 = new NativeImage(nativeImage.getWidth() >> 1, nativeImage.getHeight() >> 1, false);
int j = nativeImage2.getWidth();
int k = nativeImage2.getHeight();
for (int l = 0; l < j; l++) {
for (int m = 0; m < k; m++) {
nativeImage2.setPixel(
l,
m,
alphaBlend(
nativeImage.getPixel(l * 2 + 0, m * 2 + 0),
nativeImage.getPixel(l * 2 + 1, m * 2 + 0),
nativeImage.getPixel(l * 2 + 0, m * 2 + 1),
nativeImage.getPixel(l * 2 + 1, m * 2 + 1),
bl
)
);
}
}
nativeImages[i] = nativeImage2;
}
}
return nativeImages;
}
}
private static boolean hasTransparentPixel(NativeImage image) {
for (int i = 0; i < image.getWidth(); i++) {
for (int j = 0; j < image.getHeight(); j++) {
if (ARGB.alpha(image.getPixel(i, j)) == 0) {
return true;
}
}
}
return false;
}
private static int alphaBlend(int col0, int col1, int col2, int col3, boolean transparent) {
if (transparent) {
float f = 0.0F;
float g = 0.0F;
float h = 0.0F;
float i = 0.0F;
if (col0 >> 24 != 0) {
f += getPow22(col0 >> 24);
g += getPow22(col0 >> 16);
h += getPow22(col0 >> 8);
i += getPow22(col0 >> 0);
}
if (col1 >> 24 != 0) {
f += getPow22(col1 >> 24);
g += getPow22(col1 >> 16);
h += getPow22(col1 >> 8);
i += getPow22(col1 >> 0);
}
if (col2 >> 24 != 0) {
f += getPow22(col2 >> 24);
g += getPow22(col2 >> 16);
h += getPow22(col2 >> 8);
i += getPow22(col2 >> 0);
}
if (col3 >> 24 != 0) {
f += getPow22(col3 >> 24);
g += getPow22(col3 >> 16);
h += getPow22(col3 >> 8);
i += getPow22(col3 >> 0);
}
f /= 4.0F;
g /= 4.0F;
h /= 4.0F;
i /= 4.0F;
int j = (int)(Math.pow(f, 0.45454545454545453) * 255.0);
int k = (int)(Math.pow(g, 0.45454545454545453) * 255.0);
int l = (int)(Math.pow(h, 0.45454545454545453) * 255.0);
int m = (int)(Math.pow(i, 0.45454545454545453) * 255.0);
if (j < 96) {
j = 0;
}
return ARGB.color(j, k, l, m);
} else {
int n = gammaBlend(col0, col1, col2, col3, 24);
int o = gammaBlend(col0, col1, col2, col3, 16);
int p = gammaBlend(col0, col1, col2, col3, 8);
int q = gammaBlend(col0, col1, col2, col3, 0);
return ARGB.color(n, o, p, q);
}
}
private static int gammaBlend(int col0, int col1, int col2, int col3, int bitOffset) {
float f = getPow22(col0 >> bitOffset);
float g = getPow22(col1 >> bitOffset);
float h = getPow22(col2 >> bitOffset);
float i = getPow22(col3 >> bitOffset);
float j = (float)((float)Math.pow((f + g + h + i) * 0.25, 0.45454545454545453));
return (int)(j * 255.0);
}
private static float getPow22(int value) {
return POW22[value & 0xFF];
}
}