Skip to content

Commit d5b1483

Browse files
committed
docs: add AGENTS.md
Signed-off-by: Niu Zhihong <zhihong@nzhnb.com>
1 parent 9718b21 commit d5b1483

2 files changed

Lines changed: 186 additions & 0 deletions

File tree

AGENTS.md

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
# PROJECT KNOWLEDGE BASE
2+
3+
**Generated:** 2026-03-10
4+
**Commit:** 9718b21
5+
**Branch:** main
6+
7+
## OVERVIEW
8+
9+
Educational C++ software renderer (C++23) mimicking OpenGL's GPU pipeline. Builds as a static library (`SimpleRenderer`) with SDL2 display, GLM math, Assimp model loading, spdlog logging, and OpenMP parallelism.
10+
11+
## STRUCTURE
12+
13+
```
14+
SimpleRenderer/
15+
├── src/ # Core static library (see src/AGENTS.md)
16+
│ ├── include/ # All public headers
17+
│ │ └── renderers/ # Renderer strategy headers
18+
│ └── renderers/ # Renderer strategy implementations
19+
├── test/
20+
│ ├── system_test/ # Visual demo app (ONLY main() lives here)
21+
│ └── unit_test/ # GoogleTest unit tests (*_test.cpp)
22+
├── cmake/ # Build helpers (deps, compile opts, functions)
23+
├── obj/ # Bundled 3D models (.obj/.mtl)
24+
├── doc/ # Doxygen (generated, not committed)
25+
└── tools/ # cppcheck suppression config
26+
```
27+
28+
## WHERE TO LOOK
29+
30+
| Task | Location | Notes |
31+
|------|----------|-------|
32+
| Add/modify rendering algorithm | `src/renderers/` + `src/include/renderers/` | Subclass `RendererBase`, register in `renderer.cpp` |
33+
| Change shader behavior | `src/shader.cpp` + `src/include/shader.hpp` | Vertex/Fragment shaders, uniform caching, specular LUT |
34+
| Modify rasterization | `src/rasterizer.cpp` + `src/include/rasterizer.hpp` | Barycentric interpolation, perspective correction |
35+
| Add new model format | `src/model.cpp` + `src/include/model.hpp` | Uses Assimp; texture cache in `Model` |
36+
| Change display/input | `test/system_test/display.cpp` + `camera.h` | SDL2 window, keyboard handling |
37+
| Run the app | `test/system_test/main.cpp` | `./build/bin/system_test ./obj` |
38+
| Add unit tests | `test/unit_test/` | Use `*_test.cpp` naming, GoogleTest |
39+
| Modify build deps | `cmake/3rd.cmake` | CPM.cmake package manager |
40+
| Change compile flags | `cmake/compile_config.cmake` | `-Wall -Wextra`, `-Werror` in Release |
41+
| Generated config values | `cmake/config.h.in``src/include/config.h` | Thread count, log paths, OBJ path |
42+
43+
## CODE MAP
44+
45+
| Symbol | Type | Location | Role |
46+
|--------|------|----------|------|
47+
| `SimpleRenderer` | Facade class | `renderer.h` | Mode selection + unified `DrawModel` entry point |
48+
| `RendererBase` | Abstract base | `renderers/renderer_base.hpp` | Defines `Render()` interface, shared perspective/viewport transforms |
49+
| `PerTriangleRenderer` | Strategy | `renderers/per_triangle_renderer.hpp` | AoS forward rendering (traditional) |
50+
| `TileBasedRenderer` | Strategy | `renderers/tile_based_renderer.hpp` | SoA + tile binning + optional Early-Z |
51+
| `DeferredRenderer` | Strategy | `renderers/deferred_renderer.hpp` | AoS deferred (collect fragments → shade winners) |
52+
| `TileBasedDeferredRenderer` | Strategy | `renderers/tile_based_deferred_renderer.hpp` | TBDR: tile binning + 2-pass (Z-prepass + deferred shade) |
53+
| `Shader` | Class | `shader.hpp` | Vertex/Fragment shaders, uniform buffer, specular LUT cache |
54+
| `Rasterizer` | Class | `rasterizer.hpp` | Triangle rasterization, barycentric coords, perspective correction |
55+
| `Model` | Class | `model.hpp` | Assimp-based OBJ loader, vertex/face/material storage |
56+
| `Vertex` | Data class | `vertex.hpp` | Position, normal, UV, color, optional clip-space coord |
57+
| `VertexSoA` | Struct | `vertex.hpp` | Structure-of-Arrays layout for tile-based renderers |
58+
| `Color` | Class | `color.h` | 32-bit RGBA, operator overloads for arithmetic |
59+
| `Buffer` | Class | `buffer.hpp` | Double-buffered framebuffer (draw + display swap) |
60+
| `Fragment` | Struct | `shader.hpp` | Fragment shader input (screen coord, normal, UV, depth, material) |
61+
62+
## CONVENTIONS
63+
64+
- **Namespace**: All code in `simple_renderer`
65+
- **Style**: Google C++ style (`.clang-format`), enforced via `clang-format` target
66+
- **Headers**: `.h` for C-compatible / `.hpp` for C++-only (templates, classes with methods)
67+
- **Comments**: Bilingual (Chinese + English) — Chinese for design intent, English for API docs
68+
- **Naming**: `PascalCase` classes/methods, `snake_case_` private members with trailing underscore, `kPascalCase` constants
69+
- **Return style**: Trailing return `auto Foo() -> ReturnType` used in some classes (Color, Rasterizer)
70+
- **Standard**: C++23 (`CMAKE_CXX_STANDARD 23`), no extensions
71+
- **In-source builds**: Prohibited (CMake fatal error)
72+
- **Static analysis**: clang-tidy (see `.clang-tidy` for enabled checks), cppcheck with `tools/cppcheck-suppressions.xml`
73+
74+
## ANTI-PATTERNS (THIS PROJECT)
75+
76+
- **Do NOT** modify `Color` memory layout (marked `@note` in `color.h` — 4-byte RGBA assumed by `uint32_t` cast)
77+
- **Do NOT** build in-source (`mkdir build` required)
78+
- **Do NOT** edit `src/include/config.h` — generated from `cmake/config.h.in` by CMake
79+
- Unit tests `todo1` and `todo2` are placeholder stubs — do not treat as passing tests
80+
81+
## COMMANDS
82+
83+
```bash
84+
# Configure (Linux)
85+
cmake --preset=build
86+
87+
# Configure (macOS)
88+
cmake --preset=build-macos
89+
90+
# Build all
91+
cmake --build build --target all
92+
93+
# Run demo
94+
./build/bin/system_test ./obj
95+
96+
# Unit tests + coverage
97+
cmake --build build --target coverage
98+
99+
# Static analysis
100+
cmake --build build --target clang-tidy
101+
cmake --build build --target cppcheck
102+
103+
# Format code
104+
cmake --build build --target clang-format
105+
106+
# Generate docs
107+
cmake --build build --target doc
108+
```
109+
110+
## DEPENDENCIES (via CPM.cmake)
111+
112+
| Library | Purpose |
113+
|---------|---------|
114+
| SDL2 (2.30.6) | Window/display, keyboard input |
115+
| GLM (1.0.1) | Vector/matrix math (`Vector3f = glm::vec3`, `Matrix4f = glm::mat4`) |
116+
| stb | Image loading (textures) |
117+
| spdlog | Logging (system-installed, not CPM) |
118+
| Assimp | 3D model loading (.obj/.mtl) |
119+
| OpenMP | Parallel rasterization |
120+
| GoogleTest (1.15.2) | Unit testing |
121+
| wqy-zenhei font | CJK font for text rendering |
122+
123+
## NOTES
124+
125+
- **Entry point is in test/**: No `main()` in `src/`. The runnable demo lives at `test/system_test/main.cpp`. The library itself is headless.
126+
- **obj/ is committed**: 3D model assets are tracked in git (teapot, cube, cornell box, etc.)
127+
- **Four rendering modes**: Switch at runtime via `SetRenderingMode()` — PER_TRIANGLE, TILE_BASED, DEFERRED, TILE_BASED_DEFERRED
128+
- **System test hotkeys**: `1` = toggle wireframe, `2` = toggle triangles, `TAB` = switch model
129+
- **CI**: GitHub Actions runs build + coverage on push/PR, deploys Doxygen to gh-pages on release

src/AGENTS.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# src/ — Core Renderer Library
2+
3+
Static library (`SimpleRenderer`) built from all `.cpp` files here + `renderers/`. Headers live in `include/`.
4+
5+
## ARCHITECTURE
6+
7+
```
8+
SimpleRenderer (Facade) renderer.h / renderer.cpp
9+
└─▶ RendererBase (abstract) renderers/renderer_base.hpp
10+
├── PerTriangleRenderer AoS, per-thread local framebuffer merge
11+
├── TileBasedRenderer SoA, tile binning, optional Early-Z
12+
├── DeferredRenderer AoS, collect-then-shade (GPU pipeline mimic)
13+
└── TileBasedDeferredRenderer SoA, 2-pass: Z-prepass + deferred shade
14+
```
15+
16+
`SimpleRenderer::DrawModel()` → delegates to active `RendererBase::Render()`.
17+
18+
Mode switch: `SetRenderingMode()` → reconstructs `renderer_` via `EnsureRenderer()`.
19+
20+
## RENDERING PIPELINE (per Render() call)
21+
22+
1. **Vertex Shader** (`Shader::VertexShader`) — model→clip space via cached MVP
23+
2. **Perspective Division** (`RendererBase::PerspectiveDivision`) — clip→NDC
24+
3. **Viewport Transform** (`RendererBase::ViewportTransformation`) — NDC→screen
25+
4. **Rasterization** (`Rasterizer::Rasterize`) — barycentric interpolation, perspective correction
26+
5. **Fragment Shader** (`Shader::FragmentShader`) — Phong lighting, texture sampling, specular LUT
27+
28+
## WHERE TO LOOK
29+
30+
| Task | Files | Notes |
31+
|------|-------|-------|
32+
| Add new renderer | `renderers/` + `include/renderers/` + `renderer.cpp` | Subclass `RendererBase`, add enum value to `RenderingMode`, register in `EnsureRenderer()` |
33+
| Modify vertex transform | `shader.cpp` (VertexShader) | Uses `VertexUniformCache` for matrix caching |
34+
| Modify fragment shading | `shader.cpp` (FragmentShader) | Phong model, multi-light, specular LUT with `shared_mutex` |
35+
| Change rasterization | `rasterizer.cpp` | `Rasterize()` returns `vector<Fragment>` |
36+
| Modify model loading | `model.cpp` | Assimp-based; `ProcessNode``ProcessMesh``ProcessMaterial` |
37+
| Add new data type | `include/` | Follow `.h`/`.hpp` convention |
38+
39+
## KEY PATTERNS
40+
41+
- **AoS vs SoA**: `PerTriangleRenderer`/`DeferredRenderer` use `Vertex` (AoS). `TileBasedRenderer`/`TileBasedDeferredRenderer` convert to `VertexSoA` for cache-friendly tile processing.
42+
- **Uniform caching**: `Shader` caches derived matrices (`mvp`, `normal`) in `VertexUniformCache` and light dirs in `FragmentUniformCache`. Call `PrepareUniformCaches()` before render loop or rely on auto-invalidation via `SetUniform()`.
43+
- **Specular LUT**: `Shader` maintains a thread-safe `unordered_map<uint32_t, SpecularLUT>` keyed by `bit_cast<uint32_t>(shininess)`. Guarded by `shared_mutex` (read-shared, write-exclusive).
44+
- **Tile binning**: Two-pass approach — count pass (size reservation) then fill pass. `TileTriangleRef` stores SoA indices + material pointer.
45+
- **OpenMP parallelism**: Renderers parallelize over triangles (PerTriangle) or tiles (TileBased). Thread-local buffers merged post-loop.
46+
47+
## CONVENTIONS (src-specific)
48+
49+
- **Header/source pairing**: `include/foo.hpp``foo.cpp`. Renderers: `include/renderers/foo.hpp``renderers/foo.cpp`
50+
- **Math aliases**: `Vector3f = glm::vec3`, `Matrix4f = glm::mat4` (defined in `math.hpp`)
51+
- **GLM experimental**: `GLM_ENABLE_EXPERIMENTAL` is `#define`d in `math.hpp` for `glm::to_string()`
52+
- **spdlog formatters**: Custom `fmt::formatter` specializations for `Vector3f`, `Vector4f`, `Matrix4f`, `Color` in `math.hpp`
53+
54+
## ANTI-PATTERNS
55+
56+
- **Do NOT** add `main()` here — library is headless; entry point lives in `test/system_test/`
57+
- **Do NOT** break header convention: `.h` = C-compatible, `.hpp` = C++-only

0 commit comments

Comments
 (0)