MipmapGenerator.java
net.minecraft.client.renderer.texture.MipmapGenerator
信息
- 全限定名:net.minecraft.client.renderer.texture.MipmapGenerator
- 类型:public class
- 包:net.minecraft.client.renderer.texture
- 源码路径:src/main/java/net/minecraft/client/renderer/texture/MipmapGenerator.java
- 起始行号:L12
- 职责:
TODO
字段/常量
-
ITEM_PREFIX- 类型:
String - 修饰符:
private static final - 源码定位:
L13 - 说明:
TODO
- 类型:
-
ALPHA_CUTOFF- 类型:
float - 修饰符:
private static final - 源码定位:
L14 - 说明:
TODO
- 类型:
-
STRICT_ALPHA_CUTOFF- 类型:
float - 修饰符:
private static final - 源码定位:
L15 - 说明:
TODO
- 类型:
内部类/嵌套类型
- 无
构造器
private MipmapGenerator() @ L17
- 构造器名:MipmapGenerator
- 源码定位:L17
- 修饰符:private
参数:
- 无
说明:
TODO
方法
下面的方法块按源码顺序生成。
private static float alphaTestCoverage(NativeImage image, float alphaRef, float alphaScale) @ L20
- 方法名:alphaTestCoverage
- 源码定位:L20
- 返回类型:float
- 修饰符:private static
参数:
- image: NativeImage
- alphaRef: float
- alphaScale: float
说明:
TODO
private static void scaleAlphaToCoverage(NativeImage image, float desiredCoverage, float alphaRef, float alphaCutoffBias) @ L53
- 方法名:scaleAlphaToCoverage
- 源码定位:L53
- 返回类型:void
- 修饰符:private static
参数:
- image: NativeImage
- desiredCoverage: float
- alphaRef: float
- alphaCutoffBias: float
说明:
TODO
public static NativeImage[] generateMipLevels(Identifier name, NativeImage[] currentMips, int newMipLevel, MipmapStrategy mipmapStrategy, float alphaCutoffBias, Transparency transparency) @ L94
- 方法名:generateMipLevels
- 源码定位:L94
- 返回类型:NativeImage[]
- 修饰符:public static
参数:
- name: Identifier
- currentMips: NativeImage[]
- newMipLevel: int
- mipmapStrategy: MipmapStrategy
- alphaCutoffBias: float
- transparency: Transparency
说明:
TODO
private static int darkenedAlphaBlend(int color1, int color2, int color3, int color4) @ L158
- 方法名:darkenedAlphaBlend
- 源码定位:L158
- 返回类型:int
- 修饰符:private static
参数:
- color1: int
- color2: int
- color3: int
- color4: int
说明:
TODO
代码
@OnlyIn(Dist.CLIENT)
public class MipmapGenerator {
private static final String ITEM_PREFIX = "item/";
private static final float ALPHA_CUTOFF = 0.5F;
private static final float STRICT_ALPHA_CUTOFF = 0.3F;
private MipmapGenerator() {
}
private static float alphaTestCoverage(NativeImage image, float alphaRef, float alphaScale) {
int width = image.getWidth();
int height = image.getHeight();
float coverage = 0.0F;
int subsample_count = 4;
for (int y = 0; y < height - 1; y++) {
for (int x = 0; x < width - 1; x++) {
float alpha00 = Math.clamp(ARGB.alphaFloat(image.getPixel(x, y)) * alphaScale, 0.0F, 1.0F);
float alpha10 = Math.clamp(ARGB.alphaFloat(image.getPixel(x + 1, y)) * alphaScale, 0.0F, 1.0F);
float alpha01 = Math.clamp(ARGB.alphaFloat(image.getPixel(x, y + 1)) * alphaScale, 0.0F, 1.0F);
float alpha11 = Math.clamp(ARGB.alphaFloat(image.getPixel(x + 1, y + 1)) * alphaScale, 0.0F, 1.0F);
float texelCoverage = 0.0F;
for (int subsample_y = 0; subsample_y < 4; subsample_y++) {
float fy = (subsample_y + 0.5F) / 4.0F;
for (int subsample_x = 0; subsample_x < 4; subsample_x++) {
float fx = (subsample_x + 0.5F) / 4.0F;
float alpha = alpha00 * (1.0F - fx) * (1.0F - fy) + alpha10 * fx * (1.0F - fy) + alpha01 * (1.0F - fx) * fy + alpha11 * fx * fy;
if (alpha > alphaRef) {
texelCoverage++;
}
}
}
coverage += texelCoverage / 16.0F;
}
}
return coverage / ((width - 1) * (height - 1));
}
private static void scaleAlphaToCoverage(NativeImage image, float desiredCoverage, float alphaRef, float alphaCutoffBias) {
float minAlphaScale = 0.0F;
float maxAlphaScale = 4.0F;
float alphaScale = 1.0F;
float bestAlphaScale = 1.0F;
float bestError = Float.MAX_VALUE;
int width = image.getWidth();
int height = image.getHeight();
for (int i = 0; i < 5; i++) {
float currentCoverage = alphaTestCoverage(image, alphaRef, alphaScale);
float error = Math.abs(currentCoverage - desiredCoverage);
if (error < bestError) {
bestError = error;
bestAlphaScale = alphaScale;
}
if (currentCoverage < desiredCoverage) {
minAlphaScale = alphaScale;
} else {
if (!(currentCoverage > desiredCoverage)) {
break;
}
maxAlphaScale = alphaScale;
}
alphaScale = (minAlphaScale + maxAlphaScale) * 0.5F;
}
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int pixel = image.getPixel(x, y);
float alpha = ARGB.alphaFloat(pixel);
alpha = alpha * bestAlphaScale + alphaCutoffBias + 0.025F;
alpha = Math.clamp(alpha, 0.0F, 1.0F);
image.setPixel(x, y, ARGB.color(alpha, pixel));
}
}
}
public static NativeImage[] generateMipLevels(
Identifier name, NativeImage[] currentMips, int newMipLevel, MipmapStrategy mipmapStrategy, float alphaCutoffBias, Transparency transparency
) {
if (mipmapStrategy == MipmapStrategy.AUTO) {
mipmapStrategy = transparency.hasTransparent() ? MipmapStrategy.CUTOUT : MipmapStrategy.MEAN;
}
if (currentMips.length == 1 && !name.getPath().startsWith("item/")) {
if (mipmapStrategy == MipmapStrategy.CUTOUT || mipmapStrategy == MipmapStrategy.STRICT_CUTOUT) {
TextureUtil.solidify(currentMips[0]);
} else if (mipmapStrategy == MipmapStrategy.DARK_CUTOUT) {
TextureUtil.fillEmptyAreasWithDarkColor(currentMips[0]);
}
}
if (newMipLevel + 1 <= currentMips.length) {
return currentMips;
} else {
NativeImage[] result = new NativeImage[newMipLevel + 1];
result[0] = currentMips[0];
boolean isCutoutMip = mipmapStrategy == MipmapStrategy.CUTOUT
|| mipmapStrategy == MipmapStrategy.STRICT_CUTOUT
|| mipmapStrategy == MipmapStrategy.DARK_CUTOUT;
float cutoutRef = mipmapStrategy == MipmapStrategy.STRICT_CUTOUT ? 0.3F : 0.5F;
float originalCoverage = isCutoutMip ? alphaTestCoverage(currentMips[0], cutoutRef, 1.0F) : 0.0F;
for (int level = 1; level <= newMipLevel; level++) {
if (level < currentMips.length) {
result[level] = currentMips[level];
} else {
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 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);
int color;
if (mipmapStrategy == MipmapStrategy.DARK_CUTOUT) {
color = darkenedAlphaBlend(color1, color2, color3, color4);
} else {
color = ARGB.meanLinear(color1, color2, color3, color4);
}
data.setPixel(x, y, color);
}
}
result[level] = data;
}
if (isCutoutMip) {
scaleAlphaToCoverage(result[level], originalCoverage, cutoutRef, alphaCutoffBias);
}
}
return result;
}
}
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));
}
aTotal /= 4.0F;
rTotal /= 4.0F;
gTotal /= 4.0F;
bTotal /= 4.0F;
return ARGB.color(
ARGB.linearToSrgbChannel(aTotal), ARGB.linearToSrgbChannel(rTotal), ARGB.linearToSrgbChannel(gTotal), ARGB.linearToSrgbChannel(bTotal)
);
}
}引用的其他类
-
- 引用位置:
参数/构造调用/返回值 - 关联成员:
NativeImage()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
TextureUtil.fillEmptyAreasWithDarkColor(), TextureUtil.solidify()
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
ARGB.alpha(), ARGB.alphaFloat(), ARGB.blue(), ARGB.color(), ARGB.green(), ARGB.linearToSrgbChannel(), ARGB.meanLinear(), ARGB.red(), ARGB.srgbToLinearChannel()
- 引用位置: