From c7c3f59a9b67b74aa2609842a8c004f7d8a0480c Mon Sep 17 00:00:00 2001 From: Bixilon Date: Thu, 18 Feb 2021 22:42:37 +0100 Subject: [PATCH] rendering: improve multi texture using --- .../minosoft/gui/rendering/RenderWindow.kt | 4 ++- .../minosoft/gui/rendering/Renderer.kt | 1 + .../gui/rendering/chunk/ChunkRenderer.kt | 36 +++++++++++-------- .../minosoft/gui/rendering/hud/HUDRenderer.kt | 6 ++++ .../gui/rendering/hud/elements/HUDElement.kt | 1 + .../hud/elements/text/HUDTextElement.kt | 20 +++++++---- .../minosoft/gui/rendering/shader/Shader.kt | 9 +++-- .../gui/rendering/textures/TextureArray.kt | 10 ++++-- .../protocol/protocol/OutByteBuffer.java | 13 +++++++ .../rendering/shader/chunk_fragment.glsl | 4 +-- .../rendering/shader/font_fragment.glsl | 4 +-- 11 files changed, 78 insertions(+), 30 deletions(-) diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/RenderWindow.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/RenderWindow.kt index f0aff213e..6545be5fb 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/RenderWindow.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/RenderWindow.kt @@ -217,9 +217,11 @@ class RenderWindow(private val connection: Connection, val rendering: Rendering) chunkRenderer.init() - hudRenderer.init() + chunkRenderer.postInit() + hudRenderer.postInit() + glfwSetWindowSizeCallback(windowId, object : GLFWWindowSizeCallback() { override fun invoke(window: Long, width: Int, height: Int) { diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/Renderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/Renderer.kt index d727bafd9..17f884c5a 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/Renderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/Renderer.kt @@ -15,6 +15,7 @@ package de.bixilon.minosoft.gui.rendering interface Renderer { fun init() + fun postInit() fun draw() fun screenChangeResizeCallback(width: Int, height: Int) {} } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/ChunkRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/ChunkRenderer.kt index 21df609b9..a5137bfaf 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/ChunkRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/ChunkRenderer.kt @@ -19,20 +19,23 @@ import de.bixilon.minosoft.data.world.* import de.bixilon.minosoft.gui.rendering.RenderWindow import de.bixilon.minosoft.gui.rendering.Renderer import de.bixilon.minosoft.gui.rendering.shader.Shader +import de.bixilon.minosoft.gui.rendering.shader.ShaderTextureBuffer import de.bixilon.minosoft.gui.rendering.textures.Texture import de.bixilon.minosoft.gui.rendering.textures.TextureArray import de.bixilon.minosoft.protocol.network.Connection +import de.bixilon.minosoft.protocol.protocol.OutByteBuffer import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition import glm_.vec3.Vec3 import org.lwjgl.opengl.GL11.GL_CULL_FACE import org.lwjgl.opengl.GL11.glEnable -import org.lwjgl.opengl.GL13.GL_TEXTURE0 import org.lwjgl.opengl.GL13.glDisable +import java.nio.ByteBuffer import java.util.concurrent.ConcurrentHashMap class ChunkRenderer(private val connection: Connection, private val world: World, val renderWindow: RenderWindow) : Renderer { private lateinit var minecraftTextures: TextureArray lateinit var chunkShader: Shader + lateinit var chunkShaderDataBuffer: ShaderTextureBuffer private val chunkSectionsToDraw = ConcurrentHashMap>() private var currentTick = 0 // for animation usage private var lastTickIncrementTime = 0L @@ -98,28 +101,31 @@ class ChunkRenderer(private val connection: Connection, private val world: World minecraftTextures = TextureArray.createTextureArray(connection.version.assetsManager, resolveBlockTextureIds(connection.version.mapping.blockIdMap.values)) minecraftTextures.load() + chunkShaderDataBuffer = ShaderTextureBuffer() + + for (texture in minecraftTextures.textures) { + val buffer = ByteBuffer.allocate(12) + val byteBuffer = OutByteBuffer() + byteBuffer.writeInt(texture.animationFrameTime) + byteBuffer.writeInt(texture.animations) + byteBuffer.writeFloat(texture.heightFactor) + byteBuffer.writeTo(buffer) + chunkShaderDataBuffer.data[texture.id] = buffer + } + // chunkShaderDataBuffer.load() + chunkShader = Shader("chunk_vertex.glsl", "chunk_fragment.glsl") // ToDo: chunkShader.replace("%{textureSize}", minecraftTextures.textures.size) chunkShader.load() - chunkShader.use() - chunkShader.setInt("textureCount", minecraftTextures.textures.size) - val animatedTextureFrameTimes: MutableList = mutableListOf() - val animatedTextureAnimations: MutableList = mutableListOf() - val textureSingleSizeY: MutableList = mutableListOf() - for (texture in minecraftTextures.textures) { - animatedTextureFrameTimes.add(texture.animationFrameTime) - animatedTextureAnimations.add(texture.animations) - textureSingleSizeY.add(texture.heightFactor) - } - chunkShader.setArray("animatedTextureFrameTimes", animatedTextureFrameTimes.toTypedArray()) - chunkShader.setArray("animatedTextureAnimations", animatedTextureAnimations.toTypedArray()) - chunkShader.setArray("textureSingleSizeY", textureSingleSizeY.toTypedArray()) + } + + override fun postInit() { + minecraftTextures.use(chunkShader, "blockTextureArray") } override fun draw() { glEnable(GL_CULL_FACE) - minecraftTextures.use(GL_TEXTURE0) chunkShader.use() val currentTime = System.currentTimeMillis() diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/HUDRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/HUDRenderer.kt index 8a58c21e3..0a50d8506 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/HUDRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/HUDRenderer.kt @@ -35,6 +35,12 @@ class HUDRenderer(private val connection: Connection, renderWindow: RenderWindow } } + override fun postInit() { + for (element in hudElements.values) { + element.postInit() + } + } + override fun screenChangeResizeCallback(width: Int, height: Int) { for (element in hudElements.values) { element.screenChangeResizeCallback(width, height) diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/HUDElement.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/HUDElement.kt index 3d14a48c6..664568d58 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/HUDElement.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/HUDElement.kt @@ -16,6 +16,7 @@ package de.bixilon.minosoft.gui.rendering.hud.elements interface HUDElement { fun init() + fun postInit() fun prepare() fun update() fun draw() diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/text/HUDTextElement.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/text/HUDTextElement.kt index cf17edc63..42c9e6cb6 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/text/HUDTextElement.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/text/HUDTextElement.kt @@ -28,7 +28,6 @@ import glm_.glm import glm_.mat4x4.Mat4 import glm_.vec2.Vec2 import glm_.vec4.Vec4 -import org.lwjgl.opengl.GL13.GL_TEXTURE0 class HUDTextElement(val connection: Connection, val hudRenderer: HUDRenderer, val renderWindow: RenderWindow) : HUDElement { private val fontBindingPerspectiveMatrices = mutableListOf(Mat4(), Mat4(), Mat4(), Mat4()) // according to FontBindings::ordinal @@ -125,23 +124,32 @@ class HUDTextElement(val connection: Connection, val hudRenderer: HUDRenderer, v hudMeshHUD = HUDFontMesh(meshData.toFloatArray()) } + override fun init() { font.load(connection.version.assetsManager) - fontShader = Shader("font_vertex.glsl", "font_fragment.glsl") - fontShader.load() - hudMeshHUD = HUDFontMesh(floatArrayOf()) - fontAtlasTexture = font.createAtlasTexture() fontAtlasTexture.load() + hudMeshHUD = HUDFontMesh(floatArrayOf()) + + fontShader = Shader("font_vertex.glsl", "font_fragment.glsl") + fontShader.load() + + + // fontAtlasTexture.use(fontShader, "textureArray") + + for (hudTextElement in hudTextElements.values) { hudTextElement.init() } } + override fun postInit() { + fontAtlasTexture.use(fontShader, "fontTextureArray") + } + override fun draw() { - fontAtlasTexture.use(GL_TEXTURE0) fontShader.use() for (hudTextElement in hudTextElements.values) { diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/shader/Shader.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/shader/Shader.kt index a088e219d..a63b3d505 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/shader/Shader.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/shader/Shader.kt @@ -14,6 +14,7 @@ package de.bixilon.minosoft.gui.rendering.shader import de.bixilon.minosoft.gui.rendering.exceptions.ShaderLoadingException +import de.bixilon.minosoft.gui.rendering.textures.TextureArray import de.bixilon.minosoft.gui.rendering.util.OpenGLUtil import glm_.mat4x4.Mat4 import glm_.vec2.Vec2 @@ -65,8 +66,8 @@ class Shader(private val vertexPath: String, private val fragmentPath: String) { return this } - private fun getUniformLocation(variableName: String): Int { - return glGetUniformLocation(programId, variableName) + fun getUniformLocation(uniformName: String): Int { + return glGetUniformLocation(programId, uniformName) } fun setFloat(uniformName: String, value: Float) { @@ -104,6 +105,10 @@ class Shader(private val vertexPath: String, private val fragmentPath: String) { } } + fun setTexture(uniformName: String, textureArray: TextureArray) { + glUniform1i(getUniformLocation(uniformName), textureArray.textureId) + } + companion object { private var usedShader: Shader? = null diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/textures/TextureArray.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/textures/TextureArray.kt index a14662f80..d655416cb 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/textures/TextureArray.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/textures/TextureArray.kt @@ -14,10 +14,10 @@ package de.bixilon.minosoft.gui.rendering.textures import de.bixilon.minosoft.data.assets.AssetsManager -import org.lwjgl.opengl.GL11.* +import de.bixilon.minosoft.gui.rendering.shader.Shader import org.lwjgl.opengl.GL12.glTexImage3D import org.lwjgl.opengl.GL12.glTexSubImage3D -import org.lwjgl.opengl.GL13.glActiveTexture +import org.lwjgl.opengl.GL13.* import org.lwjgl.opengl.GL30.GL_TEXTURE_2D_ARRAY import org.lwjgl.opengl.GL30.glGenerateMipmap import java.nio.ByteBuffer @@ -50,6 +50,12 @@ class TextureArray(val textures: List, val maxWidth: Int, val maxHeight glBindTexture(GL_TEXTURE_2D_ARRAY, textureId) } + fun use(shader: Shader, arrayName: String) { + glActiveTexture(GL_TEXTURE0 + textureId) + glBindTexture(GL_TEXTURE_2D_ARRAY, textureId) + shader.use().setTexture(arrayName, this) + } + companion object { val DEBUG_TEXTURE = Texture("block/debug", 0) diff --git a/src/main/java/de/bixilon/minosoft/protocol/protocol/OutByteBuffer.java b/src/main/java/de/bixilon/minosoft/protocol/protocol/OutByteBuffer.java index c4fe463dc..f80ecf572 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/protocol/OutByteBuffer.java +++ b/src/main/java/de/bixilon/minosoft/protocol/protocol/OutByteBuffer.java @@ -21,6 +21,7 @@ import de.bixilon.minosoft.protocol.network.Connection; import de.bixilon.minosoft.util.Util; import de.bixilon.minosoft.util.nbt.tag.CompoundTag; +import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.UUID; @@ -32,6 +33,12 @@ public class OutByteBuffer { private final Connection connection; private final int versionId; + public OutByteBuffer() { + this.bytes = new ArrayList<>(); + this.connection = null; + this.versionId = -1; + } + public OutByteBuffer(Connection connection) { this.bytes = new ArrayList<>(); this.connection = connection; @@ -248,4 +255,10 @@ public class OutByteBuffer { public Connection getConnection() { return this.connection; } + + public void writeTo(ByteBuffer buffer) { + for (byte b : this.bytes) { + buffer.put(b); + } + } } diff --git a/src/main/resources/assets/rendering/shader/chunk_fragment.glsl b/src/main/resources/assets/rendering/shader/chunk_fragment.glsl index 512a3cb43..1155a394f 100644 --- a/src/main/resources/assets/rendering/shader/chunk_fragment.glsl +++ b/src/main/resources/assets/rendering/shader/chunk_fragment.glsl @@ -17,10 +17,10 @@ out vec4 outColor; in vec3 passTextureCoordinates; -uniform sampler2DArray texureArray; +uniform sampler2DArray blockTextureArray; void main() { - vec4 texColor = texture(texureArray, passTextureCoordinates); + vec4 texColor = texture(blockTextureArray, passTextureCoordinates); if (texColor.a == 0) { // ToDo: This only works for alpha == 0. What about semi transparency? We would need to sort the faces, etc. See: https://learnopengl.com/Advanced-OpenGL/Blending discard; } diff --git a/src/main/resources/assets/rendering/shader/font_fragment.glsl b/src/main/resources/assets/rendering/shader/font_fragment.glsl index eda050ca6..66032840e 100644 --- a/src/main/resources/assets/rendering/shader/font_fragment.glsl +++ b/src/main/resources/assets/rendering/shader/font_fragment.glsl @@ -18,11 +18,11 @@ out vec4 outColor; in vec3 passTextureCoordinates; in vec4 passCharColor; -uniform sampler2DArray texureArray; +uniform sampler2DArray fontTextureArray; void main() { - vec4 textureColor = texture(texureArray, passTextureCoordinates); + vec4 textureColor = texture(fontTextureArray, passTextureCoordinates); if (passCharColor.a == 1.0f && textureColor.a == 0) { discard; }