wip improve shaders, replace all rendering callbacks with events

This commit is contained in:
Bixilon 2021-05-11 18:07:27 +02:00
parent 250778e608
commit 2fdad3dbce
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
24 changed files with 159 additions and 158 deletions

View File

@ -20,13 +20,14 @@ import de.bixilon.minosoft.data.entities.entities.player.PlayerEntity
import de.bixilon.minosoft.data.mappings.biomes.Biome import de.bixilon.minosoft.data.mappings.biomes.Biome
import de.bixilon.minosoft.gui.rendering.RenderConstants import de.bixilon.minosoft.gui.rendering.RenderConstants
import de.bixilon.minosoft.gui.rendering.RenderWindow import de.bixilon.minosoft.gui.rendering.RenderWindow
import de.bixilon.minosoft.gui.rendering.shader.Shader import de.bixilon.minosoft.gui.rendering.modding.events.FrustumChangeEvent
import de.bixilon.minosoft.gui.rendering.modding.events.ScreenResizeEvent
import de.bixilon.minosoft.gui.rendering.util.VecUtil import de.bixilon.minosoft.gui.rendering.util.VecUtil
import de.bixilon.minosoft.gui.rendering.util.VecUtil.blockPosition import de.bixilon.minosoft.gui.rendering.util.VecUtil.blockPosition
import de.bixilon.minosoft.gui.rendering.util.VecUtil.chunkPosition import de.bixilon.minosoft.gui.rendering.util.VecUtil.chunkPosition
import de.bixilon.minosoft.gui.rendering.util.VecUtil.inChunkSectionPosition import de.bixilon.minosoft.gui.rendering.util.VecUtil.inChunkSectionPosition
import de.bixilon.minosoft.gui.rendering.util.VecUtil.sectionHeight import de.bixilon.minosoft.gui.rendering.util.VecUtil.sectionHeight
import de.bixilon.minosoft.gui.rendering.util.abstractions.ScreenResizeCallback import de.bixilon.minosoft.modding.event.CallbackEventInvoker
import de.bixilon.minosoft.protocol.network.connection.PlayConnection import de.bixilon.minosoft.protocol.network.connection.PlayConnection
import de.bixilon.minosoft.protocol.packets.c2s.play.PositionAndRotationC2SP import de.bixilon.minosoft.protocol.packets.c2s.play.PositionAndRotationC2SP
import de.bixilon.minosoft.protocol.packets.c2s.play.PositionC2SP import de.bixilon.minosoft.protocol.packets.c2s.play.PositionC2SP
@ -46,7 +47,7 @@ class Camera(
val connection: PlayConnection, val connection: PlayConnection,
var fov: Float, var fov: Float,
val renderWindow: RenderWindow, val renderWindow: RenderWindow,
) : ScreenResizeCallback { ) {
private var mouseSensitivity = Minosoft.getConfig().config.game.camera.moseSensitivity private var mouseSensitivity = Minosoft.getConfig().config.game.camera.moseSensitivity
private val walkingSpeed get() = connection.player.baseAbilities.walkingSpeed * ProtocolDefinition.TICKS_PER_SECOND * 2 private val walkingSpeed get() = connection.player.baseAbilities.walkingSpeed * ProtocolDefinition.TICKS_PER_SECOND * 2
private val flyingSpeed get() = connection.player.baseAbilities.flyingSpeed * ProtocolDefinition.TICKS_PER_SECOND * 2 private val flyingSpeed get() = connection.player.baseAbilities.flyingSpeed * ProtocolDefinition.TICKS_PER_SECOND * 2
@ -80,9 +81,6 @@ class Camera(
val frustum: Frustum = Frustum(this) val frustum: Frustum = Frustum(this)
private val shaders: MutableSet<Shader> = mutableSetOf()
private val frustumChangeCallbacks: MutableSet<FrustumChangeCallback> = mutableSetOf()
var viewMatrix = calculateViewMatrix() var viewMatrix = calculateViewMatrix()
private set private set
@ -135,10 +133,9 @@ class Camera(
KeyBindingsNames.MOVE_JUMP, KeyBindingsNames.MOVE_JUMP,
) )
connection.registerEvent(CallbackEventInvoker.of<ScreenResizeEvent> { recalculateViewProjectionMatrix() })
frustum.recalculate() frustum.recalculate()
for (frustumChangeCallback in frustumChangeCallbacks) { connection.fireEvent(FrustumChangeEvent(renderWindow, frustum))
frustumChangeCallback.onFrustumChange()
}
} }
fun handleInput(deltaTime: Double) { fun handleInput(deltaTime: Double) {
@ -211,26 +208,16 @@ class Camera(
} }
} }
fun addShaders(vararg shaders: Shader) {
this.shaders.addAll(shaders)
}
fun addFrustumChangeCallback(vararg shaders: FrustumChangeCallback) {
this.frustumChangeCallbacks.addAll(shaders)
}
override fun onScreenResize(screenDimensions: Vec2i) {
recalculateViewProjectionMatrix()
}
private fun recalculateViewProjectionMatrix() { private fun recalculateViewProjectionMatrix() {
viewMatrix = calculateViewMatrix() viewMatrix = calculateViewMatrix()
projectionMatrix = calculateProjectionMatrix(renderWindow.screenDimensionsF) projectionMatrix = calculateProjectionMatrix(renderWindow.screenDimensionsF)
viewProjectionMatrix = projectionMatrix * viewMatrix viewProjectionMatrix = projectionMatrix * viewMatrix
lastMatrixChange = System.currentTimeMillis() lastMatrixChange = System.currentTimeMillis()
for (shader in shaders) { for (shader in renderWindow.shaders) {
if (shader.uniforms.contains("viewProjectionMatrix")) {
shader.use().setMat4("viewProjectionMatrix", viewProjectionMatrix) shader.use().setMat4("viewProjectionMatrix", viewProjectionMatrix)
} }
}
positionChangeCallback() positionChangeCallback()
} }
@ -244,9 +231,7 @@ class Camera(
renderWindow.setSkyColor(connection.world.getBiome(blockPosition)?.skyColor ?: RenderConstants.DEFAULT_SKY_COLOR) renderWindow.setSkyColor(connection.world.getBiome(blockPosition)?.skyColor ?: RenderConstants.DEFAULT_SKY_COLOR)
frustum.recalculate() frustum.recalculate()
for (frustumChangeCallback in frustumChangeCallbacks) { connection.fireEvent(FrustumChangeEvent(renderWindow, frustum))
frustumChangeCallback.onFrustumChange()
}
connection.world.dimension?.hasSkyLight?.let { connection.world.dimension?.hasSkyLight?.let {
if (it) { if (it) {

View File

@ -18,20 +18,19 @@ import de.bixilon.minosoft.config.config.game.controls.KeyBindingsNames
import de.bixilon.minosoft.data.mappings.ResourceLocation import de.bixilon.minosoft.data.mappings.ResourceLocation
import de.bixilon.minosoft.data.text.RGBColor import de.bixilon.minosoft.data.text.RGBColor
import de.bixilon.minosoft.data.text.RGBColor.Companion.asColor import de.bixilon.minosoft.data.text.RGBColor.Companion.asColor
import de.bixilon.minosoft.gui.input.camera.FrustumChangeCallback
import de.bixilon.minosoft.gui.input.key.RenderWindowInputHandler import de.bixilon.minosoft.gui.input.key.RenderWindowInputHandler
import de.bixilon.minosoft.gui.modding.events.RenderingStateChangeEvent
import de.bixilon.minosoft.gui.rendering.chunk.WorldRenderer import de.bixilon.minosoft.gui.rendering.chunk.WorldRenderer
import de.bixilon.minosoft.gui.rendering.font.Font import de.bixilon.minosoft.gui.rendering.font.Font
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer
import de.bixilon.minosoft.gui.rendering.hud.atlas.TextureLike import de.bixilon.minosoft.gui.rendering.hud.atlas.TextureLike
import de.bixilon.minosoft.gui.rendering.hud.atlas.TextureLikeTexture import de.bixilon.minosoft.gui.rendering.hud.atlas.TextureLikeTexture
import de.bixilon.minosoft.gui.rendering.shader.ShaderHolder import de.bixilon.minosoft.gui.rendering.modding.events.RenderingStateChangeEvent
import de.bixilon.minosoft.gui.rendering.modding.events.ScreenResizeEvent
import de.bixilon.minosoft.gui.rendering.shader.Shader
import de.bixilon.minosoft.gui.rendering.sky.SkyRenderer import de.bixilon.minosoft.gui.rendering.sky.SkyRenderer
import de.bixilon.minosoft.gui.rendering.textures.Texture import de.bixilon.minosoft.gui.rendering.textures.Texture
import de.bixilon.minosoft.gui.rendering.textures.TextureArray import de.bixilon.minosoft.gui.rendering.textures.TextureArray
import de.bixilon.minosoft.gui.rendering.util.ScreenshotTaker import de.bixilon.minosoft.gui.rendering.util.ScreenshotTaker
import de.bixilon.minosoft.gui.rendering.util.abstractions.ScreenResizeCallback
import de.bixilon.minosoft.modding.event.CallbackEventInvoker import de.bixilon.minosoft.modding.event.CallbackEventInvoker
import de.bixilon.minosoft.modding.event.events.ConnectionStateChangeEvent import de.bixilon.minosoft.modding.event.events.ConnectionStateChangeEvent
import de.bixilon.minosoft.modding.event.events.PacketReceiveEvent import de.bixilon.minosoft.modding.event.events.PacketReceiveEvent
@ -41,7 +40,6 @@ import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
import de.bixilon.minosoft.util.CountUpAndDownLatch import de.bixilon.minosoft.util.CountUpAndDownLatch
import de.bixilon.minosoft.util.KUtil.synchronizedListOf import de.bixilon.minosoft.util.KUtil.synchronizedListOf
import de.bixilon.minosoft.util.KUtil.synchronizedMapOf import de.bixilon.minosoft.util.KUtil.synchronizedMapOf
import de.bixilon.minosoft.util.KUtil.synchronizedSetOf
import de.bixilon.minosoft.util.Stopwatch import de.bixilon.minosoft.util.Stopwatch
import de.bixilon.minosoft.util.logging.Log import de.bixilon.minosoft.util.logging.Log
import de.bixilon.minosoft.util.logging.LogMessageType import de.bixilon.minosoft.util.logging.LogMessageType
@ -84,11 +82,12 @@ class RenderWindow(
val renderQueue: MutableList<Runnable> = synchronizedListOf() val renderQueue: MutableList<Runnable> = synchronizedListOf()
val shaders: MutableList<Shader> = mutableListOf()
lateinit var WHITE_TEXTURE: TextureLike lateinit var WHITE_TEXTURE: TextureLike
val screenResizeCallbacks: MutableSet<ScreenResizeCallback> = synchronizedSetOf(inputHandler.camera)
var tickCount = 0L var tickCount = 0L
var lastTickTimer = System.currentTimeMillis() var lastTickTimer = System.currentTimeMillis()
@ -221,9 +220,6 @@ class RenderWindow(
Log.log(LogMessageType.RENDERING_LOADING) { "Post loading renderer (${stopwatch.labTime()})..." } Log.log(LogMessageType.RENDERING_LOADING) { "Post loading renderer (${stopwatch.labTime()})..." }
for (renderer in rendererMap.values) { for (renderer in rendererMap.values) {
renderer.postInit() renderer.postInit()
if (renderer is ShaderHolder) {
inputHandler.camera.addShaders(renderer.shader)
}
} }
@ -231,11 +227,10 @@ class RenderWindow(
glfwSetWindowSizeCallback(windowId, object : GLFWWindowSizeCallback() { glfwSetWindowSizeCallback(windowId, object : GLFWWindowSizeCallback() {
override fun invoke(window: Long, width: Int, height: Int) { override fun invoke(window: Long, width: Int, height: Int) {
glViewport(0, 0, width, height) glViewport(0, 0, width, height)
val previousSize = screenDimensions
screenDimensions = Vec2i(width, height) screenDimensions = Vec2i(width, height)
screenDimensionsF = Vec2(screenDimensions) screenDimensionsF = Vec2(screenDimensions)
for (callback in screenResizeCallbacks) { connection.fireEvent(ScreenResizeEvent(previousScreenDimensions = previousSize, screenDimensions = screenDimensions))
callback.onScreenResize(screenDimensions)
}
} }
}) })
@ -266,9 +261,7 @@ class RenderWindow(
registerGlobalKeyCombinations() registerGlobalKeyCombinations()
for (callback in screenResizeCallbacks) { connection.fireEvent(ScreenResizeEvent(previousScreenDimensions = Vec2i(0, 0), screenDimensions = screenDimensions))
callback.onScreenResize(screenDimensions)
}
Log.log(LogMessageType.RENDERING_LOADING) { "Rendering is fully prepared in ${stopwatch.totalTime()}" } Log.log(LogMessageType.RENDERING_LOADING) { "Rendering is fully prepared in ${stopwatch.totalTime()}" }
@ -392,12 +385,6 @@ class RenderWindow(
fun registerRenderer(renderBuilder: RenderBuilder) { fun registerRenderer(renderBuilder: RenderBuilder) {
val renderer = renderBuilder.build(connection, this) val renderer = renderBuilder.build(connection, this)
rendererMap[renderBuilder.RESOURCE_LOCATION] = renderer rendererMap[renderBuilder.RESOURCE_LOCATION] = renderer
if (renderer is ScreenResizeCallback) {
screenResizeCallbacks.add(renderer)
}
if (renderer is FrustumChangeCallback) {
inputHandler.camera.addFrustumChangeCallback(renderer)
}
} }
@Deprecated(message = "Will be replaced with SkyRenderer") @Deprecated(message = "Will be replaced with SkyRenderer")

View File

@ -14,7 +14,7 @@
package de.bixilon.minosoft.gui.rendering package de.bixilon.minosoft.gui.rendering
interface Renderer { interface Renderer {
fun init() fun init() {}
fun postInit() fun postInit() {}
fun draw() fun draw() {}
} }

View File

@ -29,10 +29,12 @@ class Rendering(private val connection: PlayConnection) {
Thread({ Thread({
try { try {
Log.log(LogMessageType.RENDERING_GENERAL, LogLevels.INFO) { "Hello LWJGL ${Version.getVersion()}!" } Log.log(LogMessageType.RENDERING_GENERAL, LogLevels.INFO) { "Hello LWJGL ${Version.getVersion()}!" }
CONTEXT_MAP[Thread.currentThread()] = renderWindow
renderWindow.init(latch) renderWindow.init(latch)
renderWindow.startRenderLoop() renderWindow.startRenderLoop()
renderWindow.exit() renderWindow.exit()
} catch (exception: Throwable) { } catch (exception: Throwable) {
CONTEXT_MAP.remove(Thread.currentThread())
exception.printStackTrace() exception.printStackTrace()
try { try {
renderWindow.exit() renderWindow.exit()
@ -45,4 +47,11 @@ class Rendering(private val connection: PlayConnection) {
} }
}, "Rendering").start() }, "Rendering").start()
} }
companion object {
private val CONTEXT_MAP: MutableMap<Thread, RenderWindow> = mutableMapOf()
val currentContext: RenderWindow?
get() = CONTEXT_MAP[Thread.currentThread()]
}
} }

View File

@ -27,8 +27,6 @@ import org.lwjgl.opengl.GL20.glVertexAttribPointer
class SectionArrayMesh : Mesh(initialCacheSize = 100000) { class SectionArrayMesh : Mesh(initialCacheSize = 100000) {
fun addVertex(position: Vec3, textureCoordinates: Vec2, texture: Texture, tintColor: RGBColor?, lightLevel: Int = 14) { fun addVertex(position: Vec3, textureCoordinates: Vec2, texture: Texture, tintColor: RGBColor?, lightLevel: Int = 14) {
val data = data!!
val color = tintColor ?: ChatColors.WHITE val color = tintColor ?: ChatColors.WHITE
val lightFactor = (lightLevel + 1) / MAX_LIGHT_LEVEL_FLOAT val lightFactor = (lightLevel + 1) / MAX_LIGHT_LEVEL_FLOAT

View File

@ -25,11 +25,11 @@ import de.bixilon.minosoft.data.world.Chunk
import de.bixilon.minosoft.data.world.ChunkSection import de.bixilon.minosoft.data.world.ChunkSection
import de.bixilon.minosoft.data.world.ChunkSection.Companion.indexPosition import de.bixilon.minosoft.data.world.ChunkSection.Companion.indexPosition
import de.bixilon.minosoft.data.world.World import de.bixilon.minosoft.data.world.World
import de.bixilon.minosoft.gui.input.camera.FrustumChangeCallback import de.bixilon.minosoft.gui.input.camera.Frustum
import de.bixilon.minosoft.gui.modding.events.RenderingStateChangeEvent
import de.bixilon.minosoft.gui.rendering.* import de.bixilon.minosoft.gui.rendering.*
import de.bixilon.minosoft.gui.rendering.modding.events.FrustumChangeEvent
import de.bixilon.minosoft.gui.rendering.modding.events.RenderingStateChangeEvent
import de.bixilon.minosoft.gui.rendering.shader.Shader import de.bixilon.minosoft.gui.rendering.shader.Shader
import de.bixilon.minosoft.gui.rendering.shader.ShaderHolder
import de.bixilon.minosoft.gui.rendering.textures.Texture import de.bixilon.minosoft.gui.rendering.textures.Texture
import de.bixilon.minosoft.gui.rendering.util.VecUtil.chunkPosition import de.bixilon.minosoft.gui.rendering.util.VecUtil.chunkPosition
import de.bixilon.minosoft.gui.rendering.util.VecUtil.of import de.bixilon.minosoft.gui.rendering.util.VecUtil.of
@ -52,11 +52,11 @@ import org.lwjgl.opengl.GL11.glDepthMask
class WorldRenderer( class WorldRenderer(
private val connection: PlayConnection, private val connection: PlayConnection,
val renderWindow: RenderWindow, val renderWindow: RenderWindow,
) : Renderer, ShaderHolder, FrustumChangeCallback { ) : Renderer {
private val world: World = connection.world private val world: World = connection.world
private val waterBlock = connection.mapping.blockRegistry.get(ResourceLocation("minecraft:water"))?.nullCast<FluidBlock>() private val waterBlock = connection.mapping.blockRegistry.get(ResourceLocation("minecraft:water"))?.nullCast<FluidBlock>()
override lateinit var shader: Shader lateinit var chunkShader: Shader
val allChunkSections: MutableMap<Vec2i, MutableMap<Int, ChunkMeshCollection>> = synchronizedMapOf() val allChunkSections: MutableMap<Vec2i, MutableMap<Int, ChunkMeshCollection>> = synchronizedMapOf()
val visibleChunks: MutableMap<Vec2i, MutableMap<Int, ChunkMeshCollection>> = synchronizedMapOf() val visibleChunks: MutableMap<Vec2i, MutableMap<Int, ChunkMeshCollection>> = synchronizedMapOf()
val queuedChunks: MutableSet<Vec2i> = synchronizedSetOf() val queuedChunks: MutableSet<Vec2i> = synchronizedSetOf()
@ -160,19 +160,20 @@ class WorldRenderer(
clearChunkCache() clearChunkCache()
} }
}) })
connection.registerEvent(CallbackEventInvoker.of<FrustumChangeEvent> { onFrustumChange(it.frustum) })
} }
override fun postInit() { override fun postInit() {
check(renderWindow.textures.animator.animatedTextures.size < 4096) { "Can not have more than 4096 animated textures!" } // uniform buffer limit: 16kb. 4 ints per texture check(renderWindow.textures.animator.animatedTextures.size < 4096) { "Can not have more than 4096 animated textures!" } // uniform buffer limit: 16kb. 4 ints per texture
shader = Shader( chunkShader = Shader(
vertexPath = ResourceLocation(ProtocolDefinition.MINOSOFT_NAMESPACE, "rendering/shader/chunk_vertex.glsl"), resourceLocation = ResourceLocation(ProtocolDefinition.MINOSOFT_NAMESPACE, "chunk"),
fragmentPath = ResourceLocation(ProtocolDefinition.MINOSOFT_NAMESPACE, "rendering/shader/chunk_fragment.glsl"),
defines = mapOf("ANIMATED_TEXTURE_COUNT" to MMath.clamp(renderWindow.textures.animator.animatedTextures.size, 1, Int.MAX_VALUE)), defines = mapOf("ANIMATED_TEXTURE_COUNT" to MMath.clamp(renderWindow.textures.animator.animatedTextures.size, 1, Int.MAX_VALUE)),
) )
shader.load() chunkShader.load()
renderWindow.textures.use(shader, "textureArray") renderWindow.textures.use(chunkShader, "textureArray")
renderWindow.textures.animator.use(shader, "AnimatedDataBuffer") renderWindow.textures.animator.use(chunkShader, "AnimatedDataBuffer")
for (blockState in allBlocks!!) { for (blockState in allBlocks!!) {
for (model in blockState.renderers) { for (model in blockState.renderers) {
@ -183,7 +184,7 @@ class WorldRenderer(
} }
override fun draw() { override fun draw() {
shader.use() chunkShader.use()
val visibleChunks = visibleChunks.toSynchronizedMap() val visibleChunks = visibleChunks.toSynchronizedMap()
for ((_, map) in visibleChunks) { for ((_, map) in visibleChunks) {
@ -398,13 +399,13 @@ class WorldRenderer(
prepareWorld(connection.world) prepareWorld(connection.world)
} }
override fun onFrustumChange() { private fun onFrustumChange(frustum: Frustum) {
visibleChunks.clear() visibleChunks.clear()
for ((chunkLocation, rawIndexMap) in allChunkSections.toSynchronizedMap()) { for ((chunkLocation, rawIndexMap) in allChunkSections.toSynchronizedMap()) {
val visibleIndexMap: MutableMap<Int, ChunkMeshCollection> = synchronizedMapOf() val visibleIndexMap: MutableMap<Int, ChunkMeshCollection> = synchronizedMapOf()
val indexMap = rawIndexMap.toMap() val indexMap = rawIndexMap.toMap()
for ((index, mesh) in indexMap) { for ((index, mesh) in indexMap) {
if (renderWindow.inputHandler.camera.frustum.containsChunk(chunkLocation, mesh.lowestBlockHeight, mesh.highestBlockHeight)) { if (frustum.containsChunk(chunkLocation, mesh.lowestBlockHeight, mesh.highestBlockHeight)) {
visibleIndexMap[index] = mesh visibleIndexMap[index] = mesh
} }
} }

View File

@ -35,7 +35,7 @@ class HUDMesh : Mesh() {
} }
fun addCacheMesh(cacheMesh: HUDCacheMesh) { fun addCacheMesh(cacheMesh: HUDCacheMesh) {
data!!.addAll(cacheMesh.cache) data.addAll(cacheMesh.cache)
} }

View File

@ -26,8 +26,9 @@ import de.bixilon.minosoft.gui.rendering.hud.nodes.HUDElement
import de.bixilon.minosoft.gui.rendering.hud.nodes.chat.ChatBoxHUDElement import de.bixilon.minosoft.gui.rendering.hud.nodes.chat.ChatBoxHUDElement
import de.bixilon.minosoft.gui.rendering.hud.nodes.debug.HUDSystemDebugNode import de.bixilon.minosoft.gui.rendering.hud.nodes.debug.HUDSystemDebugNode
import de.bixilon.minosoft.gui.rendering.hud.nodes.debug.HUDWorldDebugNode import de.bixilon.minosoft.gui.rendering.hud.nodes.debug.HUDWorldDebugNode
import de.bixilon.minosoft.gui.rendering.modding.events.ScreenResizeEvent
import de.bixilon.minosoft.gui.rendering.shader.Shader import de.bixilon.minosoft.gui.rendering.shader.Shader
import de.bixilon.minosoft.gui.rendering.util.abstractions.ScreenResizeCallback import de.bixilon.minosoft.modding.event.CallbackEventInvoker
import de.bixilon.minosoft.protocol.network.connection.PlayConnection import de.bixilon.minosoft.protocol.network.connection.PlayConnection
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
import de.bixilon.minosoft.util.MMath import de.bixilon.minosoft.util.MMath
@ -36,12 +37,11 @@ import glm_.glm
import glm_.mat4x4.Mat4 import glm_.mat4x4.Mat4
import glm_.vec2.Vec2i import glm_.vec2.Vec2i
class HUDRenderer(val connection: PlayConnection, val renderWindow: RenderWindow) : Renderer, ScreenResizeCallback { class HUDRenderer(val connection: PlayConnection, val renderWindow: RenderWindow) : Renderer {
private val hudElements: MutableMap<ResourceLocation, Pair<HUDElementProperties, HUDElement>> = mutableMapOf() private val hudElements: MutableMap<ResourceLocation, Pair<HUDElementProperties, HUDElement>> = mutableMapOf()
private val enabledHUDElement: MutableMap<ResourceLocation, Pair<HUDElementProperties, HUDElement>> = mutableMapOf() private val enabledHUDElement: MutableMap<ResourceLocation, Pair<HUDElementProperties, HUDElement>> = mutableMapOf()
private val hudShader = Shader( private val hudShader = Shader(
vertexPath = ResourceLocation(ProtocolDefinition.MINOSOFT_NAMESPACE, "rendering/shader/hud_vertex.glsl"), resourceLocation = ResourceLocation(ProtocolDefinition.MINOSOFT_NAMESPACE, "hud"),
fragmentPath = ResourceLocation(ProtocolDefinition.MINOSOFT_NAMESPACE, "rendering/shader/hud_fragment.glsl"),
) )
lateinit var hudAtlasElements: Map<ResourceLocation, HUDAtlasElement> lateinit var hudAtlasElements: Map<ResourceLocation, HUDAtlasElement>
var orthographicMatrix: Mat4 = Mat4() var orthographicMatrix: Mat4 = Mat4()
@ -74,6 +74,13 @@ class HUDRenderer(val connection: PlayConnection, val renderWindow: RenderWindow
renderWindow.inputHandler.registerKeyCallback(KeyBindingsNames.CLOSE) { renderWindow.inputHandler.registerKeyCallback(KeyBindingsNames.CLOSE) {
} }
connection.registerEvent(CallbackEventInvoker.of<ScreenResizeEvent> {
orthographicMatrix = glm.ortho(-it.screenDimensions.x / 2.0f, it.screenDimensions.x / 2.0f, -it.screenDimensions.y / 2.0f, it.screenDimensions.y / 2.0f)
for ((_, hudElement) in hudElements.values) {
hudElement.layout.clearChildrenCache()
}
})
} }
private fun registerDefaultElements() { private fun registerDefaultElements() {
@ -95,9 +102,6 @@ class HUDRenderer(val connection: PlayConnection, val renderWindow: RenderWindow
} }
val hudElement = builder.build(this) val hudElement = builder.build(this)
hudElement.properties = properties hudElement.properties = properties
if (hudElement is ScreenResizeCallback) {
renderWindow.screenResizeCallbacks.add(hudElement)
}
val pair = Pair(properties, hudElement) val pair = Pair(properties, hudElement)
hudElements[builder.RESOURCE_LOCATION] = pair hudElements[builder.RESOURCE_LOCATION] = pair
@ -124,12 +128,6 @@ class HUDRenderer(val connection: PlayConnection, val renderWindow: RenderWindow
fun removeElement(resourceLocation: ResourceLocation) { fun removeElement(resourceLocation: ResourceLocation) {
val element = hudElements[resourceLocation] ?: return val element = hudElements[resourceLocation] ?: return
element.second.let {
if (it is ScreenResizeCallback) {
renderWindow.screenResizeCallbacks.remove(it)
}
}
element.first.toggleKeyBinding?.let { element.first.toggleKeyBinding?.let {
renderWindow.inputHandler.unregisterKeyBinding(it) renderWindow.inputHandler.unregisterKeyBinding(it)
} }
@ -150,13 +148,6 @@ class HUDRenderer(val connection: PlayConnection, val renderWindow: RenderWindow
} }
} }
override fun onScreenResize(screenDimensions: Vec2i) {
orthographicMatrix = glm.ortho(-screenDimensions.x / 2.0f, screenDimensions.x / 2.0f, -screenDimensions.y / 2.0f, screenDimensions.y / 2.0f)
for ((_, hudElement) in hudElements.values) {
hudElement.layout.clearChildrenCache()
}
}
override fun draw() { override fun draw() {
if (!RenderConstants.RENDER_HUD) { if (!RenderConstants.RENDER_HUD) {
return return

View File

@ -23,11 +23,12 @@ import de.bixilon.minosoft.gui.rendering.hud.elements.input.TextField
import de.bixilon.minosoft.gui.rendering.hud.elements.input.TextFieldProperties import de.bixilon.minosoft.gui.rendering.hud.elements.input.TextFieldProperties
import de.bixilon.minosoft.gui.rendering.hud.nodes.HUDElement import de.bixilon.minosoft.gui.rendering.hud.nodes.HUDElement
import de.bixilon.minosoft.gui.rendering.hud.nodes.layout.AbsoluteLayout import de.bixilon.minosoft.gui.rendering.hud.nodes.layout.AbsoluteLayout
import de.bixilon.minosoft.gui.rendering.util.abstractions.ScreenResizeCallback import de.bixilon.minosoft.gui.rendering.modding.events.ScreenResizeEvent
import de.bixilon.minosoft.modding.event.CallbackEventInvoker
import glm_.vec2.Vec2 import glm_.vec2.Vec2
import glm_.vec2.Vec2i import glm_.vec2.Vec2i
class ChatBoxHUDElement(hudRenderer: HUDRenderer) : HUDElement(hudRenderer), ScreenResizeCallback { class ChatBoxHUDElement(hudRenderer: HUDRenderer) : HUDElement(hudRenderer) {
override val layout = AbsoluteLayout(hudRenderer.renderWindow) override val layout = AbsoluteLayout(hudRenderer.renderWindow)
private lateinit var inputField: TextField private lateinit var inputField: TextField
@ -48,13 +49,12 @@ class ChatBoxHUDElement(hudRenderer: HUDRenderer) : HUDElement(hudRenderer), Scr
hudRenderer.renderWindow.inputHandler.registerKeyCallback(KeyBindingsNames.OPEN_CHAT) { hudRenderer.renderWindow.inputHandler.registerKeyCallback(KeyBindingsNames.OPEN_CHAT) {
openChat() openChat()
} }
} hudRenderer.connection.registerEvent(CallbackEventInvoker.of<ScreenResizeEvent> {
layout.sizing.minSize.x = it.screenDimensions.x
override fun onScreenResize(screenDimensions: Vec2i) { layout.sizing.maxSize.x = it.screenDimensions.x
layout.sizing.minSize.x = screenDimensions.x
layout.sizing.maxSize.x = screenDimensions.x
inputField.textElement.setProperties.hardWrap = (inputField.textElement.sizing.minSize.x / scale).toInt() inputField.textElement.setProperties.hardWrap = (inputField.textElement.sizing.minSize.x / scale).toInt()
layout.apply() layout.apply()
})
} }
fun openChat() { fun openChat() {

View File

@ -19,18 +19,18 @@ import de.bixilon.minosoft.gui.rendering.hud.HUDElementProperties
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderBuilder import de.bixilon.minosoft.gui.rendering.hud.HUDRenderBuilder
import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer import de.bixilon.minosoft.gui.rendering.hud.HUDRenderer
import de.bixilon.minosoft.gui.rendering.hud.nodes.properties.NodeAlignment import de.bixilon.minosoft.gui.rendering.hud.nodes.properties.NodeAlignment
import de.bixilon.minosoft.gui.rendering.util.abstractions.ScreenResizeCallback import de.bixilon.minosoft.gui.rendering.modding.events.ScreenResizeEvent
import de.bixilon.minosoft.modding.event.CallbackEventInvoker
import de.bixilon.minosoft.modding.loading.ModLoader import de.bixilon.minosoft.modding.loading.ModLoader
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
import de.bixilon.minosoft.util.GitInfo import de.bixilon.minosoft.util.GitInfo
import de.bixilon.minosoft.util.SystemInformation import de.bixilon.minosoft.util.SystemInformation
import de.bixilon.minosoft.util.UnitFormatter import de.bixilon.minosoft.util.UnitFormatter
import glm_.vec2.Vec2 import glm_.vec2.Vec2
import glm_.vec2.Vec2i
import org.lwjgl.opengl.GL11.* import org.lwjgl.opengl.GL11.*
class HUDSystemDebugNode(hudRenderer: HUDRenderer) : DebugScreenNode(hudRenderer), ScreenResizeCallback { class HUDSystemDebugNode(hudRenderer: HUDRenderer) : DebugScreenNode(hudRenderer) {
init { init {
layout.sizing.forceAlign = NodeAlignment.RIGHT layout.sizing.forceAlign = NodeAlignment.RIGHT
@ -67,13 +67,13 @@ class HUDSystemDebugNode(hudRenderer: HUDRenderer) : DebugScreenNode(hudRenderer
text("Mods: ${ModLoader.MOD_MAP.size} active, ${hudRenderer.connection.eventListenerSize} listeners") text("Mods: ${ModLoader.MOD_MAP.size} active, ${hudRenderer.connection.eventListenerSize} listeners")
} }
override fun onScreenResize(screenDimensions: Vec2i) {
displayText.sText = "Display: ${getScreenDimensions()}"
}
override fun init() { override fun init() {
gpuText.sText = "GPU: " + (glGetString(GL_RENDERER) ?: "unknown") gpuText.sText = "GPU: " + (glGetString(GL_RENDERER) ?: "unknown")
gpuVersionText.sText = "Version: " + (glGetString(GL_VERSION) ?: "unknown") gpuVersionText.sText = "Version: " + (glGetString(GL_VERSION) ?: "unknown")
hudRenderer.connection.registerEvent(CallbackEventInvoker.of<ScreenResizeEvent> {
displayText.sText = "Display: ${getScreenDimensions()}"
})
} }
override fun draw() { override fun draw() {

View File

@ -11,8 +11,13 @@
* This software is not affiliated with Mojang AB, the original developer of Minecraft. * This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/ */
package de.bixilon.minosoft.gui.input.camera package de.bixilon.minosoft.gui.rendering.modding.events
interface FrustumChangeCallback { import de.bixilon.minosoft.gui.input.camera.Frustum
fun onFrustumChange() import de.bixilon.minosoft.gui.rendering.RenderWindow
} import de.bixilon.minosoft.gui.rendering.Rendering
class FrustumChangeEvent(
renderWindow: RenderWindow = Rendering.currentContext!!,
val frustum: Frustum,
) : RenderEvent(renderWindow)

View File

@ -11,11 +11,11 @@
* This software is not affiliated with Mojang AB, the original developer of Minecraft. * This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/ */
package de.bixilon.minosoft.gui.rendering.util.abstractions package de.bixilon.minosoft.gui.rendering.modding.events
import glm_.vec2.Vec2i import de.bixilon.minosoft.gui.rendering.RenderWindow
import de.bixilon.minosoft.modding.event.events.PlayConnectionEvent
interface ScreenResizeCallback { abstract class RenderEvent(
val renderWindow: RenderWindow,
fun onScreenResize(screenDimensions: Vec2i) {} ) : PlayConnectionEvent(renderWindow.connection)
}

View File

@ -11,7 +11,7 @@
* This software is not affiliated with Mojang AB, the original developer of Minecraft. * This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/ */
package de.bixilon.minosoft.gui.modding.events package de.bixilon.minosoft.gui.rendering.modding.events
import de.bixilon.minosoft.gui.rendering.RenderingStates import de.bixilon.minosoft.gui.rendering.RenderingStates
import de.bixilon.minosoft.modding.event.events.PlayConnectionEvent import de.bixilon.minosoft.modding.event.events.PlayConnectionEvent

View File

@ -11,8 +11,14 @@
* This software is not affiliated with Mojang AB, the original developer of Minecraft. * This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/ */
package de.bixilon.minosoft.gui.rendering.shader package de.bixilon.minosoft.gui.rendering.modding.events
interface ShaderHolder { import de.bixilon.minosoft.gui.rendering.RenderWindow
val shader: Shader import de.bixilon.minosoft.gui.rendering.Rendering
} import glm_.vec2.Vec2i
class ScreenResizeEvent(
renderWindow: RenderWindow = Rendering.currentContext!!,
val previousScreenDimensions: Vec2i,
val screenDimensions: Vec2i,
) : RenderEvent(renderWindow)

View File

@ -15,7 +15,9 @@ package de.bixilon.minosoft.gui.rendering.shader
import de.bixilon.minosoft.Minosoft import de.bixilon.minosoft.Minosoft
import de.bixilon.minosoft.data.assets.AssetsManager import de.bixilon.minosoft.data.assets.AssetsManager
import de.bixilon.minosoft.data.commands.CommandStringReader
import de.bixilon.minosoft.data.mappings.ResourceLocation import de.bixilon.minosoft.data.mappings.ResourceLocation
import de.bixilon.minosoft.gui.rendering.Rendering
import de.bixilon.minosoft.gui.rendering.exceptions.ShaderLoadingException import de.bixilon.minosoft.gui.rendering.exceptions.ShaderLoadingException
import de.bixilon.minosoft.gui.rendering.util.OpenGLUtil import de.bixilon.minosoft.gui.rendering.util.OpenGLUtil
import glm_.mat4x4.Mat4 import glm_.mat4x4.Mat4
@ -30,19 +32,23 @@ import org.lwjgl.opengl.ARBVertexShader.GL_VERTEX_SHADER_ARB
import org.lwjgl.opengl.GL11.GL_FALSE import org.lwjgl.opengl.GL11.GL_FALSE
import org.lwjgl.opengl.GL43.* import org.lwjgl.opengl.GL43.*
import org.lwjgl.system.MemoryUtil import org.lwjgl.system.MemoryUtil
import java.io.FileNotFoundException
class Shader( class Shader(
private val vertexPath: ResourceLocation, private val resourceLocation: ResourceLocation,
private val geometryPath: ResourceLocation? = null,
private val fragmentPath: ResourceLocation,
private val defines: Map<String, Any> = mapOf(), private val defines: Map<String, Any> = mapOf(),
) { ) {
lateinit var uniforms: List<String>
private set
private var programId = 0 private var programId = 0
fun load(assetsManager: AssetsManager = Minosoft.MINOSOFT_ASSETS_MANAGER): Int { fun load(assetsManager: AssetsManager = Minosoft.MINOSOFT_ASSETS_MANAGER): Int {
val vertexShader = createShader(assetsManager, vertexPath, GL_VERTEX_SHADER_ARB, defines) val uniforms: MutableList<String> = mutableListOf()
val geometryShader = geometryPath?.let { createShader(assetsManager, it, GL_GEOMETRY_SHADER_ARB, defines) } val pathPrefix = resourceLocation.namespace + ":rendering/shader/" + resourceLocation.path + "/" + resourceLocation.path.replace("/", "_")
val fragmentShader = createShader(assetsManager, fragmentPath, GL_FRAGMENT_SHADER_ARB, defines) val vertexShader = createShader(assetsManager, ResourceLocation("$pathPrefix.vsh"), GL_VERTEX_SHADER_ARB, defines, uniforms)!!
val geometryShader = createShader(assetsManager, ResourceLocation("$pathPrefix.gsh"), GL_GEOMETRY_SHADER_ARB, defines, uniforms)
val fragmentShader = createShader(assetsManager, ResourceLocation("$pathPrefix.fsh"), GL_FRAGMENT_SHADER_ARB, defines, uniforms)!!
this.uniforms = uniforms.toList()
programId = glCreateProgramObjectARB() programId = glCreateProgramObjectARB()
if (programId.toLong() == MemoryUtil.NULL) { if (programId.toLong() == MemoryUtil.NULL) {
@ -71,13 +77,15 @@ class Shader(
} }
glDeleteShader(fragmentShader) glDeleteShader(fragmentShader)
val context = Rendering.currentContext!!
context.shaders.add(this)
return programId return programId
} }
fun use(): Shader { fun use(): Shader {
if (usedShader !== this) { if (currentShaderInUse !== this) {
glUseProgram(programId) glUseProgram(programId)
usedShader = this currentShaderInUse = this
} }
return this return this
} }
@ -142,22 +150,26 @@ class Shader(
companion object { companion object {
private var usedShader: Shader? = null private var currentShaderInUse: Shader? = null
private fun createShader(assetsManager: AssetsManager = Minosoft.MINOSOFT_ASSETS_MANAGER, resourceLocation: ResourceLocation, shaderType: Int, defines: Map<String, Any>, uniforms: MutableList<String>): Int? {
private fun createShader(assetsManager: AssetsManager = Minosoft.MINOSOFT_ASSETS_MANAGER, resourceLocation: ResourceLocation, shaderType: Int, defines: Map<String, Any>): Int {
val shaderId = glCreateShaderObjectARB(shaderType) val shaderId = glCreateShaderObjectARB(shaderType)
if (shaderId.toLong() == MemoryUtil.NULL) { if (shaderId.toLong() == MemoryUtil.NULL) {
throw ShaderLoadingException() throw ShaderLoadingException()
} }
val total = StringBuilder() val total = StringBuilder()
val lines = assetsManager.readStringAsset(resourceLocation).lines() val lines = try {
assetsManager.readStringAsset(resourceLocation).lines()
} catch (exception: FileNotFoundException) {
return null
}
for (line in lines) { for (line in lines) {
total.append(line) total.append(line)
total.append('\n') total.append('\n')
if (line.startsWith("#version")) { val reader = CommandStringReader(line)
when {
line.startsWith("#version") -> {
// add all defines // add all defines
total.append('\n') total.append('\n')
for ((define, value) in defines) { for ((define, value) in defines) {
@ -168,6 +180,14 @@ class Shader(
total.append('\n') total.append('\n')
} }
} }
line.startsWith("uniform ") -> { // ToDo: Packed in layout
reader.readUnquotedString() // "uniform"
reader.skipWhitespaces()
reader.readUnquotedString() // datatype
reader.skipWhitespaces()
uniforms.add(reader.readString()) // uniform name
}
}
} }
glShaderSourceARB(shaderId, total.toString()) glShaderSourceARB(shaderId, total.toString())

View File

@ -22,8 +22,6 @@ import org.lwjgl.opengl.GL20.glVertexAttribPointer
class SkyMesh : Mesh(initialCacheSize = 6 * 2 * 3 * FLOATS_PER_VERTEX) { class SkyMesh : Mesh(initialCacheSize = 6 * 2 * 3 * FLOATS_PER_VERTEX) {
fun addVertex(position: Vec3) { fun addVertex(position: Vec3) {
val data = data!!
data.addAll(floatArrayOf( data.addAll(floatArrayOf(
position.x, position.x,
position.y, position.y,

View File

@ -18,7 +18,6 @@ import de.bixilon.minosoft.gui.rendering.RenderBuilder
import de.bixilon.minosoft.gui.rendering.RenderWindow import de.bixilon.minosoft.gui.rendering.RenderWindow
import de.bixilon.minosoft.gui.rendering.Renderer import de.bixilon.minosoft.gui.rendering.Renderer
import de.bixilon.minosoft.gui.rendering.shader.Shader import de.bixilon.minosoft.gui.rendering.shader.Shader
import de.bixilon.minosoft.gui.rendering.shader.ShaderHolder
import de.bixilon.minosoft.protocol.network.connection.PlayConnection import de.bixilon.minosoft.protocol.network.connection.PlayConnection
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
import org.lwjgl.opengl.GL11.* import org.lwjgl.opengl.GL11.*
@ -26,39 +25,35 @@ import org.lwjgl.opengl.GL11.*
class SkyRenderer( class SkyRenderer(
private val connection: PlayConnection, private val connection: PlayConnection,
val renderWindow: RenderWindow, val renderWindow: RenderWindow,
) : Renderer, ShaderHolder { ) : Renderer {
private var lastMatrixUpdate = System.currentTimeMillis() private var lastMatrixUpdate = System.currentTimeMillis()
override val shader = Shader( private val skyColorShader = Shader(
vertexPath = ResourceLocation(ProtocolDefinition.MINOSOFT_NAMESPACE, "rendering/shader/sky_vertex.glsl"), resourceLocation = ResourceLocation(ProtocolDefinition.MINOSOFT_NAMESPACE, "sky/color"),
fragmentPath = ResourceLocation(ProtocolDefinition.MINOSOFT_NAMESPACE, "rendering/shader/sky_fragment.glsl"),
) )
private val mesh = SkyMesh() private val mesh = SkyMesh()
init { init {
mesh.data!!.addAll(VERTICES) mesh.data.addAll(VERTICES)
} }
override fun init() { override fun init() {
shader.load() skyColorShader.load()
mesh.load() mesh.load()
} }
override fun postInit() {
}
private fun setShaderMatrix() { private fun setShaderMatrix() {
if (lastMatrixUpdate == renderWindow.inputHandler.camera.lastMatrixChange) { if (lastMatrixUpdate == renderWindow.inputHandler.camera.lastMatrixChange) {
return return
} }
shader.use().setMat4("skyViewProjectionMatrix", renderWindow.inputHandler.camera.projectionMatrix * renderWindow.inputHandler.camera.viewMatrix.toMat3().toMat4()) skyColorShader.use().setMat4("skyViewProjectionMatrix", renderWindow.inputHandler.camera.projectionMatrix * renderWindow.inputHandler.camera.viewMatrix.toMat3().toMat4())
lastMatrixUpdate = renderWindow.inputHandler.camera.lastMatrixChange lastMatrixUpdate = renderWindow.inputHandler.camera.lastMatrixChange
} }
override fun draw() { override fun draw() {
glDepthFunc(GL_LEQUAL) glDepthFunc(GL_LEQUAL)
shader.use() skyColorShader.use()
setShaderMatrix() setShaderMatrix()
mesh.draw() mesh.draw()
glDepthFunc(GL_LESS) glDepthFunc(GL_LESS)

View File

@ -21,7 +21,13 @@ import org.lwjgl.opengl.GL30.*
abstract class Mesh( abstract class Mesh(
initialCacheSize: Int = 10000, initialCacheSize: Int = 10000,
) { ) {
var data: ArrayFloatList? = ArrayFloatList(initialCacheSize) private var _data: ArrayFloatList? = ArrayFloatList(initialCacheSize)
var data: ArrayFloatList
get() = _data!!
set(value) {
_data = value
}
private var vao: Int = -1 private var vao: Int = -1
private var vbo: Int = -1 private var vbo: Int = -1
var trianglesCount: Int = -1 var trianglesCount: Int = -1
@ -36,16 +42,16 @@ abstract class Mesh(
protected fun initializeBuffers(floatsPerVertex: Int) { protected fun initializeBuffers(floatsPerVertex: Int) {
check(state == MeshStates.PREPARING) { "Mesh already loaded: $state" } check(state == MeshStates.PREPARING) { "Mesh already loaded: $state" }
trianglesCount = data!!.size / floatsPerVertex trianglesCount = data.size / floatsPerVertex
vao = glGenVertexArrays() vao = glGenVertexArrays()
vbo = glGenBuffers() vbo = glGenBuffers()
glBindVertexArray(vao) glBindVertexArray(vao)
glBindBuffer(GL_ARRAY_BUFFER, vbo) glBindBuffer(GL_ARRAY_BUFFER, vbo)
glBufferData(GL_ARRAY_BUFFER, data!!.toArray(), GL_STATIC_DRAW) glBufferData(GL_ARRAY_BUFFER, data.toArray(), GL_STATIC_DRAW)
state = MeshStates.LOADED state = MeshStates.LOADED
data = null _data = null
} }
protected fun unbind() { protected fun unbind() {