I wanted to have a very robust animation system that other programmers can use because it saves a lot of time.
The animation system supports the following:
- State machine driven for transitions
- Crossfading between animations
- Triggers & Conditions to transition betwenn states
- Any state
- Root motion
- Frame event callbacks
- Get joint world positions
- Data driven using JSON
Being driven through JSON I learned that sitting with big animation state machines in JSON was hard. Therefore, for the next project an animation editor was planned.
We needed a efficient and easy to use debug drawer quickly for the gameplay programmers to quickly start prototyping. It renders everything batched, so no big performance problems caused by it.
I am also proud to say that every group in our class has requested it and been given this to use for their own projects.
I needed an easy way to the Tech Artists to be able to create shaders and materials themselves without help from us programmers, therefore I implemented a basic material system.
- Support for multiple passes
- Each pass can have different renderer (forward/deferred)
- Assign shaders to each material
- Can create variables that are automatically exposed to programmers
- Can bind extra textures
- Each material instance has its own local shader values.
The left image is a simple example material.
OFFLINE RESOURCE PIPELINE
I noticed quickly that loading FBX’es was a slow operation for both animations and models. Loading a navmesh from ASCII was also very slow.
The solution was to create my own binary formats and load models, animations and navmesh using them.
The very big advantage was that we could process the models and animations offline during this stage to prepare them for the engine to avoid runtime performance penalties. An example is calculating the bounding volume.
I learned that the key to high performance binary loading it to structure the format such that when parsing it, you can simply cast the raw memory into the struct or array you want to read. This avoid all copying.
Below is cut-down example of reading animation translation keys.
RUNTIME RESOURCE MANAGEMENT
I felt a good resource manager was going to be key to a good engine because:
- If properly abstracted away, it eases the job for other programmers with a general interface for all resources
- Being a general solution we can easily multithread all resources loading using jobs
- Ensures resource are only loaded once and re-used
- Automatic memory management using reference counting
- Ability to stream resources
- Can use file watcher to automatically reload resources in runtime
Runtime hot reloading of resources was a high priority to save time for me and others in the group. This allowed us to hot-reload shaders, images, JSON files, etc.
In previous projects, logging has always been a mess seeing other programmers logs. A proper logging system was important, and even more when we had multiple threads calling logs as well, therefore it had to be thread safe as well.
The solution was to divide logs into channels and try to get same interface as cout.
The base of the rendering engine was written during the graphics programming course. However, I have added and re-written major parts. Some notable changes include.
- Proper window handling and DX11 resource re-creating upon window resolution changes. As well and fullscreen and cursor management.
- Perspective and orthographic frustum culling.
- MP4 video rendering.
- Our own material system.
- Fog for both forward and deferred rendering.
- Shadow mapping for Directional Light, Pointlights and Spotlights.
- Smooth shadows using Percentage-Closer-Filtering
- Forward and deferred rendering live in harmony.
- Proper support for transparent meshes
- Screen space sprites with proper window scaling support.
- Gamma correction as post process step
SPOTLIGHT & DIRECTIONAL LIGHT PCF SMOOTH SHADOWS
Knowing that the Level Designer never used shadow casting on pointlights, I only added smooth shadows for directional light and spotlights using PCF to hide the fact that the shadow texture resolutions are very small on spotlights. The below image shows a smoothed shadow texture that is 128×128.