Ray Tracing: Tracing the Light
"RTX ON: New World or Just Lag?"
I booted up Cyberpunk 2077 with my shiny new RTX 3070. The moment I flipped "Ray Tracing: ON" in the settings, the puddles on the street looked jaw-droppingly real. The neon signs reflected on the wet pavement felt like actual reality, and I thought, "Is this even a game?" But at the same time, the framerate became a slideshow (60 FPS → 30 FPS).
I bought an RTX card specifically for this, and yet the framerate still tanked. What on earth is it calculating to make my computer struggle this much? Out of curiosity, I dug deeper and learned that ray tracing isn't just "a graphics quality toggle." It's simulating the physics of light in real-time inside the game.
1. Shadow Puppets vs True Light Simulation
At first, I didn't get the difference between ray tracing and traditional rendering. "Aren't they both just drawing graphics?" I thought.
But once I understood this analogy, everything clicked.
Rasterization: Shadow Puppets
The traditional method, Rasterization, is like 'Shadow Puppets'. When you make shadow puppets with your hands, you don't calculate how light penetrates your skin cells and scatters. You just 'fake it': "There's a light here, so a shadow should fall roughly here."
Developers use pre-written Shader programs to approximate: "If the light is here, it should look this bright from this angle." It's fast, but complex effects like mirrors or glass reflections look obviously fake.
For example, to implement a mirror:
- Create another camera on the opposite side of the mirror
- Bake the view from that camera into a texture
- Paste it onto the mirror surface
The result looks decent, but only works in static environments. If the player moves or other objects need to be reflected, you need additional tricks.
Ray Tracing: Like a Detective Following Clues
Ray Tracing, on the other hand, literally 'Traces Rays'. Like a detective following footprints one by one, it backtracks the path of light.
In reality, light shoots out from sources, bounces around, and eventually enters our eyes. But most light never reaches our eyes, so calculating all of it would be inefficient.
So ray tracing does it backwards:
- Shoot rays from the virtual eye (camera) (Primary Ray)
- When a ray hits an object, trace back where the light came from (Shadow Ray, Reflection Ray, Refraction Ray)
- Calculate the path as rays bounce and refract until they hit a light source or run out of energy
It's like calculating how a billiard ball bounces using physics laws. It's simulating real-world physics.
2. How Ray Tracing Actually Works: The 4 Types of Rays
I used to think ray tracing was just "shooting light," but I had an aha moment when I learned it actually uses four types of rays.
Primary Ray
Rays shot from the camera toward each pixel on the screen. For a 1920x1080 resolution, that's 2,073,600 rays.
for each pixel (x, y) in screen:
ray = create_ray(camera_position, pixel_direction)
color = trace_ray(ray, max_depth=5)
set_pixel_color(x, y, color)
When these rays hit objects, additional rays are shot to determine "what color should this pixel be?"
Shadow Ray
From the point where the Primary Ray hits an object, a ray is shot toward the light source. If another object blocks the path, a shadow forms. If not, the point is illuminated.
def trace_shadow_ray(hit_point, light_position):
direction = normalize(light_position - hit_point)
ray = Ray(hit_point + epsilon * direction, direction) # epsilon: avoid self-intersection
if intersects_any_object(ray, distance_to_light):
return 0.0 # In shadow
else:
return calculate_lighting(hit_point, light_position) # Illuminated
Rasterization "paints" shadows, while ray tracing "checks if light actually reaches the point."
Reflection Ray
When a ray hits a mirror or metal surface, a ray bounces off at the reflection angle.
Physics law: Angle of incidence = Angle of reflection
def calculate_reflection(incident_ray, normal):
# Reflect the incident vector around the normal vector
return incident_ray - 2 * dot(incident_ray, normal) * normal
def trace_reflection_ray(hit_point, incident_direction, normal):
reflected_direction = calculate_reflection(incident_direction, normal)
reflected_ray = Ray(hit_point + epsilon * normal, reflected_direction)
return trace_ray(reflected_ray, depth + 1) # Recursive call
The key here is recursion. Reflected rays can hit other objects, which generate more reflections... infinitely. That's why we usually limit the max depth to 5-10.
Refraction Ray
When a ray passes through transparent objects like glass or water, it bends at the refraction angle.
Physics law: Snell's Law
n₁ × sin(θ₁) = n₂ × sin(θ₂)
(n: refractive index, θ: incident/refracted angle)
def calculate_refraction(incident_ray, normal, n1, n2):
# Calculate Snell's law using vectors
eta = n1 / n2
cos_i = -dot(normal, incident_ray)
sin_t2 = eta * eta * (1.0 - cos_i * cos_i)
if sin_t2 > 1.0:
return None # Total Internal Reflection
cos_t = sqrt(1.0 - sin_t2)
return eta * incident_ray + (eta * cos_i - cos_t) * normal
Light bends when entering glass, and bends again when exiting—all calculated using physics laws.
Ray-Sphere Intersection
How do you know if a ray hits an object? The simplest example is the ray-sphere intersection test.
def ray_sphere_intersection(ray_origin, ray_direction, sphere_center, sphere_radius):
# Ray: P(t) = O + t*D (O: origin, D: direction, t: distance)
# Sphere: |P - C|² = r² (C: center, r: radius)
oc = ray_origin - sphere_center
a = dot(ray_direction, ray_direction)
b = 2.0 * dot(oc, ray_direction)
c = dot(oc, oc) - sphere_radius * sphere_radius
discriminant = b*b - 4*a*c
if discriminant < 0:
return None # No intersection
else:
t = (-b - sqrt(discriminant)) / (2.0 * a)
if t < 0:
return None # Sphere is behind the ray
return ray_origin + t * ray_direction # Intersection point
This calculation must be done for every pixel, every object, and every ray. That's why it's slow.
3. The Rendering Equation: Physics of Light in One Line
The theoretical foundation of ray tracing is the Rendering Equation. I wanted to run away when I first saw the complex formula, but once I understood the core idea, it clicked.
Rendering Equation (Simplified)
L_out = L_emit + ∫ L_in × BRDF × cos(θ) dω
In plain English:
"Light going out (L_out) = Self-emitted light (L_emit) + Sum of incoming light"
- L_out: Light going toward the camera
- L_emit: Light emitted by the object itself (light bulbs, neon signs)
- L_in: Incoming light from other sources
- BRDF: Bidirectional Reflectance Distribution Function (how light reflects)
- cos(θ): Attenuation based on incident angle
- ∫ dω: Integration over all directions
The Key Insight
"Light exiting a point is the sum of all light entering that point."
The crucial part is that this is recursive. To calculate light exiting point A → you need light entering from point B → which requires light exiting point B → which needs light entering from point C...
Ray tracing cuts this infinite recursion at 5-10 levels deep.
Path Tracing vs Ray Tracing
Depending on how you solve the rendering equation, the method gets different names.
| Method | Ray Tracing | Path Tracing |
|---|---|---|
| Rays per Pixel | 1~few (deterministic) | Hundreds~thousands (stochastic) |
| Reflection Type | Specular only (like mirrors) | Diffuse included (like reality) |
| Indirect Lighting | Approximated | Physically accurate |
| Use Case | Real-time games (RTX) | Movie CGI (Pixar, ILM) |
RTX in games is technically a "hybrid approach." Rasterization draws the base frame, and ray tracing adds reflections, shadows, and indirect lighting on top.
4. BVH: The Secret to Fast Searching Through Millions of Triangles
The biggest problem with ray tracing is "every ray must test intersection with every object."
For example:
- Screen: 1920×1080 = 2,073,600 pixels
- Rays per pixel: 4 (Primary + Shadow + Reflection + Refraction)
- Triangles in scene: 1,000,000 (AAA game standard)
Total calculations = 2,073,600 × 4 × 1,000,000 = ~8 trillion times
This needs to finish in 1/60th of a second. No wonder it's slow.
BVH: Divide Space into a Tree Structure
BVH (Bounding Volume Hierarchy) is the key data structure that solves this problem.
Think of it like "finding a book in a library". If there are a million books and you search one by one, it'll take forever. Instead, you do this:
- Building → Floor → Shelf → Section → Book — narrow down the range hierarchically
- If a ray doesn't hit the bounding box of Floor 1, skip the entire floor
class BVHNode:
def __init__(self, bounding_box, left_child, right_child, objects):
self.bbox = bounding_box # Volume this node encompasses
self.left = left_child
self.right = right_child
self.objects = objects # Only filled if leaf node
def intersect_bvh(ray, node):
if not ray_intersects_box(ray, node.bbox):
return None # Skip entire node if ray misses bounding box
if node.is_leaf():
# Leaf node: test actual objects
closest_hit = None
for obj in node.objects:
hit = ray_intersects_object(ray, obj)
if hit and (not closest_hit or hit.distance < closest_hit.distance):
closest_hit = hit
return closest_hit
else:
# Internal node: recurse into children
hit_left = intersect_bvh(ray, node.left)
hit_right = intersect_bvh(ray, node.right)
return closer_of(hit_left, hit_right)
The Impact
Without BVH: O(n) - test all objects With BVH: O(log n) - tree traversal
For 1 million objects, 1,000,000 tests → reduced to 20.
RT Cores are chips that hardware-accelerate this BVH traversal.
5. Why Only Now?
This technology existed since the 1980s. Turner Whitted published the seminal paper "An Improved Illumination Model for Shaded Display" in 1980.
But it was only used for movie CGI (Avatar, Iron Man). Movies can afford to take hours to render a single frame.
Games Need to Render 60 Frames Per Second
But games need to draw 60 frames per second. Calculating billions of light paths in 0.016 seconds? Impossible.
Existing GPUs couldn't do it. GPUs were originally optimized for rasterization—"drawing triangles on screen." Ray tracing is a fundamentally different task.
RT Cores: Dedicated Light Calculation Chips
What made it possible was NVIDIA's RT Cores (Ray Tracing Cores).
RTX 2080 launched in 2018
What RT Cores do:
- BVH traversal acceleration: Quickly find which objects a ray hits
- Ray-Triangle Intersection hardware acceleration: Process ray-triangle collision tests with dedicated circuits
By embedding a "calculator dedicated to light paths" into the chip, real-time ray tracing became reality.
| Era | Technology | Render Time |
|---|---|---|
| 1980s | Software ray tracing | Hours per frame |
| 2000s | GPU acceleration (CUDA) | Minutes per frame |
| 2018~ | RT Cores (RTX) | 60 frames per second (real-time) |
6. DLSS: The Art of Cheating
Even with RT Cores, turning on ray tracing at 4K resolution tanks the framerate. So NVIDIA pulled off a genius trick: DLSS (Deep Learning Super Sampling).
How DLSS Works
- Render the frame at a lower resolution (e.g., 1080p) ← Reduces ray tracing load
- AI (Tensor Core) upscales the image to 4K
- AI infers what color missing pixels should be: "This spot should probably be this color"
Why DLSS is Special
Traditional upscaling (Bilinear, Bicubic) simply interpolates pixels. But DLSS leverages temporal data.
DLSS Inputs:
- Current frame (low resolution)
- Previous frame (high resolution)
- Motion vectors (which direction objects moved)
- Depth information (which objects are in front/behind)
DLSS Output:
- Current frame (high resolution) - AI infers "this object looked like this in the previous frame, so now it should look like this"
The result was a huge success. Half the performance cost while looking like 4K. Sometimes it even looks sharper than native 4K (thanks to anti-aliasing effects).
FSR: AMD's Open-Source Response
AMD introduced FSR (FidelityFX Super Resolution), which works without hardware dependency.
| Type | DLSS (NVIDIA) | FSR (AMD) |
|---|---|---|
| Technology | AI-based (Tensor Cores) | Spatial upscaling (algorithm) |
| Hardware Requirement | RTX card required | All GPUs supported |
| Quality | Sharper (temporal data) | Good (single frame only) |
| Compatibility | Per-game training needed | Immediately applicable |
On my RTX 3070, DLSS doubled my framerate from 30 → 60. This was the secret to how I could enjoy high-fidelity gaming on modest hardware.
7. Beyond Gaming: Architecture, Automotive Design, Movies
Ray tracing isn't just for games. It's used in "every field where light accuracy matters."
Architectural Rendering
Before constructing a building, architects preview "what will this building look like at 3 PM?"
Using Autodesk Arnold, V-Ray, Unreal Engine 5:
- Shadow changes based on sun angle
- Surrounding buildings reflected in glass
- Natural light entering interiors
These are rendered with physical accuracy. Clients often ask "is this a real photo?" because it looks so realistic.
Automotive Design
Companies like BMW, Audi, Tesla render with ray tracing before building actual prototypes.
Using NVIDIA Omniverse, Autodesk VRED:
- Metallic paint reflections (Metallic BRDF)
- Chrome part mirror effects
- How headlight beams spread to surroundings
They adjust designs while viewing these effects in real-time. Physically Based Rendering (PBR) is so accurate that designers can confidently say "this is how it'll look when we build it."
Movie VFX
Pixar RenderMan, Disney Hyperion use Path Tracing. They calculate with much deeper recursion depths (hundreds of bounces) than games.
- Avatar's Pandora jungle - light filtering through leaves
- Iron Man suit's metallic reflections
- Frozen's ice surfaces
These scenes render hours per frame. But the result is indistinguishable from live-action footage.
8. Summary: From Fake to Real
| Type | Rasterization (Old) | Ray Tracing (RTX) |
|---|---|---|
| Analogy | Shadow Puppets (faking it) | Detective Following Clues (tracing it) |
| Realism | Limited reflection/refraction | Photorealistic (perfect mirrors/glass) |
| Core Tech | Shader tricks | BVH + RT Cores + DLSS |
| Cost | Lightweight (120fps possible) | Extremely Heavy (30fps without DLSS) |
What resonated with me most while studying ray tracing was this:
"The history of computer graphics is a journey from 'tricks' to 'truth'."
In the 1990s, shadows were drawn as textures. In the 2000s, normal maps faked bumpy surfaces. In the 2010s, Screen Space Reflections (SSR) approximated mirrors.
But in the 2020s, we can finally "simulate the physics of light in real-time."
Whether it's the Metaverse or whatever comes next, if light doesn't behave realistically, our brains will always know it's fake. Ray tracing isn't just about "better graphics." It means "the virtual world gains physical laws."