The RayCast Renderer is a lightweight 3D rendering engine that uses ray tracing principles to produce high-quality 2D images from 3D scenes. This project implements concepts such as vector mathematics, intersection logic, and parallel processing, while integrating advanced techniques like sub-camera splitting and asynchronous programming for optimized performance.
Ray casting is the process of tracing rays from a viewpoint (camera) into a scene to identify the closest object alaong each ray's path. This forms the basis for rendering 3D scenes onto a 2D plane.
Ray casting is the process of tracing rays from a viewpoint (camera) into a scene to identify the closest object along each ray's path. This forms the basis for rendering 3D scenes onto a 2D plane.
Ray Equation: R(t) = O + t * D
- O: Ray origin, typically the camera position.
- D: Ray direction, represented as a normalized 3D vector.
- t: Scalar parameter, determining the point along the ray.
In this renderer, all objects are represented as collections of triangles—the fundamental geometric primitive. Each triangle is defined by:
- Vertices: Three points in 3D space (v1, v2, v3).
- Color: A color value that determines how the triangle will appear in the final image.
The renderer employs the linear algebra intersection to efficiently calculate intersections between rays and triangles. When a ray intersects a triangle, the color of the triangle is assigned to the corresponding pixel in the rendered image.
- Lightweight Rendering: Direct computation of ray-object intersections.
- Custom Scene Setup: Users can define custom objects, camera settings, and colors for the scene.
- Optimized Intersection Detection: Efficiently computes intersections using advanced geometric algorithms.
- Multiple Output Formats: Rendered images can be saved in standard formats like PNG or PPM.
Define objects using triangles and configure the camera:
// Define a triangle with three vertices
Triangle triangle({{0, 0, 0}, {1, 0, 0}, {0, 1, 0}}, Color(255, 0, 0));
// Set up the camera
Camera camera(Point(0, 0, -5), Vec3(0, 0, 1), 90.0);
- Rays are generated for each pixel in the image grid.
- Each ray is cast into the scene to test for intersections with objects.
- The linear algebra intercection algorithm determines:
- Whether a ray intersects a triangle.
- The point of intersection.
- The triangle closest to the ray's origin.
- Assign the color of the intersected triangle to the corresponding pixel on the image plane.
- Combine all pixel data to generate the final 2D image.
- Save the rendered image in formats like PNG or PPM.
- Low-resolution and high-resolution renders of basic shapes like cubes.
// Render a cube at low resolution
Image image(128, 128);
Renderer renderer(scene, camera);
renderer.render(image);
image.save("low_res_cube.png");
- High-detail renders of models like the Dahlia flower and Suzanne.
// Load and render a complex model
MeshReader reader;
space scene = space("dahlia.obj");
Image image(1920, 1080);
Camera camera(Point(0, 0, -5), Vec3(0, 0, 1), 90.0);
scene.addCamera(camera);
scene.triggerCameras();
image.save("dahlia_render.png");
This project requires ImageMagick installed and linked to your system's path. Specifically, the project uses the following command to convert the PPM file to PNG format:
std::string convertCommand = "magick convert " + filePath + " " + pngFile;
Ensure that ImageMagick is installed and its executable is available in your system's PATH for this to work correctly.
-
ImageMagick:
- Required for image format conversion (e.g., PPM to PNG).
- Ensure it is installed and accessible in the system's PATH.
- Example usage:
std::string convertCommand = "magick convert " + filePath + " " + pngFile;
-
C++ Compiler:
- Supports C++11 or later.
Intersection Testing: The renderer solves the ray-triangle intersection problem:
- Check if the ray intersects the plane of the triangle.
- Confirm the intersection point lies inside the triangle bounds.
Color Mapping: Each triangle is assigned a unique color. When a ray hits a triangle, the pixel corresponding to the ray is updated with the triangle’s color.
- No Advanced Lighting: No shadows, reflections, or refractions.
- Scene Complexity: Performance drops with many triangles.
- Basic Output: Limited to simple color-based rendering.
- No direct way to color triangles.
This project is a personal project for educational purposes.