# Notes for AI agents C++20 / OpenGL 4.5 HD-2D engine (`engine/`) plus a demo (`demo/`). Read `README.md` for features and the frame pipeline, and **`docs/ASSET_GUIDE.md` before making any sprite, texture or model**. ## Build and run ```sh cmake -S . -B build -G Ninja && ninja -C build ./build/hd2d_demo # interactive (WASD, R/O/G = rain/overcast/fog, [ ] = hour, F1 = panels) ./build/hd2d_demo --screenshot out.png --frames 90 \ --pos 25,43.6 --dist 10 --yaw 30 --rain 1 --set dof=0 # scripted capture (hidden) ``` There is no test suite; verification is visual. After any rendering, asset or gameplay change, capture screenshots of the affected area and look at them. Use a Debug build (`-DCMAKE_BUILD_TYPE=Debug`) to get OpenGL errors printed. Captures run hidden: `--screenshot` implies a hidden window + offscreen target (`Window::create(..., visible = false)`, `OffscreenTarget`, `Renderer::setOutputFramebuffer`) and ignores keyboard/mouse, so they never pop up on or react to the user's desktop. Add `--show` only if you really need to watch a capture. New capture paths in any app must keep this behaviour. ## Map | Path | What | | --- | --- | | `engine/include/hd2d/`, `engine/src/` | engine library (`Renderer`, `Terrain`, `BillboardBatch`, `SpriteAtlas`, `ModelLibrary`/`ModelBatch`, `Water`, `ParticleSystem`, `Weather`, `DayCycle`, `GroundOcclusion`, `DebugUI`) | | `assets/shaders/` | GLSL; `common.glsl` holds the shared `Frame` UBO and lighting helpers | | `demo/` | meadow scene: terrain layout, prop scattering, bridge, fires, player movement | | `tools/pixellab.py` + `tools/assets.json` | pixel-art generation (PixelLab API, key in `.env`) | | `tools/scenery_textures.py` | high-res painted textures for models | | `tools/blender_scenery.py` | procedural 3D models → `assets/models/scenery.glb` | ## Rules - `FrameUBO` in `engine/src/Renderer.cpp` must mirror `Frame` in `assets/shaders/common.glsl` exactly (std140, vec4/mat4 only); update the `static_assert` size when adding fields. - `BillboardInstance` (`Billboard.h`, 64 bytes = four vec4s) must match the attributes in `billboard.vert` and the VAO in `Billboard.cpp`; keep new fields in vec4-sized groups, update the `static_assert`, and keep the defaults rendering exactly like the old whole-texture sprite. - `pixelart.glsl` uses derivatives: include it only in fragment shaders. - Game UI is `hd2d::ui` (`UI.h`): ImDrawList only, sizes in 1080p px × `scaleFor(viewport)`, OFL fonts in `assets/fonts/`; verify with `--ui-demo` captures (`--frames 120` mid-reveal, `420` revealed). - Use GL 4.5 DSA calls (`glCreate*`, `glNamed*`, `glTexture*`) like the rest of the code. Shaders hot-reload with F5. - Shaders and assets load from `HD2D_ASSET_DIR` (demo, set by CMake to `assets/`); the `hd2d` target exports `HD2D_ENGINE_ASSET_DIR` for parent projects that `add_subdirectory` the engine (demo off by default there). - Generated files (`assets/textures/*`, `assets/models/*`) come from scripts in `tools/`; change the script, not the output. - PixelLab calls cost credits: check `--balance`, reuse `tile_id`s, and do not regenerate assets that already exist unless asked. - The Blender script only touches its `HD2D_Scenery` collection; keep it that way when running it inside a user's open Blender session. - New tunables go in `RenderSettings` (or the owning class), get a slider in `DebugUI.cpp`, and, if useful for captures, an entry in `applySetting` in `demo/main.cpp`. - Update `README.md` / `docs/ASSET_GUIDE.md` when behavior or conventions change.