Raycaster is a small learning-focused C++ project that renders a pseudo-3D scene from a 2D tile map. It uses SDL3 for the window, input, and presenting the final image, while the actual scene is drawn manually in software by calculating pixels, rays, wall distances, and texture coordinates.
This project is a handmade raycasting renderer inspired by the classic rendering style of early 3D games. The world is stored as a grid, the player moves through that grid, and each frame is generated by casting rays into the map and drawing the visible walls, floor, and ceiling.
SDL3 is used for the application shell: creating the window, handling keyboard events, managing the renderer, and displaying a streaming texture that acts as the software-rendered frame buffer. SDL_image is used to load PNG textures before rendering begins.
Current features include:
- Textured wall rendering
- Textured floor and ceiling rendering
- DDA-based ray traversal
- Fisheye correction for wall projection
- Basic collision checks
- Resizable SDL window
- Minimap with player position and view ray
- WASD movement and rotation
- FPS output in the console
Raycasting creates a 3D-looking image from a 2D map. Instead of rendering real 3D geometry, the program treats the map as a grid of tiles and asks a simple question for each vertical screen column: how far can the player see in this direction before the ray hits a wall?
For every column of the 640x360 render buffer, the renderer calculates a ray direction based on the player's view direction and the field of view. The ray then moves through the tile grid with the DDA algorithm. DDA checks which grid border the ray reaches next, steps into the next tile, and repeats until a wall tile is found.
Once a wall is hit, the distance to that wall determines how tall the wall column should appear on screen. Nearby walls are drawn taller, distant walls are drawn smaller. The distance is corrected with the ray angle to reduce the fisheye effect, so walls do not bend unnaturally near the edges of the screen.
Textures are mapped by using the exact position where a ray hits a wall. That hit position selects the horizontal texture coordinate, while the current pixel inside the projected wall column selects the vertical coordinate. Floor and ceiling textures are drawn separately by projecting screen rows back into world space and sampling the matching map tile texture.
Main.cppowns the SDL lifecycle, input state, movement, collision checks, frame timing, and the main callback loop.Render.cppwrites the scene into a streaming SDL texture, including floor, ceiling, wall columns, shadows, and the minimap overlay.DDA.cppcontains the ray traversal logic and vector math used to rotate directions and convert angles.Map.cppdefines the static 8x8 floor, wall, and ceiling maps, plus the player's starting position.Texture.cpploads 64x64 PNG textures into a fixed-size in-memory texture array for fast lookup during rendering.
The renderer draws into a fixed internal resolution of 640x360 pixels. The SDL window can be resized, but the software buffer stays at the same resolution and is scaled up with nearest-neighbor filtering.
W: Move forwardS: Move backwardA: Rotate leftD: Rotate right
- CMake 3.29 or newer
- A C++20 compatible compiler
- Git submodules for SDL and SDL_image
- PNG textures in
res/textures
Clone the repository with submodules, or initialize them after cloning:
git submodule update --init --recursiveBuild the project with CMake:
cmake -S . -B build
cmake --build buildRun the executable:
./build/src/RaycasterThe executable expects PNG textures under res/textures. The current source tree references that directory from CMake and at runtime, but the texture assets are not included in this workspace. Textures should be 64x64 PNG files and named so their numeric ID can be read from the filename, for example texture1.png and texture2.png.
.
├── CMakeLists.txt # Root CMake configuration and SDL setup
├── lib/
│ ├── SDL/ # SDL submodule
│ └── SDL_image/ # SDL_image submodule
├── res/
│ └── textures/ # Expected 64x64 PNG texture assets
└── src/
├── Main.cpp # SDL callbacks, input, movement, frame loop
├── Render.cpp # Software rendering and minimap
├── DDA.cpp # Ray traversal and vector helpers
├── Map.cpp # Static tile maps and start position
└── Texture.cpp # PNG loading and texture lookup
- The map is currently a static 8x8 grid compiled into the program.
- Sprites, enemies, weapons, and GUI elements are not implemented yet.
- Texture size and texture count are compile-time constants.
- The renderer is intentionally simple and educational rather than a full game engine.
- Add Sprites
- Add GUI
- Add Weapons
- Add Enemy AI
This project is licensed under the MIT License.
