LevekGL — Learning How Rendering Works
Student project · 2021–2023 · 3 min read
I started LevekGL during my studies because I wanted to understand what was happening underneath the game engines I was using. Building a small rendering library felt like the most direct way to learn: isolate one problem, make it visible, then move to the next layer.

Starting with the rendering foundations
I began by wrapping the OpenGL objects needed to draw something on screen: vertex and index buffers, vertex arrays, textures, framebuffers and GLSL shaders.
The RenderingEngine brought the main services together. It created the GLFW window and input controllers, initialised the OpenGL context, and exposed the renderers and model loader. Each sample still owned its main loop, which kept experiments small and easy to change.
From a Blender asset to a rendered frame
The next step was to load content made outside the code. I integrated Assimp to read Blender exports and convert them into LevekGL models. A model stored meshes alongside their transforms, while each mesh contained positions, normals, UVs and indices.
Those values were uploaded to GPU buffers, combined with a shader and camera matrices, then submitted through the renderer. This same path supported experiments with cubemaps, framebuffers and shadow maps.
Three concrete milestones
1. Phong lighting
This experiment made the relationship between geometry, normals, diffuse light and specular highlights concrete.
2. Loading Blender scenes
Assimp turned the renderer into a small content pipeline capable of preserving meshes and transforms from a scene.
3. Rigid-body collisions
I also used the renderer as a base for a Bullet Physics experiment, connecting simulated rigid bodies to their visual transforms.
Looking back
I also started designing a more general system of rendering passes and states. That part remained experimental, but it pushed me to think beyond individual effects and about how a renderer should be organised as it grows.
LevekGL was never meant to compete with a complete engine. Its value was in the process: build a small example, understand the layer behind it, identify its limits, and use that knowledge to approach the next problem.
That project gave me a much clearer understanding of the path from an asset on disk to an interactive rendered scene, and it shaped the way I approach technical R&D today.