diff --git a/build.gradle.kts b/build.gradle.kts index c6fae1cca..9da0da51f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -229,7 +229,7 @@ testing { val options = this as TestNGOptions options.preserveOrder = true // options.excludeGroups("models", "mesher", "chunk", "input", "font", "command", "registry", "biome", "version", "fluid", "world", "raycasting", "pixlyzer", "item", "block", "physics", "light", "packet", "container", "item_stack", "signature", "private_key", "interaction", "item_digging", "chunk_renderer", "rendering", "texture", "atlas", "gui") - options.excludeGroups("models", "chunk", "input", "font", "command", "registry", "biome", "version", "fluid", "world", "raycasting", "pixlyzer", "item", "physics", "light", "packet", "container", "item_stack", "signature", "private_key", "interaction", "item_digging", "chunk_renderer", "texture", "atlas", "gui") + // options.excludeGroups("models", "chunk", "input", "font", "command", "registry", "biome", "version", "fluid", "world", "raycasting", "pixlyzer", "item", "physics", "light", "packet", "container", "item_stack", "signature", "private_key", "interaction", "item_digging", "chunk_renderer", "texture", "atlas", "gui") } } } diff --git a/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/system/dummy/texture/DummyStaticTextureArray.kt b/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/system/dummy/texture/DummyStaticTextureArray.kt index eb47fa695..549ac1a87 100644 --- a/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/system/dummy/texture/DummyStaticTextureArray.kt +++ b/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/system/dummy/texture/DummyStaticTextureArray.kt @@ -23,6 +23,7 @@ import de.bixilon.minosoft.gui.rendering.system.base.texture.array.StaticTexture import de.bixilon.minosoft.gui.rendering.system.base.texture.array.TextureArrayStates import de.bixilon.minosoft.gui.rendering.system.base.texture.sprite.SpriteAnimator import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.Texture +import java.nio.ByteBuffer class DummyStaticTextureArray(renderSystem: RenderSystem) : StaticTextureArray { private val textures: MutableMap = synchronizedMapOf() @@ -52,6 +53,6 @@ class DummyStaticTextureArray(renderSystem: RenderSystem) : StaticTextureArray { override fun activate() { } - override fun use(shader: NativeShader, name: String) { - } + override fun use(shader: NativeShader, name: String) = Unit + override fun dump(texture: Texture): ByteBuffer = throw UnsupportedOperationException() } diff --git a/src/main/java/de/bixilon/minosoft/data/entities/EntityRenderInfo.kt b/src/main/java/de/bixilon/minosoft/data/entities/EntityRenderInfo.kt index 4f2c2b734..84f021cd9 100644 --- a/src/main/java/de/bixilon/minosoft/data/entities/EntityRenderInfo.kt +++ b/src/main/java/de/bixilon/minosoft/data/entities/EntityRenderInfo.kt @@ -32,7 +32,7 @@ class EntityRenderInfo(private val entity: Entity) : Drawable, Tickable { private var eyeHeight0 = 0.0f - private var eyeHeight1 = entity.eyeHeight + private var eyeHeight1 = eyeHeight0 var position: Vec3d = position1 private set diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/array/StaticTextureArray.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/array/StaticTextureArray.kt index f1fc4e492..9b090306d 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/array/StaticTextureArray.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/array/StaticTextureArray.kt @@ -18,6 +18,7 @@ import de.bixilon.minosoft.data.registries.identified.ResourceLocation import de.bixilon.minosoft.gui.rendering.system.base.texture.sprite.SpriteAnimator import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.Texture import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.file.PNGTexture +import java.nio.ByteBuffer interface StaticTextureArray : TextureArray { val animator: SpriteAnimator @@ -30,4 +31,6 @@ interface StaticTextureArray : TextureArray { fun createTexture(resourceLocation: ResourceLocation, mipmaps: Boolean = true, properties: Boolean = true, default: (mipmaps: Boolean) -> Texture = { PNGTexture(resourceLocation, mipmaps = it) }): Texture fun load(latch: AbstractLatch) + + fun dump(texture: Texture): ByteBuffer } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/system/opengl/texture/OpenGLTextureArray.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/system/opengl/texture/OpenGLTextureArray.kt index 4fbecc152..5dce5e61a 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/system/opengl/texture/OpenGLTextureArray.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/system/opengl/texture/OpenGLTextureArray.kt @@ -41,10 +41,12 @@ import de.bixilon.minosoft.util.json.Jackson import de.bixilon.minosoft.util.logging.Log import de.bixilon.minosoft.util.logging.LogLevels import de.bixilon.minosoft.util.logging.LogMessageType +import org.lwjgl.BufferUtils import org.lwjgl.opengl.GL12.* import org.lwjgl.opengl.GL13.GL_TEXTURE0 import org.lwjgl.opengl.GL13.glActiveTexture import org.lwjgl.opengl.GL30.GL_TEXTURE_2D_ARRAY +import org.lwjgl.opengl.GL45.glGetTextureSubImage import java.nio.ByteBuffer import java.util.concurrent.atomic.AtomicInteger @@ -245,6 +247,19 @@ class OpenGLTextureArray( } } + override fun dump(texture: Texture): ByteBuffer { + val shaderId = texture.shaderId + val level = 0 + + val buffer = BufferUtils.createByteBuffer(texture.array.size * texture.array.size * 4) + + // glBindTexture(GL_TEXTURE_2D_ARRAY, shaderId shr 28) + + glGetTextureSubImage(textureIds[TEXTURE_RESOLUTION_ID_MAP.indexOf(texture.array.size)], 0, 0, 0, (shaderId shr 12) and 0xFFFFF, texture.array.size shr level, texture.array.size shr level, 1, GL_RGBA, GL_UNSIGNED_BYTE, buffer) + + return buffer + } + companion object { const val TEXTURE_MAX_RESOLUTION = 2048 diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/textures/TextureUtil.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/textures/TextureUtil.kt index ed0964c14..027bd1f30 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/textures/TextureUtil.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/textures/TextureUtil.kt @@ -14,6 +14,7 @@ package de.bixilon.minosoft.gui.rendering.textures import de.bixilon.kotlinglm.vec2.Vec2i +import de.bixilon.kutil.file.FileUtil.createParent import de.bixilon.minosoft.data.registries.identified.ResourceLocation import de.bixilon.minosoft.data.registries.identified.ResourceLocationUtil.extend import de.bixilon.minosoft.gui.rendering.chunk.mesh.ChunkMesh @@ -26,7 +27,9 @@ import org.lwjgl.system.MemoryUtil import java.awt.image.BufferedImage import java.io.ByteArrayOutputStream import java.io.DataOutputStream +import java.io.File import java.io.InputStream +import java.nio.ByteBuffer import javax.imageio.ImageIO object TextureUtil { @@ -94,4 +97,30 @@ object TextureUtil { readTexture2() } } + + fun dump(file: File, size: Vec2i, buffer: ByteBuffer, alpha: Boolean, flipY: Boolean) { + val bufferedImage = BufferedImage(size.x, size.y, if (alpha) BufferedImage.TYPE_INT_ARGB else BufferedImage.TYPE_INT_RGB) + val components = if (alpha) 4 else 3 + + for (x in 0 until size.x) { + for (y in 0 until size.y) { + val index: Int = (x + size.x * y) * components + val red: Int = buffer[index].toInt() and 0xFF + val green: Int = buffer[index + 1].toInt() and 0xFF + val blue: Int = buffer[index + 2].toInt() and 0xFF + + val targetY = if (flipY) size.y - (y + 1) else y + + bufferedImage.setRGB(x, targetY, 0xFF shl 24 or (red shl 16) or (green shl 8) or blue) + if (alpha) { + val alpha = buffer[index + 3].toInt() and 0xFF + bufferedImage.alphaRaster.setSample(x, targetY, 0, alpha) + } + } + } + + file.createParent() + + ImageIO.write(bufferedImage, "png", file) + } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/util/ScreenshotTaker.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/util/ScreenshotTaker.kt index 72a89cdbe..897f83634 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/util/ScreenshotTaker.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/util/ScreenshotTaker.kt @@ -17,7 +17,6 @@ import de.bixilon.kotlinglm.vec2.Vec2i import de.bixilon.kutil.concurrent.pool.DefaultThreadPool import de.bixilon.kutil.concurrent.pool.ThreadPool import de.bixilon.kutil.concurrent.pool.runnable.ForcePooledRunnable -import de.bixilon.kutil.file.FileUtil.createParent import de.bixilon.kutil.file.FileUtil.slashPath import de.bixilon.kutil.time.TimeUtil.millis import de.bixilon.minosoft.assets.util.AssetsOptions @@ -31,10 +30,9 @@ import de.bixilon.minosoft.gui.rendering.RenderContext import de.bixilon.minosoft.gui.rendering.gui.GUIRenderer import de.bixilon.minosoft.gui.rendering.gui.gui.screen.menu.confirmation.DeleteScreenshotDialog import de.bixilon.minosoft.gui.rendering.system.base.PixelTypes +import de.bixilon.minosoft.gui.rendering.textures.TextureUtil import de.bixilon.minosoft.terminal.RunConfiguration -import java.awt.image.BufferedImage import java.text.SimpleDateFormat -import javax.imageio.ImageIO class ScreenshotTaker( @@ -44,7 +42,7 @@ class ScreenshotTaker( try { val width = context.window.size.x val height = context.window.size.y - val buffer = context.system.readPixels(Vec2i(0, 0), Vec2i(width, height), PixelTypes.RGBA) + val buffer = context.system.readPixels(Vec2i(0, 0), Vec2i(width, height), PixelTypes.RGB) val path = RunConfiguration.HOME_DIRECTORY.resolve("screenshots").resolve(context.connection.address.hostname) @@ -60,22 +58,8 @@ class ScreenshotTaker( DefaultThreadPool += ForcePooledRunnable(priority = ThreadPool.HIGHER) { try { - val bufferedImage = BufferedImage(width, height, BufferedImage.TYPE_INT_RGB) - - for (x in 0 until width) { - for (y in 0 until height) { - val index: Int = (x + width * y) * 4 - val red: Int = buffer[index].toInt() and 0xFF - val green: Int = buffer[index + 1].toInt() and 0xFF - val blue: Int = buffer[index + 2].toInt() and 0xFF - bufferedImage.setRGB(x, height - (y + 1), 0xFF shl 24 or (red shl 16) or (green shl 8) or blue) - } - } - val file = path.resolve(filename).toFile() - file.createParent() - - ImageIO.write(bufferedImage, "png", file) + TextureUtil.dump(file, Vec2i(width, height), buffer, false, true) var deleted = false val component = BaseComponent()