Through The Veil.
Through The Veil is a Diablo-inspired, swamp-themed, hack n slash game. A project made with a self-made Game Engine, during the span of 14 weeks together with 13 people: 5 programmers, 3 level designers, and 5 artists.
Genre: Dungeon Crawler
Engine: Group Made
Inspiration: Diablo
Overview.
Throughout the development phase, my primary focus was on the back end of the project. Working closely with another programmer, our main objective was to construct and maintain an engine that was both user-friendly and capable of delivering high performance at scale. While my fellow programmer was more dedicated to pure engine development, I was able to refine my graphics rendering skills and apply them to the project’s needs.
As I delved deeper into the various graphics-related tasks required for the engine’s development, I found myself quickly gaining expertise in this area. This allowed me to efficiently implement a wide range of exciting features that ultimately contributed to the overall success of the project.
Challanges.
My main challenge during the game’s development was to create a functional engine under time pressure. I had to make numerous decisions prioritizing certain tasks over others to ensure the rest of the team had the necessary resources in a timely manner.
Contributions:
PCF Filtered Shadows: Directional, Point and Spot liaghts
Instanced Rendering in Deferred & Forward Pipelines
Threaded Animation System With Blending
Post Processing with Bloom, TM, CC
Threaded Particle Systems
FBXSDK & Assimp for Model & Animation Import
Extra Player Functionalities
Window Handling
Instanced Rendering.
Given that our game relied heavily on vast amounts of foliage, instancing was an essential requirement for ensuring optimal performance. However, this came with a certain amount of overhead, as the architecture had to support sorting all of the objects.
Culling, Sorting, and Rendering submitted meshes
Deferred Rendered Instanced Models.
Abstract Renderer Class
Renderer
Since we knew that we would need to separate the instanced objects from the others we developed a pure virtual base class which would be derived from our Deferred and Forward renderer. Both of these had their own implementation of submitting meshes and rendering them correctly.
Submitting & Sorting
The submitting and sorting of the instanced models were done with the help of 3 main components:
MeshRenderOptions
Mesh
Mask data
Next, all of these elements are converted into a render batch, which is subsequently added to an unordered map in the deferred renderer. If the batch already exists, only its transform needs to be added to the mapped vector, resulting in a sorted output.
I would insert the instance batch into an unordered map, mapping the batch to a vector containing the instance data. This approach not only allows us to access the data in a sorted manner by default but also gives us the flexibility to create our own struct with a customized hashing function. This facilitates the addition of per-instance data, which in turn enables us to sort the objects based on specific criteria.
Threaded Animation System.
During the time of development, we were eager to implement blended animations to further enhance the visual fidelity. Some of the features are:
Blended Animations
Threading the System
Animated Model Import with FBXSDK & Assimp
State-Based Animation System: Easy to Implement & Adjust
Animation Blending
The blending of the animations is done through an Animation controller. It consists of States and Transitions, trying to replicate the animation system of Unity for user experience.
The system finds the controller and gets the current and next state. We update both the animations in each state, de-compose the matrix, and lerp the position and scale, then we slerp the quaternions and add them all together.
My colleague, an engine programmer, and I collaborated on revamping the node/transition system that I had previously created for an older project.
Threading was a straightforward process. The job system accepts a lambda function and self-marks when it completes, which makes threading tasks that don’t require shared memory very straightforward. The job manager, a fantastic piece of work, was created by the talented Adam Rohdin.