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
* 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) {
}
}

View File

@ -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 {

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
* 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<ResizeWindowEvent> {
world.framebuffer.resize(it.size)
gui.framebuffer.resize(it.size)
world.resize(it.size)
gui.resize(it.size)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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)
}
}

View File

@ -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

View File

@ -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)
}

View File

@ -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 {

View File

@ -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()

View File

@ -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)

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())
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())