Overview
Cub3D renders a 3D view by casting one ray per screen column and drawing vertical strips of textured walls. The rendering happens in real-time at the game’s frame rate, creating a smooth first-person perspective.The Render Loop
The main rendering function is called every frame by MiniLibX:utils6.c:74-91
Update player movement
Process WASD key inputs to move the player and arrow keys to rotate the view.
Update direction vectors
Recalculate the direction and camera plane vectors based on the current angle.
main.c:96
Screen Resolution
The rendering resolution is defined as constants:cub3.h:30-31
- Width: 1732 pixels - Each column represents one ray
- Height: 1000 pixels - Determines vertical resolution
The aspect ratio is approximately 16:9 (1.732:1), which is close to standard widescreen.
Wall Height Calculation
Wall height on screen is inversely proportional to distance from the player:raycasting.c:76
- Closer walls appear taller
- Distant walls appear shorter
- The division by perpendicular distance prevents fish-eye distortion
Calculating Draw Bounds
The vertical position where the wall should be drawn:raycasting.c:119-124
- Center the wall vertically on screen
- Clamp to screen bounds to handle very close walls
Drawing a Vertical Strip
Each screen column is rendered in three parts:drawing.c:52-66
Ceiling
Pixels above the wall (0 to
start_y) are filled with color 0x87CEEB (sky blue).Wall
Pixels from
start_y to end_y are textured using the selected wall texture.Floor
Pixels below the wall (
end_y to HEIGHT) are filled with color 0x444444 (dark grey).Pixel Operations
Theput_pixel function writes directly to the image buffer:
utils7.c:228-229 (referenced from cub3.h)
main.c:68-70
Texture Coordinate Mapping
Horizontal (X) Texture Coordinate
Determined by where the ray hits the wall:drawing.c:35-44
- Extract fractional part of hit position
- Scale to texture width
- Flip for certain orientations to maintain visual consistency
Vertical (Y) Texture Coordinate
Calculated for each pixel based on its screen position:drawing.c:15-32
- Multiply by 256 for precision
- Scale by texture height and wall height
- Divide by 256 to convert back to integer
Image Buffer Management
Creating the Frame Buffer
The image buffer is allocated once during initialization:main.c:68-71
Clearing the Buffer
At the start of each frame, the buffer can be cleared:drawing.c:68-84
In practice, this clear operation may be skipped since every pixel is overwritten during rendering (ceiling, wall, or floor).
Raycasting Integration
The raycasting function processes all screen columns:raycasting.c:102-127
- Calculate ray direction
- Perform DDA to find wall hit
- Calculate wall distance and height
- Select appropriate texture
- Calculate draw boundaries
- Render the column
Floor and Ceiling Rendering
Currently, floor and ceiling use solid colors:drawing.c:57-65
Using Parsed Colors
The map file defines floor and ceiling colors that are parsed:main.c:63-64
- Replace
0x87CEEBwithmapa->ceiling_color - Replace
0x444444withmapa->floor_color
Performance Optimizations
Single Image Buffer
One frame buffer is reused every frame, avoiding repeated allocation.
Direct Memory Access
Pixel data is written directly to memory without function call overhead per pixel.
Integer Arithmetic
Uses fixed-point integer math instead of floating-point where possible.
Bounds Clamping
Clamps draw ranges to screen bounds to avoid unnecessary conditional checks in inner loops.
Rendering Pipeline Summary
Key Constants
From cub3.h:cub3.h:30-34
- WIDTH: Screen width and number of rays cast
- HEIGHT: Screen height for vertical resolution
- PI: Used for angle calculations
- SIZE: Map tile size in pixels
- POV: Field of view multiplier (≈66 degrees)
Next Steps
Raycasting
Dive deeper into the raycasting algorithm
Textures
Learn about texture mapping in detail