ASCII 3D Renderer

By Yansong Zhu
🏆 Highlight Submission

Background

This project was created as a creative final assignment for CSC317 Computer Graphics at the University of Toronto. Inspired by the retro aesthetic of terminal-based graphics and the elegance of ray tracing, I wanted to create something that bridges classical rendering techniques with an unconventional output medium.

The idea emerged from a simple question: “What if we could experience ray-traced 3D graphics in pure ASCII?” This project explores that intersection, combining the mathematical precision of computer graphics with the nostalgic charm of text-based art.

Project Overview

This renderer takes standard 3D mesh files (OBJ format) and renders them in real-time as ASCII art using ray tracing techniques. The output is displayed in a live GUI where users can interactively adjust rendering parameters, lighting, and camera settings.

Key Features:

Technical Implementation

1. Foundation: Building on Course Material

The project leverages fundamental components from previous CSC317 assignments:

2. Novel Components: The ASCII Renderer

ASCIIRenderer Class (ASCIIRenderer.h/cpp)

The heart of the project - converts 3D geometry to ASCII characters:

For each character position (i, j):
  1. Generate viewing ray through pixel
  2. Trace ray through BVH to find nearest intersection
  3. Compute lighting at hit point (Lambertian + ambient)
  4. Map brightness [0,1] → character from charset

Character Mapping:

Brightness is calculated using basic Phong-style shading:

brightness = ambient_strength + max(0, normal · (-light_direction)) * intensity

Camera System (CameraController.h)

Implements a spherical camera controller:

Lighting Model

Camera-Space Directional Light: The lighting system uses a directional light defined in camera space, meaning the light rotates with the camera. This ensures consistent illumination regardless of viewing angle.

light_direction = sin(θ) * cos(φ) * camera.right +
                  cos(θ) * camera.up +
                  sin(θ) * sin(φ) * camera.forward

Why camera space? For ASCII art, we want the model to always be well-lit from the viewer’s perspective, similar to 3D modeling software viewport lighting. This prevents dark, unreadable views when the camera rotates behind the object.

3. GUI Integration (main.cpp)

Built with ImGui + GLFW + OpenGL, the interface provides:

4. Performance Optimizations

Typical Performance:

Controls: