Minity is a minimal 3d game engine.
The main purpose is to do a fun project to re-learn modern C++ and try to follow the new guidelines. SDL2 is used to get a simple canvas to draw to (setPixel(x, y)
) and input handling. Math is written all by hand to re-learn vector and matrix operations. Write all graphics pipeline operations by hand to understand what the GPU does for us and compare them with metal API](https://developer.apple.com/metal/) results. Dear ImGui is used for adding a statistics window to the rendered area.
Design choices for the software renderer:
- matrices are in row-major order to align with maths notation (unlike OpenGL!)
- coordinate system and rotation follow the right-hand rule like OpenGL
- axis rotation follows the right-hand rule: right thumb to positive axis and fingers point to positive rotation
- camera is watching towards the negative Z-axis
- screen coordinates are top-left (0,0) to bottom-right (screen-width, screen-height)
- texture coordinates are top-left (0,0) to bottom-right (1,1) when flipped vertically on load
- model faces are defined in clockwise winding order faces follow the LEFT-hand rule: e.g. center > up > right and LEFT-thumb points front
Working:
- simple scene object with light, camera, and model (no entity hierarchy)
- object loading from a simple obj file (vertices, faces, normals, and texture coordinates)
- object scaling, rotation, and movement (translation)
- rudimentary input handling for
- moving the target (arrow-keys, +, -)
- rotate target with (wasd)
- no z-rotation as q is currently for quit
- orthographic perspective correction with fixed FoV, field-of-view
- rudimentary clipping (TODO: proper clipping)
- back-face culling: face normal check to discard hidden triangles
- draw wireframe, normals, point cloud, and axes
- global face color
- flat shading for models without pre-calculated normals (teapot)
- Phong-shading with normals for a smooth surface
- textures with perspective-corrected model texture coordinates
- basic math tests with Catch2
- z-buffer check (instead of z-sorting the vertices before rendering)
- rendering on metal API
- simple util for generating a cube
TODO:
- proper clipping (zoom in and the entire face is removed if clipped)
- input handling:
- z-rotation with q/e but move quit
- map all keys
- re-implement fps camera movement (now we move the target)
- camera movement is not good for exploration
- cannot change the target between mesh/camera/light
- re-implement a simple util for generating a sphere
- split scene header to smaller parts and have corresponding tests
- wire-frame line color (done) > painting (done) > texturing (done) > anti-aliasing
- vertex/face color from model
- jump from classic make to CMake
- consider
clang-format
- add address/thread/memory sanitizer
Main influences:
- OneLoneCoder/Javidx9: console game engine and 3d videos
- Michael Kissner/Kayzaks: StupidGL gamasutra article
- Gabriel Gambetta: Computer Graphics from Scratch
- Dmitry Sokolov: Tiny renderer
Tilted yellow sphere with 50 meridians and parallels in basic global illumination:
Simple statistics window (turn on with [F1]) to get basic fps and library information:
Head model with texture (incomplete mesh split and no eye/lash textures)
Texture with perspective-correct interpolation (no dent in face)
Rendering differences between software rasterizer and metal API