From 91c0e2b3659b79721dbf85f9332dfccd70e8c793 Mon Sep 17 00:00:00 2001 From: Moritz Zwerger Date: Fri, 10 May 2024 21:50:30 +0200 Subject: [PATCH] config: framebuffer scaling This option allows setting a different resolution for the world or gui framebuffer than the actual screen has. This can improve performance if you don't need as much quality and the whole game is fragment shader bottlenecked --- .../system/dummy/buffer/DummyFramebuffer.kt | 4 +-- .../profiles/rendering/RenderingProfile.kt | 4 ++- .../profiles/rendering/quality/QualityC.kt | 21 ++++++++++++ .../quality/resolution/ResolutionC.kt | 34 +++++++++++++++++++ .../framebuffer/FramebufferManager.kt | 6 ++-- .../framebuffer/IntegratedFramebuffer.kt | 8 ++++- .../framebuffer/gui/GUIFramebuffer.kt | 15 +++++++- .../framebuffer/world/WorldFramebuffer.kt | 11 +++++- .../gui/rendering/system/base/RenderSystem.kt | 4 +-- .../system/base/buffer/frame/Framebuffer.kt | 4 +-- .../system/opengl/OpenGLRenderSystem.kt | 7 ++-- .../opengl/buffer/frame/OpenGLFramebuffer.kt | 19 +++++++---- .../system/window/glfw/GLFWWindow.kt | 3 +- .../minosoft/protocol/PlayerPublicKey.kt | 12 +++---- 14 files changed, 122 insertions(+), 30 deletions(-) create mode 100644 src/main/java/de/bixilon/minosoft/config/profile/profiles/rendering/quality/QualityC.kt create mode 100644 src/main/java/de/bixilon/minosoft/config/profile/profiles/rendering/quality/resolution/ResolutionC.kt diff --git a/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/system/dummy/buffer/DummyFramebuffer.kt b/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/system/dummy/buffer/DummyFramebuffer.kt index 85fb7f26d..e128ab2dc 100644 --- a/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/system/dummy/buffer/DummyFramebuffer.kt +++ b/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/system/dummy/buffer/DummyFramebuffer.kt @@ -1,6 +1,6 @@ /* * Minosoft - * Copyright (C) 2020-2022 Moritz Zwerger + * Copyright (C) 2020-2024 Moritz Zwerger * * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. * @@ -37,6 +37,6 @@ class DummyFramebuffer : Framebuffer { override fun bindTexture() { } - override fun resize(size: Vec2i) { + override fun resize(size: Vec2i, scale: Float) { } } diff --git a/src/main/java/de/bixilon/minosoft/config/profile/profiles/rendering/RenderingProfile.kt b/src/main/java/de/bixilon/minosoft/config/profile/profiles/rendering/RenderingProfile.kt index 106a4e395..796d81786 100644 --- a/src/main/java/de/bixilon/minosoft/config/profile/profiles/rendering/RenderingProfile.kt +++ b/src/main/java/de/bixilon/minosoft/config/profile/profiles/rendering/RenderingProfile.kt @@ -1,6 +1,6 @@ /* * Minosoft - * Copyright (C) 2020-2023 Moritz Zwerger + * Copyright (C) 2020-2024 Moritz Zwerger * * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. * @@ -26,6 +26,7 @@ import de.bixilon.minosoft.config.profile.profiles.rendering.light.LightC import de.bixilon.minosoft.config.profile.profiles.rendering.movement.MovementC import de.bixilon.minosoft.config.profile.profiles.rendering.overlay.OverlayC import de.bixilon.minosoft.config.profile.profiles.rendering.performance.PerformanceC +import de.bixilon.minosoft.config.profile.profiles.rendering.quality.QualityC import de.bixilon.minosoft.config.profile.profiles.rendering.sky.SkyC import de.bixilon.minosoft.config.profile.profiles.rendering.textures.TexturesC import de.bixilon.minosoft.config.profile.storage.ProfileStorage @@ -53,6 +54,7 @@ class RenderingProfile( val overlay = OverlayC(this) val sky = SkyC(this) val textures = TexturesC(this) + val quality = QualityC(this) override fun toString(): String { diff --git a/src/main/java/de/bixilon/minosoft/config/profile/profiles/rendering/quality/QualityC.kt b/src/main/java/de/bixilon/minosoft/config/profile/profiles/rendering/quality/QualityC.kt new file mode 100644 index 000000000..61d280a91 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/config/profile/profiles/rendering/quality/QualityC.kt @@ -0,0 +1,21 @@ +/* + * Minosoft + * Copyright (C) 2020-2024 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.config.profile.profiles.rendering.quality + +import de.bixilon.minosoft.config.profile.profiles.rendering.RenderingProfile +import de.bixilon.minosoft.config.profile.profiles.rendering.quality.resolution.ResolutionC + +class QualityC(profile: RenderingProfile) { + val resolution = ResolutionC(profile) +} diff --git a/src/main/java/de/bixilon/minosoft/config/profile/profiles/rendering/quality/resolution/ResolutionC.kt b/src/main/java/de/bixilon/minosoft/config/profile/profiles/rendering/quality/resolution/ResolutionC.kt new file mode 100644 index 000000000..e24c90ab6 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/config/profile/profiles/rendering/quality/resolution/ResolutionC.kt @@ -0,0 +1,34 @@ +/* + * Minosoft + * Copyright (C) 2020-2024 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.config.profile.profiles.rendering.quality.resolution + +import de.bixilon.minosoft.config.profile.delegate.primitive.FloatDelegate +import de.bixilon.minosoft.config.profile.profiles.rendering.RenderingProfile + +class ResolutionC(profile: RenderingProfile) { + + /** + * Scale of the gui (and hud) framebuffer. If you change this, the font will look weird and maybe blurry. Do not change this. + */ + var guiScale by FloatDelegate(profile, 1.0f, ranges = arrayOf(0.0001f..4.0f)) + + /** + * Scale of the world (blocks, entities, particles, ...) framebuffer. + * If you lower this, the framebuffer will be smaller and thus performance should go up. + * This is only useful when your gpu is bottlenecked by the number of pixels/texels + * (e.g. if you make the window smaller, your fps go up) + * Otherwise do not change this, this will not reduce cpu load or gpu load of other stages. + */ + var worldScale by FloatDelegate(profile, 1.0f, ranges = arrayOf(0.0001f..4.0f)) +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/framebuffer/FramebufferManager.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/framebuffer/FramebufferManager.kt index 2db9953da..c14ca23d3 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/framebuffer/FramebufferManager.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/framebuffer/FramebufferManager.kt @@ -1,6 +1,6 @@ /* * Minosoft - * Copyright (C) 2020-2023 Moritz Zwerger + * Copyright (C) 2020-2024 Moritz Zwerger * * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. * @@ -33,8 +33,8 @@ class FramebufferManager( gui.init() context.connection.events.listen { - world.framebuffer.resize(it.size) - gui.framebuffer.resize(it.size) + world.resize(it.size) + gui.resize(it.size) } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/framebuffer/IntegratedFramebuffer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/framebuffer/IntegratedFramebuffer.kt index 67fde704a..3d283142f 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/framebuffer/IntegratedFramebuffer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/framebuffer/IntegratedFramebuffer.kt @@ -1,6 +1,6 @@ /* * Minosoft - * Copyright (C) 2020-2023 Moritz Zwerger + * Copyright (C) 2020-2024 Moritz Zwerger * * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. * @@ -13,6 +13,7 @@ package de.bixilon.minosoft.gui.rendering.framebuffer +import de.bixilon.kotlinglm.vec2.Vec2i import de.bixilon.minosoft.gui.rendering.RenderContext import de.bixilon.minosoft.gui.rendering.renderer.drawable.Drawable import de.bixilon.minosoft.gui.rendering.system.base.BlendingFunctions @@ -54,4 +55,9 @@ interface IntegratedFramebuffer : Drawable { shader.use() mesh.draw() } + + fun resize(size: Vec2i) = resize(size, 1.0f) + fun resize(size: Vec2i, scale: Float) { + framebuffer.resize(size, scale) + } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/framebuffer/gui/GUIFramebuffer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/framebuffer/gui/GUIFramebuffer.kt index d1f4a8c6e..e821ba60e 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/framebuffer/gui/GUIFramebuffer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/framebuffer/gui/GUIFramebuffer.kt @@ -1,6 +1,6 @@ /* * Minosoft - * Copyright (C) 2020-2023 Moritz Zwerger + * Copyright (C) 2020-2024 Moritz Zwerger * * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. * @@ -13,6 +13,8 @@ package de.bixilon.minosoft.gui.rendering.framebuffer.gui +import de.bixilon.kotlinglm.vec2.Vec2i +import de.bixilon.kutil.observer.DataObserver.Companion.observe import de.bixilon.minosoft.gui.rendering.RenderContext import de.bixilon.minosoft.gui.rendering.framebuffer.FramebufferMesh import de.bixilon.minosoft.gui.rendering.framebuffer.FramebufferShader @@ -28,4 +30,15 @@ class GUIFramebuffer( override val framebuffer: Framebuffer = context.system.createFramebuffer(color = true, depth = false) override val mesh = FramebufferMesh(context) override var polygonMode: PolygonModes = PolygonModes.DEFAULT + + private var scale = 1.0f + + override fun init() { + super.init() + context.connection.profiles.rendering.quality.resolution::guiScale.observe(this, instant = true) { this.scale = it } + } + + override fun resize(size: Vec2i) { + super.resize(size, this.scale) + } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/framebuffer/world/WorldFramebuffer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/framebuffer/world/WorldFramebuffer.kt index 9a947a973..84fe69e7f 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/framebuffer/world/WorldFramebuffer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/framebuffer/world/WorldFramebuffer.kt @@ -1,6 +1,6 @@ /* * Minosoft - * Copyright (C) 2020-2023 Moritz Zwerger + * Copyright (C) 2020-2024 Moritz Zwerger * * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. * @@ -13,6 +13,8 @@ package de.bixilon.minosoft.gui.rendering.framebuffer.world +import de.bixilon.kotlinglm.vec2.Vec2i +import de.bixilon.kutil.observer.DataObserver.Companion.observe import de.bixilon.minosoft.gui.rendering.RenderContext import de.bixilon.minosoft.gui.rendering.framebuffer.FramebufferMesh import de.bixilon.minosoft.gui.rendering.framebuffer.FramebufferShader @@ -35,6 +37,8 @@ class WorldFramebuffer( override val mesh = FramebufferMesh(context) override var polygonMode: PolygonModes = PolygonModes.DEFAULT + private var scale = 1.0f + override fun init() { framebuffer.init() defaultShader.load() @@ -43,6 +47,7 @@ class WorldFramebuffer( mesh.load() overlay.init() + context.connection.profiles.rendering.quality.resolution::worldScale.observe(this, instant = true) { this.scale = it } } override fun postInit() { @@ -56,4 +61,8 @@ class WorldFramebuffer( super.draw() overlay.draw() } + + override fun resize(size: Vec2i) { + super.resize(size, this.scale) + } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/RenderSystem.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/RenderSystem.kt index 546b01150..5b9f83ae4 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/RenderSystem.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/RenderSystem.kt @@ -1,6 +1,6 @@ /* * Minosoft - * Copyright (C) 2020-2023 Moritz Zwerger + * Copyright (C) 2020-2024 Moritz Zwerger * * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. * @@ -142,7 +142,7 @@ interface RenderSystem { fun createIntUniformBuffer(data: IntArray = IntArray(0)): IntUniformBuffer fun createFloatUniformBuffer(data: FloatBuffer): FloatUniformBuffer - fun createFramebuffer(color: Boolean, depth: Boolean): Framebuffer + fun createFramebuffer(color: Boolean, depth: Boolean, scale: Float = 1.0f): Framebuffer fun createTextureManager(): TextureManager diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/buffer/frame/Framebuffer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/buffer/frame/Framebuffer.kt index 779369d14..b32ad6bb8 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/buffer/frame/Framebuffer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/buffer/frame/Framebuffer.kt @@ -1,6 +1,6 @@ /* * Minosoft - * Copyright (C) 2020-2022 Moritz Zwerger + * Copyright (C) 2020-2024 Moritz Zwerger * * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. * @@ -28,5 +28,5 @@ interface Framebuffer { fun bindTexture() - fun resize(size: Vec2i) + fun resize(size: Vec2i, scale: Float = 1.0f) } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/system/opengl/OpenGLRenderSystem.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/system/opengl/OpenGLRenderSystem.kt index b53c91a58..74588c35d 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/system/opengl/OpenGLRenderSystem.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/system/opengl/OpenGLRenderSystem.kt @@ -98,6 +98,7 @@ class OpenGLRenderSystem( } if (value == null) { glBindFramebuffer(GL_FRAMEBUFFER, 0) + viewport = context.window.size } else { check(value is OpenGLFramebuffer) { "Can not use non OpenGL framebuffer!" } value.bind() @@ -238,7 +239,7 @@ class OpenGLRenderSystem( override fun readPixels(start: Vec2i, end: Vec2i): TextureBuffer { val size = Vec2i(end.x - start.x, end.y - start.y) val buffer = RGB8Buffer(size) - glReadPixels(start.x, start.y, end.x, end.y, GL_RGB8, GL_UNSIGNED_BYTE, buffer.data) + glReadPixels(start.x, start.y, end.x, end.y, GL_RGB8, GL_UNSIGNED_BYTE, buffer.data) // TODO: This is somehow through a GL_INVALID_ENUM error return buffer } @@ -258,8 +259,8 @@ class OpenGLRenderSystem( return IntOpenGLUniformBuffer(this, uniformBufferBindingIndex++, data) } - override fun createFramebuffer(color: Boolean, depth: Boolean): OpenGLFramebuffer { - return OpenGLFramebuffer(this, context.window.size, color, depth) + override fun createFramebuffer(color: Boolean, depth: Boolean, scale: Float): OpenGLFramebuffer { + return OpenGLFramebuffer(this, context.window.size, scale, color, depth) } override fun createTextureManager(): OpenGLTextureManager { diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/system/opengl/buffer/frame/OpenGLFramebuffer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/system/opengl/buffer/frame/OpenGLFramebuffer.kt index fb0de7160..5f707d21b 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/system/opengl/buffer/frame/OpenGLFramebuffer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/system/opengl/buffer/frame/OpenGLFramebuffer.kt @@ -1,6 +1,6 @@ /* * Minosoft - * Copyright (C) 2020-2023 Moritz Zwerger + * Copyright (C) 2020-2024 Moritz Zwerger * * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. * @@ -29,9 +29,11 @@ import org.lwjgl.opengl.GL30.* class OpenGLFramebuffer( val system: OpenGLRenderSystem, var size: Vec2i, + var scale: Float, val color: Boolean, val depth: Boolean, ) : Framebuffer { + private var scaled = size override var state: FramebufferState = FramebufferState.PREPARING private set @@ -43,21 +45,23 @@ class OpenGLFramebuffer( override fun init() { check(state != FramebufferState.COMPLETE) { "Framebuffer is complete!" } + if (scale <= 0.0f) throw IllegalArgumentException("Invalid scale: $scale") + if (size.x <= 0 || size.y <= 0) throw IllegalArgumentException("Invalid framebuffer size: $size") system.log { "Generated framebuffer buffer $this" } id = glGenFramebuffers() unsafeBind() - glViewport(0, 0, size.x, size.y) + this.scaled = if (scale == 1.0f) size else Vec2i(size.x * scale, size.y * scale) if (color) { - val colorTexture = OpenGLFramebufferColorTexture(size) + val colorTexture = OpenGLFramebufferColorTexture(scaled) this.colorTexture = colorTexture colorTexture.init() attach(colorTexture) } if (depth) { - val depth = OpenGLRenderbuffer(system, RenderbufferModes.DEPTH_COMPONENT24, size) + val depth = OpenGLRenderbuffer(system, RenderbufferModes.DEPTH_COMPONENT24, scaled) this.depthBuffer = depth depth.init() attach(depth) @@ -75,6 +79,7 @@ class OpenGLFramebuffer( fun bind() { check(state == FramebufferState.COMPLETE) { "Framebuffer is incomplete: $state" } unsafeBind() + system.viewport = scaled } private fun unsafeBind() { @@ -108,12 +113,14 @@ class OpenGLFramebuffer( depthTexture?.bind(1) } - override fun resize(size: Vec2i) { - if (size == this.size) { + override fun resize(size: Vec2i, scale: Float) { + if (size.x <= 0 || size.y <= 0) throw IllegalArgumentException("Invalid framebuffer size: $size") + if (size == this.size && this.scale == scale) { return } colorTexture?.unload() depthBuffer?.unload() + this.scale = scale this.size = size delete() init() diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/system/window/glfw/GLFWWindow.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/system/window/glfw/GLFWWindow.kt index 9c63fad3f..bdc2d0c49 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/system/window/glfw/GLFWWindow.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/system/window/glfw/GLFWWindow.kt @@ -1,6 +1,6 @@ /* * Minosoft - * Copyright (C) 2020-2023 Moritz Zwerger + * Copyright (C) 2020-2024 Moritz Zwerger * * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. * @@ -190,6 +190,7 @@ class GLFWWindow( setOpenGLVersion(3, 3, true) } glfwWindowHint(GLFW_VISIBLE, false.glfw) + glfwWindowHint(GLFW_ALPHA_BITS, 0) glfwWindowHint(GLFW_DEPTH_BITS, 0) glfwWindowHint(GLFW_STENCIL_BITS, 0) diff --git a/src/main/java/de/bixilon/minosoft/protocol/PlayerPublicKey.kt b/src/main/java/de/bixilon/minosoft/protocol/PlayerPublicKey.kt index cdb85b87f..4dbd8f7c2 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/PlayerPublicKey.kt +++ b/src/main/java/de/bixilon/minosoft/protocol/PlayerPublicKey.kt @@ -36,13 +36,11 @@ class PlayerPublicKey( constructor(nbt: JsonObject) : this(Instant.ofEpochMilli(nbt["expires_at"].toLong()), CryptManager.getPlayerPublicKey(nbt["key"].toString()), nbt["signature"].toString().fromBase64()) - fun toNbt(): JsonObject { - return mapOf( - "expires_at" to expiresAt.epochSecond, - "key" to publicKey.encoded.toBase64(), - "signature" to signature.toBase64(), - ) - } + fun toNbt() = mapOf( + "expires_at" to expiresAt.epochSecond, + "key" to publicKey.encoded.toBase64(), + "signature" to signature.toBase64(), + ) fun isExpired(): Boolean { return expiresAt.isAfter(Instant.now())