177 lines
7.3 KiB
Java
177 lines
7.3 KiB
Java
/*
|
|
* Decompiled with CFR 0.152.
|
|
*
|
|
* Could not load the following classes:
|
|
* com.mojang.logging.LogUtils
|
|
* it.unimi.dsi.fastutil.ints.IntArrayFIFOQueue
|
|
* org.lwjgl.system.MemoryUtil
|
|
* org.slf4j.Logger
|
|
*/
|
|
package com.mojang.blaze3d.platform;
|
|
|
|
import com.mojang.blaze3d.buffers.GpuBuffer;
|
|
import com.mojang.blaze3d.platform.NativeImage;
|
|
import com.mojang.blaze3d.systems.CommandEncoder;
|
|
import com.mojang.blaze3d.systems.RenderSystem;
|
|
import com.mojang.blaze3d.textures.GpuTexture;
|
|
import com.mojang.logging.LogUtils;
|
|
import it.unimi.dsi.fastutil.ints.IntArrayFIFOQueue;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.nio.Buffer;
|
|
import java.nio.ByteBuffer;
|
|
import java.nio.channels.Channels;
|
|
import java.nio.channels.ReadableByteChannel;
|
|
import java.nio.channels.SeekableByteChannel;
|
|
import java.nio.file.Path;
|
|
import java.util.Arrays;
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
|
import java.util.function.IntUnaryOperator;
|
|
import net.minecraft.util.ARGB;
|
|
import org.lwjgl.system.MemoryUtil;
|
|
import org.slf4j.Logger;
|
|
|
|
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);
|
|
if (channel instanceof SeekableByteChannel) {
|
|
SeekableByteChannel seekableChannel = (SeekableByteChannel)channel;
|
|
return TextureUtil.readResource(channel, (int)seekableChannel.size() + 1);
|
|
}
|
|
return TextureUtil.readResource(channel, 8192);
|
|
}
|
|
|
|
private static ByteBuffer readResource(ReadableByteChannel channel, int expectedSize) throws IOException {
|
|
ByteBuffer buffer = MemoryUtil.memAlloc((int)expectedSize);
|
|
try {
|
|
while (channel.read(buffer) != -1) {
|
|
if (buffer.hasRemaining()) continue;
|
|
buffer = MemoryUtil.memRealloc((ByteBuffer)buffer, (int)(buffer.capacity() * 2));
|
|
}
|
|
buffer.flip();
|
|
return buffer;
|
|
}
|
|
catch (IOException e) {
|
|
MemoryUtil.memFree((Buffer)buffer);
|
|
throw e;
|
|
}
|
|
}
|
|
|
|
public static void writeAsPNG(Path dir, String prefix, GpuTexture texture, int maxMipLevel, IntUnaryOperator pixelModifier) {
|
|
RenderSystem.assertOnRenderThread();
|
|
int bufferLength = 0;
|
|
for (int i = 0; i <= maxMipLevel; ++i) {
|
|
bufferLength += texture.getFormat().pixelSize() * texture.getWidth(i) * texture.getHeight(i);
|
|
}
|
|
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);){
|
|
int offset = 0;
|
|
for (int i = 0; i <= maxMipLevel; ++i) {
|
|
int mipWidth = texture.getWidth(i);
|
|
int mipHeight = texture.getHeight(i);
|
|
try (NativeImage image = new NativeImage(mipWidth, mipHeight, false);){
|
|
for (int y = 0; y < mipHeight; ++y) {
|
|
for (int x = 0; x < mipWidth; ++x) {
|
|
int argb = read.data().getInt(offset + (x + y * mipWidth) * texture.getFormat().pixelSize());
|
|
image.setPixelABGR(x, y, pixelModifier.applyAsInt(argb));
|
|
}
|
|
}
|
|
Path target = dir.resolve(prefix + "_" + i + ".png");
|
|
image.writeToFile(target);
|
|
LOGGER.debug("Exported png to: {}", (Object)target.toAbsolutePath());
|
|
}
|
|
catch (IOException e) {
|
|
LOGGER.debug("Unable to write: ", (Throwable)e);
|
|
}
|
|
offset += 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 TextureUtil.getDebugTexturePath(Path.of(".", new String[0]));
|
|
}
|
|
|
|
public static void solidify(NativeImage image) {
|
|
int color;
|
|
int y;
|
|
int x;
|
|
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 (x = 0; x < width; ++x) {
|
|
for (y = 0; y < height; ++y) {
|
|
color = image.getPixel(x, y);
|
|
if (ARGB.alpha(color) == 0) continue;
|
|
int packedCoordinates = TextureUtil.pack(x, y, width);
|
|
distances[packedCoordinates] = 0;
|
|
nearestColor[packedCoordinates] = color;
|
|
queue.enqueue(packedCoordinates);
|
|
}
|
|
}
|
|
while (!queue.isEmpty()) {
|
|
int packedCoordinates = queue.dequeueInt();
|
|
int x2 = TextureUtil.x(packedCoordinates, width);
|
|
int y2 = TextureUtil.y(packedCoordinates, width);
|
|
for (int[] direction : DIRECTIONS) {
|
|
int neighborX = x2 + direction[0];
|
|
int neighborY = y2 + direction[1];
|
|
int packedNeighborCoordinates = TextureUtil.pack(neighborX, neighborY, width);
|
|
if (neighborX < 0 || neighborY < 0 || neighborX >= width || neighborY >= height || distances[packedNeighborCoordinates] <= distances[packedCoordinates] + 1) continue;
|
|
distances[packedNeighborCoordinates] = distances[packedCoordinates] + 1;
|
|
nearestColor[packedNeighborCoordinates] = nearestColor[packedCoordinates];
|
|
queue.enqueue(packedNeighborCoordinates);
|
|
}
|
|
}
|
|
for (x = 0; x < width; ++x) {
|
|
for (y = 0; y < height; ++y) {
|
|
color = image.getPixel(x, y);
|
|
if (ARGB.alpha(color) == 0) {
|
|
image.setPixel(x, y, ARGB.color(0, nearestColor[TextureUtil.pack(x, y, width)]));
|
|
continue;
|
|
}
|
|
image.setPixel(x, y, color);
|
|
}
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
|