mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-18 20:05:02 -04:00
improve item rendering
This commit is contained in:
parent
442a06a6c9
commit
b88680e75d
@ -44,7 +44,7 @@ Minosoft is an open source minecraft client, written from scratch in kotlin (and
|
||||
### Features
|
||||
|
||||
- Blocks
|
||||
- Entities (hitboxes and players for now)
|
||||
- Entities
|
||||
- Block entities (e.g. signs, chests)
|
||||
- HUD and GUI (inventory, menus, ...)
|
||||
- Particles
|
||||
|
@ -23,6 +23,7 @@ import de.bixilon.minosoft.gui.rendering.gui.GUIRenderer
|
||||
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIMeshCache
|
||||
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer
|
||||
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexOptions
|
||||
import de.bixilon.minosoft.gui.rendering.models.raw.display.ModelDisplay
|
||||
import de.bixilon.minosoft.gui.rendering.models.util.CuboidUtil
|
||||
import de.bixilon.minosoft.gui.rendering.system.base.texture.shader.ShaderTexture
|
||||
import de.bixilon.minosoft.gui.rendering.util.mesh.MeshOrder
|
||||
@ -36,7 +37,7 @@ class BlockGUIConsumerTest {
|
||||
val gui = GUIRenderer::class.java.allocate()
|
||||
val consumer = GUIConsumer()
|
||||
|
||||
return BlockGUIConsumer(gui, Vec2(11, 12), consumer, null, Vec2(45))
|
||||
return BlockGUIConsumer(gui, Vec2(11, 12), consumer, null, ModelDisplay.DEFAULT, Vec2(45))
|
||||
}
|
||||
|
||||
private fun BlockGUIConsumer.assertVertices(vararg expected: Vec2) {
|
||||
|
@ -16,7 +16,6 @@ package de.bixilon.minosoft.gui.rendering
|
||||
import de.bixilon.minosoft.data.registries.identified.Namespaces.minosoft
|
||||
import de.bixilon.minosoft.data.text.formatting.color.RGBColor
|
||||
import de.bixilon.minosoft.data.text.formatting.color.RGBColor.Companion.asColor
|
||||
import de.bixilon.minosoft.util.KUtil
|
||||
|
||||
object RenderConstants {
|
||||
val EXPERIENCE_BAR_LEVEL_COLOR = "#80ff20".asColor()
|
||||
@ -47,7 +46,7 @@ object RenderConstants {
|
||||
|
||||
const val UV_ADD = 0.001f
|
||||
|
||||
const val DISABLE_GUI_CACHE = false
|
||||
const val DISABLE_GUI_CACHE = true
|
||||
|
||||
const val OPENGL_DEBUG_MODE = false
|
||||
const val DIRTY_BUFFER_UNBIND = true
|
||||
|
@ -310,7 +310,8 @@ class ChunkRenderer(
|
||||
|
||||
companion object : RendererBuilder<ChunkRenderer> {
|
||||
|
||||
override fun build(connection: PlayConnection, context: RenderContext): ChunkRenderer {
|
||||
override fun build(connection: PlayConnection, context: RenderContext): ChunkRenderer? {
|
||||
return null
|
||||
return ChunkRenderer(connection, context)
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* 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.feature.item
|
||||
|
||||
import de.bixilon.kotlinglm.mat4x4.Mat4
|
||||
import de.bixilon.minosoft.data.container.stack.ItemStack
|
||||
import de.bixilon.minosoft.gui.rendering.entities.feature.EntityRenderFeature
|
||||
import de.bixilon.minosoft.gui.rendering.entities.feature.block.BlockMesh
|
||||
import de.bixilon.minosoft.gui.rendering.entities.feature.block.BlockShader
|
||||
import de.bixilon.minosoft.gui.rendering.entities.renderer.EntityRenderer
|
||||
import de.bixilon.minosoft.gui.rendering.entities.visibility.EntityLayer
|
||||
import de.bixilon.minosoft.gui.rendering.models.item.ItemRenderUtil.getModel
|
||||
import de.bixilon.minosoft.gui.rendering.models.raw.display.DisplayPositions
|
||||
import de.bixilon.minosoft.gui.rendering.util.mat.mat4.Mat4Util.reset
|
||||
import de.bixilon.minosoft.gui.rendering.util.mat.mat4.Mat4Util.translateXAssign
|
||||
import de.bixilon.minosoft.gui.rendering.util.mat.mat4.Mat4Util.translateZAssign
|
||||
import de.bixilon.minosoft.gui.rendering.util.mesh.Mesh
|
||||
|
||||
open class ItemFeature(
|
||||
renderer: EntityRenderer<*>,
|
||||
stack: ItemStack?,
|
||||
val display: DisplayPositions,
|
||||
) : EntityRenderFeature(renderer) {
|
||||
private var mesh: BlockMesh? = null
|
||||
private var matrix = Mat4()
|
||||
override var enabled: Boolean
|
||||
get() = super.enabled && mesh != null
|
||||
set(value) {
|
||||
super.enabled = value
|
||||
}
|
||||
var stack: ItemStack? = stack
|
||||
set(value) {
|
||||
if (field == value) return
|
||||
field = value
|
||||
unload()
|
||||
}
|
||||
|
||||
// TODO: observe stack
|
||||
|
||||
override val layer get() = EntityLayer.Translucent // TODO
|
||||
|
||||
override fun update(millis: Long, delta: Float) {
|
||||
if (!super.enabled) return unload()
|
||||
if (this.mesh == null) {
|
||||
val stack = this.stack ?: return unload()
|
||||
createMesh(stack)
|
||||
}
|
||||
updateMatrix()
|
||||
}
|
||||
|
||||
private fun createMesh(stack: ItemStack) {
|
||||
val model = stack.item.item.getModel(renderer.renderer.connection) ?: return
|
||||
val mesh = BlockMesh(renderer.renderer.context)
|
||||
|
||||
val tint = renderer.renderer.context.tints.getItemTint(stack)
|
||||
|
||||
model.render(mesh, stack, tint)
|
||||
|
||||
this.mesh = mesh
|
||||
}
|
||||
|
||||
private fun updateMatrix() {
|
||||
this.matrix.reset()
|
||||
this.matrix
|
||||
.translateXAssign(-0.5f).translateZAssign(-0.5f)
|
||||
|
||||
// TODO: rotate?
|
||||
|
||||
this.matrix = renderer.matrix * matrix
|
||||
}
|
||||
|
||||
override fun draw() {
|
||||
val mesh = this.mesh ?: return
|
||||
if (mesh.state != Mesh.MeshStates.LOADED) mesh.load()
|
||||
renderer.renderer.context.system.reset(faceCulling = false)
|
||||
val shader = renderer.renderer.features.block.shader
|
||||
draw(mesh, shader)
|
||||
}
|
||||
|
||||
protected open fun draw(mesh: BlockMesh, shader: BlockShader) {
|
||||
shader.use()
|
||||
shader.matrix = matrix
|
||||
shader.tint = renderer.light.value
|
||||
mesh.draw()
|
||||
}
|
||||
|
||||
override fun unload() {
|
||||
val mesh = this.mesh ?: return
|
||||
this.mesh = null
|
||||
renderer.renderer.queue += { mesh.unload() }
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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.renderer.item
|
||||
|
||||
import de.bixilon.kutil.observer.DataObserver.Companion.observe
|
||||
import de.bixilon.minosoft.data.entities.entities.item.FallingBlockEntity
|
||||
import de.bixilon.minosoft.data.registries.identified.Identified
|
||||
import de.bixilon.minosoft.gui.rendering.entities.EntitiesRenderer
|
||||
import de.bixilon.minosoft.gui.rendering.entities.factory.RegisteredEntityModelFactory
|
||||
import de.bixilon.minosoft.gui.rendering.entities.feature.block.BlockFeature
|
||||
import de.bixilon.minosoft.gui.rendering.entities.renderer.EntityRenderer
|
||||
|
||||
class ItemEntityRenderer(renderer: EntitiesRenderer, entity: FallingBlockEntity) : EntityRenderer<FallingBlockEntity>(renderer, entity) {
|
||||
val block = BlockFeature(this, null).register()
|
||||
|
||||
init {
|
||||
entity::blockState.observe(this, true) { block.state = it }
|
||||
}
|
||||
|
||||
|
||||
companion object : RegisteredEntityModelFactory<FallingBlockEntity>, Identified {
|
||||
override val identifier get() = FallingBlockEntity.identifier
|
||||
|
||||
override fun create(renderer: EntitiesRenderer, entity: FallingBlockEntity) = ItemEntityRenderer(renderer, entity)
|
||||
}
|
||||
}
|
@ -97,6 +97,7 @@ class GUIRenderer(
|
||||
destinationRGB = BlendingFunctions.ONE_MINUS_SOURCE_ALPHA,
|
||||
sourceAlpha = BlendingFunctions.ONE,
|
||||
destinationAlpha = BlendingFunctions.ONE_MINUS_SOURCE_ALPHA,
|
||||
faceCulling = false,
|
||||
)
|
||||
shader.use()
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ class RawItemElement(
|
||||
val textureSize = size - 1
|
||||
|
||||
val item = stack.item.item
|
||||
val model = item.getModel(guiRenderer)
|
||||
val model = item.getModel(guiRenderer.connection)
|
||||
if (model != null) {
|
||||
val tints = context.tints.getItemTint(stack)
|
||||
model.render(guiRenderer, offset, consumer, options, textureSize, stack, tints)
|
||||
|
@ -62,7 +62,8 @@ class BakedModel(
|
||||
}
|
||||
|
||||
private fun render(mesh: BlockVertexConsumer, tints: IntArray?) {
|
||||
for (faces in faces) {
|
||||
for ((directionIndex, faces) in faces.withIndex()) {
|
||||
// if(directionIndex == Directions.O_NORTH || directionIndex == Directions.O_UP || directionIndex == Directions.O_EAST)
|
||||
for (face in faces) {
|
||||
face.render(mesh, tints)
|
||||
}
|
||||
|
@ -14,7 +14,6 @@
|
||||
package de.bixilon.minosoft.gui.rendering.models.block.state.render
|
||||
|
||||
import de.bixilon.kotlinglm.GLM
|
||||
import de.bixilon.kotlinglm.func.rad
|
||||
import de.bixilon.kotlinglm.vec2.Vec2
|
||||
import de.bixilon.kotlinglm.vec3.Vec3
|
||||
import de.bixilon.kotlinglm.vec4.Vec4
|
||||
@ -25,6 +24,7 @@ import de.bixilon.minosoft.gui.rendering.gui.GUIRenderer
|
||||
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer
|
||||
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexOptions
|
||||
import de.bixilon.minosoft.gui.rendering.models.block.element.FaceVertexData
|
||||
import de.bixilon.minosoft.gui.rendering.models.raw.display.ModelDisplay
|
||||
import de.bixilon.minosoft.gui.rendering.system.base.texture.shader.ShaderTexture
|
||||
|
||||
class BlockGUIConsumer(
|
||||
@ -32,6 +32,7 @@ class BlockGUIConsumer(
|
||||
val offset: Vec2,
|
||||
val consumer: GUIVertexConsumer,
|
||||
val options: GUIVertexOptions?,
|
||||
val display: ModelDisplay,
|
||||
val size: Vec2,
|
||||
) : BlockVertexConsumer {
|
||||
override val order = consumer.order
|
||||
@ -42,28 +43,32 @@ class BlockGUIConsumer(
|
||||
override fun addQuad(offset: FloatArray, positions: FaceVertexData, uvData: FaceVertexData, textureId: Float, lightTint: Float) = Broken("Not chunk rendering")
|
||||
|
||||
override fun addQuad(positions: FaceVertexData, uvData: FaceVertexData, textureId: Float, lightTint: Float) {
|
||||
val position = Vec3(0, 0, -1) // one block offset in north direction
|
||||
val front = Vec3(0, 0, 1) // and directly looking onto the south side
|
||||
// TODO: look from front (whatever that means) to the block in 45° angle from above
|
||||
val position = Vec3(1.6f, 1.65f, 0.5f)// one block offset in north direction
|
||||
// TODO: look from front
|
||||
val front = Vec3(-0.5f, -0.3f, 0.5f).normalizeAssign() // EntityRotation(45.0f, 45.0f).front
|
||||
val view = GLM.lookAt(position, position + front, CameraDefinition.CAMERA_UP_VEC3)
|
||||
val projection = GLM.perspective(45.0f.rad, size.x / size.y, CameraDefinition.NEAR_PLANE, CameraDefinition.FAR_PLANE)
|
||||
val size = size * 1.3f * 10.0f
|
||||
// val projection = GLM.perspective(105.0f.rad, size.x / size.y, CameraDefinition.NEAR_PLANE, 3.0f)
|
||||
|
||||
val viewProjection = view * projection
|
||||
val viewProjection = view //* projection
|
||||
|
||||
val tint = (lightTint.toBits() shl 8) or 0xFF
|
||||
|
||||
order.iterate { p, uv ->
|
||||
|
||||
gui.context.system.quadOrder.iterate { p, uv ->
|
||||
val vertexOffset = p * Vec3.length
|
||||
val uvOffset = uv * Vec2.length
|
||||
|
||||
val xyz = Vec4(positions[vertexOffset], positions[vertexOffset + 1], positions[vertexOffset + 2], 1.0f)
|
||||
|
||||
val a = viewProjection * xyz
|
||||
val out = viewProjection * xyz
|
||||
|
||||
var x = (a.x * 0.5f) + 0.5f
|
||||
var x = ((out.x * 0.5f))
|
||||
x = (x * size.x) + offset.x
|
||||
var y = (a.y * 0.5f) + 0.5f
|
||||
y = (y * size.y) + offset.y
|
||||
var y = ((out.y * 0.5f))
|
||||
y = (-y * size.y) + offset.y
|
||||
|
||||
// TODO: depth
|
||||
|
||||
consumer.addVertex(x, y, textureId, uvData[uvOffset], uvData[uvOffset + 1], tint, options)
|
||||
}
|
||||
|
@ -26,6 +26,8 @@ import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer
|
||||
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexOptions
|
||||
import de.bixilon.minosoft.gui.rendering.models.block.state.baked.cull.side.SideProperties
|
||||
import de.bixilon.minosoft.gui.rendering.models.item.ItemRender
|
||||
import de.bixilon.minosoft.gui.rendering.models.raw.display.DisplayPositions
|
||||
import de.bixilon.minosoft.gui.rendering.models.raw.display.ModelDisplay
|
||||
import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.Texture
|
||||
import java.util.*
|
||||
|
||||
@ -37,7 +39,7 @@ interface BlockRender : ItemRender {
|
||||
|
||||
|
||||
override fun render(gui: GUIRenderer, offset: Vec2, consumer: GUIVertexConsumer, options: GUIVertexOptions?, size: Vec2, stack: ItemStack, tints: IntArray?) {
|
||||
val consumer = BlockGUIConsumer(gui, offset, consumer, options, size)
|
||||
val consumer = BlockGUIConsumer(gui, offset, consumer, options, getDisplay(DisplayPositions.GUI) ?: ModelDisplay.DEFAULT, size)
|
||||
|
||||
render(consumer, stack, tints)
|
||||
}
|
||||
|
@ -14,14 +14,23 @@
|
||||
package de.bixilon.minosoft.gui.rendering.models.item
|
||||
|
||||
import de.bixilon.kotlinglm.vec2.Vec2
|
||||
import de.bixilon.kotlinglm.vec3.Vec3
|
||||
import de.bixilon.minosoft.data.container.stack.ItemStack
|
||||
import de.bixilon.minosoft.gui.rendering.chunk.mesh.BlockVertexConsumer
|
||||
import de.bixilon.minosoft.gui.rendering.gui.GUIRenderer
|
||||
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer
|
||||
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexOptions
|
||||
import de.bixilon.minosoft.gui.rendering.models.raw.display.DisplayPositions
|
||||
import de.bixilon.minosoft.gui.rendering.models.raw.display.ModelDisplay
|
||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.rad
|
||||
|
||||
interface ItemRender {
|
||||
|
||||
fun render(gui: GUIRenderer, offset: Vec2, consumer: GUIVertexConsumer, options: GUIVertexOptions?, size: Vec2, stack: ItemStack, tints: IntArray?)
|
||||
fun render(mesh: BlockVertexConsumer, stack: ItemStack, tints: IntArray?)
|
||||
|
||||
fun getDisplay(position: DisplayPositions): ModelDisplay? = when (position) { // TODO: remove hardcoded value
|
||||
DisplayPositions.GUI -> ModelDisplay(Vec3(30, 225, 0).rad, scale = Vec3(0.625f))
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
@ -14,13 +14,13 @@
|
||||
package de.bixilon.minosoft.gui.rendering.models.item
|
||||
|
||||
import de.bixilon.minosoft.data.registries.item.items.Item
|
||||
import de.bixilon.minosoft.gui.rendering.gui.GUIRenderer
|
||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||
|
||||
object ItemRenderUtil {
|
||||
|
||||
@Deprecated("please let this be the last fucking hack in this game") // TODO
|
||||
fun Item.getModel(gui: GUIRenderer): ItemRender? {
|
||||
val block = gui.connection.registries.block[identifier]
|
||||
fun Item.getModel(connection: PlayConnection): ItemRender? {
|
||||
val block = connection.registries.block[identifier]
|
||||
return block?.model ?: block?.states?.default?.model ?: model
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ enum class DisplayPositions(vararg names: String = arrayOf()) : AliasableEnum {
|
||||
HEAD,
|
||||
GROUND,
|
||||
FIXED,
|
||||
WORLD,
|
||||
;
|
||||
|
||||
override val names: Array<String> = names.unsafeCast()
|
||||
|
@ -15,21 +15,24 @@ package de.bixilon.minosoft.gui.rendering.models.raw.display
|
||||
|
||||
import de.bixilon.kotlinglm.vec3.Vec3
|
||||
import de.bixilon.kutil.json.JsonObject
|
||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.EMPTY_INSTANCE
|
||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.ONE
|
||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.rad
|
||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.toVec3
|
||||
|
||||
data class ModelDisplay(
|
||||
val rotation: Vec3?,
|
||||
val translation: Vec3?,
|
||||
val scale: Vec3?,
|
||||
val rotation: Vec3 = Vec3.EMPTY_INSTANCE,
|
||||
val translation: Vec3 = Vec3.EMPTY_INSTANCE,
|
||||
val scale: Vec3 = Vec3.ONE,
|
||||
) {
|
||||
companion object {
|
||||
val DEFAULT = ModelDisplay()
|
||||
|
||||
fun deserialize(data: JsonObject): ModelDisplay {
|
||||
return ModelDisplay(
|
||||
rotation = data["rotation"]?.toVec3()?.rad,
|
||||
translation = data["translation"]?.toVec3(),
|
||||
scale = data["scale"]?.toVec3(),
|
||||
rotation = data["rotation"]?.toVec3()?.rad ?: Vec3.EMPTY_INSTANCE,
|
||||
translation = data["translation"]?.toVec3() ?: Vec3.EMPTY_INSTANCE,
|
||||
scale = data["scale"]?.toVec3() ?: Vec3.ONE,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user