The modern 3D graphics engines that are behind today's biggest games are incredible works of mathematics and programming, and understanding them in their entirety is a difficult task. Seasoned industry veterans lead the teams building the astounding architectures that serve as middleware connecting graphics hardware and game logic. A game is comprised of an incredible amount of different parts no matter if we look at it from a technical standpoint (models, textures, sounds, game rules, scripts, AI...) or just from a consumer's standpoint (story, characters, locations, activities...). The amount of content in some of today’s AAA releases is truly unbelievable. What enables game creators to build these vast worlds are the complex software systems that are today’s modern game engines.
My master thesis will introduce some aspects of modern engine development using DirectX 11 API and the C++ programming language.
An engine is a big and complex system. My concrete engine implementation uses a modular approach, where the graphics engine is only part of a bigger software architecture. The tools to build such architecture have to be chosen accordingly. In the first chapter I present some of the programming paradigms and patterns I have used to create the engine and all of its helper subsystems. As I explain the working of the architecture from a higher standpoint, I will also introduce all of the smaller subsystems supporting the graphics engine.
The second chapter is about the component-based graphics engine itself. The first section is an overview of the engine, where I present the most basic operations required to run a game. In the later sections I expand upon the main parts of the engine, such as the animation (movement) system, physics system, resource and asset handling and entity (game object) creation.
The third and last chapter is all about the rendering. After discussing the capabilities of the rendering engine (deferred shading, PCF shadow maps), I address the optimization problems connected to them. In the later sections I will describe the methods I have used to maximize the number of draw calls in the engine. These methods are instancing, view frustum culling and an algorithm for ordering state change operations. This algorithm enables creating a flexible framework that groups together drawing calls that share any of the conceivable render states, minimizing the number of CPU-GPU communication instances required to set them.