153 lines
3.9 KiB
Markdown
153 lines
3.9 KiB
Markdown
# 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 <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.
|