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.gui.rendering.RenderConstants
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.blockPosition
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.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.packets.c2s.play.PositionAndRotationC2SP
import de.bixilon.minosoft.protocol.packets.c2s.play.PositionC2SP
@ -46,7 +47,7 @@ class Camera(
val connection: PlayConnection,
var fov: Float,
val renderWindow: RenderWindow,
) : ScreenResizeCallback {
) {
private var mouseSensitivity = Minosoft.getConfig().config.game.camera.moseSensitivity
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
@ -80,9 +81,6 @@ class Camera(
val frustum: Frustum = Frustum(this)
private val shaders: MutableSet<Shader> = mutableSetOf()
private val frustumChangeCallbacks: MutableSet<FrustumChangeCallback> = mutableSetOf()
var viewMatrix = calculateViewMatrix()
private set
@ -135,10 +133,9 @@ class Camera(
KeyBindingsNames.MOVE_JUMP,
)
connection.registerEvent(CallbackEventInvoker.of<ScreenResizeEvent> { recalculateViewProjectionMatrix() })
frustum.recalculate()
for (frustumChangeCallback in frustumChangeCallbacks) {
frustumChangeCallback.onFrustumChange()
}
connection.fireEvent(FrustumChangeEvent(renderWindow, frustum))
}
fun handleInput(deltaTime: Double) {
@ -211,25 +208,15 @@ 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() {
viewMatrix = calculateViewMatrix()
projectionMatrix = calculateProjectionMatrix(renderWindow.screenDimensionsF)
viewProjectionMatrix = projectionMatrix * viewMatrix
lastMatrixChange = System.currentTimeMillis()
for (shader in shaders) {
shader.use().setMat4("viewProjectionMatrix", viewProjectionMatrix)
for (shader in renderWindow.shaders) {
if (shader.uniforms.contains("viewProjectionMatrix")) {
shader.use().setMat4("viewProjectionMatrix", viewProjectionMatrix)
}
}
positionChangeCallback()
}
@ -244,9 +231,7 @@ class Camera(
renderWindow.setSkyColor(connection.world.getBiome(blockPosition)?.skyColor ?: RenderConstants.DEFAULT_SKY_COLOR)
frustum.recalculate()
for (frustumChangeCallback in frustumChangeCallbacks) {
frustumChangeCallback.onFrustumChange()
}
connection.fireEvent(FrustumChangeEvent(renderWindow, frustum))
connection.world.dimension?.hasSkyLight?.let {
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.text.RGBColor
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.modding.events.RenderingStateChangeEvent
import de.bixilon.minosoft.gui.rendering.chunk.WorldRenderer
import de.bixilon.minosoft.gui.rendering.font.Font
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.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.textures.Texture
import de.bixilon.minosoft.gui.rendering.textures.TextureArray
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.events.ConnectionStateChangeEvent
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.KUtil.synchronizedListOf
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.logging.Log
import de.bixilon.minosoft.util.logging.LogMessageType
@ -84,11 +82,12 @@ class RenderWindow(
val renderQueue: MutableList<Runnable> = synchronizedListOf()
val shaders: MutableList<Shader> = mutableListOf()
lateinit var WHITE_TEXTURE: TextureLike
val screenResizeCallbacks: MutableSet<ScreenResizeCallback> = synchronizedSetOf(inputHandler.camera)
var tickCount = 0L
var lastTickTimer = System.currentTimeMillis()
@ -221,9 +220,6 @@ class RenderWindow(
Log.log(LogMessageType.RENDERING_LOADING) { "Post loading renderer (${stopwatch.labTime()})..." }
for (renderer in rendererMap.values) {
renderer.postInit()
if (renderer is ShaderHolder) {
inputHandler.camera.addShaders(renderer.shader)
}
}
@ -231,11 +227,10 @@ class RenderWindow(
glfwSetWindowSizeCallback(windowId, object : GLFWWindowSizeCallback() {
override fun invoke(window: Long, width: Int, height: Int) {
glViewport(0, 0, width, height)
val previousSize = screenDimensions
screenDimensions = Vec2i(width, height)
screenDimensionsF = Vec2(screenDimensions)
for (callback in screenResizeCallbacks) {
callback.onScreenResize(screenDimensions)
}
connection.fireEvent(ScreenResizeEvent(previousScreenDimensions = previousSize, screenDimensions = screenDimensions))
}
})
@ -266,9 +261,7 @@ class RenderWindow(
registerGlobalKeyCombinations()
for (callback in screenResizeCallbacks) {
callback.onScreenResize(screenDimensions)
}
connection.fireEvent(ScreenResizeEvent(previousScreenDimensions = Vec2i(0, 0), screenDimensions = screenDimensions))
Log.log(LogMessageType.RENDERING_LOADING) { "Rendering is fully prepared in ${stopwatch.totalTime()}" }
@ -392,12 +385,6 @@ class RenderWindow(
fun registerRenderer(renderBuilder: RenderBuilder) {
val renderer = renderBuilder.build(connection, this)
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")

View File

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

View File

@ -29,10 +29,12 @@ class Rendering(private val connection: PlayConnection) {
Thread({
try {
Log.log(LogMessageType.RENDERING_GENERAL, LogLevels.INFO) { "Hello LWJGL ${Version.getVersion()}!" }
CONTEXT_MAP[Thread.currentThread()] = renderWindow
renderWindow.init(latch)
renderWindow.startRenderLoop()
renderWindow.exit()
} catch (exception: Throwable) {
CONTEXT_MAP.remove(Thread.currentThread())
exception.printStackTrace()
try {
renderWindow.exit()
@ -45,4 +47,11 @@ class Rendering(private val connection: PlayConnection) {
}
}, "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) {
fun addVertex(position: Vec3, textureCoordinates: Vec2, texture: Texture, tintColor: RGBColor?, lightLevel: Int = 14) {
val data = data!!
val color = tintColor ?: ChatColors.WHITE
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.Companion.indexPosition
import de.bixilon.minosoft.data.world.World
import de.bixilon.minosoft.gui.input.camera.FrustumChangeCallback
import de.bixilon.minosoft.gui.modding.events.RenderingStateChangeEvent
import de.bixilon.minosoft.gui.input.camera.Frustum
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.ShaderHolder
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.of
@ -52,11 +52,11 @@ import org.lwjgl.opengl.GL11.glDepthMask
class WorldRenderer(
private val connection: PlayConnection,
val renderWindow: RenderWindow,
) : Renderer, ShaderHolder, FrustumChangeCallback {
) : Renderer {
private val world: World = connection.world
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 visibleChunks: MutableMap<Vec2i, MutableMap<Int, ChunkMeshCollection>> = synchronizedMapOf()
val queuedChunks: MutableSet<Vec2i> = synchronizedSetOf()
@ -160,19 +160,20 @@ class WorldRenderer(
clearChunkCache()
}
})
connection.registerEvent(CallbackEventInvoker.of<FrustumChangeEvent> { onFrustumChange(it.frustum) })
}
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
shader = Shader(
vertexPath = ResourceLocation(ProtocolDefinition.MINOSOFT_NAMESPACE, "rendering/shader/chunk_vertex.glsl"),
fragmentPath = ResourceLocation(ProtocolDefinition.MINOSOFT_NAMESPACE, "rendering/shader/chunk_fragment.glsl"),
chunkShader = Shader(
resourceLocation = ResourceLocation(ProtocolDefinition.MINOSOFT_NAMESPACE, "chunk"),
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.animator.use(shader, "AnimatedDataBuffer")
renderWindow.textures.use(chunkShader, "textureArray")
renderWindow.textures.animator.use(chunkShader, "AnimatedDataBuffer")
for (blockState in allBlocks!!) {
for (model in blockState.renderers) {
@ -183,7 +184,7 @@ class WorldRenderer(
}
override fun draw() {
shader.use()
chunkShader.use()
val visibleChunks = visibleChunks.toSynchronizedMap()
for ((_, map) in visibleChunks) {
@ -398,13 +399,13 @@ class WorldRenderer(
prepareWorld(connection.world)
}
override fun onFrustumChange() {
private fun onFrustumChange(frustum: Frustum) {
visibleChunks.clear()
for ((chunkLocation, rawIndexMap) in allChunkSections.toSynchronizedMap()) {
val visibleIndexMap: MutableMap<Int, ChunkMeshCollection> = synchronizedMapOf()
val indexMap = rawIndexMap.toMap()
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
}
}

View File

@ -35,7 +35,7 @@ class HUDMesh : Mesh() {
}
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.debug.HUDSystemDebugNode
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.util.abstractions.ScreenResizeCallback
import de.bixilon.minosoft.modding.event.CallbackEventInvoker
import de.bixilon.minosoft.protocol.network.connection.PlayConnection
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
import de.bixilon.minosoft.util.MMath
@ -36,12 +37,11 @@ import glm_.glm
import glm_.mat4x4.Mat4
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 enabledHUDElement: MutableMap<ResourceLocation, Pair<HUDElementProperties, HUDElement>> = mutableMapOf()
private val hudShader = Shader(
vertexPath = ResourceLocation(ProtocolDefinition.MINOSOFT_NAMESPACE, "rendering/shader/hud_vertex.glsl"),
fragmentPath = ResourceLocation(ProtocolDefinition.MINOSOFT_NAMESPACE, "rendering/shader/hud_fragment.glsl"),
resourceLocation = ResourceLocation(ProtocolDefinition.MINOSOFT_NAMESPACE, "hud"),
)
lateinit var hudAtlasElements: Map<ResourceLocation, HUDAtlasElement>
var orthographicMatrix: Mat4 = Mat4()
@ -74,6 +74,13 @@ class HUDRenderer(val connection: PlayConnection, val renderWindow: RenderWindow
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() {
@ -95,9 +102,6 @@ class HUDRenderer(val connection: PlayConnection, val renderWindow: RenderWindow
}
val hudElement = builder.build(this)
hudElement.properties = properties
if (hudElement is ScreenResizeCallback) {
renderWindow.screenResizeCallbacks.add(hudElement)
}
val pair = Pair(properties, hudElement)
hudElements[builder.RESOURCE_LOCATION] = pair
@ -124,12 +128,6 @@ class HUDRenderer(val connection: PlayConnection, val renderWindow: RenderWindow
fun removeElement(resourceLocation: ResourceLocation) {
val element = hudElements[resourceLocation] ?: return
element.second.let {
if (it is ScreenResizeCallback) {
renderWindow.screenResizeCallbacks.remove(it)
}
}
element.first.toggleKeyBinding?.let {
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() {
if (!RenderConstants.RENDER_HUD) {
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.nodes.HUDElement
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.Vec2i
class ChatBoxHUDElement(hudRenderer: HUDRenderer) : HUDElement(hudRenderer), ScreenResizeCallback {
class ChatBoxHUDElement(hudRenderer: HUDRenderer) : HUDElement(hudRenderer) {
override val layout = AbsoluteLayout(hudRenderer.renderWindow)
private lateinit var inputField: TextField
@ -48,13 +49,12 @@ class ChatBoxHUDElement(hudRenderer: HUDRenderer) : HUDElement(hudRenderer), Scr
hudRenderer.renderWindow.inputHandler.registerKeyCallback(KeyBindingsNames.OPEN_CHAT) {
openChat()
}
}
override fun onScreenResize(screenDimensions: Vec2i) {
layout.sizing.minSize.x = screenDimensions.x
layout.sizing.maxSize.x = screenDimensions.x
inputField.textElement.setProperties.hardWrap = (inputField.textElement.sizing.minSize.x / scale).toInt()
layout.apply()
hudRenderer.connection.registerEvent(CallbackEventInvoker.of<ScreenResizeEvent> {
layout.sizing.minSize.x = it.screenDimensions.x
layout.sizing.maxSize.x = it.screenDimensions.x
inputField.textElement.setProperties.hardWrap = (inputField.textElement.sizing.minSize.x / scale).toInt()
layout.apply()
})
}
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.HUDRenderer
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.protocol.protocol.ProtocolDefinition
import de.bixilon.minosoft.util.GitInfo
import de.bixilon.minosoft.util.SystemInformation
import de.bixilon.minosoft.util.UnitFormatter
import glm_.vec2.Vec2
import glm_.vec2.Vec2i
import org.lwjgl.opengl.GL11.*
class HUDSystemDebugNode(hudRenderer: HUDRenderer) : DebugScreenNode(hudRenderer), ScreenResizeCallback {
class HUDSystemDebugNode(hudRenderer: HUDRenderer) : DebugScreenNode(hudRenderer) {
init {
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")
}
override fun onScreenResize(screenDimensions: Vec2i) {
displayText.sText = "Display: ${getScreenDimensions()}"
}
override fun init() {
gpuText.sText = "GPU: " + (glGetString(GL_RENDERER) ?: "unknown")
gpuVersionText.sText = "Version: " + (glGetString(GL_VERSION) ?: "unknown")
hudRenderer.connection.registerEvent(CallbackEventInvoker.of<ScreenResizeEvent> {
displayText.sText = "Display: ${getScreenDimensions()}"
})
}
override fun draw() {

View File

@ -11,8 +11,13 @@
* 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 {
fun onFrustumChange()
}
import de.bixilon.minosoft.gui.input.camera.Frustum
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.
*/
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 {
fun onScreenResize(screenDimensions: Vec2i) {}
}
abstract class RenderEvent(
val renderWindow: RenderWindow,
) : PlayConnectionEvent(renderWindow.connection)

View File

@ -11,7 +11,7 @@
* 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.modding.event.events.PlayConnectionEvent

View File

@ -11,8 +11,14 @@
* 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 {
val shader: Shader
}
import de.bixilon.minosoft.gui.rendering.RenderWindow
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.data.assets.AssetsManager
import de.bixilon.minosoft.data.commands.CommandStringReader
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.util.OpenGLUtil
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.GL43.*
import org.lwjgl.system.MemoryUtil
import java.io.FileNotFoundException
class Shader(
private val vertexPath: ResourceLocation,
private val geometryPath: ResourceLocation? = null,
private val fragmentPath: ResourceLocation,
private val resourceLocation: ResourceLocation,
private val defines: Map<String, Any> = mapOf(),
) {
lateinit var uniforms: List<String>
private set
private var programId = 0
fun load(assetsManager: AssetsManager = Minosoft.MINOSOFT_ASSETS_MANAGER): Int {
val vertexShader = createShader(assetsManager, vertexPath, GL_VERTEX_SHADER_ARB, defines)
val geometryShader = geometryPath?.let { createShader(assetsManager, it, GL_GEOMETRY_SHADER_ARB, defines) }
val fragmentShader = createShader(assetsManager, fragmentPath, GL_FRAGMENT_SHADER_ARB, defines)
val uniforms: MutableList<String> = mutableListOf()
val pathPrefix = resourceLocation.namespace + ":rendering/shader/" + resourceLocation.path + "/" + resourceLocation.path.replace("/", "_")
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()
if (programId.toLong() == MemoryUtil.NULL) {
@ -71,13 +77,15 @@ class Shader(
}
glDeleteShader(fragmentShader)
val context = Rendering.currentContext!!
context.shaders.add(this)
return programId
}
fun use(): Shader {
if (usedShader !== this) {
if (currentShaderInUse !== this) {
glUseProgram(programId)
usedShader = this
currentShaderInUse = this
}
return this
}
@ -142,30 +150,42 @@ class Shader(
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>): Int {
private fun createShader(assetsManager: AssetsManager = Minosoft.MINOSOFT_ASSETS_MANAGER, resourceLocation: ResourceLocation, shaderType: Int, defines: Map<String, Any>, uniforms: MutableList<String>): Int? {
val shaderId = glCreateShaderObjectARB(shaderType)
if (shaderId.toLong() == MemoryUtil.NULL) {
throw ShaderLoadingException()
}
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) {
total.append(line)
total.append('\n')
if (line.startsWith("#version")) {
// add all defines
total.append('\n')
for ((define, value) in defines) {
total.append("#define ")
total.append(define)
total.append(' ')
total.append(value)
val reader = CommandStringReader(line)
when {
line.startsWith("#version") -> {
// add all defines
total.append('\n')
for ((define, value) in defines) {
total.append("#define ")
total.append(define)
total.append(' ')
total.append(value)
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
}
}
}

View File

@ -22,8 +22,6 @@ import org.lwjgl.opengl.GL20.glVertexAttribPointer
class SkyMesh : Mesh(initialCacheSize = 6 * 2 * 3 * FLOATS_PER_VERTEX) {
fun addVertex(position: Vec3) {
val data = data!!
data.addAll(floatArrayOf(
position.x,
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.Renderer
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.protocol.ProtocolDefinition
import org.lwjgl.opengl.GL11.*
@ -26,39 +25,35 @@ import org.lwjgl.opengl.GL11.*
class SkyRenderer(
private val connection: PlayConnection,
val renderWindow: RenderWindow,
) : Renderer, ShaderHolder {
) : Renderer {
private var lastMatrixUpdate = System.currentTimeMillis()
override val shader = Shader(
vertexPath = ResourceLocation(ProtocolDefinition.MINOSOFT_NAMESPACE, "rendering/shader/sky_vertex.glsl"),
fragmentPath = ResourceLocation(ProtocolDefinition.MINOSOFT_NAMESPACE, "rendering/shader/sky_fragment.glsl"),
private val skyColorShader = Shader(
resourceLocation = ResourceLocation(ProtocolDefinition.MINOSOFT_NAMESPACE, "sky/color"),
)
private val mesh = SkyMesh()
init {
mesh.data!!.addAll(VERTICES)
mesh.data.addAll(VERTICES)
}
override fun init() {
shader.load()
skyColorShader.load()
mesh.load()
}
override fun postInit() {
}
private fun setShaderMatrix() {
if (lastMatrixUpdate == renderWindow.inputHandler.camera.lastMatrixChange) {
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
}
override fun draw() {
glDepthFunc(GL_LEQUAL)
shader.use()
skyColorShader.use()
setShaderMatrix()
mesh.draw()
glDepthFunc(GL_LESS)

View File

@ -21,7 +21,13 @@ import org.lwjgl.opengl.GL30.*
abstract class Mesh(
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 vbo: Int = -1
var trianglesCount: Int = -1
@ -36,16 +42,16 @@ abstract class Mesh(
protected fun initializeBuffers(floatsPerVertex: Int) {
check(state == MeshStates.PREPARING) { "Mesh already loaded: $state" }
trianglesCount = data!!.size / floatsPerVertex
trianglesCount = data.size / floatsPerVertex
vao = glGenVertexArrays()
vbo = glGenBuffers()
glBindVertexArray(vao)
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
data = null
_data = null
}
protected fun unbind() {