mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-13 01:16:46 -04:00
multiple entity render layers
This commit is contained in:
parent
0a2a92cdfe
commit
15b0d653d7
@ -18,16 +18,15 @@ import de.bixilon.kutil.latch.AbstractLatch
|
|||||||
import de.bixilon.kutil.observer.DataObserver.Companion.observe
|
import de.bixilon.kutil.observer.DataObserver.Companion.observe
|
||||||
import de.bixilon.kutil.time.TimeUtil.millis
|
import de.bixilon.kutil.time.TimeUtil.millis
|
||||||
import de.bixilon.minosoft.gui.rendering.RenderContext
|
import de.bixilon.minosoft.gui.rendering.RenderContext
|
||||||
|
import de.bixilon.minosoft.gui.rendering.entities.feature.EntityRenderFeature
|
||||||
import de.bixilon.minosoft.gui.rendering.entities.feature.register.EntityRenderFeatures
|
import de.bixilon.minosoft.gui.rendering.entities.feature.register.EntityRenderFeatures
|
||||||
|
import de.bixilon.minosoft.gui.rendering.entities.visibility.EntityLayer
|
||||||
import de.bixilon.minosoft.gui.rendering.entities.visibility.VisibilityManager
|
import de.bixilon.minosoft.gui.rendering.entities.visibility.VisibilityManager
|
||||||
import de.bixilon.minosoft.gui.rendering.renderer.renderer.AsyncRenderer
|
import de.bixilon.minosoft.gui.rendering.renderer.renderer.AsyncRenderer
|
||||||
import de.bixilon.minosoft.gui.rendering.renderer.renderer.RendererBuilder
|
import de.bixilon.minosoft.gui.rendering.renderer.renderer.RendererBuilder
|
||||||
import de.bixilon.minosoft.gui.rendering.renderer.renderer.world.LayerSettings
|
import de.bixilon.minosoft.gui.rendering.renderer.renderer.world.LayerSettings
|
||||||
import de.bixilon.minosoft.gui.rendering.renderer.renderer.world.WorldRenderer
|
import de.bixilon.minosoft.gui.rendering.renderer.renderer.world.WorldRenderer
|
||||||
import de.bixilon.minosoft.gui.rendering.system.base.RenderSystem
|
import de.bixilon.minosoft.gui.rendering.system.base.RenderSystem
|
||||||
import de.bixilon.minosoft.gui.rendering.system.base.layer.RenderLayer
|
|
||||||
import de.bixilon.minosoft.gui.rendering.system.base.layer.TranslucentLayer
|
|
||||||
import de.bixilon.minosoft.gui.rendering.system.base.settings.RenderSettings
|
|
||||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||||
|
|
||||||
class EntitiesRenderer(
|
class EntitiesRenderer(
|
||||||
@ -47,7 +46,8 @@ class EntitiesRenderer(
|
|||||||
private var reset = false
|
private var reset = false
|
||||||
|
|
||||||
override fun registerLayers() {
|
override fun registerLayers() {
|
||||||
layers.register(EntityLayer, null, this::draw) { visibility.size <= 0 }
|
layers.register(EntityLayer.OpaqueEntityLayer, null, { visibility.opaque.draw() }) { visibility.opaque.size <= 0 }
|
||||||
|
layers.register(EntityLayer.TranslucentEntityLayer, null, { visibility.translucent.draw() }) { visibility.opaque.size <= 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun prePrepareDraw() {
|
override fun prePrepareDraw() {
|
||||||
@ -83,18 +83,12 @@ class EntitiesRenderer(
|
|||||||
features.postInit()
|
features.postInit()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun draw() {
|
private fun ArrayList<EntityRenderFeature>.draw() {
|
||||||
for (feature in visibility) {
|
for (feature in this) {
|
||||||
feature.draw()
|
feature.draw()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object EntityLayer : RenderLayer {
|
|
||||||
override val settings = RenderSettings(faceCulling = false)
|
|
||||||
override val priority: Int get() = TranslucentLayer.priority - 1
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
companion object : RendererBuilder<EntitiesRenderer> {
|
companion object : RendererBuilder<EntitiesRenderer> {
|
||||||
|
|
||||||
override fun build(connection: PlayConnection, context: RenderContext): EntitiesRenderer {
|
override fun build(connection: PlayConnection, context: RenderContext): EntitiesRenderer {
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
package de.bixilon.minosoft.gui.rendering.entities.feature
|
package de.bixilon.minosoft.gui.rendering.entities.feature
|
||||||
|
|
||||||
import de.bixilon.minosoft.gui.rendering.entities.renderer.EntityRenderer
|
import de.bixilon.minosoft.gui.rendering.entities.renderer.EntityRenderer
|
||||||
|
import de.bixilon.minosoft.gui.rendering.entities.visibility.EntityLayer
|
||||||
|
import de.bixilon.minosoft.gui.rendering.entities.visibility.VisibilityManager
|
||||||
|
|
||||||
abstract class EntityRenderFeature(val renderer: EntityRenderer<*>) : Comparable<EntityRenderFeature> {
|
abstract class EntityRenderFeature(val renderer: EntityRenderer<*>) : Comparable<EntityRenderFeature> {
|
||||||
open var enabled = true
|
open var enabled = true
|
||||||
@ -21,6 +23,8 @@ abstract class EntityRenderFeature(val renderer: EntityRenderer<*>) : Comparable
|
|||||||
open val priority: Int get() = 0
|
open val priority: Int get() = 0
|
||||||
val sort = this::class.java.hashCode()
|
val sort = this::class.java.hashCode()
|
||||||
|
|
||||||
|
open val layer: EntityLayer get() = EntityLayer.OpaqueEntityLayer
|
||||||
|
|
||||||
open fun updateVisibility(occluded: Boolean) {
|
open fun updateVisibility(occluded: Boolean) {
|
||||||
this.visible = !occluded
|
this.visible = !occluded
|
||||||
}
|
}
|
||||||
@ -32,7 +36,9 @@ abstract class EntityRenderFeature(val renderer: EntityRenderer<*>) : Comparable
|
|||||||
abstract fun draw()
|
abstract fun draw()
|
||||||
|
|
||||||
open fun compareByDistance(other: EntityRenderFeature): Int {
|
open fun compareByDistance(other: EntityRenderFeature): Int {
|
||||||
return renderer.distance.compareTo(other.renderer.distance)
|
val compared = renderer.distance.compareTo(other.renderer.distance)
|
||||||
|
if (layer === EntityLayer.TranslucentEntityLayer) return -compared // translucent is sorted the exact other way
|
||||||
|
return compared
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun compareTo(other: EntityRenderFeature): Int {
|
override fun compareTo(other: EntityRenderFeature): Int {
|
||||||
@ -43,4 +49,8 @@ abstract class EntityRenderFeature(val renderer: EntityRenderer<*>) : Comparable
|
|||||||
|
|
||||||
return compareByDistance(other)
|
return compareByDistance(other)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open fun collect(visibility: VisibilityManager) {
|
||||||
|
visibility[layer] += this
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ import de.bixilon.minosoft.data.entities.EntityRotation
|
|||||||
import de.bixilon.minosoft.data.text.ChatComponent
|
import de.bixilon.minosoft.data.text.ChatComponent
|
||||||
import de.bixilon.minosoft.gui.rendering.entities.feature.EntityRenderFeature
|
import de.bixilon.minosoft.gui.rendering.entities.feature.EntityRenderFeature
|
||||||
import de.bixilon.minosoft.gui.rendering.entities.renderer.EntityRenderer
|
import de.bixilon.minosoft.gui.rendering.entities.renderer.EntityRenderer
|
||||||
|
import de.bixilon.minosoft.gui.rendering.entities.visibility.EntityLayer
|
||||||
import de.bixilon.minosoft.gui.rendering.font.renderer.component.ChatComponentRenderer
|
import de.bixilon.minosoft.gui.rendering.font.renderer.component.ChatComponentRenderer
|
||||||
import de.bixilon.minosoft.gui.rendering.font.renderer.element.CharSpacing
|
import de.bixilon.minosoft.gui.rendering.font.renderer.element.CharSpacing
|
||||||
import de.bixilon.minosoft.gui.rendering.font.renderer.element.TextRenderInfo
|
import de.bixilon.minosoft.gui.rendering.font.renderer.element.TextRenderInfo
|
||||||
@ -57,6 +58,8 @@ open class BillboardTextFeature(
|
|||||||
unload() // TODO: just update matrix
|
unload() // TODO: just update matrix
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override val layer get() = EntityLayer.TranslucentEntityLayer
|
||||||
|
|
||||||
override fun update(millis: Long, delta: Float) {
|
override fun update(millis: Long, delta: Float) {
|
||||||
if (!super.enabled) return unload()
|
if (!super.enabled) return unload()
|
||||||
if (!isInRenderDistance()) return unload()
|
if (!isInRenderDistance()) return unload()
|
||||||
@ -122,10 +125,6 @@ open class BillboardTextFeature(
|
|||||||
renderer.renderer.queue += { mesh.unload() }
|
renderer.renderer.queue += { mesh.unload() }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun compareByDistance(other: EntityRenderFeature): Int {
|
|
||||||
return -super.compareByDistance(other)
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val PROPERTIES = TextRenderProperties(allowNewLine = false, shadow = false, charSpacing = CharSpacing(top = 1.0f, bottom = 1.0f))
|
val PROPERTIES = TextRenderProperties(allowNewLine = false, shadow = false, charSpacing = CharSpacing(top = 1.0f, bottom = 1.0f))
|
||||||
val MAX_SIZE = Vec2(300.0f, PROPERTIES.lineHeight)
|
val MAX_SIZE = Vec2(300.0f, PROPERTIES.lineHeight)
|
||||||
|
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Minosoft
|
||||||
|
* Copyright (C) 2020-2023 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.gui.rendering.entities.visibility
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.gui.rendering.system.base.layer.OpaqueLayer
|
||||||
|
import de.bixilon.minosoft.gui.rendering.system.base.layer.RenderLayer
|
||||||
|
import de.bixilon.minosoft.gui.rendering.system.base.layer.TranslucentLayer
|
||||||
|
import de.bixilon.minosoft.gui.rendering.system.base.settings.RenderSettings
|
||||||
|
|
||||||
|
interface EntityLayer : RenderLayer {
|
||||||
|
|
||||||
|
object OpaqueEntityLayer : EntityLayer {
|
||||||
|
override val settings = RenderSettings(faceCulling = false)
|
||||||
|
override val priority: Int get() = OpaqueLayer.priority + 1 // entities are mostly more expensive to render, let the gpu clip all fragments first
|
||||||
|
}
|
||||||
|
|
||||||
|
object TranslucentEntityLayer : EntityLayer {
|
||||||
|
override val settings = RenderSettings(faceCulling = false)
|
||||||
|
override val priority: Int get() = TranslucentLayer.priority - 1 // otherwise not visible through water, etc
|
||||||
|
}
|
||||||
|
}
|
@ -21,13 +21,14 @@ import de.bixilon.minosoft.gui.rendering.events.VisibilityGraphChangeEvent
|
|||||||
import de.bixilon.minosoft.modding.event.listener.CallbackEventListener.Companion.listen
|
import de.bixilon.minosoft.modding.event.listener.CallbackEventListener.Companion.listen
|
||||||
import java.util.concurrent.atomic.AtomicInteger
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
|
|
||||||
class VisibilityManager(val renderer: EntitiesRenderer) : Iterable<EntityRenderFeature> {
|
class VisibilityManager(val renderer: EntitiesRenderer) {
|
||||||
private var update = false
|
private var update = false
|
||||||
var size: Int = 0
|
var size: Int = 0
|
||||||
private set
|
private set
|
||||||
|
|
||||||
private val count = AtomicInteger()
|
private val count = AtomicInteger()
|
||||||
private val visible: ArrayList<EntityRenderFeature> = ArrayList(1000)
|
val opaque: ArrayList<EntityRenderFeature> = ArrayList(1000)
|
||||||
|
val translucent: ArrayList<EntityRenderFeature> = ArrayList(1000)
|
||||||
private val lock = SimpleLock()
|
private val lock = SimpleLock()
|
||||||
private val graph = renderer.context.camera.visibilityGraph
|
private val graph = renderer.context.camera.visibilityGraph
|
||||||
private val frustum = renderer.context.camera.matrixHandler.frustum
|
private val frustum = renderer.context.camera.matrixHandler.frustum
|
||||||
@ -37,7 +38,8 @@ class VisibilityManager(val renderer: EntitiesRenderer) : Iterable<EntityRenderF
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun reset() {
|
fun reset() {
|
||||||
this.visible.clear()
|
opaque.clear()
|
||||||
|
translucent.clear()
|
||||||
count.set(0)
|
count.set(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,18 +61,22 @@ class VisibilityManager(val renderer: EntitiesRenderer) : Iterable<EntityRenderF
|
|||||||
lock.lock()
|
lock.lock()
|
||||||
for (feature in renderer.features) {
|
for (feature in renderer.features) {
|
||||||
if (!feature.enabled || !feature.visible) continue
|
if (!feature.enabled || !feature.visible) continue
|
||||||
this.visible += feature
|
feature.collect(this)
|
||||||
}
|
}
|
||||||
lock.unlock()
|
lock.unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun finish() {
|
fun finish() {
|
||||||
this.visible.sort() // TODO: Optimize it (pre create array, just work with array?)
|
// TODO: Optimize it (pre create array, just work with array?)
|
||||||
|
this.opaque.sort()
|
||||||
|
this.translucent.sort()
|
||||||
this.update = false
|
this.update = false
|
||||||
size = count.get()
|
size = count.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun iterator(): Iterator<EntityRenderFeature> {
|
operator fun get(layer: EntityLayer) = when (layer) {
|
||||||
return this.visible.iterator()
|
EntityLayer.OpaqueEntityLayer -> opaque
|
||||||
|
EntityLayer.TranslucentEntityLayer -> translucent
|
||||||
|
else -> throw IllegalStateException("Unknown entity layer: $layer")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user