Skip to main content

What is Raycasting?

Raycasting is a rendering technique used to create a 3D perspective in a 2D map. Unlike true 3D rendering, raycasting casts rays from the player’s position to determine what walls are visible and how they should be drawn on screen. Cub3D uses the DDA (Digital Differential Analysis) algorithm to efficiently trace rays through the map grid and detect wall collisions.

Ray Direction Calculation

For each vertical stripe on the screen, a ray is cast from the player’s position. The ray direction is calculated based on the player’s viewing direction and the camera plane.
raycasting.c:102-114
void	raycasting(t_map *mapa, int i)
{
	double	camera_x;
	double	side_x;
	double	side_y;
	double	dist;
	int		start_y;

	while (++i < WIDTH)
	{
		camera_x = 2 * i / (double)WIDTH - 1;
		mapa->ray_dir_x = mapa->dir_x + mapa->plane_x * camera_x;
		mapa->ray_dir_y = mapa->dir_y + mapa->plane_y * camera_x;
The camera_x value ranges from -1 (left edge) to +1 (right edge) of the screen. This is multiplied by the camera plane vector to create the field of view.

The DDA Algorithm

Initialization

Before performing DDA, we need to calculate the delta distances - how far the ray must travel to cross one grid cell.
raycasting.c:40-66
void	init_dda(t_map *mapa, double *side_dist_x, double *side_dist_y)
{
	mapa->map_x = (int)(mapa->xx);
	mapa->map_y = (int)(mapa->yy);
	mapa->delta_dist_x = fabs(1 / mapa->ray_dir_x);
	mapa->delta_dist_y = fabs(1 / mapa->ray_dir_y);
	if (mapa->ray_dir_x < 0)
	{
		mapa->step_x = -1;
		*side_dist_x = (mapa->xx - mapa->map_x) * mapa->delta_dist_x;
	}
	else
	{
		mapa->step_x = 1;
		*side_dist_x = (mapa->map_x + 1.0 - mapa->xx) * mapa->delta_dist_x;
	}
	if (mapa->ray_dir_y < 0)
	{
		mapa->step_y = -1;
		*side_dist_y = (mapa->yy - mapa->map_y) * mapa->delta_dist_y;
	}
	else
	{
		mapa->step_y = 1;
		*side_dist_y = (mapa->map_y + 1.0 - mapa->yy) * mapa->delta_dist_y;
	}
}
1

Calculate delta distances

delta_dist_x and delta_dist_y represent how far the ray travels to cross one map square in each direction.
2

Determine step direction

step_x and step_y are set to either +1 or -1, indicating which direction to step through the grid.
3

Calculate initial side distances

The initial distance from the player position to the first grid line in each direction.

Ray Traversal

The DDA algorithm steps through the grid one square at a time, always moving along the axis where the next grid line is closest.
raycasting.c:15-38
int	perform_dda(t_map *mapa, double *side_dist_x, double *side_dist_y)
{
	int	hit;

	hit = 0;
	while (!hit)
	{
		if (*side_dist_x < *side_dist_y)
		{
			*side_dist_x += mapa->delta_dist_x;
			mapa->map_x += mapa->step_x;
			mapa->side = 0;
		}
		else
		{
			*side_dist_y += mapa->delta_dist_y;
			mapa->map_y += mapa->step_y;
			mapa->side = 1;
		}
		if (mapa->final_map[mapa->map_y / SIZE][mapa->map_x / SIZE] == '1')
			hit = 1;
	}
	return (mapa->side);
}
The side variable tracks whether we hit a vertical wall (side = 0) or horizontal wall (side = 1). This is crucial for texture selection later.

Wall Distance Calculation

Once a wall is hit, we calculate the perpendicular distance to avoid the “fish-eye” effect that would occur with Euclidean distance.
raycasting.c:68-82
void	calculate_wall_data(t_map *mapa, double *dist)
{
	if (mapa->side == 0)
		*dist = (mapa->map_x - mapa->xx + (1 - mapa->step_x) / 2)
			/ mapa->ray_dir_x / SIZE;
	else
		*dist = (mapa->map_y - mapa->yy + (1 - mapa->step_y) / 2)
			/ mapa->ray_dir_y / SIZE;
	mapa->line_height = (int)(HEIGHT / *dist);
	if (mapa->side == 0)
		mapa->wall_x = mapa->yy / SIZE + *dist * mapa->ray_dir_y;
	else
		mapa->wall_x = mapa->xx / SIZE + *dist * mapa->ray_dir_x;
	mapa->wall_x -= floor(mapa->wall_x);
}

Mathematical Concepts

Field of View

The field of view is controlled by the camera plane, which is perpendicular to the viewing direction:
utils6.c:66-72
void	set_player_dir_and_plane(t_map *mapa)
{
	mapa->dir_x = cos(mapa->starting_angle);
	mapa->dir_y = sin(mapa->starting_angle);
	mapa->plane_x = -mapa->dir_y * 0.66;
	mapa->plane_y = mapa->dir_x * 0.66;
}
The multiplier 0.66 determines the FOV. This corresponds to approximately 66 degrees (defined as POV 1.17 in cub3.h:34, where FOV ≈ 2 * atan(0.66)).

Wall Height Projection

The wall height on screen is inversely proportional to its distance:
line_height = HEIGHT / perpendicular_distance
This creates the perspective effect where closer walls appear larger.
Always use perpendicular distance, not Euclidean distance, to avoid the fish-eye distortion effect.

Key Constants

From cub3.h:
  • WIDTH 1732 - Screen width in pixels
  • HEIGHT 1000 - Screen height in pixels
  • SIZE 30 - Map tile size in pixels
  • POV 1.17 - Field of view constant

Next Steps

Rendering

Learn how raycasting results are rendered to the screen

Textures

Understand how textures are mapped to walls