Skip to content

appleweiping/games202

Repository files navigation

GAMES202 — High-Quality Real-Time Rendering (offline CPU reimplementation)

A from-scratch, CPU-only software implementation of the five GAMES202 programming assignments — an independent build that is part of a csdiy.wiki full-catalog effort.

status language license

Overview

GAMES202 — High-Quality Real-Time Rendering (Lingqi Yan, UC Santa Barbara) teaches the algorithms behind a modern real-time renderer: soft shadows, precomputed global illumination, screen-space effects, physically based shading, and real-time ray tracing with denoising. The official homeworks ship as an interactive WebGL / GLSL framework that needs a GPU and a browser.

This repository re-implements the core algorithm of every assignment as an offline software renderer in pure Python + NumPy, so each one actually runs on a CPU-only machine and produces a real, committed output image / measured result. The interactive GPU/WebGL harness is documented as a partial (see Scope & partials); every algorithm here is genuinely executed and verified, no fabricated renders.

Results (measured on Windows, CPU-only, NumPy)

# Assignment Core implemented Measured result
HW1 Real-time shadows shadow map + PCF + PCSS (blocker search → penumbra → variable PCF) soft, contact-hardening penumbrae over a 9.3k-tri scene; hard vs PCF vs PCSS
HW2 PRT (precomputed radiance transfer) order-2 SH env projection + per-vertex diffuse transport (unshadowed + ray-traced shadowed) 745,744 BVH visibility rays; white-furnace energy check radiance/albedo = 1.0007
HW3 Screen-space SSAO + SSR on a deferred G-buffer SSAO mean AO 0.907; SSR reflection hit on 50.8 % of the reflective floor
HW4 Kulla-Conty BRDF GGX directional-albedo LUT + multiple-scattering energy compensation single-scatter GGX loses 20.6 % energy (down to 0.40 at roughness 1.0); KC restores reflectance to 1.0000
HW5 Real-time ray tracing Monte-Carlo path tracer (NEE) + edge-avoiding à-trous denoiser PSNR 1 spp → denoised: 23.55 dB → 34.08 dB (+10.53 dB) vs 256-spp reference

HW1 — Shadow mapping / PCF / PCSS

Hard shadow map (crisp) → PCF (uniform soft edge) → PCSS (penumbra widens with blocker distance, sharp at contact):

PCSS

HW2 — Precomputed Radiance Transfer

Diffuse PRT under a low-frequency environment. Left→right the shadowed transport adds self-shadowing in the torus hole and a soft contact shadow on the ground that the unshadowed transport cannot represent:

shadowed (ray-traced visibility) unshadowed
shadow unshadow

HW3 — SSAO + SSR

Deferred G-buffer, hemisphere-kernel SSAO, and screen-space reflections marched in view space with binary-search refinement:

SSR final

HW4 — Kulla-Conty energy compensation

The white-furnace test: with only single scattering (top) a GGX metal darkens as roughness grows because masking-shadowing discards energy; adding the Kulla-Conty multiple-scattering lobe (bottom) conserves energy at every roughness.

single scatter only (energy lost) + Kulla-Conty multi-scatter (conserved)
no comp comp

Precomputed directional-albedo LUT E(mu, roughness) and E_avg(roughness):

LUT

HW5 — Path tracing + à-trous denoising

1 spp path trace (noisy) → à-trous reconstruction → high-spp reference:

compare

Implemented assignments

  • HW1 — Real-time shadows: light-space depth map, hard shadows with slope-scaled bias, PCF (Poisson disk), and PCSS (blocker search → similar- triangles penumbra estimate → variable-radius PCF).
  • HW2 — PRT: project HDR environment maps onto 9 real SH coefficients; precompute per-vertex diffuse transport vectors (unshadowed analytic cosine lobe, and shadowed via BVH ray-cast visibility); relight as a 9-D dot product incl. a rotating-light sequence.
  • HW3 — Screen space: G-buffer deferred shading; SSAO (view-space hemisphere kernel + range check + blur); SSR (view-space reflection ray marched in screen space with binary-search hit refinement).
  • HW4 — Kulla-Conty: GGX microfacet BRDF (D/G/F), importance-sampled directional-albedo LUT, E_avg, and the multiple-scattering compensation lobe; verified with a white-furnace energy test; environment-lit metal spheres.
  • HW5 — RTRT + denoise: vectorized Monte-Carlo path tracer (Cornell box) and the edge-avoiding à-trous wavelet filter (albedo demodulation + joint luminance/normal/position weights), scored by PSNR vs a high-spp reference.

Project structure

games202/
├── common/              # shared CPU rendering core
│   ├── geometry.py      #   vectors, procedural meshes, camera matrices
│   ├── rasterizer.py    #   software triangle rasterizer + G-buffer
│   ├── raytracer.py     #   BVH + batched vectorized occlusion queries
│   ├── sh.py            #   order-2 real spherical harmonics
│   ├── brdf.py          #   GGX microfacet BRDF + Kulla-Conty
│   └── img.py           #   PNG I/O, tone mapping, PSNR
├── hw1_shadow/          # shadow map / PCF / PCSS
├── hw2_prt/             # precomputed radiance transfer
├── hw3_screenspace/     # SSAO + SSR
├── hw4_kulla_conty/     # microfacet energy compensation
├── hw5_rtrt_denoise/    # path tracer + à-trous denoiser
├── results/             # all rendered PNGs + LUT figure (committed)
└── run_all.py           # run every assignment

How to run

# uses the shared csdiy Python 3.11 env (numpy / pillow / matplotlib):
#   D:\Project\_csdiy\.venv-ml\Scripts\python.exe
pip install -r requirements.txt

python run_all.py            # run everything, regenerate results/
python run_all.py hw4 hw5    # or a subset
python hw1_shadow/run.py     # or one assignment directly

Everything is single-threaded NumPy; approximate CPU wall-times: HW1 ~10 s, HW2 ~65 s (745k visibility rays), HW3 ~35 s, HW4 ~55 s, HW5 a few minutes (high-spp reference path trace).

Verification

Each assignment prints measured quantities and writes images to results/:

  • HW1 prints mean surface visibility per technique; PCSS penumbra visibly widens with blocker distance (results/hw1_{hard,pcf,pcss}.png).
  • HW2 white-furnace energy check radiance/albedo = 1.0007 (expect 1.0), confirming the SH projection + cosine-lobe convolution are energy-correct.
  • HW3 SSAO mean AO 0.907; SSR hits 50.8 % of the reflective floor.
  • HW4 furnace test table — single-scatter reflectance 0.9994 → 0.4036 as roughness 0.1 → 1.0; Kulla-Conty compensated reflectance 1.0000 at every roughness (energy conservation).
  • HW5 against a 256-spp reference, PSNR improves from 23.55 dB (raw 1 spp) to 34.08 dB after the à-trous denoiser (+10.53 dB); the denoised image is visually as clean as the reference (results/hw5_*.png).

Tech stack

Python 3.11, NumPy (all rendering math), Pillow (PNG), Matplotlib (LUT figure). No GPU, no external rendering libraries — the rasterizer, BVH ray tracer, path tracer, SH, and BRDF are all implemented from scratch in common/.

Key ideas / what I learned

  • PCSS turns a shadow map into soft shadows by estimating a penumbra width from the average blocker depth (similar triangles) and scaling the PCF kernel.
  • PRT moves the lighting integral offline: a per-vertex SH transport vector bakes cosine + visibility, so relighting is a cheap dot product — and the shadowed transport is what makes self-shadowing "free" at runtime.
  • Screen-space methods trade correctness for speed by working in the G-buffer: SSAO and SSR both march/sample in view space and must handle depth discontinuities and off-screen misses.
  • Kulla-Conty shows why naive microfacet metals look too dark and fixes it with an energy-conserving multiple-scattering term derived from a precomputed directional-albedo table — verifiable exactly with a furnace test.
  • à-trous / SVGF-style denoising reconstructs a 1-spp path trace by filtering albedo-demodulated irradiance with edge-stopping weights from the G-buffer.

Scope & partials

The original assignments are interactive WebGL/GLSL programs. This repo implements and verifies the core algorithm of each as an offline CPU renderer producing real images and measured numbers. What is intentionally not reproduced (and why): the real-time GPU shader harness itself — live WebGL frame loop, GLSL fragment shaders, mouse-orbit camera, and interactive frame-rate — because this machine is CPU-only with no GPU/browser rendering target. The algorithmic content (PCSS math, SH transport, SSAO/SSR sampling, Kulla-Conty LUT + compensation, path tracing + à-trous filter) is fully implemented and executed here.

Credits & license

Based on the assignments of GAMES202 — High-Quality Real-Time Rendering by Prof. Lingqi Yan (UC Santa Barbara / GAMES). This repository is an independent educational reimplementation; all course materials and assignment specifications belong to their original authors. Original code in this repo is released under the MIT License.

About

GAMES202 High-Quality Real-Time Rendering - offline CPU reimplementation of all 5 assignments (PCSS shadows, SH-PRT, SSAO/SSR, Kulla-Conty energy compensation, path-tracing + a-trous denoise)

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages