diff --git a/src/main/kotlin/solve/rendering/canvas/OpenGLCanvas.kt b/src/main/kotlin/solve/rendering/canvas/OpenGLCanvas.kt index 2877ef7f..2d8ca139 100644 --- a/src/main/kotlin/solve/rendering/canvas/OpenGLCanvas.kt +++ b/src/main/kotlin/solve/rendering/canvas/OpenGLCanvas.kt @@ -46,10 +46,12 @@ import org.lwjgl.opengl.GL30.glDisableVertexAttribArray import org.lwjgl.opengl.GL30.glEnableVertexAttribArray import solve.constants.ShadersDefaultFragmentPath import solve.constants.ShadersDefaultVertexPath +import solve.project.model.ProjectFrame import solve.rendering.engine.Window import solve.rendering.engine.camera.Camera import solve.rendering.engine.components.SpriteRenderer import solve.rendering.engine.rendering.renderers.DefaultRenderer +import solve.rendering.engine.rendering.renderers.FramesRenderer import solve.rendering.engine.rendering.texture.Texture import solve.rendering.engine.scene.GameObject import solve.rendering.engine.scene.Scene @@ -57,6 +59,8 @@ import solve.rendering.engine.scene.Transform import solve.rendering.engine.shader.ShaderProgram import solve.rendering.engine.shader.ShaderType import solve.rendering.engine.structures.Color +import solve.utils.getResourceAbsolutePath +import java.nio.file.Path import kotlin.math.sin import com.huskerdev.openglfx.OpenGLCanvas as OpenGLFXCanvas @@ -72,9 +76,7 @@ class OpenGLCanvas { } private lateinit var window: Window - private lateinit var renderer: DefaultRenderer - private lateinit var gameObject: GameObject - private var gs = mutableListOf() + private lateinit var renderer: FramesRenderer var time = 0f @@ -91,7 +93,6 @@ class OpenGLCanvas { println(1/deltaTime) renderer.render() time += deltaTime - gameObject.transform.position.x = sin(time) * 100 /*shaderProgram.use() shaderProgram.uploadTexture("uTex", 0) @@ -170,44 +171,12 @@ class OpenGLCanvas { texture = Texture("icons/img.png")*/ - window = Window(1920, 600, Camera(Vector2f(), 1f)) - val scene = Scene(Camera()) - val texture1 = Texture("icons/img.png") - gameObject = GameObject( - "gameObject1", - Transform(Vector2f(), 0f, Vector2f(1000f, 1000f)), - listOf(SpriteRenderer(texture1)) - ) - - /*val gameObject2 = GameObject( - "gameObject2", - Transform(Vector2f(1f, 0f)), - listOf(SpriteRenderer(texture1).also { it.setColor(Color.black) }) - ) - val gameObject3 = GameObject( - "gameObject3", - Transform(Vector2f(300f, 300f)), - listOf(SpriteRenderer(texture1)) - )*/ - scene.addGameObject(gameObject) - //scene.addGameObject(gameObject2) - //scene.addGameObject(gameObject3) + window = Window(1920, 600, Camera(Vector2f(0f, 0f), 5f)) + val scene = Scene() window.changeScene(scene) - - renderer = DefaultRenderer(window) - renderer.addGameObject(gameObject) - //renderer.addGameObject(gameObject2) - //renderer.addGameObject(gameObject3) - - - for (i in -20 until 20) - for (j in -20 until 20) { - renderer.addGameObject( GameObject( - "gameObject1", - Transform(Vector2f(i * 10f, j * 10f), 0f, Vector2f(100f, 100f)), - listOf(SpriteRenderer(texture1)) - )) - } + val frames = List(100000) { ProjectFrame(0L, Path.of(getResourceAbsolutePath("icons/img.png")!!), emptyList()) } + renderer = FramesRenderer(window) + renderer.setSceneFrames(frames) } @Suppress("UNUSED_PARAMETER") 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 fdf53bdb..2b7b489a 100644 --- a/src/main/kotlin/solve/rendering/engine/rendering/batch/RenderBatch.kt +++ b/src/main/kotlin/solve/rendering/engine/rendering/batch/RenderBatch.kt @@ -3,6 +3,7 @@ package solve.rendering.engine.rendering.batch import org.joml.Vector2f import org.joml.Vector3f import org.joml.Vector4f +import org.lwjgl.BufferUtils 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 @@ -187,6 +188,10 @@ open class RenderBatch( pushFloat(value.toFloat()) } + fun pushNone() { + ++verticesDataBufferIndexPointer + } + companion object { private const val MaxTexturesNumber = 8 } diff --git a/src/main/kotlin/solve/rendering/engine/rendering/renderers/FramesRenderer.kt b/src/main/kotlin/solve/rendering/engine/rendering/renderers/FramesRenderer.kt index 3f646e9f..e3fc8b61 100644 --- a/src/main/kotlin/solve/rendering/engine/rendering/renderers/FramesRenderer.kt +++ b/src/main/kotlin/solve/rendering/engine/rendering/renderers/FramesRenderer.kt @@ -1,10 +1,13 @@ package solve.rendering.engine.rendering.renderers import org.joml.Matrix4f +import org.joml.Vector2f import org.joml.Vector2i +import org.lwjgl.opengl.GL11 import org.lwjgl.opengl.GL11.GL_UNSIGNED_BYTE import org.lwjgl.opengl.GL11.glBindTexture import org.lwjgl.opengl.GL11.glGenTextures +import org.lwjgl.opengl.GL13 import org.lwjgl.opengl.GL30.GL_TEXTURE_2D_ARRAY import org.lwjgl.opengl.GL45.glTextureStorage3D import org.lwjgl.opengl.GL45.glTextureSubImage3D @@ -44,12 +47,19 @@ class FramesRenderer( private var cameraLastGridCellPosition = Vector2i(0) + val texture = Texture("icons/img.png") + fun changeModelsCommonMatrix(newMatrix: Matrix4f) { modelsCommonMatrix = newMatrix } fun setSceneFrames(frames: List) { + if (frames.isEmpty()) + return + this.frames = frames + initializeTexturesBuffers(frames) + needToRebuffer = true } @@ -68,19 +78,24 @@ class FramesRenderer( shaderProgram.uploadMatrix4f(ModelUniformName, modelsCommonMatrix) shaderProgram.uploadInt(GridWidthUniformName, gridWidth) shaderProgram.uploadVector2i(BuffersSizeUniformName, buffersSize) + shaderProgram.uploadInt(TexturesArrayUniformName, buffersTexturesArrayID) } override fun createNewBatch(zIndex: Int) = - RenderBatch(maxBatchSize, zIndex, PrimitiveType.Point, listOf(ShaderAttributeType.FLOAT2)) + RenderBatch(maxBatchSize, zIndex, PrimitiveType.Point, listOf(ShaderAttributeType.FLOAT)) override fun updateBatchesData() { - frames.forEach { - // val + frames.forEachIndexed { index, _ -> + val batch = getAvailableBatch(null, 0) + //val frameGridCellPosition = Vector2f((1..5).random().toFloat(), (1..5).random().toFloat()) + batch.pushInt(index % 1000); } } override fun beforeRender() { + texture.bindToSlot(1) + val cameraGridCellPosition = getCameraGridCellPosition() if (cameraGridCellPosition != cameraLastGridCellPosition) { updateBuffersTextures(cameraGridCellPosition) @@ -106,7 +121,7 @@ class FramesRenderer( private fun getFramesAtRect(rect: IntRect): List> { val framesRect = mutableListOf>() for (y in rect.y0 until rect.y0 + rect.height) { - framesRect.add(frames.subList(rect.x0, rect.x0 + rect.width - 1)) + framesRect.add(frames.subList(rect.x0, rect.x0 + rect.width)) } return framesRect @@ -117,15 +132,13 @@ class FramesRenderer( return val buffersOffset = Vector2i(framesRect.x0 % buffersSize.x, framesRect.y0 % buffersSize.y) - val framesWidth = rectFrames.first().count() - val framesHeight = rectFrames.count() - if (framesWidth + buffersOffset.x > buffersSize.x || framesHeight + buffersOffset.y > buffersSize.y) { + if (framesRect.width + buffersOffset.x > buffersSize.x || framesRect.height + buffersOffset.y > buffersSize.y) { println("The size of the loading frames is out of buffers bounds!") return } - for (y in 0 until framesHeight) { - for (x in 0 until framesWidth) { + for (y in 0 until framesRect.height) { + for (x in 0 until framesRect.width) { val textureBuffersIndex = (y + buffersOffset.y) * buffersSize.x + x + buffersOffset.x uploadFrameToBuffer(rectFrames[y][x], textureBuffersIndex) } @@ -149,20 +162,16 @@ class FramesRenderer( } } - private fun initializeTexturesBuffers( - framesWidth: Int, - framesHeight: Int, - framesChannelsType: TextureChannelsType - ) { + private fun initializeTexturesBuffers(frames: List) { val firstTextureData = Texture.loadData(frames.first().imagePath.toString()) if (firstTextureData == null) { println("The read texture is null!") return } - this.framesWidth = framesWidth - this.framesHeight = framesHeight - this.framesChannelsType = framesChannelsType + framesWidth = firstTextureData.width + framesHeight = firstTextureData.height + framesChannelsType = firstTextureData.channelsType buffersTexturesArrayID = glGenTextures() glBindTexture(GL_TEXTURE_2D_ARRAY, buffersTexturesArrayID) @@ -196,6 +205,8 @@ class FramesRenderer( GL_UNSIGNED_BYTE, textureData.data ) + + Texture.freeData(textureData) } companion object { @@ -203,10 +214,10 @@ class FramesRenderer( private const val ModelUniformName = "uModel" private const val GridWidthUniformName = "uGridWidth" private const val BuffersSizeUniformName = "uBuffersSize" - private const val TexturesUniformName = "uTextures" + private const val TexturesArrayUniformName = "uTextures" - private const val DefaultGridWidth = 5 + private const val DefaultGridWidth = 50 private val defaultBuffersSize = Vector2i(10, 10) } -} \ No newline at end of file +} diff --git a/src/main/kotlin/solve/rendering/engine/rendering/texture/Texture.kt b/src/main/kotlin/solve/rendering/engine/rendering/texture/Texture.kt index 728e304c..b4da9da7 100644 --- a/src/main/kotlin/solve/rendering/engine/rendering/texture/Texture.kt +++ b/src/main/kotlin/solve/rendering/engine/rendering/texture/Texture.kt @@ -89,6 +89,8 @@ class Texture(private val resourcesPath: String) { GL_UNSIGNED_BYTE, textureData.data ) + + freeData(textureData) } override fun equals(other: Any?): Boolean { @@ -134,9 +136,12 @@ class Texture(private val resourcesPath: String) { println("Wrong type of the texture image channels!") return null } - stbi_image_free(data) return TextureData(data, width, height, imageChannelsType) } + + fun freeData(textureData: TextureData) { + stbi_image_free(textureData.data) + } } } diff --git a/src/main/kotlin/solve/rendering/engine/shader/ShaderAttributeType.kt b/src/main/kotlin/solve/rendering/engine/shader/ShaderAttributeType.kt index da2efc44..96a9a11c 100644 --- a/src/main/kotlin/solve/rendering/engine/shader/ShaderAttributeType.kt +++ b/src/main/kotlin/solve/rendering/engine/shader/ShaderAttributeType.kt @@ -1,5 +1,6 @@ package solve.rendering.engine.shader +import org.lwjgl.opengl.GL11.GL_BYTE import org.lwjgl.opengl.GL11.GL_FLOAT import org.lwjgl.opengl.GL11.GL_INT diff --git a/src/main/kotlin/solve/rendering/engine/utils/StructuresUtils.kt b/src/main/kotlin/solve/rendering/engine/utils/StructuresUtils.kt index 9ed45928..763921ac 100644 --- a/src/main/kotlin/solve/rendering/engine/utils/StructuresUtils.kt +++ b/src/main/kotlin/solve/rendering/engine/utils/StructuresUtils.kt @@ -26,12 +26,6 @@ operator fun Vector3f.times(value: Float): Vector3f = Vector3f(this).mul(value) operator fun Vector4f.times(value: Float): Vector4f = Vector4f(this).mul(value) -operator fun Vector2f.div(value: Float): Vector2f = this * (1 / value) - -operator fun Vector3f.div(value: Float): Vector3f = this * (1 / value) - -operator fun Vector4f.div(value: Float): Vector4f = this * (1 / value) - fun Vector2f.toIntVector(): Vector2i = Vector2i(x.toInt(), y.toInt()) fun Vector3f.toIntVector(): Vector3i = Vector3i(x.toInt(), y.toInt(), z.toInt()) diff --git a/src/main/resources/engine/shaders/frame/frame.frag b/src/main/resources/engine/shaders/frame/frame.frag index 04de9701..78ee304b 100644 --- a/src/main/resources/engine/shaders/frame/frame.frag +++ b/src/main/resources/engine/shaders/frame/frame.frag @@ -1,13 +1,12 @@ #version 330 core in vec2 fTexCoords; -in int fTexID; -uniform sampler2DArray uTextures; +uniform sampler2D uTextures[2]; out vec4 color; void main() { - color = texture(uTextures, vec3(fTexCoords, fTexID)); + color = texture(uTextures[1], fTexCoords); } diff --git a/src/main/resources/engine/shaders/frame/frame.geom b/src/main/resources/engine/shaders/frame/frame.geom index eb482dd9..7359c4f8 100644 --- a/src/main/resources/engine/shaders/frame/frame.geom +++ b/src/main/resources/engine/shaders/frame/frame.geom @@ -6,27 +6,24 @@ uniform int uGridWidth; uniform ivec2 uBuffersSize; in VS_OUT { - uint frameID; -} gs_in[0]; + int frameID; +} gs_in[]; out vec2 fTexCoords; -out int fTexID; layout (points) in; layout (triangle_strip, max_vertices = 4) out; void main() { - uint frameID = gs_in[0].frameID; + int frameID = gs_in[0].frameID; int frameX = frameID / uGridWidth; - int frameY = mod(frameID, uGridWidth); + int frameY = int(mod(frameID, uGridWidth)); - int bufferX = mod(frameID, uBuffersSize.x); - int bufferY = mod(frameID, uBuffersSize.y); - - fTexID = bufferY * uBuffersSize.x + bufferX; + int bufferX = int(mod(frameID, uBuffersSize.x)); + int bufferY = int(mod(frameID, uBuffersSize.y)); gl_Position = uProjection * uModel * gl_in[0].gl_Position; - fTexCoords = vec2(-1.0, 1.0); + fTexCoords = vec2(0.0, 1.0); EmitVertex(); gl_Position = uProjection * uModel * (gl_in[0].gl_Position + vec4(1.0, 0.0, 0.0, 0.0)); @@ -34,11 +31,11 @@ void main() { EmitVertex(); gl_Position = uProjection * uModel * (gl_in[0].gl_Position + vec4(0.0, 1.0, 0.0, 0.0)); - fTexCoords = vec2(-1.0, -1.0); + fTexCoords = vec2(0.0, 0.0); EmitVertex(); gl_Position = uProjection * uModel * (gl_in[0].gl_Position + vec4(1.0, 1.0, 0.0, 0.0)); - fTexCoords = vec2(1.0, -1.0); + fTexCoords = vec2(1.0, 0.0); EmitVertex(); EndPrimitive(); diff --git a/src/main/resources/engine/shaders/frame/frame.vert b/src/main/resources/engine/shaders/frame/frame.vert index 4bb4fe46..f98b0dd4 100644 --- a/src/main/resources/engine/shaders/frame/frame.vert +++ b/src/main/resources/engine/shaders/frame/frame.vert @@ -1,18 +1,22 @@ #version 330 core -layout (location=0) in vec2 aGridPos; +layout (location=0) in float aIndex; uniform mat4 uProjection; uniform mat4 uModel; +uniform int uGridWidth; out VS_OUT { - uint frameID; + int frameID; } vs_out; void main() { int i = gl_VertexID; - gl_Position = uProjection * uModel * vec4(aGridPos, 1.0); + int index = int(aIndex); + int xPos = index % uGridWidth; + int yPos = index / uGridWidth; + gl_Position = vec4(xPos, yPos, 0.0, 1.0); vs_out.frameID = i; }