DarkLight
The Engine is a 3D game engine built in C++ and uses OpenGL for the graphics, Assimp for animations, FMOD for the audio and a mixture of it's own physics and Bullet physics.
Download
Creation
The engine started being made in September, while I learned how to use OpenGL and the graphics card. The engine then was much messier, having one giant game object class for most things. Back then it was code named Shooting Star.
During christmas break I reworked and revamped the engine using an Entity/Component (ECS) system model in mind in order to get rid of problems regarding inheritances that were starting to become too prevalent.
The engine uses Json files to save and load the current state it is in during play time, and upon restarting, the state is loaded and the work can later be resumed.
ECS System
The ECS system uses a blend
of a strict ECS system, but it takes some of its own liberties.
Each component is a struct, with
its type and unique ID. Inside the component, any data that the system needs to know is stored and can be accessed via getters and setters.
The components do contain simple functions. Any functionality that pertains to the component itself like setting attributes or updating small parts like vectors are inside the components themselves, not the system.
Functions that are more complex and require more calculations are controlled inside the specific systems.
Each system is able to either look in
each Entity and search for the required components on the map, or Schedule
and Unschedule entities upon creation, so it doesn't need to go through unecessary entities.
Each system updates every component
that it has control over, so it is much
easier to create pieces that can be
built together to generate different types
of entities with ease, without falling into
the inheritance problems of not knowing
what each entity should really be.
Shaders
The shaders are the most important
part of an engine. Without them, nothing
would be shown on the screen.
The DarkLight engine currently uses
two different shader programs that are switched when needed.
The first is a general "Simple Shader"
that contains most of the graphical
code, from the vertices to the lighting.
The second is a "Text Shader" that
contains code for writing text on the
screen.
The first shader can be subdivided into
other multiple shaders, but given the
time I had to built it, it wasn't a priority.
Lighting
The engine uses forward shading for lighting, manipulated in two passes.
The first pass calculates all colours from
textures and lighting and saves it into
an offscreen quad texture that is then
drawn during the second pass.
Lights are calculated depending on each light type:
Directional lights are simply calculated by adding colour to each pixel depending on the angle between the vertex normal and the light direction.
Point Lights are similar, but they have
attenuation to them based on the distance to the pixel (constant, linear or quadratic).
Spot Lights also take into account the cone angle and the place of the pixel inside the cone, either lighting it or not at all.
Effects
Thanks to the second pass, effects can
be added to the shader in orther to change the overall look of the scene.
The engine includes a Bloom effect, where each pixel is converted into a grayscale value and adds more colour to adjacent pixels depending on a selected threshold.
A toon Cel-Shaded effect can also be
applied, where the shader uses the angle between the vertex normal and the light direction to block colour values
into certain thresholds, effectively locking colour into specific values and creates a visible contrast.
A Night Vision effect can also be used,
making the shader check the grayscale value once again and painting over white values green and any others black.
Physics
DarkLight contains its own physics
inside the "Simple Physics" portion of it.
The one being used in the example is the Bullet physics one.
The Simple Physics contains simple collisions between infinite plane shapes and sphere shapes. It uses concepts such as reflection to reposition objects that have overlapped back into appropriate positions. It also uses RK4 equations for the integration of the physics frame.
Bullet Physics in contrast is controlled by Bullet itself, and uses the "Interfaces" to connect virtual interfaces with DarkLight's own implementations when needed. Whn using Bullet, DarkLight has its own Character Controller with collision calculations being overriden from Bullet to a custom collision check.
This is done in part because Bullet does not have collisions between kinematic objects and static objects, which is the case btween the character and the terrain.
AI
The engine contains many types of AI, though none of them are currently active on the scene. During development, I worked with manipulating many common known AI behaviours.
Behaviours: There are many behaviour components available, mainly
-Seek and Flee: Entity will seek or flee a target's current position.
-Pursue and Evade: Entity will calculate a future position to pursue or evade.
-Approach: Entity will approach a target and keep a distance, pursuing or evading it.
-Wandering and Idling: Entity wanders between generated points in a radius and idles for chosen time.
Flocking: Entities will maintain a flock using three mathematical calculations -
Cohesion, Separation and Alignment
Pathfinding: There are two pathfinding methods that can be used. Both use a method to generate a terrain divided into nodes that have their own difiiculty of travelling.
-Dijkstra: dijkstra is calculated using an algorithm that is good at finding every single object on the map. It is also slower due to the fact that it must go through all the nodes.
-A*: calculated using an algorithm that is best at finding the closest path towards a point. It is faster due to the fact that it doesn't need to go through all the nodes, but it isn't that good for finding more than 1 point at the same time.
Neural Networking: This method consists in generating sensors in multiple entities that try to steer towards a goal point, until they either all fail or achieve the goal. All entities receive information from the two best tries and use them on the next iteration, getting better each time at moving towards the goal point. (This is still in development)