Back to projects

GPU Path Tracing

GLSL Path Tracer

A GPU-accelerated global illumination path tracer implemented entirely in GLSL fragment shaders using OpenGL 3.3 and Qt 6. Each pixel is a fragment shader invocation that traces rays through the scene and progressively accumulates light across frames.

GLSL 3.30 OpenGL 3.3 Qt 6 C++17 Global Illumination MIS

Overview

The renderer runs the full path tracing loop on the GPU. The CPU side uses Qt and C++ to load scene data, upload uniforms, manage OpenGL resources, and render a full-screen quad. The fragment shader performs ray-scene intersection, BSDF sampling, light sampling, multiple importance sampling, and frame accumulation.

Architecture

CPU Host and GPU Shader Pipeline

The project separates host orchestration from shader-side rendering. C++ and Qt upload scene state and drive the render loop; GLSL modules implement the actual path tracing logic.

CPU (Qt / C++)                 GPU (GLSL Fragment Shader)
----------------              ---------------------------------------
Upload uniforms           ->   pathtracer.defines.glsl        structs, math, RNG
Upload scene data         ->   pathtracer.intersection.glsl   ray-scene intersection
Render full-screen quad   ->   pathtracer.bsdf.glsl           material / BSDF eval
Accumulate frames         ->   pathtracer.sampleWarping.glsl  sampling functions
                               pathtracer.light.glsl          lights and MIS
                               pathtracer.frag.glsl           Li_Naive / Li_Full

Progressive rendering blends the current sample with the accumulated result over time.

accumulated = mix(lastFrame, currentSample, 1.0 / float(iteration));

Features

Integrators and Lighting

Li_Naive

Iterative path tracing that accumulates emitted radiance when a path directly hits a light. This baseline integrator does not perform direct light sampling.

Li_Full

Full path tracing integrator with direct lighting and global illumination at every bounce.

Supported Light Sources

Rectangle area lights, sphere area lights, point lights, spot lights, and HDR environment lighting. Area lights use explicit sampling; point and spot lights are evaluated directly; environment lighting uses hemisphere sampling.

Sampling

Multiple Importance Sampling

ComputeDirectLight_MIS combines light-source sampling and BSDF sampling using the power heuristic. Area lights use full MIS, point and spot lights use light sampling only, and specular surfaces skip MIS to avoid double-counting direct emission.

float PowerHeuristic(float nf, float fPdf, float ng, float gPdf)
{
    float f = nf * fPdf;
    float g = ng * gPdf;
    return (f * f) / (f * f + g * g);
}

Materials

BSDF Material System

Diffuse

Lambertian evaluation with cosine-weighted hemisphere sampling.

Specular Reflection

Perfect mirror reflection using reflect(wo).

Specular Transmission and Glass

Snell's law refraction with Fresnel reflection/transmission blending for dielectric glass.

Microfacet GGX

Trowbridge-Reitz normal distribution with Smith shadowing-masking for rough mirror materials.

Geometry

Ray-Scene Intersection

The renderer supports multiple primitive types, all transformed through inverse transform matrices so rays can be evaluated in object space.

Analytic Primitives

Rectangle, box with slab intersection, and sphere with quadratic analytic intersection.

Triangle Meshes

Moller-Trumbore triangle intersection with mesh data packed into sampler2D textures for shader access.

Texture Support

Material Maps

Albedo Maps

Gamma-corrected color textures for surface base color.

Normal Maps

Tangent-space normal maps transformed through TBN for local detail.

Roughness Maps

Texture-driven roughness for microfacet material variation.

Tech Stack

Implementation Details

glsl/
  pathtracer.defines.glsl       constants, structs, math helpers, RNG
  pathtracer.sampleWarping.glsl disk / hemisphere / sphere sampling
  pathtracer.intersection.glsl  primitive intersection
  pathtracer.bsdf.glsl          f(), Sample_f(), Pdf()
  pathtracer.light.glsl         Sample_Li(), Pdf_Li(), MIS
  pathtracer.frag.glsl          Li_Naive, Li_Full, main()
src/
  scene/                        scene loading, geometry, lights, materials
  mygl.cpp                      OpenGL setup, render loop, framebuffer ping-pong
jsons/                          scene description files
images/                         render outputs