So I've been working on quite a lot of things lately; I decided to rebuild the engine with cleaner more organized code + add documentation. So instead of cleaning the existing code I decided to find an old backup of the original rendering engine, And go up from there. The advantage to that is that there won't be any surprise errors from old code so that saves us the time having to debug for hours trying to find the origin of these errors, The disadvantage, Of course is the fact that I have to rewrite the whole engine from scratch, Being me I tried to keep the copy-pasting to the minimum and instead try to write more efficient code. Which seems to have worked; Now that I rewrote the master rendering engine class, We now have two new class types [PostProcessingEffect, PreProcessingEffect], Users can now dynamically edit the rendering engine without having to rewrite the whole class, One can easily invoke the AddEffect() method to add a post processing effect or a pre processing effect. The user can now also choose between forward-shading and deferred-shading.
Now a lot of you might be familiar with post processing effects, But not pre processing effects, The class handles any rendering effects done before the post processing step, So rendering the objects to screen, Shadow step, Lighting step, etc.. The class name could have either been "RenderStep" or "PreProcessingEffect", The latter seemed to make more sense.
Rebuilding the engine also allowed me to fix my resource management and instancing engines.
Admittedly, The previous engine did have some issues with resource management, Mostly due to test code that was piled up over time, How it handles resources was with object pools if you're wondering.
The new engine now handles it in steps, And in addition to the instancing engine, It is now very efficient.
Previously instancing was optional (Because it was added so late to the engine), Now the instancing engine is embedded, And all gameobjects by default are now instanciable, Which means you can invoke the NewInstance() method to create a new instance of the object. And instance class is usually 117 bytes, While an object class with a single MeshRenderer is 4996 bytes. You can see how instances can be useful in this case, We can create one game object with a bunch of components, And let's say it's size will be around 15000 bytes.
You can see having 10 of the same object can be a waste of resources, Instead we use the instancing engine, We create 10 instance and let the instancing engine handle the rest. Instead of using up 150000 bytes we are only using 1170, This reduces our resource usage by 99.22%
An instance class holds the transform, and a pointer to it's parent object. This can be very useful when objects containing clustered static meshes are being used.
I've also reduced the class sizes significantly, Using the beautiful power of inheritance classes are now very straight forward, They only do what they are supposed to do and no more, But they are now also highly optimised for inheritance, So you can add functions and features without having to rewrite the original code. So there are no more wasted resources (looking at you texture class!)
Also added some neat post processing effects, Optimized some of the old ones (bloom does not oversaturate the final image thanks to colour correction!). And added gamma colour correction.
Now that the engine specific stuff is out of the way, I've also been working on a visual scripting language, Also using the same engine. Writing a language isn't that easy of course, The first one I've made was a text based language and I wrote a real-time interpreter, It works fine but it seems kind of complicated now, And the code is very disorganized. So I'm taking it slow this time.
Finally, Here's a gif demonstrating the lighting system, It has the same features as before (harshness, roughness, normal mapping, and displacement mapping). But the code has been optimized and cleaned up.
(You can see how the grooves get darker as the cube moves)