TextureUtil.java
com.mojang.blaze3d.platform.TextureUtil
信息
- 全限定名:com.mojang.blaze3d.platform.TextureUtil
- 类型:public class
- 包:com.mojang.blaze3d.platform
- 源码路径:src/main/java/com/mojang/blaze3d/platform/TextureUtil.java
- 起始行号:L26
- 职责:
TODO
字段/常量
-
LOGGER- 类型:
Logger - 修饰符:
private static final - 源码定位:
L27 - 说明:
TODO
- 类型:
-
MIN_MIPMAP_LEVEL- 类型:
int - 修饰符:
public static final - 源码定位:
L28 - 说明:
TODO
- 类型:
-
DEFAULT_IMAGE_BUFFER_SIZE- 类型:
int - 修饰符:
private static final - 源码定位:
L29 - 说明:
TODO
- 类型:
-
DIRECTIONS- 类型:
int[][] - 修饰符:
private static final - 源码定位:
L30 - 说明:
TODO
- 类型:
内部类/嵌套类型
- 无
构造器
- 无
方法
下面的方法块按源码顺序生成。
public static ByteBuffer readResource(InputStream inputStream) @ L32
- 方法名:readResource
- 源码定位:L32
- 返回类型:ByteBuffer
- 修饰符:public static
参数:
- inputStream: InputStream
说明:
TODO
private static ByteBuffer readResource(ReadableByteChannel channel, int expectedSize) @ L37
- 方法名:readResource
- 源码定位:L37
- 返回类型:ByteBuffer
- 修饰符:private static
参数:
- channel: ReadableByteChannel
- expectedSize: int
说明:
TODO
public static void writeAsPNG(Path dir, String prefix, GpuTexture texture, int maxMipLevel, IntUnaryOperator pixelModifier) @ L55
- 方法名:writeAsPNG
- 源码定位:L55
- 返回类型:void
- 修饰符:public static
参数:
- dir: Path
- prefix: String
- texture: GpuTexture
- maxMipLevel: int
- pixelModifier: IntUnaryOperator
说明:
TODO
public static Path getDebugTexturePath(Path root) @ L125
- 方法名:getDebugTexturePath
- 源码定位:L125
- 返回类型:Path
- 修饰符:public static
参数:
- root: Path
说明:
TODO
public static Path getDebugTexturePath() @ L129
- 方法名:getDebugTexturePath
- 源码定位:L129
- 返回类型:Path
- 修饰符:public static
参数:
- 无
说明:
TODO
public static void solidify(NativeImage image) @ L133
- 方法名:solidify
- 源码定位:L133
- 返回类型:void
- 修饰符:public static
参数:
- image: NativeImage
说明:
TODO
public static void fillEmptyAreasWithDarkColor(NativeImage image) @ L186
- 方法名:fillEmptyAreasWithDarkColor
- 源码定位:L186
- 返回类型:void
- 修饰符:public static
参数:
- image: NativeImage
说明:
TODO
private static int pack(int x, int y, int width) @ L224
- 方法名:pack
- 源码定位:L224
- 返回类型:int
- 修饰符:private static
参数:
- x: int
- y: int
- width: int
说明:
TODO
private static int x(int packed, int width) @ L228
- 方法名:x
- 源码定位:L228
- 返回类型:int
- 修饰符:private static
参数:
- packed: int
- width: int
说明:
TODO
private static int y(int packed, int width) @ L232
- 方法名:y
- 源码定位:L232
- 返回类型:int
- 修饰符:private static
参数:
- packed: int
- width: int
说明:
TODO
代码
@OnlyIn(Dist.CLIENT)
public class TextureUtil {
private static final Logger LOGGER = LogUtils.getLogger();
public static final int MIN_MIPMAP_LEVEL = 0;
private static final int DEFAULT_IMAGE_BUFFER_SIZE = 8192;
private static final int[][] DIRECTIONS = new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
public static ByteBuffer readResource(InputStream inputStream) throws IOException {
ReadableByteChannel channel = Channels.newChannel(inputStream);
return channel instanceof SeekableByteChannel seekableChannel ? readResource(channel, (int)seekableChannel.size() + 1) : readResource(channel, 8192);
}
private static ByteBuffer readResource(ReadableByteChannel channel, int expectedSize) throws IOException {
ByteBuffer buffer = MemoryUtil.memAlloc(expectedSize);
try {
while (channel.read(buffer) != -1) {
if (!buffer.hasRemaining()) {
buffer = MemoryUtil.memRealloc(buffer, buffer.capacity() * 2);
}
}
buffer.flip();
return buffer;
} catch (IOException var4) {
MemoryUtil.memFree(buffer);
throw var4;
}
}
public static void writeAsPNG(Path dir, String prefix, GpuTexture texture, int maxMipLevel, IntUnaryOperator pixelModifier) {
RenderSystem.assertOnRenderThread();
long bufferLength = 0L;
for (int i = 0; i <= maxMipLevel; i++) {
bufferLength += (long)texture.getFormat().pixelSize() * texture.getWidth(i) * texture.getHeight(i);
}
if (bufferLength > 2147483647L) {
throw new IllegalArgumentException("Exporting textures larger than 2GB is not supported");
} else {
GpuBuffer buffer = RenderSystem.getDevice().createBuffer(() -> "Texture output buffer", 9, bufferLength);
CommandEncoder commandEncoder = RenderSystem.getDevice().createCommandEncoder();
Runnable onCopyComplete = () -> {
try (GpuBuffer.MappedView read = commandEncoder.mapBuffer(buffer, true, false)) {
ByteBuffer data = read.data();
IntUnaryOperator decodeTexel = switch (texture.getFormat()) {
case RED8 -> byteOffset -> {
int luminance = Byte.toUnsignedInt(data.get(byteOffset));
return ARGB.color(luminance, luminance, luminance);
};
case RED8I -> byteOffset -> {
int luminance = data.get(byteOffset) + 128;
return ARGB.color(luminance, luminance, luminance);
};
case RGBA8 -> byteOffset -> data.getInt(byteOffset);
case DEPTH32 -> byteOffset -> ARGB.gray(data.getFloat(byteOffset));
};
int offsetx = 0;
for (int ix = 0; ix <= maxMipLevel; ix++) {
int mipWidth = texture.getWidth(ix);
int mipHeight = texture.getHeight(ix);
try (NativeImage image = new NativeImage(mipWidth, mipHeight, false)) {
for (int y = 0; y < mipHeight; y++) {
for (int x = 0; x < mipWidth; x++) {
int argb = decodeTexel.applyAsInt(offsetx + (x + y * mipWidth) * texture.getFormat().pixelSize());
image.setPixelABGR(x, y, pixelModifier.applyAsInt(argb));
}
}
Path target = dir.resolve(prefix + "_" + ix + ".png");
image.writeToFile(target);
LOGGER.debug("Exported png to: {}", target.toAbsolutePath());
} catch (IOException var21) {
LOGGER.debug("Unable to write: ", (Throwable)var21);
}
offsetx += texture.getFormat().pixelSize() * mipWidth * mipHeight;
}
}
buffer.close();
};
AtomicInteger completedCopies = new AtomicInteger();
int offset = 0;
for (int i = 0; i <= maxMipLevel; i++) {
commandEncoder.copyTextureToBuffer(texture, buffer, offset, () -> {
if (completedCopies.getAndIncrement() == maxMipLevel) {
onCopyComplete.run();
}
}, i);
offset += texture.getFormat().pixelSize() * texture.getWidth(i) * texture.getHeight(i);
}
}
}
public static Path getDebugTexturePath(Path root) {
return root.resolve("screenshots").resolve("debug");
}
public static Path getDebugTexturePath() {
return getDebugTexturePath(Path.of("."));
}
public static void solidify(NativeImage image) {
int width = image.getWidth();
int height = image.getHeight();
int[] nearestColor = new int[width * height];
int[] distances = new int[width * height];
Arrays.fill(distances, Integer.MAX_VALUE);
IntArrayFIFOQueue queue = new IntArrayFIFOQueue();
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
int color = image.getPixel(x, y);
if (ARGB.alpha(color) != 0) {
int packedCoordinates = pack(x, y, width);
distances[packedCoordinates] = 0;
nearestColor[packedCoordinates] = color;
queue.enqueue(packedCoordinates);
}
}
}
while (!queue.isEmpty()) {
int packedCoordinates = queue.dequeueInt();
int x = x(packedCoordinates, width);
int yx = y(packedCoordinates, width);
for (int[] direction : DIRECTIONS) {
int neighborX = x + direction[0];
int neighborY = yx + direction[1];
int packedNeighborCoordinates = pack(neighborX, neighborY, width);
if (neighborX >= 0
&& neighborY >= 0
&& neighborX < width
&& neighborY < height
&& distances[packedNeighborCoordinates] > distances[packedCoordinates] + 1) {
distances[packedNeighborCoordinates] = distances[packedCoordinates] + 1;
nearestColor[packedNeighborCoordinates] = nearestColor[packedCoordinates];
queue.enqueue(packedNeighborCoordinates);
}
}
}
for (int x = 0; x < width; x++) {
for (int yx = 0; yx < height; yx++) {
int color = image.getPixel(x, yx);
if (ARGB.alpha(color) == 0) {
image.setPixel(x, yx, ARGB.color(0, nearestColor[pack(x, yx, width)]));
} else {
image.setPixel(x, yx, color);
}
}
}
}
public static void fillEmptyAreasWithDarkColor(NativeImage image) {
int width = image.getWidth();
int height = image.getHeight();
int darkestColor = -1;
int minBrightness = Integer.MAX_VALUE;
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
int color = image.getPixel(x, y);
int alpha = ARGB.alpha(color);
if (alpha != 0) {
int red = ARGB.red(color);
int green = ARGB.green(color);
int blue = ARGB.blue(color);
int brightness = red + green + blue;
if (brightness < minBrightness) {
minBrightness = brightness;
darkestColor = color;
}
}
}
}
int darkRed = 3 * ARGB.red(darkestColor) / 4;
int darkGreen = 3 * ARGB.green(darkestColor) / 4;
int darkBlue = 3 * ARGB.blue(darkestColor) / 4;
int darkenedColor = ARGB.color(0, darkRed, darkGreen, darkBlue);
for (int x = 0; x < width; x++) {
for (int yx = 0; yx < height; yx++) {
int color = image.getPixel(x, yx);
if (ARGB.alpha(color) == 0) {
image.setPixel(x, yx, darkenedColor);
}
}
}
}
private static int pack(int x, int y, int width) {
return x + y * width;
}
private static int x(int packed, int width) {
return packed % width;
}
private static int y(int packed, int width) {
return packed / width;
}
}引用的其他类
-
- 引用位置:
参数/构造调用 - 关联成员:
NativeImage()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
RenderSystem.assertOnRenderThread(), RenderSystem.getDevice()
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
ARGB.alpha(), ARGB.blue(), ARGB.color(), ARGB.gray(), ARGB.green(), ARGB.red()
- 引用位置: