This user has been banned.
June 16, 2025
I integrated Jolt into the engine, I used C bindings for Jolt called joltc and borrowed a lot of my implementation from my previous engine, salamander. There was also a weird issue where a dynamic rigidbody with a rotation with the w component of 0 would crash the program if it collided with another body but I fixed it by setting the w to 1. I also added a new component called skRigidbody3D.
Line rendering. So, for the line rendering, I added an skLineObject much like the skRenderObject and added a new vector of them in the skRenderer struct. I made two new shaders for the line and thus a new graphics pipeline. I reused the descriptor set for render objects for the UBO which is pretty hacky since it still contains all the texture info which we don't need. I added line rendering so that when I add physics integration in the future, we will be able to display the colliders of rigidbodies.
Skeletal animations! I've added three new classes, skBone, skAnimation, skAnimator. I've also added a new storage buffer to the vertex shader for bone matrices so that vertices are correctly deformed by bones. The implementation is based off of the one from learnopengl.com.
I changed the lighting in the fragment shader from the phong shading model to PBR rendering with the Cook-Torrance BRDF following the tutorial from learnopengl.com. I initially wanted to add shadow mapping but I thought that would be too complicated and expensive, I also saw that Ultrakill didn't have any shadow mapping so that vindicated me a little. Also I reached 50+ hours!
Skyboxes! I added two new shaders for the skybox, and with new shaders, comes a new VkPipeline. There's a new skRenderObject in the skRenderer struct now called skybox
and it holds a model of a sphere or box which will be initialized with a texture and rendered, the view matrix for the render object is non relative to the camera meaning you can never get close to it.
Coloured lights. There was also a bug when I adjusted the radius, the intensity was getting adjusted in the shader, and this was because I was moving forward 16 bytes after memcpying the color (vec3) into the shader which is what I'm SUPPOSED to do because vec3s have a 16 byte alignment requirement, so I skipped 12 bytes instead and it worked correctly.
In the previous devlog, I added lights and support for multiple of them with a storage buffer, but the fragment shader didn't actually know how many lights there were in the scene so I have made another descriptor set and with comes another descriptor set layout, this one for global uniforms, it's a single struct called skGlobalUniformBufferObject, in which there is one integer called lightCount
. Also I fixed up the updating of the storage buffer maps since Vulkan has 16 byte alignment requirements for each vec3 and I made it so I would add 4 byte padding after each memcpy of each vec3 in the skLight struct.
Added some basic diffuse lighting in the fragment shader. I have made a VkDescriptorSetLayout purely for the storage buffer in which lights will be stored. There's also now a descriptor set (the trifecta of VkDescriptorSet, VkDeviceMemory, and void*) in the skRenderer class. I also made a small but very nice change to micah so that it doesn't regenerate a function in micah.h if it has an // IGNORE comment above it, allowing for you to manually edit the drawers, serializers and deserializers.
I got saving and loading working in the engine! I've made a Json API in C to get Json working and there are two new procedurally generated functions for each component, _Save and _Load, the first one returns a json object for its respective component, and the second one takes in a json object and loads its component with the values in the json object. There's also two new micah functions for saving and loading all components. There's also a new tray window in which you can save and load the scene. All the scene data is stored inside a 'scene.json' file in the working directory currently but I plan to have a scenes folder in the future.
Made the editor for the ECS. There's a .cpp file now called micah.cpp which procedurally generates functions for displaying the component in the ImGui editor for as many components it finds in the file which you feed it. There was a previous engine I made where I had to make serializer, deserializer and renderer functions for every single component which got exhausting pretty quickly, so I hope to mitigate that by generating those functions programatically. I've made sort of an extremely basic and specific reflection system for C. All the components are displayed in the inspector window, there are only two components I have at the minute, skTransform and skName. Having an skMeshRenderer and skSpriteRenderer would be conventional but I fear that looping through the scene and checking for meshes and sprites would be slower than having a vectory of contiguous memory in which render objects are stored.
Got ImGui integrated into the renderer, something weird was happening where the program kept crashing for no reason only in Release mode, I did something with the build configuration and it worked, but even after resetting the build configuration and deleting and rebuilding it, it also works, so no clue what was making it crash.
My next step is to add an editor, which would require reflection which I'm going to add into C with a parser that runs over all the files in the project and generates source files with info about components and generates serialization/deserialization/rendering code where I tell it to.
Added a camera. Now you can look around! There's a new viewTransform
matrix in the renderer class, and there's a new camera class, the camera class system runs every frame to handle input and change the camera's rotation and position accordingly, it then computes a view matrix based on the camera's values and sets the renderer's view transform as the that matrix. Also added a skECSState struct that gets passed to systems.
I made it so multiple objects can be rendered at the same time. I ditched the vector of uniform buffers and descriptor sets in the renderer struct and made a new structure called skRenderObject, which is very primitive and only has a vertex buffer, index buffer and a texture, in vulkan's format of course. There's an array of descriptors and uniforms as many times as there are frames in flight and these descriptors and uniforms are created as the object is added into the scene. I plan to add more high level rendering objects such as skMeshRenderer and skSpriteRenderer which build on top of skRenderObject.
Finally figured out how to use descriptors in Vulkan and made the scene 3D. There was a bug where I was treating pointers to pointers to void the same as pointers to void in the vector data structure but after fixing that up, and also setting the model matrix to identity BEFORE rotating it. But now we have a spinning square, nice.
A game engine in C utilizing the ECS paradigm for good performance. Sulkan uses the Vulkan graphics API for rendering. The engine has an editor in which entities are displayed in the hierarchy and their components are displayed in the inspector. The drawing, serialization, and deserialization of the components is handled automatically by a subproject called micah which generates these functions accordingly with the struct definitions, so you don't need to manually render the components in the GUI or manually save and load them.
Finished the project. It was pretty simple actually. This is a template parser for C that takes templated functions and structs, comments them out and generates them as many times as there are unique instantiations and replaces the template types with the types that we instantiated them with.
Added custom pane rendering from lua, you can make a lua function called DisplayPane and it will get called instead of the DisplayPane from C++ if it is found inside the lua code.
Also added syntax highlighting, this is all done in lua inside the syntax.lua file which gets read by Slote.
Added lua integration. You can now make a lua file and the editor will interpret it. There's a start function within the lua code where it only gets executed once, and a display function which gets executed each frame after the status and panes rendering. I also made a lua API for ncurses.
Made the start screen on the same interface as the panes and status bar. Previously, it was its own little screen in which it was the only thing visible. I also fixed a bug where all panes would scroll simultaneously when you scrolled only of them, I fixed this by making viewport variables local to each pane. Also made the filename local to each pane so you get a different filename upon switching between panes.
The terminal multiplexing is finally here. I've switched from pure ANSI escape codes to ncurses because I just couldn't make multiple panes with ANSI escape codes alone, it just wasn't working for whatever reason. But with switching to ncurses, I've made programs that use ANSI escape codes break, because ncurses is stupid and doesn't know how to interpret escape codes. I'll have to build a vt100 terminal emulator, but hey! At least, we got multiple panes now!
Previously the pseudoconsole started in a separate window. But now it runs in the same window as the terminal. This may make it seem as if I've just made a program that runs cmd.exe but it's so much greater than that. This is a pseudoconsole you are looking at. Also I can make multiple of them in the same window, allowing me to make a terminal multiplexer... FOR WINDOWS! I've also got input and output working, all output from the pseudoconsole is printed into the main terminal and input is taken from the main terminal and passed through the pseudoconsole, previously I wasn't able to do this because the damn pipes weren't transferring anything. All hail ConPTY.
Finally added a pseudo console using the Windows ConPTY API. The pseudo console currently starts in a separate window which I don't want, I'll change it to be in the main window in the next devlog. The reason I'm using virtual terminals is because I'm using ncurses for the terminal UI in the main window so output of external commands isn't going to mesh well with ncurses. Also it gives me the potential option of making multiple pseudoconsoles which would make the project a terminal multiplexer. UNIX PTYs will have to wait though, that's a whole other can of worms.
This was widely regarded as a great move by everyone.