OpenGL 3 and OpenGL 4 with GLSL
Dependency pin update only; no example changes, rendered output unchanged.
eglSwapBuffers reports a failed post as EGL_BAD_NATIVE_WINDOW per
EGL 1.5 section 3.10.4 on every backend (it returned EGL_FALSE with no
error code before), and the Wayland backend of the vendored EGL was
brought up to the X11 one. Example50 itself is unaffected - it runs on
Windows, where nothing changed in rendering.Dependency pin update only; no example changes, rendered output unchanged.
eglSwapBuffers has nothing to swap - the window stays
blank while the example runs. Example50's SDR outputs (sRGB, linear) open
exactly such plain window surfaces; v1.0.14 makes window surfaces
back-buffered by default again, as EGL 1.5 section 3.5.1 requires. The
HDR outputs present through Vulkan and were not affected. The sibling
layout (the documented multi-repo development setup) is unaffected and was
already using the working-tree checkout.Dependency pin update only; no example changes, rendered output unchanged.
Comment and refactoring pass over four examples; rendered output unchanged. Requires GLUS v1.1.4; Example50 vendors EGL v1.0.11.
trace() into five named phases; Example46 update() into
three passes with a shared bindGroupMaterial; Example33 init() into
the eight IBL-pipeline phases its banners already described; Example28
init() into eight named stages.Build-system fixes, dependency pins and CI; no example code changes.
AGL
framework, removed from modern macOS SDKs, so every example executable
failed to link on a current Mac. The FetchContent patch now drops the AGL
link. 51 of 52 examples build and link on Apple Silicon; Example50 requires
the Vulkan SDK and remains Windows/Linux only.Dependency and static-analysis pass across all 52 examples:
v1.0.1 and Example50's EGL at the moving main ref; both now track the tagged releases above.count * stride products across the examples so the multiplication happens in the wide type rather than being widened after a narrow 32-bit multiply.OutputColorspaceCandidate to remove 8 bytes of padding; winProc now has an explicit default:.#define literals (operator-precedence hazard).cppcheck and clang-tidy analysis lanes and AGENTS.md.Security and correctness fixes across all 52 examples:
glMemoryBarrier calls in Examples 21, 30, 36, 45.glUniform4fv/glUniform2fv count (vec4/vec2 elements, not floats) in Example15.glDeleteRenderbuffers on texture names in Examples 12, 34.glusFileLoadText in Examples 47, 51, 52.glViewport in Example27 reshape().glDrawBuffer(GL_COLOR_ATTACHMENT0) on default framebuffer in Examples 28, 31.FetchContent_Populate in root CMakeLists.txt.glusGltfLoadScene / glusGltfGetCgltfData). GLUS now provides cgltf + stb_image and exposes GLUS_SHADER_DIR; the copied OpenGL/GLUS/ folder is gone.../GLUS when present, otherwise fetched from McNopper/GLUS.The project is distributed under the MIT License — see LICENSE.
These examples are built on GLUS (MIT), which
bundles glfw, glew, cgltf and stb — their notices live in the
GLUS third-party file.
The dependencies and bundled assets added by this repository — McNopper/EGL
(MIT) and the Einstein / phoenix 3D models (CC-BY-4.0) — are documented in
THIRD-PARTY.md; per-example attributions are noted in each
example's section below.
Required:
Check if CMake is installed:
cmake --version
Should show version 3.14 or higher.
Check if Git is installed:
git --version
Dependencies (GLUS, GLFW and GLEW) are automatically downloaded and built via CMake FetchContent. GLUS is taken from the sibling local checkout ../GLUS when present (multi-repo development layout), and otherwise fetched from its own repository at github.com/McNopper/GLUS. GLUS in turn provides cgltf and stb_image, and exposes its shader directory through the GLUS_SHADER_DIR compile definition.
Windows (Visual Studio):
mkdir build && cd build
cmake ..
cmake --build .
Linux / macOS:
mkdir build && cd build
cmake ..
make
Executables will be in the Binaries/ directory.
All dependencies are automatically fetched and built:
All examples demonstrate various OpenGL 3.x and 4.x features with GLSL shaders.













































Real-time global illumination using voxel cone tracing based on Crassin et al. 2011. The Sponza scene is first voxelized into a 256³ RGBA16F 3D texture with a dominant-axis geometry shader. Mipmaps are generated for the voxel grid, then the final pass traces six diffuse cones plus a specular cone per fragment to compute indirect illumination, ambient occlusion, and specular reflections. A small emissive sphere orbits the scene as the sole indirect light source (Space to pause/resume).
Simplifications vs. the original paper:
| Aspect | Paper | This implementation |
|---|---|---|
| Scene representation | Sparse Voxel Octree (SVO) — adaptive, high-resolution | Flat 256³ RGBA16F 3D texture — simpler, lower resolution |
| Voxel filtering | Anisotropic pre-filtering: per-face directional radiance propagated up the octree | Isotropic glGenerateMipmap box filter |
| Radiance storage | Per-face (6 directions) for directional shadowing | Single isotropic value per voxel |
| Voxel write | Atomic accumulation when multiple triangles cover the same voxel | Plain imageStore (last-write-wins) |

What already exists. Odd-even transposition sort was described by Knuth (1973) and maps directly to parallel hardware. Shearsort — sorting a 2D grid by alternating row and column passes — was introduced by Scherson & Sen (1986). Extending it to a 3D grid by cycling through three axis passes is a straightforward generalisation studied in the parallel computing literature. GPU sort implementations (bitonic, radix, odd-even) have existed since the mid-2000s.
What is the application insight. Using a 3D RGBA8 texture directly as the sort array, where the sort key of each element is its own colour — Red sorted along X, Green along Y, Blue along Z — with no index remapping. The data set is the complete RGB8 lattice: all N³ distinct colours, one per voxel, so every axis sort has a unique total order.
| Dispatch | Sort key | Converges to |
|---|---|---|
| X-axis lines | Red (R) | R increases with x |
| Y-axis lines | Green (G) | G increases with y |
| Z-axis lines | Blue (B) | B increases with z |
What makes it elegant. The choice of data produces a unique fixed-point property: the only configuration that simultaneously satisfies all three axis sorts is the perfect RGB cube,
texel(x, y, z).rgb = (x, y, z) × 255 / (N − 1)
This means correctness is self-evident — if the rendered cube shows a smooth
RGB gradient the sort has converged correctly, with no checksum or external
oracle needed. Starting from random colour noise the cube crystallises step by
step, making convergence visually striking. Corners map to pure colours:
(0,0,0)→black, (1,0,0)→red, (0,1,0)→green, (0,0,1)→blue,
(1,1,1)→white; the main diagonal becomes the greyscale ramp.
GL 4.6 highlight. The sort runs in a compute shader using shared memory
and two barrier() calls per pass (one after the read phase, one after the
write phase). At startup GL_MAX_COMPUTE_WORK_GROUP_SIZE and
GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS are queried and GRID_N is capped at 32
(32³ = 32 768 points, fits in shared memory on all hardware). Controls: Space
to start, +/- to adjust step delay, R to reshuffle.


Loads a glTF 2.0 scene and renders it with physically-based metallic-roughness shading and Image-Based Lighting (IBL). Scene loading (parse, mesh upload, node hierarchy, materials, textures) is handled by the GLUS glTF loader (glusGltfLoadScene); the IBL precomputation pipeline is provided by GLUS (glusIblBuild*). The glTF / IBL shaders are loaded from the GLUS shader directory (GLUS_SHADER_DIR).
Usage:
Example48 [model.gltf] [panorama.hdr]
Defaults to einstein/scene.gltf and sunny_rose_garden_4k.hdr in the working directory.
Controls: ↑/↓ camera height · ←/→ orbit speed · +/− zoom
Third-party licenses:
THIRD-PARTY.md.Model: This work is based on "Albert Einstein" by pattarrian licensed under CC-BY-4.0

Extends Example48 with TRS node animation and skeletal skinning. Animation interpolation (STEP, LINEAR, CUBICSPLINE) for vec3 and quaternion tracks is provided by the GLUS library (glusAnimationSample*).
Usage:
Example49 [model.gltf] [panorama.hdr]
Defaults to phoenix/scene.gltf and sunny_rose_garden_4k.hdr in the working directory.
Controls: ↑/↓ camera height · ←/→ orbit speed · +/− zoom
Third-party licenses:
THIRD-PARTY.md.Model: This work is based on "phoenix bird" by NORBERTO-3D licensed under CC-BY-4.0

Extends Example49. New in this example:
EGL_GL_COLORSPACE_BT2020_PQ_EXT (HDR10) and falls back through scRGB linear / BT.2020 linear / Display-P3 / sRGB depending on what the driver and surface advertise.Example50.log written next to the executable, listing EGL vendor / version, all advertised colorspace extensions, and which candidate was used to create the surface.Usage:
Example50 [model.gltf] [panorama.hdr]
Defaults to phoenix/scene.gltf and sunny_rose_garden_4k.hdr in the working directory.
Controls: ↑/↓ camera height · ←/→ orbit speed · +/− zoom
Requires: an HDR-capable display with HDR enabled in Windows. On systems without HDR the app transparently falls back to sRGB output.
Third-party licenses:
THIRD-PARTY.md.Model: This work is based on "phoenix bird" by NORBERTO-3D licensed under CC-BY-4.0

Implements the KHR_gaussian_splatting glTF 2.0 extension. Loads a .gltf file containing 3D Gaussian splats and renders them in real time using OpenGL 4.6 compute shaders and instanced rendering.
glusSHBuildRotation1f/2f/3f).Usage:
Example51 [path/to/model.gltf]
Defaults to ../Binaries/lego.gltf.
Controls: ←/→ orbit · ↑/↓ elevation · Page Up/Down zoom · Space toggles auto-rotation (off by default)
References:

A variant of Example51 that produces an identical image but handles the view-dependent spherical-harmonics colour of rotated splat nodes differently:
Both are mathematically identical (verified to machine precision); Example52 is faster — one mat3·vec3 per splat instead of rotating all SH coefficients, with no CPU rotation matrices or extra SSBO storage.
Usage: Example52 [path/to/model.gltf] (defaults to ../Binaries/lego.gltf)
Controls: ←/→ orbit · ↑/↓ elevation · Page Up/Down zoom · Space toggles auto-rotation (off by default)
377 followers · starred Mar 2014
20 followers · starred Aug 2014
26 followers · starred Jul 2015
4 followers · starred Mar 2020
OpenGL 3 and OpenGL 4 with GLSL
Dependency pin update only; no example changes, rendered output unchanged.
eglSwapBuffers reports a failed post as EGL_BAD_NATIVE_WINDOW per
EGL 1.5 section 3.10.4 on every backend (it returned EGL_FALSE with no
error code before), and the Wayland backend of the vendored EGL was
brought up to the X11 one. Example50 itself is unaffected - it runs on
Windows, where nothing changed in rendering.Dependency pin update only; no example changes, rendered output unchanged.
eglSwapBuffers has nothing to swap - the window stays
blank while the example runs. Example50's SDR outputs (sRGB, linear) open
exactly such plain window surfaces; v1.0.14 makes window surfaces
back-buffered by default again, as EGL 1.5 section 3.5.1 requires. The
HDR outputs present through Vulkan and were not affected. The sibling
layout (the documented multi-repo development setup) is unaffected and was
already using the working-tree checkout.Dependency pin update only; no example changes, rendered output unchanged.
Comment and refactoring pass over four examples; rendered output unchanged. Requires GLUS v1.1.4; Example50 vendors EGL v1.0.11.
trace() into five named phases; Example46 update() into
three passes with a shared bindGroupMaterial; Example33 init() into
the eight IBL-pipeline phases its banners already described; Example28
init() into eight named stages.Build-system fixes, dependency pins and CI; no example code changes.
AGL
framework, removed from modern macOS SDKs, so every example executable
failed to link on a current Mac. The FetchContent patch now drops the AGL
link. 51 of 52 examples build and link on Apple Silicon; Example50 requires
the Vulkan SDK and remains Windows/Linux only.Dependency and static-analysis pass across all 52 examples:
v1.0.1 and Example50's EGL at the moving main ref; both now track the tagged releases above.count * stride products across the examples so the multiplication happens in the wide type rather than being widened after a narrow 32-bit multiply.OutputColorspaceCandidate to remove 8 bytes of padding; winProc now has an explicit default:.#define literals (operator-precedence hazard).cppcheck and clang-tidy analysis lanes and AGENTS.md.Security and correctness fixes across all 52 examples:
glMemoryBarrier calls in Examples 21, 30, 36, 45.glUniform4fv/glUniform2fv count (vec4/vec2 elements, not floats) in Example15.glDeleteRenderbuffers on texture names in Examples 12, 34.glusFileLoadText in Examples 47, 51, 52.glViewport in Example27 reshape().glDrawBuffer(GL_COLOR_ATTACHMENT0) on default framebuffer in Examples 28, 31.FetchContent_Populate in root CMakeLists.txt.glusGltfLoadScene / glusGltfGetCgltfData). GLUS now provides cgltf + stb_image and exposes GLUS_SHADER_DIR; the copied OpenGL/GLUS/ folder is gone.../GLUS when present, otherwise fetched from McNopper/GLUS.The project is distributed under the MIT License — see LICENSE.
These examples are built on GLUS (MIT), which
bundles glfw, glew, cgltf and stb — their notices live in the
GLUS third-party file.
The dependencies and bundled assets added by this repository — McNopper/EGL
(MIT) and the Einstein / phoenix 3D models (CC-BY-4.0) — are documented in
THIRD-PARTY.md; per-example attributions are noted in each
example's section below.
Required:
Check if CMake is installed:
cmake --version
Should show version 3.14 or higher.
Check if Git is installed:
git --version
Dependencies (GLUS, GLFW and GLEW) are automatically downloaded and built via CMake FetchContent. GLUS is taken from the sibling local checkout ../GLUS when present (multi-repo development layout), and otherwise fetched from its own repository at github.com/McNopper/GLUS. GLUS in turn provides cgltf and stb_image, and exposes its shader directory through the GLUS_SHADER_DIR compile definition.
Windows (Visual Studio):
mkdir build && cd build
cmake ..
cmake --build .
Linux / macOS:
mkdir build && cd build
cmake ..
make
Executables will be in the Binaries/ directory.
All dependencies are automatically fetched and built:
All examples demonstrate various OpenGL 3.x and 4.x features with GLSL shaders.













































Real-time global illumination using voxel cone tracing based on Crassin et al. 2011. The Sponza scene is first voxelized into a 256³ RGBA16F 3D texture with a dominant-axis geometry shader. Mipmaps are generated for the voxel grid, then the final pass traces six diffuse cones plus a specular cone per fragment to compute indirect illumination, ambient occlusion, and specular reflections. A small emissive sphere orbits the scene as the sole indirect light source (Space to pause/resume).
Simplifications vs. the original paper:
| Aspect | Paper | This implementation |
|---|---|---|
| Scene representation | Sparse Voxel Octree (SVO) — adaptive, high-resolution | Flat 256³ RGBA16F 3D texture — simpler, lower resolution |
| Voxel filtering | Anisotropic pre-filtering: per-face directional radiance propagated up the octree | Isotropic glGenerateMipmap box filter |
| Radiance storage | Per-face (6 directions) for directional shadowing | Single isotropic value per voxel |
| Voxel write | Atomic accumulation when multiple triangles cover the same voxel | Plain imageStore (last-write-wins) |

What already exists. Odd-even transposition sort was described by Knuth (1973) and maps directly to parallel hardware. Shearsort — sorting a 2D grid by alternating row and column passes — was introduced by Scherson & Sen (1986). Extending it to a 3D grid by cycling through three axis passes is a straightforward generalisation studied in the parallel computing literature. GPU sort implementations (bitonic, radix, odd-even) have existed since the mid-2000s.
What is the application insight. Using a 3D RGBA8 texture directly as the sort array, where the sort key of each element is its own colour — Red sorted along X, Green along Y, Blue along Z — with no index remapping. The data set is the complete RGB8 lattice: all N³ distinct colours, one per voxel, so every axis sort has a unique total order.
| Dispatch | Sort key | Converges to |
|---|---|---|
| X-axis lines | Red (R) | R increases with x |
| Y-axis lines | Green (G) | G increases with y |
| Z-axis lines | Blue (B) | B increases with z |
What makes it elegant. The choice of data produces a unique fixed-point property: the only configuration that simultaneously satisfies all three axis sorts is the perfect RGB cube,
texel(x, y, z).rgb = (x, y, z) × 255 / (N − 1)
This means correctness is self-evident — if the rendered cube shows a smooth
RGB gradient the sort has converged correctly, with no checksum or external
oracle needed. Starting from random colour noise the cube crystallises step by
step, making convergence visually striking. Corners map to pure colours:
(0,0,0)→black, (1,0,0)→red, (0,1,0)→green, (0,0,1)→blue,
(1,1,1)→white; the main diagonal becomes the greyscale ramp.
GL 4.6 highlight. The sort runs in a compute shader using shared memory
and two barrier() calls per pass (one after the read phase, one after the
write phase). At startup GL_MAX_COMPUTE_WORK_GROUP_SIZE and
GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS are queried and GRID_N is capped at 32
(32³ = 32 768 points, fits in shared memory on all hardware). Controls: Space
to start, +/- to adjust step delay, R to reshuffle.


Loads a glTF 2.0 scene and renders it with physically-based metallic-roughness shading and Image-Based Lighting (IBL). Scene loading (parse, mesh upload, node hierarchy, materials, textures) is handled by the GLUS glTF loader (glusGltfLoadScene); the IBL precomputation pipeline is provided by GLUS (glusIblBuild*). The glTF / IBL shaders are loaded from the GLUS shader directory (GLUS_SHADER_DIR).
Usage:
Example48 [model.gltf] [panorama.hdr]
Defaults to einstein/scene.gltf and sunny_rose_garden_4k.hdr in the working directory.
Controls: ↑/↓ camera height · ←/→ orbit speed · +/− zoom
Third-party licenses:
THIRD-PARTY.md.Model: This work is based on "Albert Einstein" by pattarrian licensed under CC-BY-4.0

Extends Example48 with TRS node animation and skeletal skinning. Animation interpolation (STEP, LINEAR, CUBICSPLINE) for vec3 and quaternion tracks is provided by the GLUS library (glusAnimationSample*).
Usage:
Example49 [model.gltf] [panorama.hdr]
Defaults to phoenix/scene.gltf and sunny_rose_garden_4k.hdr in the working directory.
Controls: ↑/↓ camera height · ←/→ orbit speed · +/− zoom
Third-party licenses:
THIRD-PARTY.md.Model: This work is based on "phoenix bird" by NORBERTO-3D licensed under CC-BY-4.0

Extends Example49. New in this example:
EGL_GL_COLORSPACE_BT2020_PQ_EXT (HDR10) and falls back through scRGB linear / BT.2020 linear / Display-P3 / sRGB depending on what the driver and surface advertise.Example50.log written next to the executable, listing EGL vendor / version, all advertised colorspace extensions, and which candidate was used to create the surface.Usage:
Example50 [model.gltf] [panorama.hdr]
Defaults to phoenix/scene.gltf and sunny_rose_garden_4k.hdr in the working directory.
Controls: ↑/↓ camera height · ←/→ orbit speed · +/− zoom
Requires: an HDR-capable display with HDR enabled in Windows. On systems without HDR the app transparently falls back to sRGB output.
Third-party licenses:
THIRD-PARTY.md.Model: This work is based on "phoenix bird" by NORBERTO-3D licensed under CC-BY-4.0

Implements the KHR_gaussian_splatting glTF 2.0 extension. Loads a .gltf file containing 3D Gaussian splats and renders them in real time using OpenGL 4.6 compute shaders and instanced rendering.
glusSHBuildRotation1f/2f/3f).Usage:
Example51 [path/to/model.gltf]
Defaults to ../Binaries/lego.gltf.
Controls: ←/→ orbit · ↑/↓ elevation · Page Up/Down zoom · Space toggles auto-rotation (off by default)
References:

A variant of Example51 that produces an identical image but handles the view-dependent spherical-harmonics colour of rotated splat nodes differently:
Both are mathematically identical (verified to machine precision); Example52 is faster — one mat3·vec3 per splat instead of rotating all SH coefficients, with no CPU rotation matrices or extra SSBO storage.
Usage: Example52 [path/to/model.gltf] (defaults to ../Binaries/lego.gltf)
Controls: ←/→ orbit · ↑/↓ elevation · Page Up/Down zoom · Space toggles auto-rotation (off by default)
377 followers · starred Mar 2014
20 followers · starred Aug 2014
26 followers · starred Jul 2015
4 followers · starred Mar 2020