It's been a while since my last blog post more than two years, I think, even though I like writing these pieces, there wasn't much worthwhile to write about during that time.
I've been actively improving the chicane engine, almost 400 commits to be exact! Taking that into consideration, I will do my best to catch you guys up on the changes, and give a little bit of insight about what's to come.
Layering
Since I was (and still am) new to game development I sought tips and tricks on a plethora of different mediums, and I found The Cherno's channel, as an experienced developer in the game development industry he got a bunch of videos regarding this area, one video about a Layer system caught my attention, and I thought it was worth a shot. This system as the name states, opens a possibility to stack rendering techniches upon eachother making the engine more malleable, thus I've created a few core layers:
- Sky Layer - Renders the sky;
- Shadow Layer - Writes the shadow map;
- Level Layer - Renders both Meshes and its Shadows;
- UI Layer - Renders the UI.
Even though those are the core layers the system allows to include modules before or after any position reinforcing the malleability of the system, it's the duty of the developer to keep that in mind, the engine will not hold his hand when it comes to the rendering order.
Decoupling
I've started my journey with the creation of a Vulkan based game engine, but as the system evolved I grew tired of the different specks of Vulkan code scattered along the codebase, since my understanding of how the Vulkan worked improved I've decided to isolate the graphics API code and make the engine API independent.
Although I don't have any implementations with different API's in mind I've left the path somewhat open to new graphic interfaces, different API's introduces their own particularities that you can't run away from, with that in mind layers are closely related to graphics API's.
Improving the basics
While creating different test beds something became very clear, the transform system wasn't right, it was inconsistent and required a lot of code copying and pasting, this highlighted my naivety back when I first conceived this system. It took me close to three days and some tussling around with different sources to get the basic of transforms right and understand what was wrong with my implementation, fixing the main calculations of matrix and orientations brought up different issues with my shader code, taking me down the rabbit hole of trying to understand what was wrong with something that a while ago was working.
After fixing my transformations it was time to improve upon my back then Actor
and Component
attachment system, studying different approaches I've decided to bring down most of functionalities into the Transformable
base class, furthermore I've implemented a few QOL methods such as addTranslation
, addRotation
, addScale
and different overloads reducing repeated code through out the application.
The Grid System
With my short experience using Unreal Engine I grew fond of their UI system so I took their implementation with the Qt HTM5
/CSS3
/Javascript
like UI implementaiton, and created my own system called the Grid
named after the racing start positions layout. All that utilization of the ImGUI library as a base for rendering the components;
This system is reliant of XML files with attributes and values like HTML5
tags and back end value references reminiscent of AngularJS
implementations and a CSS3
like styling files.
There are a few basic components:
- Button;
- Container;
- List;
- Popup;
- Progress Bar
- Text;
- Text Input.
I've implemented this components to be used as a foundation for different components, much like div
or span
on HTM5
, below is the example for real Grid
files.
Template Example .grid
<View id="home" style="Content/Sample/Views/Home.decal">
<Container id="victory" isVisible="{{ didPlayerWin }}">
<Text id="victoryText">YOU WIN!</Text>
</Container>
<Container id="frameTelemetry" direction="row">
<Text id="framePerSecond">{{ getFPS() }} FPS</Text>
<Text id="frameTimeText">{{ getFrametime() }} ms</Text>
</Container>
<Container id="crosshair">
<Container id="crosshairTop"></Container>
<Container id="crosshairBottom"></Container>
<Container id="crosshairLeft"></Container>
<Container id="crosshairRight"></Container>
</Container>
</View>
Style Example .decal
#victory {
position: absolute;
height: 30vh;
width: 100%;
margin-top: 10vh;
background-color: #333333;
}
#victoryText {
alignment: center;
}
#frameTelemetry {
position: absolute;
width: 175px;
height: 25px;
margin-left: auto;
}
#framePerSecond {
margin-left: 1vw;
alignment: start center;
color: #24f51d;
}
#frameTimeText {
alignment: end center;
color: #24f51d;
}
#crosshairTop {
position: absolute;
height: 10px;
width: 2px;
background-color: #FFFFFF;
margin: 50% 2px 28px 50%;
}
#crosshairBottom {
position: absolute;
height: 10px;
width: 2px;
background-color: #FFFFFF;
margin: 50% 2px 8px 50%;
}
#crosshairLeft {
position: absolute;
height: 2px;
width: 10px;
background-color: #FFFFFF;
margin: 50% 15px 15px 50%;
}
#crosshairRight {
position: absolute;
height: 2px;
width: 10px;
background-color: #FFFFFF;
margin: 50% -5px 15px 50%;
}
The Box System
I've always had in mind that a engine with controlled assets is a happy engine, with that I've decided to create my own system it was basic, get a asset file being a 3D model, audio or image and insert within a template, with a racing theme in mind it got named Box
after the pit boxes where racing vehicles get maintnance during the race.
From time to time between engine updates I developed a basic asset viewer and with that it became apparent to me that the Box
system needed improvements, until then this was the template for the asset files:
Template
BOX;{FILE_VERSION};{ASSET_TYPE};{ASSET_ID};{ASSET_ENTRY_COUNT};[ENTRY{ENTRY_COUNTER};{ENTRY_IDENTIFIER}DATA]
Header Section
BOX;{FILE_VERSION};{ASSET_TYPE};{ASSET_ID};{ASSET_ENTRY_COUNT};
Data Section
[ENTRY{ENTRY_COUNTER};{ENTRY_IDENTIFIER}DATA]
At the time I tought it this implementation was clever, it looked similiar to mainframe data I deal on a daily basis at my job, a simple string with a fixed template easy and fast to parse, the problem is that this format doesn't scale well with changes, taking that the new data had to be added in the header section of the file, always requiring to keep backwards compatibility to different assets versions.
With that I've decided to rewrite the whole asset system and much like the Grid
module, implement using XML
which is a more malleable and easy to work file system.
The new implementation dropped the raw file contents and went with a Base64
approach to storing raw data, also the it heavily utilizes the XML component attributes to set custom data for different assets, this is an example of a real Box
mesh file that is the combination of meshes and textures:
Example
<Asset version="1" id="Cube">
<Group id="Body">
<Model>Content/Sample/Models/Cube.bmdl</Model>
<Texture>Content/Sample/Textures/Gray.btex</Texture>
</Group>
</Asset>
This new template holds immense power not only to future proofing but also readability.
The Future
Since the beginning I've treated this engine as a pet project, but as the time went on I've started to route a lot of bandwidth to maintain this project, as happy as I am to learn new things this is not what I want to my career at the moment, I've still got to further pursue my academic endeavors and I'm still too young in the software development industry to join any major game development company.
Taking that into considerations I've chosen to sunset this project to improve other aspects of my life. This is not a goodbye for my blog posts, but a farewell to this project in particular, as time goes on it came to me that making a game engine required a lot of time and knowledge and that's something that I don't have right now.
From now on the blog post will tackle different themes not only related to software development, such my learning journey with different languages or future abroad trips, until then this a goodbye.