From 53582d2a90fb72e02056612163239b3b3f62eb4a Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Sat, 11 Feb 2023 17:25:26 -0800 Subject: Add support for 8-bit vertex indices. --- gfx/include/gfx/render_backend.h | 19 +++++++++++------- gfx/src/render/geometry.c | 43 +++++++++++++++++++++++++++++----------- gfx/src/render/geometry.h | 3 ++- gfx/src/util/scene.c | 33 ++++++++++++++++++++++++------ 4 files changed, 72 insertions(+), 26 deletions(-) diff --git a/gfx/include/gfx/render_backend.h b/gfx/include/gfx/render_backend.h index e037f78..785c4b9 100644 --- a/gfx/include/gfx/render_backend.h +++ b/gfx/include/gfx/render_backend.h @@ -27,7 +27,8 @@ typedef struct RenderBackend RenderBackend; /// Data type for vertex indices. /// Might need U32 for bigger models. -typedef uint16_t VertexIndex; +typedef uint8_t VertexIndex8; +typedef uint16_t VertexIndex16; typedef uint16_t VertexCount; /// Geometry drawing modes. @@ -69,8 +70,11 @@ MAKE_BUFFER_VIEW(BufferViewU8, uint8_t) /// A buffer view for 16-bit unsigned integers. MAKE_BUFFER_VIEW(BufferViewU16, uint16_t) -/// A buffer view for vertex indices. -MAKE_BUFFER_VIEW(BufferViewIdx, uint16_t) +/// A buffer view for 8-bit vertex indices. +MAKE_BUFFER_VIEW(BufferViewIdx8, uint16_t) + +/// A buffer view for 16-bit vertex indices. +MAKE_BUFFER_VIEW(BufferViewIdx16, uint16_t) /// Describes a piece of geometry. /// @@ -91,10 +95,11 @@ typedef struct GeometryDesc { BufferViewU8 u8; BufferViewU16 u16; } weights; // vec4 or uvec4. - BufferViewIdx indices; - VertexCount num_verts; - size_t num_indices; - PrimitiveType type; + BufferViewIdx8 indices8; + BufferViewIdx16 indices16; + VertexCount num_verts; + size_t num_indices; + PrimitiveType type; } GeometryDesc; /// Shader compiler define. diff --git a/gfx/src/render/geometry.c b/gfx/src/render/geometry.c index 0df6efb..7f3fc46 100644 --- a/gfx/src/render/geometry.c +++ b/gfx/src/render/geometry.c @@ -83,10 +83,9 @@ bool gfx_init_geometry( view_is_populated(desc->positions2d)); assert(desc->num_verts > 0); - geometry->mode = primitive_type_to_gl(desc->type); - geometry->num_verts = desc->num_verts; - geometry->num_indices = desc->num_indices; - geometry->indices_offset_bytes = desc->indices.offset_bytes; + geometry->mode = primitive_type_to_gl(desc->type); + geometry->num_verts = desc->num_verts; + geometry->num_indices = desc->num_indices; glGenVertexArrays(1, &geometry->vao); glBindVertexArray(geometry->vao); @@ -174,16 +173,31 @@ bool gfx_init_geometry( glBindBuffer(GL_ARRAY_BUFFER, 0); - if (view_is_populated(desc->indices)) { + if (view_is_populated(desc->indices8)) { assert(desc->num_indices > 0); - assert(desc->num_indices <= desc->indices.size_bytes / sizeof(VertexIndex)); - geometry->indices = - get_or_make_buffer(render_backend, (const BufferView*)&desc->indices); - if (!geometry->indices) { + assert( + desc->num_indices <= desc->indices8.size_bytes / sizeof(VertexIndex8)); + geometry->indices_offset_bytes = desc->indices8.offset_bytes; + geometry->indices8 = + get_or_make_buffer(render_backend, (const BufferView*)&desc->indices8); + if (!geometry->indices8) { + gfx_del_geometry(geometry); + return false; + } + assert(desc->indices8.size_bytes <= geometry->indices8->size_bytes); + } else if (view_is_populated(desc->indices16)) { + assert(desc->num_indices > 0); + assert( + desc->num_indices <= + desc->indices16.size_bytes / sizeof(VertexIndex16)); + geometry->indices_offset_bytes = desc->indices16.offset_bytes; + geometry->indices16 = + get_or_make_buffer(render_backend, (const BufferView*)&desc->indices16); + if (!geometry->indices16) { gfx_del_geometry(geometry); return false; } - assert(desc->indices.size_bytes <= geometry->indices->size_bytes); + assert(desc->indices16.size_bytes <= geometry->indices16->size_bytes); } glBindVertexArray(0); @@ -203,8 +217,13 @@ void gfx_render_geometry(const Geometry* geometry) { assert(geometry); assert(geometry->vao); glBindVertexArray(geometry->vao); - if (geometry->indices) { - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, geometry->indices->vbo); + if (geometry->indices8) { + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, geometry->indices8->vbo); + glDrawElements( + geometry->mode, geometry->num_indices, GL_UNSIGNED_BYTE, + (const void*)geometry->indices_offset_bytes); + } else if (geometry->indices16) { + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, geometry->indices16->vbo); glDrawElements( geometry->mode, geometry->num_indices, GL_UNSIGNED_SHORT, (const void*)geometry->indices_offset_bytes); diff --git a/gfx/src/render/geometry.h b/gfx/src/render/geometry.h index 38e716b..fb8f923 100644 --- a/gfx/src/render/geometry.h +++ b/gfx/src/render/geometry.h @@ -27,7 +27,8 @@ typedef struct Geometry { const Buffer* texcoords; const Buffer* joints; const Buffer* weights; - const Buffer* indices; + const Buffer* indices8; + const Buffer* indices16; } Geometry; /// Create new geometry. diff --git a/gfx/src/util/scene.c b/gfx/src/util/scene.c index 6f34922..40d6686 100644 --- a/gfx/src/util/scene.c +++ b/gfx/src/util/scene.c @@ -909,12 +909,33 @@ static bool load_meshes( const cgltf_buffer_view* view = prim->indices->buffer_view; const cgltf_size buffer_index = view->buffer - data->buffers; assert(buffer_index < data->buffers_count); - const Buffer* buffer = buffers[buffer_index]; - geometry_desc.indices.buffer = buffer; - geometry_desc.indices.offset_bytes = accessor->offset + view->offset; - geometry_desc.indices.size_bytes = view->size; - geometry_desc.indices.stride_bytes = view->stride; - geometry_desc.num_indices = prim->indices->count; + const Buffer* buffer = buffers[buffer_index]; + const cgltf_size component_size = + get_component_size(accessor->component_type); + switch (component_size) { + case 1: { + BufferViewIdx8* indices = &geometry_desc.indices8; + indices->buffer = buffer; + indices->offset_bytes = accessor->offset + view->offset; + indices->size_bytes = view->size; + indices->stride_bytes = view->stride; + geometry_desc.num_indices = prim->indices->count; + break; + } + case 2: { + BufferViewIdx16* indices = &geometry_desc.indices16; + indices->buffer = buffer; + indices->offset_bytes = accessor->offset + view->offset; + indices->size_bytes = view->size; + indices->stride_bytes = view->stride; + geometry_desc.num_indices = prim->indices->count; + break; + } + default: + // TODO: Handle 32-bit indices. + assert(false); + break; + } } // Vertex attributes. -- cgit v1.2.3