Blurp is a rendering framework abstracting away Opengl and DirectX12 at feature level.
It is modelled after modern rendering pipeline requirements, allowing easy setup of lights, shadows and instancing. It is written entirely in C++.
Description
Blurp has been my personal project for a few months. I've worked on it solo during the summer and holidays. The goal for this project was to familiarize myself with rendering concepts like shadow cascading, pbr rendering and general pipeline setup. It has taught me about abstraction possibilities for different graphics API's, but it has also shown me a lot of limitations and pitfalls. The source code can be found on Github. All materials and meshes have been taken from various places on the internet where they were available for free.
Github
Materials
Blurp uses the metallic-roughness material model to do physically based rendering. GLTF materials can be converted to a custom binary format that is compressed using multple compression algorithms for optimal file size and loading time. Material attributes can be dynamically enabled and disabled using bitmasks. This makes rendering vastly different materials very easy. Shaders are recompiled dynamically to suit the materials requirements.
GLTF meshes can be converted to a custom binary mesh format that has the bitmasks and interleaved buffers ready for directly loading to the GPU.
Pipeline
Pipelines can be set up easily using the blurp API. Render passes are appended to pipeline objects and then configured. Inputs and outputs can be set at runtime. Pipeline state can be configured on a draw-call basis, with instancing built in. Shadows and lights can be set on a per draw call basis as well. All this makes the API very flexible. For example: rendering to a texture is a matter of swapping out the output target in the render pass, and shadows can be generated for nearby geometry only.
In the image on the right, a GLTF scene can be seen with some depth sorting to allow for transparency in the windows. Two point lights cast shadows on nearby geometry using the geometry shader to render all sides of the cubemap at the same time. A skybox is present in the back.
Space Game
In the image, an example scene can be seen that I constructed from free GLTF meshes I found on the internet. The scene contains a skybox, spaceship and some planets rotating around each-other. Instance drawing is applied to the asteroid belt, with each asteroid having its own unique rotation. This runs entirely on the API agnostic Blurp API, running in 1080p at a steady 120FPS due to vsync.
Lessons Learned
I modelled the API after DirectX12 and around render passes. This makes it very easy to use and set up new project quickly. This usability comes at a price however, which stems from being API agnostic. In place updating on the GPU is difficult for example when alignment requirements are not always known. Having dynamically compiled shaders is great, but also limiting in unique situations that may present themselves when making a game where you can't make changes to the shaders manually. In the end my main takeaway is that being API agnostic sounds nice, but in practice it often means shooting yourself in the foot with performance and flexibility. That's why in the future, I will instead focus on using just a single graphics API and getting the most out of that before trying to be platform independent.