My plan for this first week was to create the project and implement the multi-threading system. However, this week has been productive. I started the week creating the solution. I am using genie for this. GENie is a project generator tool that allows you to easily create projects for multiple platforms and multiple IDEs. GENie is a fork of premake, premake follows the same philosophy as genie does; however, premake has not been updated for a long time; this is where genie becomes useful. GENie uses a configuration LUA script to deploy all the configuration files for the selected IDE and platform. I created my solution following this configuration: I have 3 different projects inside my solution:
- Orange Engine
- Orange Deps
- Orange Editor
Orange Engine is the main source code solution, there is where I am writing most of my code. All the big features and all the code related to the engine functionality is developed inside of this project. Orange Deps only contain the source code for all the dependencies the engine has, at this point, my big dependencies are GLFW for multi-platform window creation, GLM for all the mathematical operations inside of the engine and GLEW as OpenGL extension library. In a close future, I will introduce in this project more dependencies such as LUA as the principal scripting language and IMGUI as GUI interface. Finally, Orange Editor is a console application where all the PBR editor tool is going to be written. At this moment I am only using this solution as a module to test the functionality I have already started working on the engine.
I decided to start the engine by the multi-threading part because threading is a complex task and in order to implement it properly, it is important to orientate all the design of the engine to be based on threads. I based my design on the GDC talks of Destiny’s engine and Naughty Dog’s engine. Therefore, I have created a task manager using all the features that C++ introduce to work with threads. All the tasks are created using C++ lambdas or instancing default object tasks inside the task manager. The task manager is also instantiable. I decided to create the manager this way to easily create different task managers running at the same time into the engine (for example, one task manager for all the logic tasks and one manager with one thread resolving input/output tasks). The default task manager is inside the engine class. The engine exists in the solution as a singleton with most of the global functionality, the actual context of the engine and its main loop. All the tasks are dispatched into the engine and are completed as soon as the task manager can. One future feature I would like to introduce is a semaphore system to freeze the execution of a specific thread until its task is done. At this point, the task manager system is working and I have not noticed problems at this point in any of my tests.
As I finished quickly my week tasks I started to work on my next week objectives. For the second week, I was planning to create the render system. My idea was to develop the rendering system in a way that could provide easy integration of new graphics APIs. With this in mind, I have developed a display list based on renderer commands. I have taken as principal reference BGFX. BGFX is a graphical library that allows you to implement render applications that compile to different rendering back-ends without having to write different rendering code. The system is based on a pure virtual abstract class that declares all the methods that all the renderers have to implement, the renderers work with handlers to all the resources and all the data transference between ram and GPU memory is made with these handlers. The engine wraps these functions inside a display list system based on commands. The window thread is the only one that can consume this kind of commands and this way I have been able to integrate multi-threading for all the logical subsystems of the engine while the window is drawing the command generated by those threads.
At this point, the logical sub-systems are based in component design. Only the GameObjects of the engine can have these components and these components have their own state. Each subsystem has its own state to allow the engine to launch each component system in a different thread. Although I have most of the components in an early stage, I have already started working: RenderComponent, TransformComponent and CameraComponent. The design of the update of these components has been made following this graph:
It is still an early stage of the engine and this graph will change soon, most of the components will have more behaviors and more components will have to be added to the design; however, at this point, I have this system fully working. With all of this implemented, I have a simple demo running with one cube turning on the screen. It is a simple demo; however, its finality is to test if all the components are working besides all the extra features that I have implemented to develop these components. Material, uniform, mesh, mesh builder, component, object and gameobject are some examples of functionality of the engine.