Turbo-Hybrid Game Engine

- C++
- SDL2
- bgfx
Details
The Turbo Hybrid Game Engine is a custom 3D game framework built using a structure-of-arrays ECS system, SDL2, JSON serialization, and bgfx rendering. It was developed over 15 weeks as part of a Champlain College course on game engine architecture.
Overview
This game engine project focused on building a custom engine from scratch, including core systems like game object management, component handling, and rendering pipelines. We supported cross-platform builds using Emscripten and implemented 3D rendering with bgfx.
I collaborated with Steven Annunziato to implement a 3D rendering system. We prioritized shader flexibility and chose bgfx for its abstraction of backend graphics APIs and strong documentation.
Technical Highlights
- Created windowing and input systems using SDL2
- Designed a structure-of-arrays ECS model for game objects and components
- Used JSON for data-driven configuration of game objects
- Integrated bgfx for efficient GPU rendering and shader pipeline support
- Supported build targets for both Windows and Web (via Emscripten)
Rendering System
Implemented a cube rendering component with MVP matrix support. Each object can define its own shader, and the engine is built to be extensible for future rendering features.


Sample GameObject JSON
Components: TRAN (Transform), CUBE (Cube Renderer), PLRC (Player Controller)
{
"GameObjects" :
[
{
"TRAN" : [0, 0,5 ],
"CUBE" : {
"Color": [1, 1, 1, 1]
},
"PLRC" : {
"Speed" : [0.1]
}
},
{
"TRAN" : [4, 0, 0],
"CUBE" : {
"Color": [1, 0, 1, 1]
}
}
]
}
Main Render Function
/*
Set up view projection matrix
*/
// Look at the first gameObject
const glm::vec3 at = gameObjects[0]->
GetTransform()->
GetLocation().
Vec3();
// location of the eye/camera
const glm::vec3 eye = { 0.0f, 0.0f, -5.0f };
// reference for up vector
const glm::vec3 up = { 0.0f, 1.0f, 0.0f };
// view matrix is created
glm::mat4x4 view = glm::lookAt(eye, at, up);
// create projection matrix using a perspective projection
glm::mat4x4 proj = glm::perspective
(80.0f, //FOV
float(WIDTH) / float(HEIGHT), //Aspect Ratio
0.1f, //Near Clipping plane
100.0f); //Far Clipping plane
// set view and projection matrix
bgfx::setViewTransform(0, &view, &proj);
/*
Render Cube components
*/
TurboHybrid::ComponentSystem::GetComponentSystem()->
renderCubes(engine->frame);
/*
Render next frame
*/
bgfx::frame();
Cube Renderer Loop
void TurboHybrid::CubeRenderer::render(const float& deltatime)
{
assert(m_vbh.idx != 0 || m_ibh.idx != 0 || m_program.idx != 0);
//set up render state for object
uint64_t state = 0
| (BGFX_STATE_WRITE_R)
| (BGFX_STATE_WRITE_G)
| (BGFX_STATE_WRITE_B)
| (BGFX_STATE_WRITE_A)
| BGFX_STATE_WRITE_Z
| BGFX_STATE_DEPTH_TEST_LESS
| BGFX_STATE_CULL_CW
| BGFX_STATE_MSAA
| UINT64_C(0)
;
// init with no translation
glm::mat4x4 model = glm::mat4(1.0f);
// Set Position to the transform component position
Vector3 pos3 = gameObject->GetTransform()->GetLocation();
glm::vec3 pos = glm::vec3(pos3.x, pos3.y, pos3.z);
model = glm::translate(model, pos);
// Set rotation
float rotationDirection = 100.0f;
if (gameObject->GetPlayerController() != nullptr) {
rotationDirection *= -1; // If player controlled invert rotation
}
model = glm::rotate(
model, //Matrix
deltatime / rotationDirection, //Rotation amount
glm::vec3(1.0f, 1.0f, 0.0f)); //axis of rotation
bgfx::setTransform(&model);
// Set Color uniform to pass information to the shader
float color[4] = { m_color.r, m_color.g, m_color.b, m_color.a };
bgfx::setUniform(m_uniform, color);
// Set Vertex and Index Buffers
bgfx::setVertexBuffer(0, m_vbh);
bgfx::setIndexBuffer(m_ibh);
// Set render states.
bgfx::setState(state); //Each object has unique state
//Submit program for rendering
bgfx::submit(0, m_program);
}
Conclusion
Building this engine gave me a deeper appreciation for the systems that power 3D games. The project helped reinforce fundamentals of rendering, data design, and low-level graphics integration.