# gren A small modern OpenGL (4.5 core) playground written in C++20. Focus: a simple, hackable renderer with hot-reloadable shaders, an orbit camera, and utilities for building meshes (quad/cube/ico and a pluggable terrain mesher). https://git.alidavid.hu/david/gren --- ## Highlights - **OpenGL 4.5 core** via GLFW context. - **Z-up world** (`+Z` is up). Terrain height is written to `Z`. - **Orbit camera** with aspect updates and input wiring. - **Uniform buffers**: - `PerFrame` (view/proj, lighting dir), - `PerObject` (model matrix), - `Material` (base color, etc.). - **Shader hot reload**: shaders are polled each frame; edit files under `assets/shaders` and see changes immediately. - **Mesh helpers**: unit quad, cube, icosahedron; GPU wrapper (`Graphics::MeshGL`) and pipeline abstraction. - **Skybox pass**: inside-out cube with depth/state tweaks. - **Procedural terrain API**: build a grid from a user-supplied height function. --- ## Repository layout ``` assets/ shaders/ GLSL vertex/fragment shaders bin/ Built binaries external/ Third-party code (if any) obj/ Intermediate objects src/ C++ sources (entry point: main.cpp) Makefile (if present) convenience build ``` --- ## Build ### Requirements - C++20 compiler (g++ 12+/clang 15+) - OpenGL 4.5 capable GPU/driver - GLFW 3.x (window/context/input) - GLM (math) - A GL loader (provided in the project via `glfwx::load_gl_or_throw()`) On Debian/Ubuntu: ```bash sudo apt update sudo apt install build-essential pkg-config libglfw3-dev libglm-dev ``` ### Compile If a `Makefile` is present: ```bash make -j ``` Otherwise, a minimal one-liner build (adjust include/lib paths as needed): ```bash g++ -std=gnu++20 -O2 -Wall -Wextra -Iexternal -Isrc \ src/*.cpp -lglfw -ldl -lpthread -o bin/main ``` Run from the repo root (so `assets/` is found): ```bash ./bin/main ``` --- ## Coordinate system - **World up:** `+Z` - **Camera/view:** right-handed - **Front faces:** counter-clockwise (CCW) If lighting looks inverted, verify your mesh winding and the Z-up assumption. --- ## Shader hot reload `Graphics::ShaderManager` polls shader files every frame: - Edit anything under `assets/shaders/*.vert|*.frag`. - The program re-links on the next poll; errors are printed to stdout/stderr. --- ## Procedural terrain (plug-in height function) Build a terrain mesh by supplying a height function `(x, y) -> z`: ```cpp #include #include "Asset.hpp" // Example: gentle ridges auto height = [](float x, float y) { using std::sin; using std::cos; return sin(x * 0.05f) * cos(y * 0.05f) * 5.0f; }; // Generate a 256x256 grid (1 unit spacing), centered-ish asset::Mesh terrain = asset::make_terrain( /*W=*/256, /*H=*/256, /*dx=*/1.0f, /*dy=*/1.0f, height, /*genNormals=*/true, /*genUVs=*/true, /*x0=*/-128.0f, /*y0=*/-128.0f); Graphics::MeshGL gpuTerrain; gpuTerrain.upload(terrain); ``` Notes: - The grid lies in the **XY** plane; height is written to **Z**. - Indices use CCW winding in XY so normals point `+Z`. - Normals are computed as area-weighted sums of face normals and normalized per vertex. --- ## Camera An orbit camera is provided. Controls are installed through the GLFW hook utilities. See the implementation files for the exact bindings. --- ## Development tips - Keep VAO attribute layouts consistent across meshes to avoid shader variant recompiles on some drivers. - After the skybox pass, restore depth writes and CCW front faces before drawing regular geometry. - For constant-screen-size debug gizmos, scale by distance in the vertex shader rather than world scale. --- ## Roadmap - Entity/placement layer on top of the tile map (sprite atlas already integrated). - Terrain polish: domain-warped noise presets, LOD chunks, and skirts. - Shadowing pass (directional light; start with simple shadow mapping). - Optional HTTP read-only clone and tarball snapshots via cgit configuration.