docs: rewrite README, DOCUMENTATION, and CHANGELOG — too robotic, rewrote from scratch

This commit is contained in:
2026-04-16 21:09:06 +00:00
parent 72e0ef4022
commit 71dd8b8354
3 changed files with 190 additions and 59 deletions

View File

@@ -1,21 +1,29 @@
# Changelog
All notable changes to the ASCII 3D Renderer project will be documented in this file.
All notable changes to this project are documented here.
## [3.0.1] - 2026-04-16
### Changed
- **Rewrote all documentation**: The README, DOCUMENTATION, and CHANGELOG all read way too robotic and stiff — rewrote everything from scratch to sound like a human actually wrote it.
- **Expanded technical docs**: `DOCUMENTATION.md` now covers the full rendering pipeline step-by-step (normal estimation, Z-buffering, font bitmap layout, 3-point light rig, projection), with a configuration reference table and an actual example of how the bitmap font data maps to pixels.
- **README overhaul**: Cleaner structure, controls in a table, straightforward descriptions of what the project does instead of overengineered marketing-speak.
## [3.0.0] - 2026-04-16
### Added
- **Interactive TUI**: A fully non-blocking TTY mode using `termios.h`, eliminating the requirement to restart the command line tool to view varying text or configuration.
- **Dynamic Text Buffering**: Real-time alphanumeric typing support overlaying the 3D rotating model.
- **Keybinding Overlay**: Rendered a helpful overlay bar detailing available interaction toggles at the bottom of the viewport matrix (`space` to pause/play, `c` to toggle color mappings, `w/s` to manage rotation speed).
- **Core TUI Module**: Explicit `tui.h` and `tui.c` segregation strictly following clean engineering isolation paradigms.
- **Interactive TUI**: You can now change text, toggle settings, and control rotation without restarting the program. The terminal is put into raw, non-blocking mode via `termios.h` so keypresses register instantly.
- **Live text input**: Type alphanumeric characters while it's running and the 3D model updates immediately to show your new text.
- **Keybinding bar**: A help overlay at the bottom of the screen shows all available controls (space to pause, c for color mode, w/s for speed, etc.).
- **TUI module**: Added `tui.h` and `tui.c` as a separate module to keep the input handling code out of the renderer.
### Changed
- **Removed Boilerplate Commentary**: Stripped all heavy `Doxygen` noise that obscured the raw logic of the C11 source codes. Instead, injected strict, professional, direct inline comments focusing on low-level 'why' rather than regurgitating standard boilerplate.
- **Makefile Restructure**: Abstracted the build targets for greater directness and improved comment clarity.
- **Cleaned up comments**: Removed the old Doxygen-style block comments that were mostly restating what the code already said. Replaced them with shorter inline comments focused on explaining *why*, not *what*.
- **Makefile cleanup**: Simplified build targets, improved the comments so they're actually useful.
### Fixed
- Stabilized terminal behavior: enforced cleanup handlers to restore standard canonical reading and buffer modes gracefully upon process interrupt or `quit` signaling, minimizing occurrences of a broken terminal interface.
- **Terminal restore on exit**: The program now properly restores terminal settings (canonical mode, echo) when you quit or hit Ctrl+C. Before this, interrupting the process could leave your terminal in a broken state where it wouldn't echo input or handle line editing correctly.

View File

@@ -1,32 +1,144 @@
# ASCII 3D Renderer - Engineering Documentation
# ASCII 3D Renderer — Technical Documentation
## Overview
ASCII 3D Renderer is a sophisticated terminal-based rendering engine implemented entirely in C11. Its goal is to bring modern 3D rendering methodologies—such as Physical-Based Lighting approximations and Depth Buffering—into a constrained ASCII viewport without utilizing external graphical libraries.
This is a software 3D renderer that outputs to a terminal. It takes text input, turns each character into a 3D shape, lights it with a multi-light Blinn-Phong model, and draws the result using ASCII characters (or colored output via ANSI escape sequences). Everything runs in a single-threaded loop at 60 FPS.
## Technical Architecture
There are no GPU calls, no windowing system, and no third-party rendering libraries. The only external dependency beyond `libc` is `libm` for math functions (`powf`, `fmaxf`, `sqrtf`, etc.).
The codebase adheres strictly to functional abstractions and strict modular boundaries to enhance performance within deep rendering loops.
## How the rendering works
### Directory Structure
The pipeline, roughly, goes like this:
- `include/`: Enforces API boundaries and struct definitions across all C modules.
- `src/`: Houses the isolated functional algorithms driving vectors, physics, and input multiplexing.
1. Look up the glyph bitmap for each character (from `font.c`)
2. Extrude the 2D bitmap into a 3D volume by adding depth along the Z-axis
3. Step through the volume at regular intervals (`VOXEL_STEP = 0.15`) and, at each point, check whether we're "inside" geometry
4. Calculate surface normals by looking at which neighboring cells are empty — a filled voxel next to an empty one means there's a surface edge there, and the normal points toward the gap
5. Apply rotation matrices (one per axis) based on the current angle
6. Project the 3D points into 2D screen coordinates using perspective projection (field of view, near/far planes)
7. For each projected point, run it through the lighting model to get a brightness value
8. Map that brightness to a character from the current shade palette
9. Write it to the framebuffer (a 2D array of chars), respecting the Z-buffer so closer surfaces win
10. Dump the entire framebuffer to stdout in one pass
### Subsystem Design
When anti-aliasing is enabled, steps 38 are repeated with jittered sample offsets (2×2 pattern by default), and the results are averaged.
1. **Input multiplexing (`tui.c`)**
Toggling standard IO into non-blocking, non-canonical states permits smooth real-time TTY interactions. Signal states are captured instantaneously and interpreted within the main event-loop per tick, altering global behavior objects without disrupting the core voxel algorithms.
## Project structure
2. **Core 3D Engine (`renderer.c`)**
Calculates pseudo-normals via 3D vector traversal. Text characters initially manifest as two-dimensional `5x7` bitmaps encoded as raw bitflags (`font.c`). `renderer.c` mathematically extrudes these glyphs along a virtual Z-axis. Multi-sampled pixel rays compute intersection boundaries and calculate normal approximations by reading empty adjacencies along geometry ridges.
```bash
src/
main.c — CLI parsing, signal handling, main loop
renderer.c — the core rendering engine: projection, voxel traversal,
framebuffer management, screen output
lighting.c — Blinn-Phong lighting: diffuse, specular, multi-light
accumulation, color math
font.c — 5×7 bitmap font data for A-Z and 0-9, stored as
bitflag arrays
tui.c — terminal input handling: puts the TTY into raw mode
for non-blocking reads, processes keypresses
timing.c — frame rate limiter using CLOCK_MONOTONIC + nanosleep
vec3.c — basic 3D vector math (dot, cross, normalize, rotate)
3. **Lighting Approximations (`lighting.c`)**
Standard Blinn-Phong equations exist within an ambient, diffuse, and specular composition loop. These color values are derived utilizing an arbitrary virtual camera and bounded to integer offsets matching one of our standard luminance dictionaries (e.g., `.:-=+*#%@`).
include/
config.h — all the tuneable constants in one place: viewport size,
camera FOV, lighting params, shade palettes, etc.
(+ headers for each .c file)
```
4. **Temporal Control (`timing.c`)**
Forces a consistent execution boundary using positive UNIX epoch resolution (`CLOCK_MONOTONIC`) mapped directly via `nanosleep`. Predictable delta steps stabilize the rotation matrix speed regardless of hardware IO constraints.
## Module details
## Compilation and Dependencies
### `font.c` — Bitmap font
The system is pure logic—`libc` and `-lm` (for `libmath`) constitute the full scope of integration dependencies. The custom `Makefile` orchestrates compilation utilizing Standard `-O3 -flto` link time passes, alongside memory sanitizer profiles natively integrated within Clang for debugging cycles.
Each character is a 5-wide, 7-tall bitmap stored as 7 bytes. Each byte represents one row — bits 4 down to 0 tell you which pixels are filled. For example, the letter "A" is:
```bash
0x0E → .###.
0x11 → #...#
0x11 → #...#
0x1F → #####
0x11 → #...#
0x11 → #...#
0x11 → #...#
```
Only AZ (case-insensitive) and 09 are supported. Anything else gets skipped.
### `renderer.c` — 3D engine
This is the biggest file and does most of the heavy lifting.
**Glyph extrusion:** Each 5×7 bitmap gets depth. The renderer walks through the glyph volume at small Z increments. At each (x, y, z) point, if the corresponding 2D pixel is "on" in the bitmap, that point is considered solid geometry.
**Normal estimation:** For shading to work, you need surface normals. Since we're working with blocky voxel-like shapes, the normals are estimated by checking adjacent cells. If a filled cell has an empty neighbor to the left, the normal has a leftward component. Same for all six directions. The result is normalized to get a unit vector. This gives you smooth-ish shading on what are otherwise cube-shaped surfaces.
**Projection:** Standard perspective projection. A 3D point gets divided by its Z distance (scaled by field-of-view), then offset to the center of the screen. Points behind the near plane or past the far plane are clipped.
**Z-buffering:** The renderer keeps a depth buffer (initialized to a large value). When drawing a point, it only updates the framebuffer if the new point is closer than what was already there. This keeps front surfaces in front.
**Render modes:**
- *Shaded* — full lighting + ASCII shade mapping (the default)
- *Solid* — everything gets drawn with `@`, no lighting
- *Wireframe* — only draw points that sit on the boundary between filled and empty cells
- *Points* — draw all filled voxels with `.`
### `lighting.c` — Blinn-Phong model
The lighting system supports up to 3 lights (configurable via `MAX_LIGHTS`). By default it sets up a classic 3-point rig:
- **Key light** — the main light, slightly above and to the right, warm white
- **Fill light** — dimmer, coming from the left, slightly blue-tinted, softens shadows
- **Rim light** — behind and below the subject, adds edge definition
Each light can be directional (parallel rays, like the sun) or point (with inverse-square falloff).
For each surface point, the shader calculates:
- **Diffuse** — Lambert's cosine law: brightness depends on the angle between the surface normal and the light direction
- **Specular** — Blinn-Phong half-vector method: creates shiny highlights where the surface reflects light toward the camera
The final brightness is the sum of ambient + all light contributions, clamped to [0, 1]. In monochrome mode this maps to an index into the shade character palette. In color mode, the full RGB result is computed per-channel and output using ANSI escape sequences.
Material properties (ambient/diffuse/specular colors, shininess) are set to sensible defaults — there's no way to change them at runtime yet.
### `tui.c` — Terminal input
On startup, the terminal gets switched to non-canonical mode with echo disabled (via `termios`). This means keypresses are available immediately without waiting for Enter, and typed characters don't show up on screen.
The original terminal settings are saved and restored on exit — this is important because if the program crashes without restoring them, you'd end up with a terminal that doesn't echo your typing or respond to Ctrl+C properly. Signal handlers for SIGINT and SIGTERM are set up specifically to make sure cleanup happens even on interrupt.
### `timing.c` — Frame limiter
Pretty straightforward. After each frame, it checks how much time has passed since the frame started using `clock_gettime(CLOCK_MONOTONIC)`. If there's time remaining in the frame budget (1/60th of a second), it sleeps for the difference with `nanosleep`. This keeps the animation speed consistent regardless of how fast the machine is.
## Build system
The Makefile has three build profiles:
| Target | Flags | Purpose |
|--------|-------|---------|
| `release` | `-O3 -march=native -flto -DNDEBUG` | Production — fast as possible |
| `debug` | `-O0 -g3 -fsanitize=address,undefined` | Development — catches memory bugs and UB |
| `profile` | `-O2 -g -pg` | Profiling with gprof |
Dependency tracking is handled with `-MMD -MP`, so incremental builds work correctly.
The `install` target copies the binary to `/usr/local/bin` (or wherever `PREFIX` points).
## Configuration
Everything tuneable lives in `include/config.h`. Some notable values:
| Constant | Default | What it controls |
|----------|---------|-----------------|
| `SCREEN_WIDTH` / `SCREEN_HEIGHT` | 120 × 45 | Framebuffer size in characters |
| `CAMERA_DISTANCE` | 30.0 | How far back the virtual camera sits |
| `FIELD_OF_VIEW` | 50.0 | Perspective FOV in degrees |
| `EXTRUSION_DEPTH` | 4.0 | How thick the 3D letters are |
| `VOXEL_STEP` | 0.15 | Sampling resolution along Z when building geometry |
| `AA_SAMPLES` | 2 | Anti-aliasing grid (2 = 2×2 = 4 samples per pixel) |
| `AMBIENT_INTENSITY` | 0.15 | Base light level in shadows |
| `DIFFUSE_INTENSITY` | 0.70 | Strength of the diffuse lighting term |
| `SPECULAR_INTENSITY` | 0.40 | Strength of specular highlights |
| `SPECULAR_POWER` | 32.0 | Shininess exponent (higher = tighter highlights) |
| `TARGET_FPS` | 60 | Frame rate cap |

View File

@@ -1,59 +1,70 @@
# ASCII 3D Renderer
An advanced software-based 3D text renderer pipeline written purely in C11.
A 3D text rendering engine that runs entirely in your terminal, written in C. Type any word and watch it spin in 3D with proper lighting, shading, and depth — all drawn with ASCII characters.
By avoiding proprietary graphics stacks, this engine demonstrates foundational rendering principles—like Z-buffer processing, Phong illumination models, matrices integration, and anti-aliasing sweeps—executing cleanly inside standard POSIX terminal boundaries.
No OpenGL, no GPU, no graphics libraries. Just math, a framebuffer made of characters, and ANSI escape codes.
## Architecture & Documentation
## What it does
Review [DOCUMENTATION.md](DOCUMENTATION.md) for deeper knowledge of subsystems, technical boundaries, and lighting logic optimizations employed in the source code.
Review [CHANGELOG.md](CHANGELOG.md) for version release tracking constraints.
You give it a string like `HELLO`, and it renders each letter as a 3D object by extruding a built-in 5×7 bitmap font along the Z-axis. A Blinn-Phong lighting model (with a 3-point light setup — key, fill, and rim) calculates the brightness at each surface point, which then gets mapped to an ASCII character from a density palette like `.:-=+*#%@`.
## Technical Feats
The whole thing runs as an interactive TUI. You can type new text on the fly, change render modes, toggle color output, adjust rotation speed — all without restarting.
- Real-time `termios`-driven TUI with non-blocking key capture for dynamic typing
- Mathematically robust 3D normal computations leveraging 2D glyph extrusion passes
- Configurable AA (multi-sampling) and shading density metrics per-pixel
- Support for RGB Truecolor processing directly through terminal escape sequences
- Strictly isolated C11 components minimizing external dependencies
## Docs
## Rapid Compilation via Makefile
- [DOCUMENTATION.md](DOCUMENTATION.md) — how the rendering pipeline works, module breakdown, and how things fit together.
- [CHANGELOG.md](CHANGELOG.md) — version history.
## Features
- Interactive TUI with non-blocking input via `termios` — no need to restart to change text or settings
- 3D normal estimation from 2D glyph bitmaps using neighbor-vacancy checks
- Multiple render modes: solid, wireframe, points, and shaded
- Anti-aliasing via multi-sample jittered rays
- Color output: monochrome, 16-color ANSI, 256-color ANSI, or full RGB truecolor
- Four different ASCII shade palettes (standard, extended 70-char, block characters, minimal)
- 60 FPS target with frame timing via `CLOCK_MONOTONIC` and `nanosleep`
## Building
You need `clang` and `make`. The only library dependency is `libm` (math).
```bash
# Deploys standard -O3 and -flto compiler optimizations
# optimized build with -O3 and LTO
make release
# Run directly, observing standard parameters
# debug build with AddressSanitizer and UBSan
make debug
# run it
./bin/ascii3d
```
## Interactive TUI Controls
There's also `make profile` for gprof, `make analyze` for cppcheck, and `make format` for clang-format.
Upon executing, the renderer spins into an active TTY session:
## Controls
- **Type Alphanumeric Characters** Immediately replaces the internal 3D model with your input in real-time.
- `[w]` and `[s]` Increase / decrease rotational velocity.
- `[Space]` Toggle rotation engine pause constraints.
- `[m]` Cycles between topology rendering (Wireframe -> Shaded Pipeline -> Solid Geometry -> Points).
- `[c]` Switch between rendering spaces (Mono Base -> 16/256 ANSI -> Full Truecolor mapping).
- `[p]` Change ASCII shading dictionaries on the fly.
- `[q]` or `ESC` Safely detaches the IO hooks and shuts the process down cleanly.
Once it's running, you're in an interactive session:
## Execution Options
| Key | What it does |
|-----|-------------|
| Any letter/number | Changes the displayed 3D text in real-time |
| `w` / `s` | Speed up / slow down rotation |
| `Space` | Pause or resume rotation |
| `m` | Cycle render mode (Solid → Wireframe → Points → Shaded) |
| `c` | Cycle color mode (Mono → ANSI 16 → ANSI 256 → Truecolor) |
| `p` | Cycle ASCII shade palette |
| `q` or `ESC` | Quit cleanly |
Command-line invocations to bypass or configure TUI session states:
## Command-line examples
```bash
# Tumbling rotation utilizing Truecolor ANSI standards
# Rotate on all axes, truecolor mode
./bin/ascii3d -a -c3 WORLD
# Quality override with heavy Anti-Aliasing pipeline
# Anti-aliasing on, 1.5x oversampling, 256-color mode
./bin/ascii3d -A -q1.5 -c2 HQ
# Show full parameter dictionary
# Show all options
./bin/ascii3d -h
```
## Contributing
The codebase attempts strict functional modularity. We accept modifications introducing new geometry patterns, deeper PBR emulation methods, or expanded rendering logic assuming complete dependency evasion.
```