From 5b0ed877b3b63321f458a3153f4c395440bf142b Mon Sep 17 00:00:00 2001 From: Emanuel Rabina Date: Sun, 4 Aug 2024 16:32:05 +1200 Subject: [PATCH] Apply an index to a mesh in a separate step --- .../ultraq/redhorizon/classic/maps/Map.groovy | 2 +- .../engine/graphics/Attribute.groovy | 11 +++-- .../engine/graphics/GraphicsRenderer.groovy | 4 +- .../engine/graphics/GraphicsRequests.groovy | 10 ++--- .../engine/graphics/GraphicsSystem.groovy | 2 +- .../redhorizon/engine/graphics/Mesh.groovy | 12 +++++- .../engine/graphics/opengl/OpenGLMesh.groovy | 41 ++++++++++--------- .../graphics/opengl/OpenGLRenderer.groovy | 15 ++++--- .../graphics/opengl/SpriteShader.groovy | 18 ++++---- .../engine/scenegraph/nodes/Primitive.groovy | 4 +- 10 files changed, 70 insertions(+), 49 deletions(-) diff --git a/redhorizon-classic/source/nz/net/ultraq/redhorizon/classic/maps/Map.groovy b/redhorizon-classic/source/nz/net/ultraq/redhorizon/classic/maps/Map.groovy index 6fa0bdcd..f399fee7 100644 --- a/redhorizon-classic/source/nz/net/ultraq/redhorizon/classic/maps/Map.groovy +++ b/redhorizon-classic/source/nz/net/ultraq/redhorizon/classic/maps/Map.groovy @@ -373,7 +373,7 @@ class Map extends Node { return scene .requestCreateOrGet(new MeshRequest(MeshType.TRIANGLES, new VertexBufferLayout(Attribute.POSITION, Attribute.COLOUR, Attribute.TEXTURE_UVS), - allVertices, Colour.WHITE, allTextureUVs, allIndices)) + allVertices, Colour.WHITE, allTextureUVs, false, allIndices)) .thenAcceptAsync { newMesh -> fullMesh = newMesh } diff --git a/redhorizon-engine/source/nz/net/ultraq/redhorizon/engine/graphics/Attribute.groovy b/redhorizon-engine/source/nz/net/ultraq/redhorizon/engine/graphics/Attribute.groovy index 55c95060..d8b09de9 100644 --- a/redhorizon-engine/source/nz/net/ultraq/redhorizon/engine/graphics/Attribute.groovy +++ b/redhorizon-engine/source/nz/net/ultraq/redhorizon/engine/graphics/Attribute.groovy @@ -29,9 +29,14 @@ import groovy.transform.TupleConstructor enum Attribute { // @formatter:off - POSITION ('position', 0, Vector2f.FLOATS), - COLOUR ('colour', 1, Colour.FLOATS), - TEXTURE_UVS ('textureUVs', 2, Vector2f.FLOATS) + POSITION ('position', 0, Vector2f.FLOATS), + COLOUR ('colour', 1, Colour.FLOATS), + + TEXTURE_UVS ('textureUVs', 2, Vector2f.FLOATS), + FRAME_STEP_X ('frameStepX', 3, 1), + FRAME_STEP_Y ('frameStepY', 4, 1), + FRAMES_HORIZONTAL ('framesHorizontal', 5, 1), + FRAMES_VERTICAL ('framesVertical', 6, 1) // @formatter:on final String name diff --git a/redhorizon-engine/source/nz/net/ultraq/redhorizon/engine/graphics/GraphicsRenderer.groovy b/redhorizon-engine/source/nz/net/ultraq/redhorizon/engine/graphics/GraphicsRenderer.groovy index a92c16d1..7c483a2e 100644 --- a/redhorizon-engine/source/nz/net/ultraq/redhorizon/engine/graphics/GraphicsRenderer.groovy +++ b/redhorizon-engine/source/nz/net/ultraq/redhorizon/engine/graphics/GraphicsRenderer.groovy @@ -59,14 +59,14 @@ interface GraphicsRenderer extends AutoCloseable, EventTarget { */ default Mesh createMesh(MeshType type, VertexBufferLayout layout, Vector2f[] vertices, Colour colour) { - return createMesh(type, layout, vertices, colour, null, null, false) + return createMesh(type, layout, vertices, colour, null, false, null) } /** * Create a mesh with all of the mesh parts. */ Mesh createMesh(MeshType type, VertexBufferLayout layout, Vector2f[] vertices, Colour colour, Vector2f[] textureUVs, - int[] indices, boolean dynamic) + boolean dynamic, int[] index) /** * Create a new shader program from the given configuration, or return the diff --git a/redhorizon-engine/source/nz/net/ultraq/redhorizon/engine/graphics/GraphicsRequests.groovy b/redhorizon-engine/source/nz/net/ultraq/redhorizon/engine/graphics/GraphicsRequests.groovy index 1c805a49..3200af2b 100644 --- a/redhorizon-engine/source/nz/net/ultraq/redhorizon/engine/graphics/GraphicsRequests.groovy +++ b/redhorizon-engine/source/nz/net/ultraq/redhorizon/engine/graphics/GraphicsRequests.groovy @@ -41,14 +41,14 @@ interface GraphicsRequests { @ImmutableOptions(knownImmutables = ['layout', 'colour']) static record MeshRequest(MeshType type, VertexBufferLayout layout, Vector2f[] vertices, Colour colour, - Vector2f[] textureUVs, int[] indices, boolean dynamic = false) implements Request { + Vector2f[] textureUVs, boolean dynamic, int[] index) implements Request { - MeshRequest(MeshType type, VertexBufferLayout layout, Vector2f[] vertices, Colour colour, int[] indices, boolean dynamic = false) { - this(type, layout, vertices, colour, null, indices, dynamic) + MeshRequest(MeshType type, VertexBufferLayout layout, Vector2f[] vertices, Colour colour, boolean dynamic, int[] index) { + this(type, layout, vertices, colour, null, dynamic, index) } - MeshRequest(MeshType type, VertexBufferLayout layout, Vector2f[] vertices, Colour colour, boolean dynamic = false) { - this(type, layout, vertices, colour, null, null, dynamic) + MeshRequest(MeshType type, VertexBufferLayout layout, Vector2f[] vertices, Colour colour, boolean dynamic) { + this(type, layout, vertices, colour, null, dynamic, null) } } diff --git a/redhorizon-engine/source/nz/net/ultraq/redhorizon/engine/graphics/GraphicsSystem.groovy b/redhorizon-engine/source/nz/net/ultraq/redhorizon/engine/graphics/GraphicsSystem.groovy index 8fc0fdfc..07d9219d 100644 --- a/redhorizon-engine/source/nz/net/ultraq/redhorizon/engine/graphics/GraphicsSystem.groovy +++ b/redhorizon-engine/source/nz/net/ultraq/redhorizon/engine/graphics/GraphicsSystem.groovy @@ -131,7 +131,7 @@ class GraphicsSystem extends EngineSystem implements GraphicsRequests { var resource = switch (request) { case ShaderRequest -> renderer.createShader(request.shaderConfig()) case MeshRequest -> renderer.createMesh(request.type(), request.layout(), request.vertices(), request.colour(), - request.textureUVs(), request.indices(), request.dynamic()) + request.textureUVs(), request.dynamic(), request.index()) case SpriteMeshRequest -> renderer.createSpriteMesh(request.surface(), request.textureUVs()) case TextureRequest -> renderer.createTexture(request.width(), request.height(), request.format(), request.data()) case SpriteSheetRequest -> renderer.createSpriteSheet(request.width(), request.height(), request.format(), request.data()) diff --git a/redhorizon-engine/source/nz/net/ultraq/redhorizon/engine/graphics/Mesh.groovy b/redhorizon-engine/source/nz/net/ultraq/redhorizon/engine/graphics/Mesh.groovy index 97ec83bd..46598e08 100644 --- a/redhorizon-engine/source/nz/net/ultraq/redhorizon/engine/graphics/Mesh.groovy +++ b/redhorizon-engine/source/nz/net/ultraq/redhorizon/engine/graphics/Mesh.groovy @@ -34,14 +34,24 @@ abstract class Mesh implements GraphicsResource { final Vector2f[] vertices final Colour colour final Vector2f[] textureUVs - final int[] indices final boolean dynamic + /** + * Add an index component to this mesh. This will then be used for rendering + * the mesh. + */ + abstract Mesh addIndex(int[] index) + /** * Use this mesh in upcoming render operations. */ abstract void bind() + /** + * The index associated with this mesh, if any. + */ + abstract int[] getIndex() + /** * Update the vertices part of the mesh data. * diff --git a/redhorizon-engine/source/nz/net/ultraq/redhorizon/engine/graphics/opengl/OpenGLMesh.groovy b/redhorizon-engine/source/nz/net/ultraq/redhorizon/engine/graphics/opengl/OpenGLMesh.groovy index a087ac17..8834fff7 100644 --- a/redhorizon-engine/source/nz/net/ultraq/redhorizon/engine/graphics/opengl/OpenGLMesh.groovy +++ b/redhorizon-engine/source/nz/net/ultraq/redhorizon/engine/graphics/opengl/OpenGLMesh.groovy @@ -38,17 +38,17 @@ class OpenGLMesh extends Mesh { final int vertexArrayId final int vertexBufferId - final int elementBufferId + int elementBufferId private Vector2f[] lastVertices + private int[] index /** * Constructor, creates a new OpenGL mesh. */ - OpenGLMesh(int type, VertexBufferLayout layout, Vector2f[] vertices, Colour colour, Vector2f[] textureUVs, int[] indices, - boolean dynamic) { + OpenGLMesh(int type, VertexBufferLayout layout, Vector2f[] vertices, Colour colour, Vector2f[] textureUVs, boolean dynamic) { - super(type, layout, vertices, colour, textureUVs, indices, dynamic) + super(type, layout, vertices, colour, textureUVs, dynamic) vertexArrayId = glGenVertexArrays() glBindVertexArray(vertexArrayId) @@ -80,24 +80,21 @@ class OpenGLMesh extends Mesh { } } - // Buffer for all the index data, if applicable - if (indices) { - elementBufferId = glGenBuffers() - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBufferId) - stackPush().withCloseable { stack -> - var indexBuffer = stack.mallocInt(indices.size()) - .put(indices) - .flip() - glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexBuffer, GL_STATIC_DRAW) - } - } - else { - elementBufferId = 0 - } - lastVertices = vertices } + @Override + OpenGLMesh addIndex(int[] index) { + + elementBufferId = glGenBuffers() + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBufferId) + stackPush().withCloseable { stack -> + glBufferData(GL_ELEMENT_ARRAY_BUFFER, stack.mallocInt(index.size()).put(index).flip(), GL_STATIC_DRAW) + } + this.index = index + return this + } + /** * A mesh is truthy/ready if its array data is valid. */ @@ -122,6 +119,12 @@ class OpenGLMesh extends Mesh { glDeleteVertexArrays(vertexArrayId) } + @Override + int[] getIndex() { + + return index + } + @Override void updateVertices(Vector2f[] vertices) { diff --git a/redhorizon-engine/source/nz/net/ultraq/redhorizon/engine/graphics/opengl/OpenGLRenderer.groovy b/redhorizon-engine/source/nz/net/ultraq/redhorizon/engine/graphics/opengl/OpenGLRenderer.groovy index 1745caf7..85e6769d 100644 --- a/redhorizon-engine/source/nz/net/ultraq/redhorizon/engine/graphics/opengl/OpenGLRenderer.groovy +++ b/redhorizon-engine/source/nz/net/ultraq/redhorizon/engine/graphics/opengl/OpenGLRenderer.groovy @@ -203,10 +203,13 @@ class OpenGLRenderer implements GraphicsRenderer { @Override Mesh createMesh(MeshType type, VertexBufferLayout layout, Vector2f[] vertices, Colour colour, Vector2f[] textureUVs, - int[] indices, boolean dynamic) { + boolean dynamic, int[] index) { var mesh = new OpenGLMesh(type == MeshType.LINES ? GL_LINES : type == MeshType.LINE_LOOP ? GL_LINE_LOOP : GL_TRIANGLES, - layout, vertices, colour, textureUVs, indices, dynamic) + layout, vertices, colour, textureUVs, dynamic) + if (index) { + mesh.addIndex(index) + } trigger(new MeshCreatedEvent(mesh)) return mesh } @@ -240,8 +243,8 @@ class OpenGLRenderer implements GraphicsRenderer { surface as Vector2f[], Colour.WHITE, textureUVs as Vector2f[], - [0, 1, 2, 0, 2, 3] as int[], - false + false, + [0, 1, 2, 0, 2, 3] as int[] ) } @@ -325,8 +328,8 @@ class OpenGLRenderer implements GraphicsRenderer { shader.use() shader.applyUniforms(transform, material, window) mesh.bind() - if (mesh.indices) { - glDrawElements(mesh.vertexType, mesh.indices.size(), GL_UNSIGNED_INT, 0) + if (mesh.index) { + glDrawElements(mesh.vertexType, mesh.index.size(), GL_UNSIGNED_INT, 0) } else { glDrawArrays(mesh.vertexType, 0, mesh.vertices.size()) diff --git a/redhorizon-engine/source/nz/net/ultraq/redhorizon/engine/graphics/opengl/SpriteShader.groovy b/redhorizon-engine/source/nz/net/ultraq/redhorizon/engine/graphics/opengl/SpriteShader.groovy index ee655df3..d0fa5372 100644 --- a/redhorizon-engine/source/nz/net/ultraq/redhorizon/engine/graphics/opengl/SpriteShader.groovy +++ b/redhorizon-engine/source/nz/net/ultraq/redhorizon/engine/graphics/opengl/SpriteShader.groovy @@ -38,15 +38,15 @@ class SpriteShader extends ShaderConfig { shader.setUniformTexture('mainTexture', 0, material.texture) }, { Shader shader, SpriteMaterial material, window -> - if (material.spriteMetadataBuffer) { - material.spriteMetadataBuffer.bind() - } - else { - shader.setUniform('framesHorizontal', material.framesHorizontal) - shader.setUniform('framesVertical', material.framesVertical) - shader.setUniform('frameStepX', material.frameStepX) - shader.setUniform('frameStepY', material.frameStepY) - } +// if (material.spriteMetadataBuffer) { +// material.spriteMetadataBuffer.bind() +// } +// else { +// shader.setUniform('framesHorizontal', material.framesHorizontal) +// shader.setUniform('framesVertical', material.framesVertical) +// shader.setUniform('frameStepX', material.frameStepX) +// shader.setUniform('frameStepY', material.frameStepY) +// } shader.setUniform('frame', material.frame) } ] diff --git a/redhorizon-engine/source/nz/net/ultraq/redhorizon/engine/scenegraph/nodes/Primitive.groovy b/redhorizon-engine/source/nz/net/ultraq/redhorizon/engine/scenegraph/nodes/Primitive.groovy index 96d440a6..6a0b914d 100644 --- a/redhorizon-engine/source/nz/net/ultraq/redhorizon/engine/scenegraph/nodes/Primitive.groovy +++ b/redhorizon-engine/source/nz/net/ultraq/redhorizon/engine/scenegraph/nodes/Primitive.groovy @@ -72,8 +72,8 @@ class Primitive extends Node implements GraphicsElement { return CompletableFuture.allOf( scene .requestCreateOrGet(type == MeshType.TRIANGLES ? - new MeshRequest(type, new VertexBufferLayout(Attribute.POSITION, Attribute.COLOUR), this.points, colour, - [0, 1, 3, 1, 2, 3] as int[], dynamic) : + new MeshRequest(type, new VertexBufferLayout(Attribute.POSITION, Attribute.COLOUR), this.points, colour, dynamic, + [0, 1, 3, 1, 2, 3] as int[]) : new MeshRequest(type, new VertexBufferLayout(Attribute.POSITION, Attribute.COLOUR), this.points, colour, dynamic)) .thenAcceptAsync { newMesh -> mesh = newMesh