In this post I take a walk down memory lane and look at some of my old computer graphics projects, how they evolved as I’ve gotten more experience and my lessons learned for my latest iteration.
Humble beginnings Link to heading
I was always fascinated by computer graphics. My first, more ambitious, development adventures were in the realm of fluid simulation:
As libraries I was only relying on SDL+OpenGL, enhanced later by some image library to export screenshots of each frame as the simulation wasn’t running in real-time for larger particle counts.
Looking back at the code as a senior developer is quite fun. This code barely held together. There were many bugs in the math, graphics and memory-management code. Yet it somehow was able to simulate something vaguely resembling water.
yorld1 Link to heading
…or cubeit back then. I managed to iterate quite a lot on this over the next years making it a somewhat proper engine, with materials, mesh loading, a physics engine (bullet)
yorld2 Link to heading
Realizing some of the flaws and being annoyed by the cumbersome cmake library
setup (I didn’t know of features like glob
or even how to properly include external libraries…),
I decided that V2 of the engine, aka yorld2, would be written in … Java. Yes, I know.
To my defense: It was the “If Minecraft can do it, so can I” times. I even made a features
trailer for that engine:
But at some point I hit a dead end. In my professional life I was mostly working with C++ and learned a lot about the “flaws” my old code had and grew to love the flexibility of the language. I pretty well remember the one thing I could not stand in Java back then: Not having the ability to overload operators! I mean look at it:
public Vec3 add(Vec3 v){
return new Vec3(x+v.x,y+v.y,z+v.z);
}
//...
Vec3 a = {1,2,3};
Vec3 b = {3,2,1};
Vec3 res = a.add(b).sub(c);
Oh you don’t want to re-alloc new Vec3 objects all the time? Sure!
public void sAdd(Vec3 v){
x += v.x;
y += v.y;
z += v.z;
}
//...
a.sAdd(b);
If you work with it for a while, you actually got used to it. But coming from C++ this was quite painful. Sure, Java has its good reasons not to include that and sure, from time to time you can shoot yourself in the foot in C++ by overdoing it, but I think it makes math-heavy code much more readable.
The second thing that pushed me towards C++ or rather away from Java was the handling of buffers. In an OpenGL context, you have to deal with writing and reading buffers. A lot! The Java library that I used, lwjgl, but also Java due to the way it works, can’t let you easily write to buffers like you can in C++.
ArrayList<Vec3> vertices;
FloatBuffer vbuffer;
//...
for(Vec3 v:vertices){
vbuffer.put(v.x);
vbuffer.put(v.y);
vbuffer.put(v.z);
}
In C++ you can copy the memory directly with vector<vec3>.data() and .size(), matching the
containers used by the rest of the code.
This is not supposed to be a language bashing. There are other things I really liked in Java, like
not having to have a header and implementation file for basically everything (and many more).
yorld3 Link to heading
So I moved back to C++ for my next iteration of a graphics engine. Still based on OpenGL but this time using a bit more external dependencies for more out-of-the-box capabilities:
glm - OpenGL Mathematics, glew, glfw, bullet (again), stb for image loading/saving, gtest and a few special ones

This version was in some parts a direct port of yorld2 as that already contained some ambitious features like an octree for only rendering what’s in camera frustum or a very basic entity-component-system.
Like with the previous iterations I initially had an idea for a simulation or a game I wanted to bring to the screen with that engine. But with feature creep, exploring technical challenges like the heightmap generation you can see above, these ideas more and more got lost, forgotten or discarded.
For yorld3 there isn’t even a fancy video to look at. The most “advanced” thing you could do, was roll around a ball in a random heightmap, which was infinitely generated (as long as float coordinates would keep up), had collision and a PBR material. Did I mention feature creep?
yorld4 - arriving today Link to heading
One flaw all the previous engines had, was that I never cleanly separated game logic from actual engine code. Numerous times I had a small game idea that, if I knew how, would easily be implemented in a couple of evenings in something like Unity or Unreal Engine. But with “spoiled” engine code that was basically impossible without a bigger rewrite.
yorld3 was already close to leaving game-logic out of the core engine completely. Coming back to
the previous chapter. There always was an idea I wanted to realize with an engine. That idea was
what motivated the work on each engine. Keeping the engine focused on that single idea made implementing
certain components very easy. E.g. yorld2 wanted to become a factorio clone
with a strategy sidekick and wonky (non-grid-based) structures for even more delicate spaghetti.
For example: Camera control was directly built in the core engines Scene.java file - yes this file
was listening to keyboard events - insanity. But why put it somewhere else and forward all the calls
if all you want is a top down camera for quickly iterating on other features.
So why go to the next iteration of an engine - yorld4?
In retrospect, I’d say it’s because not only must game logic be kept out of engine code, but even its components need to be as independent as possible. Modularity for things like a physics system, the scene graph and most importantly: the graphics backend, is a must for flexibility.
All engines (1-3) were heavily focused on OpenGL. This meant e.g. that an image was not only an object handling loading and writing to file, it also handled uploading to GPU. I realized this issue when considering moving to Vulkan as a graphics backend. Initially I tried to replace parts of yorld3 to be able to do that but it quickly was becoming clear that this would be impossible without major rewrites.
In the next posts I want to document my journey with yorld4 - and I’m already looking forward to the day I find the next flaw with it… so far many parts of the previous engines have been moved over and have been made much more modular. Here is a glimpse of the current state in some debug rendering view.
