156 lines
7.0 KiB
Java
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;
|
|
}
|
|
}
|
|
|