3D with raymarching · lesson 2 of 7 · Intermediate · about 5 min

3D, step 1: every pixel has a ray

You will build: Show every pixel's ray direction as a colour: float4(0.5 + 0.5 * rd, 1.0).

The picture produced by the shader in the lesson "3D, step 1: every pixel has a ray"
The target picture. In the lesson you write the shader that draws it, and a match bar shows how close you are.

So far every pixel has only known "where am I on the screen". To draw a 3D scene we give each pixel an extra job: shoot a ray from the camera through this pixel, out into the scene. What the ray hits decides the colour.

Two things describe a ray:

  • ro (ray origin): where it starts. Every pixel shares the same one: the camera.
  • rd (ray direction): which way it points. Different for every pixel: pixels at the top aim up, pixels on the left aim left.

The screen sits a little in front of the camera. The ray goes through the pixel's spot on that screen, so its direction is “a little right/up for this pixel, 1.5 forward”: float3(p.x, p.y, 1.5). We normalize it so its length is 1 (only the direction matters).

Move the slider: the red dot is the pixel on the screen, the yellow line is its ray. The camera is looking along +z (to the right in this side view).

float2 p = (uv - 0.5) * float2(aspect, 1.0) * 2.0;   // like before, about -1 to 1
float3 ro = float3(0.0, 0.0, -3.0);                  // the camera
float3 rd = normalize(float3(p, 1.5));               // this pixel's direction

You can't see a direction, but you can see it as a colour: directions have x, y, z between -1 and 1, so 0.5 + 0.5 * rd is a valid colour. (Same normal-colour trick as before.)

The numbers you need

Everything the picture depends on is given, so the challenge is the code, not guessing.

p
(uv - 0.5) * float2(aspect, 1.0) * 2.0
Camera
ro = float3(0.0, 0.0, -3.0)
Direction
rd = normalize(float3(p, 1.5))
Output
float4(0.5 + 0.5 * rd, 1.0)

Try it in your own language

The lesson is written once and shown in every language. Pick yours: Unity (Built-in), Unity (URP), Unreal, Shadertoy / WebGL, OpenGL (LWJGL, raylib), three.js, GameMaker, LÖVE (Lua), Godot, Apple (iOS, macOS), WebGPU / Bevy.

Start coding