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
This commit is contained in:
Moritz Zwerger 2024-05-10 21:50:30 +02:00
parent ae7a2890ab
commit 91c0e2b365
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
14 changed files with 122 additions and 30 deletions

View File

@ -1,6 +1,6 @@
/* /*
* Minosoft * 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. * 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 bindTexture() {
} }
override fun resize(size: Vec2i) { override fun resize(size: Vec2i, scale: Float) {
} }
} }

View File

@ -1,6 +1,6 @@
/* /*
* Minosoft * 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. * 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.movement.MovementC
import de.bixilon.minosoft.config.profile.profiles.rendering.overlay.OverlayC 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.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.sky.SkyC
import de.bixilon.minosoft.config.profile.profiles.rendering.textures.TexturesC import de.bixilon.minosoft.config.profile.profiles.rendering.textures.TexturesC
import de.bixilon.minosoft.config.profile.storage.ProfileStorage import de.bixilon.minosoft.config.profile.storage.ProfileStorage
@ -53,6 +54,7 @@ class RenderingProfile(
val overlay = OverlayC(this) val overlay = OverlayC(this)
val sky = SkyC(this) val sky = SkyC(this)
val textures = TexturesC(this) val textures = TexturesC(this)
val quality = QualityC(this)
override fun toString(): String { override fun toString(): String {

View File

@ -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 <https://www.gnu.org/licenses/>.
*
* 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)
}

View File

@ -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 <https://www.gnu.org/licenses/>.
*
* 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))
}

View File

@ -1,6 +1,6 @@
/* /*
* Minosoft * 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. * 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() gui.init()
context.connection.events.listen<ResizeWindowEvent> { context.connection.events.listen<ResizeWindowEvent> {
world.framebuffer.resize(it.size) world.resize(it.size)
gui.framebuffer.resize(it.size) gui.resize(it.size)
} }
} }

View File

@ -1,6 +1,6 @@
/* /*
* Minosoft * 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. * 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 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.RenderContext
import de.bixilon.minosoft.gui.rendering.renderer.drawable.Drawable import de.bixilon.minosoft.gui.rendering.renderer.drawable.Drawable
import de.bixilon.minosoft.gui.rendering.system.base.BlendingFunctions import de.bixilon.minosoft.gui.rendering.system.base.BlendingFunctions
@ -54,4 +55,9 @@ interface IntegratedFramebuffer : Drawable {
shader.use() shader.use()
mesh.draw() mesh.draw()
} }
fun resize(size: Vec2i) = resize(size, 1.0f)
fun resize(size: Vec2i, scale: Float) {
framebuffer.resize(size, scale)
}
} }

View File

@ -1,6 +1,6 @@
/* /*
* Minosoft * 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. * 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 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.RenderContext
import de.bixilon.minosoft.gui.rendering.framebuffer.FramebufferMesh import de.bixilon.minosoft.gui.rendering.framebuffer.FramebufferMesh
import de.bixilon.minosoft.gui.rendering.framebuffer.FramebufferShader 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 framebuffer: Framebuffer = context.system.createFramebuffer(color = true, depth = false)
override val mesh = FramebufferMesh(context) override val mesh = FramebufferMesh(context)
override var polygonMode: PolygonModes = PolygonModes.DEFAULT 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)
}
} }

View File

@ -1,6 +1,6 @@
/* /*
* Minosoft * 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. * 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 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.RenderContext
import de.bixilon.minosoft.gui.rendering.framebuffer.FramebufferMesh import de.bixilon.minosoft.gui.rendering.framebuffer.FramebufferMesh
import de.bixilon.minosoft.gui.rendering.framebuffer.FramebufferShader import de.bixilon.minosoft.gui.rendering.framebuffer.FramebufferShader
@ -35,6 +37,8 @@ class WorldFramebuffer(
override val mesh = FramebufferMesh(context) override val mesh = FramebufferMesh(context)
override var polygonMode: PolygonModes = PolygonModes.DEFAULT override var polygonMode: PolygonModes = PolygonModes.DEFAULT
private var scale = 1.0f
override fun init() { override fun init() {
framebuffer.init() framebuffer.init()
defaultShader.load() defaultShader.load()
@ -43,6 +47,7 @@ class WorldFramebuffer(
mesh.load() mesh.load()
overlay.init() overlay.init()
context.connection.profiles.rendering.quality.resolution::worldScale.observe(this, instant = true) { this.scale = it }
} }
override fun postInit() { override fun postInit() {
@ -56,4 +61,8 @@ class WorldFramebuffer(
super.draw() super.draw()
overlay.draw() overlay.draw()
} }
override fun resize(size: Vec2i) {
super.resize(size, this.scale)
}
} }

View File

@ -1,6 +1,6 @@
/* /*
* Minosoft * 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. * 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 createIntUniformBuffer(data: IntArray = IntArray(0)): IntUniformBuffer
fun createFloatUniformBuffer(data: FloatBuffer): FloatUniformBuffer 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 fun createTextureManager(): TextureManager

View File

@ -1,6 +1,6 @@
/* /*
* Minosoft * 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. * 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 bindTexture()
fun resize(size: Vec2i) fun resize(size: Vec2i, scale: Float = 1.0f)
} }

View File

@ -98,6 +98,7 @@ class OpenGLRenderSystem(
} }
if (value == null) { if (value == null) {
glBindFramebuffer(GL_FRAMEBUFFER, 0) glBindFramebuffer(GL_FRAMEBUFFER, 0)
viewport = context.window.size
} else { } else {
check(value is OpenGLFramebuffer) { "Can not use non OpenGL framebuffer!" } check(value is OpenGLFramebuffer) { "Can not use non OpenGL framebuffer!" }
value.bind() value.bind()
@ -238,7 +239,7 @@ class OpenGLRenderSystem(
override fun readPixels(start: Vec2i, end: Vec2i): TextureBuffer { override fun readPixels(start: Vec2i, end: Vec2i): TextureBuffer {
val size = Vec2i(end.x - start.x, end.y - start.y) val size = Vec2i(end.x - start.x, end.y - start.y)
val buffer = RGB8Buffer(size) 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 return buffer
} }
@ -258,8 +259,8 @@ class OpenGLRenderSystem(
return IntOpenGLUniformBuffer(this, uniformBufferBindingIndex++, data) return IntOpenGLUniformBuffer(this, uniformBufferBindingIndex++, data)
} }
override fun createFramebuffer(color: Boolean, depth: Boolean): OpenGLFramebuffer { override fun createFramebuffer(color: Boolean, depth: Boolean, scale: Float): OpenGLFramebuffer {
return OpenGLFramebuffer(this, context.window.size, color, depth) return OpenGLFramebuffer(this, context.window.size, scale, color, depth)
} }
override fun createTextureManager(): OpenGLTextureManager { override fun createTextureManager(): OpenGLTextureManager {

View File

@ -1,6 +1,6 @@
/* /*
* Minosoft * 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. * 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( class OpenGLFramebuffer(
val system: OpenGLRenderSystem, val system: OpenGLRenderSystem,
var size: Vec2i, var size: Vec2i,
var scale: Float,
val color: Boolean, val color: Boolean,
val depth: Boolean, val depth: Boolean,
) : Framebuffer { ) : Framebuffer {
private var scaled = size
override var state: FramebufferState = FramebufferState.PREPARING override var state: FramebufferState = FramebufferState.PREPARING
private set private set
@ -43,21 +45,23 @@ class OpenGLFramebuffer(
override fun init() { override fun init() {
check(state != FramebufferState.COMPLETE) { "Framebuffer is complete!" } 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" } system.log { "Generated framebuffer buffer $this" }
id = glGenFramebuffers() id = glGenFramebuffers()
unsafeBind() 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) { if (color) {
val colorTexture = OpenGLFramebufferColorTexture(size) val colorTexture = OpenGLFramebufferColorTexture(scaled)
this.colorTexture = colorTexture this.colorTexture = colorTexture
colorTexture.init() colorTexture.init()
attach(colorTexture) attach(colorTexture)
} }
if (depth) { if (depth) {
val depth = OpenGLRenderbuffer(system, RenderbufferModes.DEPTH_COMPONENT24, size) val depth = OpenGLRenderbuffer(system, RenderbufferModes.DEPTH_COMPONENT24, scaled)
this.depthBuffer = depth this.depthBuffer = depth
depth.init() depth.init()
attach(depth) attach(depth)
@ -75,6 +79,7 @@ class OpenGLFramebuffer(
fun bind() { fun bind() {
check(state == FramebufferState.COMPLETE) { "Framebuffer is incomplete: $state" } check(state == FramebufferState.COMPLETE) { "Framebuffer is incomplete: $state" }
unsafeBind() unsafeBind()
system.viewport = scaled
} }
private fun unsafeBind() { private fun unsafeBind() {
@ -108,12 +113,14 @@ class OpenGLFramebuffer(
depthTexture?.bind(1) depthTexture?.bind(1)
} }
override fun resize(size: Vec2i) { override fun resize(size: Vec2i, scale: Float) {
if (size == this.size) { if (size.x <= 0 || size.y <= 0) throw IllegalArgumentException("Invalid framebuffer size: $size")
if (size == this.size && this.scale == scale) {
return return
} }
colorTexture?.unload() colorTexture?.unload()
depthBuffer?.unload() depthBuffer?.unload()
this.scale = scale
this.size = size this.size = size
delete() delete()
init() init()

View File

@ -1,6 +1,6 @@
/* /*
* Minosoft * 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. * 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) setOpenGLVersion(3, 3, true)
} }
glfwWindowHint(GLFW_VISIBLE, false.glfw) glfwWindowHint(GLFW_VISIBLE, false.glfw)
glfwWindowHint(GLFW_ALPHA_BITS, 0)
glfwWindowHint(GLFW_DEPTH_BITS, 0) glfwWindowHint(GLFW_DEPTH_BITS, 0)
glfwWindowHint(GLFW_STENCIL_BITS, 0) glfwWindowHint(GLFW_STENCIL_BITS, 0)

View File

@ -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()) constructor(nbt: JsonObject) : this(Instant.ofEpochMilli(nbt["expires_at"].toLong()), CryptManager.getPlayerPublicKey(nbt["key"].toString()), nbt["signature"].toString().fromBase64())
fun toNbt(): JsonObject { fun toNbt() = mapOf(
return mapOf( "expires_at" to expiresAt.epochSecond,
"expires_at" to expiresAt.epochSecond, "key" to publicKey.encoded.toBase64(),
"key" to publicKey.encoded.toBase64(), "signature" to signature.toBase64(),
"signature" to signature.toBase64(), )
)
}
fun isExpired(): Boolean { fun isExpired(): Boolean {
return expiresAt.isAfter(Instant.now()) return expiresAt.isAfter(Instant.now())