Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

USTC Computer Graphics — Geometry Processing, Imaging & Rendering

A from-scratch implementation of the assignments of USTC "Computer Graphics" (计算机图形学) by Prof. Ligang Liu (刘利刚), covering digital image processing, discrete geometry processing, and physically-based rendering — part of a csdiy.wiki full-catalog build.

status language license

Overview

The course walks from 2D image editing through the core of discrete differential geometry to rendering. Every algorithm here is implemented from scratch in Python (numpy/scipy/PIL) — no graphics libraries, no OpenGL, no mesh toolkits. All inputs (test images and meshes) are generated procedurally so the repo is fully self-contained and reproducible, and every assignment writes a real result image / mesh into results/.

Everything runs on the CPU (this machine has no GPU): the rasterizer, the path tracer and all the sparse-linear-system solves are software. The one inherently interactive/GPU part of the original course — the real-time OpenGL handle-dragging UI — is realized here as verified offline solves that produce the same deformation/parameterization results as static renders (see Partials).

Results (measured on CPU, Windows, Python 3.11 / numpy 2.4)

# Assignment What it does Measured result
a1 Image Warping (IDW / RBF) smooth planar deformation from control points anchor interpolation error 0 (IDW) / 2e-11 px (RBF thin-plate)
a2 Poisson Image Editing seamless cloning via a sparse Poisson solve seam gradient energy 13.12 → 0.12 (≈100× smoother)
a3 Minimal Surface zero-mean-curvature soap film, fixed boundary area 20.60 → 5.40 (−73.8%), monotone
a4 Tutte / Harmonic Parameterization flatten a disk to the plane 0 flips; cotan distortion 0.652 < uniform 0.694
a5 ARAP Parameterization (Liu 2008) local/global low-distortion flattening ARAP energy 1.48 → 0.15; isometric distortion −89.7% vs harmonic
a6 ARAP Surface Deformation (Sorkine-Alexa) handle-driven rigid deformation edge-length error 6.3% (ARAP) vs 16.0% (naive Laplacian)
a7 Mesh Simplification (QEM) Garland-Heckbert quadric edge collapse 5120 → 408 faces at 1.9% mean-vertex error
a8 Software Rasterizer z-buffer + Blinn-Phong scene 5458 triangles, correct depth occlusion
a9 Path Tracer (final) Monte-Carlo Cornell box, global illumination 256×256, 400 spp — colour bleeding + soft shadows + mirror

Featured figures

Path tracing — Cornell box (final project). Global illumination with next-event estimation: soft shadows, colour bleeding from the red/green walls, and a mirror sphere reflecting the scene.

Cornell box

ARAP surface deformation. Rest tube → naive Laplacian (collapses, middle) → ARAP (preserves the circular cross-section, right).

ARAP deformation

Poisson image editing. Naive paste (visible seam, left) → seamless clone (middle) → mixed gradients (right).

Poisson

Image warping. Input with control points → IDW → RBF thin-plate.

Warping

Minimal surface. Noisy input patch → discrete minimal surface spanning a non-planar boundary.

Minimal surface

Mesh simplification (QEM). 5120 → 1280 → 408 faces, shape preserved.

QEM

Tutte / ARAP parameterization (checkerboard pulled back onto the surface):

Tutte (harmonic) ARAP (low distortion)
tutte arap

Software rasterizer — shaded scene and its z-buffer (depth):

Rasterizer

Implemented assignments

  • a1 — Image Warping: IDW (per-anchor local affine, weighted LS) and RBF thin-plate splines, exact anchor interpolation, backward-mapped resampling.
  • a2 — Poisson Image Editing: seamless cloning + mixed gradients as one sparse linear system per colour channel.
  • a3 — Minimal Surface: iterated cotangent-Laplace solve (fixed boundary) to a discrete zero-mean-curvature surface; plus explicit umbrella flow.
  • a4 — Tutte / Harmonic Parameterization: convex boundary + uniform (Tutte, bijective) and cotangent (harmonic) interior solves.
  • a5 — ARAP Parameterization: Liu et al. 2008 local/global block descent (per-triangle SVD rotation + cotangent-Laplace global step).
  • a6 — ARAP Surface Deformation: Sorkine & Alexa 2007 handle-constrained as-rigid-as-possible modeling, compared to naive Laplacian editing.
  • a7 — Mesh Simplification: Garland-Heckbert quadric error metrics with a lazy min-heap of edge collapses.
  • a8 — Software Rasterizer: full CPU pipeline — matrices, clipping, barycentric scan conversion, z-buffer, Blinn-Phong.
  • a9 — Path Tracer (final): vectorised Monte-Carlo path tracing of a Cornell box with Lambertian + mirror materials, area light, NEE, Russian roulette, Reinhard tone-mapping.

Project structure

ustc-cg/
├── src/ustc_cg/
│   ├── mesh.py        # OBJ IO, procedural mesh generators, cotangent Laplacian,
│   │                  # boundary loops, adjacency, normals
│   └── render.py      # CPU software rasterizer (z-buffer, Blinn-Phong, UV, depth)
├── assignments/
│   ├── a1_image_warping.py          a6_arap_deformation.py
│   ├── a2_poisson_editing.py        a7_mesh_simplification.py
│   ├── a3_minimal_surface.py        a8_rasterizer.py
│   ├── a4_tutte_parameterization.py a9_path_tracer.py
│   └── a5_arap_parameterization.py
├── tests/test_smoke.py     # pytest correctness checks (bijectivity, area decrease, …)
├── results/                # committed figures + .obj outputs (the evidence)
├── run_all.py              # regenerate every figure
└── requirements.txt

How to run

# Python 3.11 with numpy, scipy, Pillow, matplotlib
pip install -r requirements.txt

# regenerate every figure in results/ (path tracer at 200 spp)
python run_all.py
# quick pass (path tracer 64 spp, smaller image)
python run_all.py --fast

# or run one assignment:
python assignments/a2_poisson_editing.py
python assignments/a9_path_tracer.py 256 400   # <resolution> <samples-per-pixel>

# correctness tests (~14 s):
python -m pytest tests/ -q

Verification

  • Unit tests (tests/test_smoke.py, 7 passing): Tutte embedding has 0 flipped triangles (bijectivity), the cotangent Laplacian has the constant null-space, the icosphere satisfies Euler's formula V−E+F=2, warps interpolate their anchors, QEM reduces face count while keeping valid triangles, and the minimal-surface area decreases monotonically.
  • Measured evidence: every assignment prints and commits real numbers (table above) and writes its output image/mesh to results/. Key checks: Poisson seam energy drops ~100×; ARAP parameterization cuts isometric distortion 89.7%; ARAP deformation preserves edge lengths 2.5× better than naive Laplacian; QEM holds error under 2% of the bounding-box diagonal at 8% of the faces.
  • Renders are real: the rasterizer depth buffer (a8_raster_depth.png) confirms correct hidden-surface removal; the path traced Cornell box shows the physically-correct colour bleeding and soft shadows that only a converged GI solver produces.

Partials vs the original course

The original course ships a Qt/OpenGL application (MiniMesh/MiniDraw) for interactive handle dragging and real-time shading. This machine is CPU-only with no display/GPU, so the interactive real-time harness is not reproduced; instead every underlying algorithm is implemented and verified as an offline solve that produces the identical result (the deformation/parameterization maths is the same — only the UI event loop differs). All numerical cores, images and meshes above are genuine, not mocked.

Tech stack

Python 3.11 · numpy · scipy (sparse, sparse.linalg, spatial.cKDTree) · Pillow · matplotlib. No GPU, no OpenGL, no external mesh/geometry libraries.

Key ideas / what I learned

  • The Laplacian is everywhere. The same cotangent-Laplace operator drives minimal surfaces, harmonic parameterization, and the global step of both ARAP algorithms — geometry processing is largely "assemble the right sparse system".
  • Local/global (ARAP) optimization: alternating per-element SVD rotations with a single global linear solve is a remarkably effective, monotone way to minimize non-linear as-rigid-as-possible energies.
  • Quadric error metrics turn "how much does this edge collapse cost?" into a 4×4 quadratic form, giving near-optimal, curvature-adaptive simplification.
  • Poisson editing reframes compositing as "match gradients, fix the boundary" — a Dirichlet problem solved with one sparse system.
  • Path tracing is the rendering equation as a recursive Monte-Carlo integral; next-event estimation and importance sampling are what make it converge on a CPU.

Credits & license

Based on the assignments of "Computer Graphics" (计算机图形学) by Prof. Ligang Liu (刘利刚), University of Science and Technology of Chinacourse page, official framework. This repository is an independent educational reimplementation; all course materials and specifications belong to their original authors. Original code here is released under the MIT License.

About

From-scratch USTC Computer Graphics (Ligang Liu): image warping, Poisson editing, minimal surface, Tutte/ARAP parameterization, ARAP deformation, QEM simplification, software rasterizer & Monte-Carlo path tracer — CPU Python, real rendered results

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages