The core renderer setup

Hi, Cathal here.

For the purposes of the project a very simple rendering system was in need. The solution I landed on was a hybrid game object and ECS render system, each object you attach to a Scene which stores a MultiArrayList of the fields in a Model -- A multi arraylist rather than storing an array of structs, stores multiple arrays of the given struct's fields, this reduces wasted padding memory from the former approach aswell as making iteration of single fields more cacheable as memory is not jumped as large an offset at each iteration.

To create a object in the scene you call the register function which crucially takes a path to the file of the model you want to load. This function just returns a 0 based index into the MultiArrayList of objects in the scene. After you register a model you can attach transformations to the model using the addTransform function which will take each matrix as a different instance of the model, this allows you to render multiple objects of the same model in different places while sharing the vertex and index buffer. This multiple object "instancing" is facilitated by the instanceCount parameter to vkCmdDrawIndexed:

c.vkCmdDrawIndexed(buffer, @intCast(self.scene.objects.items(.index_buffer)[oi].size / @sizeOf(u32)), @intCast(transforms.len), 0, 0, 0);

Then in the vertex shader we can access the model transform like so:

mat4 model = models_buffer.models[push.model_offset + gl_InstanceIndex];