142 lines
3.7 KiB
Java
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];
|
|
}
|
|
}
|