Graphics¶
Requirements¶
- Draw a 2D game: hundreds of sprites (players, Bydos, missiles, explosions), a scrolling star field, text for the HUD; 60 frames per second on school machines.
- Run on Linux and Windows (cross-play), and on macOS for development.
- Stay behind an engine interface (
IRenderer) so game code never sees the graphics API. - Be learnable by the team within the project's time frame.
Graphics API¶
| API | Platforms | Strengths | Weaknesses for this project |
|---|---|---|---|
| OpenGL 4.5 core (chosen) | Linux, Windows; 4.1 on macOS | Mature, well documented, immediate feedback, every team member can debug it; direct state access (4.5) removes most bind-to-edit bugs; enough for batched 2D | Deprecated on macOS (4.1 is the maximum); driver-dependent error behaviour, mitigated with the KHR_debug callback |
| Vulkan | Linux, Windows; macOS via MoltenVK | Explicit, predictable performance, modern tooling | Several thousand lines before the first sprite (instances, swapchain, synchronisation, memory); the extra control brings nothing to a 2D game of this size |
| Direct3D 11/12 | Windows only | Excellent Windows tooling | Breaks the Linux requirement; would need a second backend |
| Metal | Apple only | Native on macOS | Not on the target platforms |
| SDL3 GPU API | Vulkan, D3D12, Metal behind one API | Modern and portable | Recent, fewer learning resources; shader cross-compilation adds a build step |
Decision: OpenGL 4.5 core profile, generated with glad, with a 4.1 build option
(AEGIS2D_MACOS_GL41) so macOS developers can run the client. The renderer is reached
only through IRenderer, so a Vulkan or SDL GPU backend could replace it later without
touching the game.
Windowing, input and audio library¶
| Library | Scope | Assessment |
|---|---|---|
| SDL3 (chosen) | Window, GL context, input, gamepads, audio | Small, portable, used by many commercial games; we keep full control of rendering; gamepads and audio come for free |
| SFML | Window, 2D graphics, audio, network | Allowed by the subject and simple, but its built-in sprite renderer would do the engine's work for us and hides batching decisions |
| raylib | Window, 2D/3D rendering, audio | Very quick to start, but close to an engine itself: little left to design |
| GLFW | Window, context, input | Good, but no audio and weaker gamepad support: a second library would be needed |
Rendering techniques¶
- Sprite batching (planned): sprites sharing a texture and layer are written into one vertex buffer and drawn with a single call. Drawing each sprite with its own call costs one driver round-trip per sprite and becomes the bottleneck long before the GPU.
- Texture atlases / sprite sheets (planned): one texture per sheet keeps batches large and texture switches rare.
- Nearest filtering (planned): keeps pixel art sharp when scaled.
- Fixed logical resolution with letterboxing (planned): the game is laid out in a fixed virtual resolution and scaled to the window, so every player sees the same play area whatever the window size.
- Interpolated rendering (planned): the simulation runs at a fixed step; rendering interpolates between the last two states, so movement is smooth at any frame rate and never tied to CPU speed.
- stb_image for PNG loading (in place): a single header, no system library, and only the decoder we need. Alternatives (SDL_image, libpng) add dependencies for formats we do not use.
- GLM for maths (in place): the reference maths library for OpenGL, header-only, types matching GLSL.
Benchmark¶
The sprite stress-test scene (planned) renders N moving sprites in batched and naive modes and records CPU and GPU frame times. Its results, measured on Linux and Windows, will be published on the benchmark page and justify the batching choice with numbers.