Files
gren/README.md
David Ali a7731b2762 fix: typo
2026-01-09 13:55:52 +01:00

3.9 KiB

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:

sudo apt update
sudo apt install build-essential pkg-config libglfw3-dev libglm-dev

Compile

If a Makefile is present:

make -j

Otherwise, a minimal one-liner build (adjust include/lib paths as needed):

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):

./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:

#include <cmath>
#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.