From 4f4ca701dbd289caf72a5091dee7e8d4f3c8aefe Mon Sep 17 00:00:00 2001 From: Stanislav Mishchenko Date: Sun, 22 Oct 2023 20:18:05 +0300 Subject: [PATCH] finish initial batch rendering logic --- .../engine/components/SpriteRenderer.kt | 3 ++ .../engine/rendering/batch/RenderBatch.kt | 43 +++++++++++++++++-- .../engine/rendering/renderers/Renderer.kt | 25 ++++++++++- .../rendering/renderers/SpriteRenderer.kt | 40 ++++++++++++++--- .../rendering/engine/scene/GameObject.kt | 2 +- .../solve/rendering/engine/scene/Transform.kt | 8 ++-- .../rendering/engine/utils/StructuresUtils.kt | 11 +++++ 7 files changed, 117 insertions(+), 15 deletions(-) create mode 100644 src/main/kotlin/solve/rendering/engine/utils/StructuresUtils.kt diff --git a/src/main/kotlin/solve/rendering/engine/components/SpriteRenderer.kt b/src/main/kotlin/solve/rendering/engine/components/SpriteRenderer.kt index 0a002ad1..af197e7e 100644 --- a/src/main/kotlin/solve/rendering/engine/components/SpriteRenderer.kt +++ b/src/main/kotlin/solve/rendering/engine/components/SpriteRenderer.kt @@ -10,6 +10,9 @@ class SpriteRenderer(gameObject: GameObject) : Component(gameObject) { var sprite: Sprite? = null private set + val texture: Texture? + get() = sprite?.texture + fun setColor(color: Color) { this.color = color } diff --git a/src/main/kotlin/solve/rendering/engine/rendering/batch/RenderBatch.kt b/src/main/kotlin/solve/rendering/engine/rendering/batch/RenderBatch.kt index d71d9721..6a7d0cbd 100644 --- a/src/main/kotlin/solve/rendering/engine/rendering/batch/RenderBatch.kt +++ b/src/main/kotlin/solve/rendering/engine/rendering/batch/RenderBatch.kt @@ -1,5 +1,9 @@ package solve.rendering.engine.rendering.batch +import org.joml.Matrix2f +import org.joml.Vector2f +import org.joml.Vector3f +import org.joml.Vector4f import org.lwjgl.opengl.GL15.GL_ARRAY_BUFFER import org.lwjgl.opengl.GL15.GL_DYNAMIC_DRAW import org.lwjgl.opengl.GL15.GL_ELEMENT_ARRAY_BUFFER @@ -16,6 +20,8 @@ import org.lwjgl.opengl.GL30.glDeleteVertexArrays import org.lwjgl.opengl.GL30.glGenVertexArrays import solve.rendering.engine.rendering.texture.Texture import solve.rendering.engine.shader.ShaderAttributeType +import solve.rendering.engine.utils.toList +import java.nio.ByteBuffer open class RenderBatch( private val maxBatchSize: Int, @@ -25,12 +31,13 @@ open class RenderBatch( ) { var isFull = false private set + var isTexturesFull = false + private set private var vboID = 0 private var vaoID = 0 private var eboID = 0 - private val textureIDs = mutableListOf() private val textures = mutableListOf() private val attributesNumber = attributes.sumOf { it.number } @@ -73,13 +80,15 @@ open class RenderBatch( textures.add(texture) textureID = textures.lastIndex + 1 - if (textures.count() >= maxBatchSize) - isFull = true + if (textures.count() >= MaxTexturesNumber) + isTexturesFull = true } return textureID } + fun getTextureLocalID(texture: Texture) = textures.indexOf(texture) + 1 + fun removeTexture(texture: Texture): Boolean = textures.remove(texture) fun containsTexture(texture: Texture) = textures.contains(texture) @@ -133,4 +142,32 @@ open class RenderBatch( return elementsBuffer } + + fun pushFloat(value: Float) { + verticesDataBuffer[verticesDataBufferIndexPointer++] = value + } + + fun pushVector2f(vector: Vector2f) { + vector.toList().forEach { pushFloat(it) } + } + + fun pushVector3f(vector: Vector3f) { + vector.toList().forEach { pushFloat(it) } + } + + fun pushVector4f(vector: Vector4f) { + vector.toList().forEach { pushFloat(it) } + } + + fun pushInt(value: Int) { + val byteArray = ByteBuffer.allocate(Int.SIZE_BYTES).putInt(value).array() + val buffer = ByteBuffer.wrap(byteArray) + val floatValue = buffer.float + + pushFloat(floatValue) + } + + companion object { + private const val MaxTexturesNumber = 8 + } } diff --git a/src/main/kotlin/solve/rendering/engine/rendering/renderers/Renderer.kt b/src/main/kotlin/solve/rendering/engine/rendering/renderers/Renderer.kt index 5a4b099e..de5aacaa 100644 --- a/src/main/kotlin/solve/rendering/engine/rendering/renderers/Renderer.kt +++ b/src/main/kotlin/solve/rendering/engine/rendering/renderers/Renderer.kt @@ -4,11 +4,14 @@ import org.lwjgl.opengl.GL11.GL_UNSIGNED_INT import org.lwjgl.opengl.GL11.glDrawElements import solve.rendering.engine.Window import solve.rendering.engine.rendering.batch.RenderBatch -import solve.rendering.engine.shader.ShaderProgram +import solve.rendering.engine.rendering.texture.Texture import solve.rendering.engine.scene.GameObject -import solve.rendering.engine.scene.Scene +import solve.rendering.engine.shader.ShaderProgram + abstract class Renderer(protected val window: Window) { + protected abstract val maxBatchSize: Int + protected var needToRebuffer = true private lateinit var shaderProgram: ShaderProgram private val batches = mutableListOf() @@ -39,6 +42,24 @@ abstract class Renderer(protected val window: Window) { batches.forEach { it.deleteBuffers() } } + protected fun getAvailableBatch(texture: Texture, requiredZIndex: Int): RenderBatch { + batches.forEach { batch -> + if (!batch.isFull && !batch.isTexturesFull && batch.zIndex == requiredZIndex) { + batch.addTexture(texture) + return batch + } + + if (batch.isTexturesFull && batch.containsTexture(texture) && batch.zIndex == requiredZIndex) + return batch + } + + val batch = createNewBatch(requiredZIndex) + batch.addTexture(texture) + batches.add(batch) + + return batch + } + protected open fun beforeRender() { } protected abstract fun createShaderProgram(): ShaderProgram diff --git a/src/main/kotlin/solve/rendering/engine/rendering/renderers/SpriteRenderer.kt b/src/main/kotlin/solve/rendering/engine/rendering/renderers/SpriteRenderer.kt index f063cbe3..e8b03660 100644 --- a/src/main/kotlin/solve/rendering/engine/rendering/renderers/SpriteRenderer.kt +++ b/src/main/kotlin/solve/rendering/engine/rendering/renderers/SpriteRenderer.kt @@ -1,6 +1,7 @@ package solve.rendering.engine.rendering.renderers import org.joml.Matrix4f +import org.joml.Vector2f import solve.constants.ShadersDefaultFragmentPath import solve.constants.ShadersDefaultVertexPath import solve.rendering.engine.Window @@ -12,7 +13,11 @@ import solve.rendering.engine.shader.ShaderProgram import solve.rendering.engine.shader.ShaderType import solve.rendering.engine.scene.GameObject -class SpriteRenderer(window: Window) : Renderer(window) { +class SpriteRenderer( + window: Window +) : Renderer(window) { + override val maxBatchSize = 1000 + private var modelsCommonMatrix: Matrix4f = Matrix4f().identity() private val spriteRenderers = mutableListOf() @@ -38,7 +43,7 @@ class SpriteRenderer(window: Window) : Renderer(window) { ) return RenderBatch( - MaxBatchSize, + maxBatchSize, zIndex, PrimitiveType.Quad, shaderAttributesTypes @@ -51,7 +56,27 @@ class SpriteRenderer(window: Window) : Renderer(window) { } override fun updateBatchesData() { - + spriteRenderers.forEach { spriteRenderer -> + val sprite = spriteRenderer.sprite ?: return@forEach + + val texture = sprite.texture + val batch = getAvailableBatch(texture, spriteRenderer.gameObject.transform.zIndex) + val textureID = batch.getTextureLocalID(texture) + val scale = spriteRenderer.gameObject.transform.scale + val position = spriteRenderer.gameObject.transform.position + val color = spriteRenderer.color + val uvCoordinates = sprite.uvCoordinates + + spriteLocalVerticesPositions.forEachIndexed { index, vertexPosition -> + val scaledX = vertexPosition.x * scale.x + val scaleY = vertexPosition.y * scale.y + + batch.pushVector2f(position) + batch.pushVector4f(color.toVector4f()) + batch.pushVector2f(uvCoordinates[index]) + batch.pushInt(textureID) + } + } } override fun addGameObject(gameObject: GameObject) { @@ -70,9 +95,14 @@ class SpriteRenderer(window: Window) : Renderer(window) { } companion object { - private const val MaxBatchSize = 1000 - private const val projectionUniformName = "uProjection" private const val modelUniformName = "uModel" + + private val spriteLocalVerticesPositions = listOf( + Vector2f(1f, 1f), + Vector2f(1f, 0f), + Vector2f(0f, 0f), + Vector2f(0f, 1f) + ) } } \ No newline at end of file diff --git a/src/main/kotlin/solve/rendering/engine/scene/GameObject.kt b/src/main/kotlin/solve/rendering/engine/scene/GameObject.kt index 6db4ba76..f8b56b44 100644 --- a/src/main/kotlin/solve/rendering/engine/scene/GameObject.kt +++ b/src/main/kotlin/solve/rendering/engine/scene/GameObject.kt @@ -4,7 +4,7 @@ import solve.rendering.engine.components.Component import kotlin.reflect.KClass class GameObject(private val name: String) { - private val transform = Transform() + val transform = Transform() private val _components = mutableListOf() val components: List get() = _components diff --git a/src/main/kotlin/solve/rendering/engine/scene/Transform.kt b/src/main/kotlin/solve/rendering/engine/scene/Transform.kt index 335a90ca..7e43f29c 100644 --- a/src/main/kotlin/solve/rendering/engine/scene/Transform.kt +++ b/src/main/kotlin/solve/rendering/engine/scene/Transform.kt @@ -3,8 +3,8 @@ package solve.rendering.engine.scene import org.joml.Vector2f data class Transform( - private val position: Vector2f = Vector2f(), - private val rotation: Float = 0f, - private val scale: Vector2f = Vector2f(), - private val zIndex: Float = 0f + val position: Vector2f = Vector2f(), + val rotation: Float = 0f, + val scale: Vector2f = Vector2f(), + val zIndex: Int = 0 ) diff --git a/src/main/kotlin/solve/rendering/engine/utils/StructuresUtils.kt b/src/main/kotlin/solve/rendering/engine/utils/StructuresUtils.kt new file mode 100644 index 00000000..f97de3e4 --- /dev/null +++ b/src/main/kotlin/solve/rendering/engine/utils/StructuresUtils.kt @@ -0,0 +1,11 @@ +package solve.rendering.engine.utils + +import org.joml.Vector2f +import org.joml.Vector3f +import org.joml.Vector4f + +fun Vector2f.toList() = listOf(x, y) + +fun Vector3f.toList() = listOf(x, y, z) + +fun Vector4f.toList() = listOf(x, y, z, w)