Welcome to our miniRT project! 🎉 This is a minimal ray tracing engine developed as part of the 42 School curriculum. It renders 3D scenes described in a custom .rt file format using fundamental ray tracing principles.
This project is intended to be a learning exercise for 42 students. Please do not copy, fork, or steal code from this repository to submit as your own. The aim of the project is to help you learn, not just complete the assignment. If you’re stuck, work through the problem, ask for help, or discuss it with peers, but do not simply use other students' solutions. We believe in the value of learning through challenges, and that’s the only way you’ll truly grow and succeed at 42. Let’s keep it fair and fun!
Greetings Andreas and Hüsrev ✌️
- Unix-like system (Linux/macOS)
- GCC or Clang
make- MiniLibX library
- (Optional) gdb, valgrind, and funcheck for debugging/testing
Clone the repository and compile using make. The Makefile includes several targets for different build configurations:
make # Compiles miniRT with basic mandatory features only
make bonus # Compiles miniRT with all bonus features enabled
make norm # Compiles miniRT to output a normal map instead of shaded rendering
make debug # Compiles miniRT with debug info; prints exit location and code after program endsRun the program from the terminal by specifying the compiled executable and the scene file path as the only argument:
./miniRT scenes/scene.rt
You can also specify the scene file inside the Makefile and use the provided make targets to build and run the project easily.
To build and run the program in one step, prepend run- to the build target:
make run # Compile and run basic features with the specified scene
make run-bonus # Compile and run including bonus features with the specified scene
make run-norm # Compile and run normal map mode with the specified sceneAdditional targets help with debugging and memory checking:
make val # Run the program using Valgrind to check for memory leaks
make gdb # Run the program in GDB for debugging
make fun # Run the program with FuncheckThe goal of the miniRT project is to implement a minimal ray tracing engine capable of rendering 3D scenes from a text-based description. The project focuses on deepening the understanding of computer graphics fundamentals, including ray-object intersection, camera projection, lighting models, and shading techniques.
The miniRT project, as defined by the 42 school curriculum, is split into two different feature tiers:
Mandatory Features: The core features that must be implemented to complete the project (100 points)
Bonus Features: Optional enhancements suggested by the project spec. Completing them can improve your final grade (up to 125 points)
On-Top Features: Completely extra features we added ourselves. These were not required or suggested but enhance realism or usability.
Throughout this README, each feature is followed by a tag that indicates its project status.
Scenes are defined using plain-text .rt files. Each line represents an element in the scene, starting with an identifier (ID), followed by the specific properties required for that element.
-
Position:x, y, z coordinates of the element in the range [-10000, 10000] -
Orientation:3D normalized vector with components in the range [-1, 1] for each axis (x, y, z) -
Ratio:Light brightness ratio in the range [0.0, 1.0] -
Diameter:Element diameter in the range [0, 99999] -
Height:Element height in the range [0, 99999] -
Color:RGB color values, each in the range [0, 255] -
Field-of-View:Horizontal field of view in degrees in the range [0, 180] -
Material [on-top feature]:Materials defined inmaterials.hthat affect shading calculations
| Element | ID | Properties |
|---|---|---|
| Ambient Light | A |
Ratio, Color |
| Point Light Source | L |
Position, Ratio, Color (bonus) |
| Camera | C |
Position, Orientation, Field-of-View |
| Plane | pl |
Position, Orientation, Color |
| Sphere | sp |
Position, Diameter, Color |
| Cylinder | cy |
Position, Orientation, Diameter, Height, Color |
| Cone | co |
Position, Orientation, Diameter, Color |
An example scene file using all supported elements:
A 0.2 255,255,255
L 5,5,5 0.7 255,255,255
C 0,0,0 0,0,0 70
pl 1,1,1 1,0,-1 255,0,0
sp 2,0,-5 2 0,120,42
cy 0,10,3 1,0,0 1.5 2 0,255,0
co 3,2,1 0,-0.5,0.1 0.8 100,100,100
To keep scene files clean, any line starting with a [ is ignored by miniRT, allowing you to add comments. Below is a picture of how a
proper scene.rt file looks like using comments to create structure
-
The scene file must contain exactly one ambient light (
A), one camera (C), and one point light source (L) for the mandatory features. -
For the bonus part, at least one point light source is required (multiple lights allowed).
-
Other elements are optional. If no objects (
pl,sp,cyorco) are present, the scene will render but display nothing visible.
The program begins by reading the input .rt scene file line by line. Each line corresponds to a specific element in the scene, identified by an ID (e.g. sp, cy, C, etc.).
Parsing is handled in a modular way: for each property (like position, orientation, color, etc.), there's a dedicated function responsible for reading that property and then skipping any following whitespace. This design allows for flexible composition: for each scene element, the corresponding ID-specific function simply calls a series of these property readers in the expected order. This makes the parsing process highly reusable and consistent across different element types.
Based on the camera's field of view, we determine the visible range of the scene. This range is then divided into pixels according to the window resolution, allowing us to compute a direction vector for a ray corresponding to each pixel (or sub-pixel, in the case of multi-sample anti-aliasing).
For each ray, we check for intersections with all objects in the scene. If an intersection is found, we compare its distance to the camera with previous hits and update the t_rend structure if it is the closest so far. Once all objects have been checked, we use the closest intersection point to compute the final color of that pixel. This includes calculating how the material interacts with the available light sources.
We use the Blinn-Phong shading model to compute the final color of each visible surface point. It is composed of three lighting components:
Ambient Light:a constant background illuminationDiffuse Light:light scattered from rough surfaces, dependent on the angle of incidenceSpecular Light:highlights caused by reflection of the light source, giving the appearance of glossiness
By combining these three components, we obtain the final shaded color for each pixel.
Instead of a single color, a checkerboard pattern can be projected onto objects. In our implementation, this effect is enabled by applying the "CHECK" material to an object in the .rt file.
Bump mapping alters the surface normals of an object to simulate texture without changing its geometry. In our program, this effect is enabled by applying the "BUMP" material to an object. Currently, only one bump map is supported per scene.
To reduce jagged edges, each pixel is subdivided into multiple samples. The number of samples per pixel is defined by the SPP macro in the minirt.h header and must be a perfect square (N²) to function correctly.
[Add picture comparing both]
Materials allow customizing shading behavior by defining material properties in a struct (found in materials.h). These are appended to an object’s properties in the .rt file. Material parameters include:
-
Reflectivity (mat.refl):The ratio between the shaded color and reflection. -
Reflection Ratio (mat.refl_rat):Brightness level of the reflected light. -
Refractive Index (mat.refr_ind):Index of refraction for the material (currently overridden by DEFAULT_REFR_IND macro in minirt.h). -
Glossiness (mat.gloss):Controls the sharpness of specular highlights. Higher values produce smaller, glossier highlights. -
Specular Highlight Ratio (mat.spec_rat):Brightness of the specular highlights. -
Opacity (mat.opac):Boolean indicating if the material is transparent (true) or opaque (false).
For added realism, reflection is implemented by recursively casting reflected rays up to a maximum bounce count defined by MAX_REFL (in minirt.h). The reflected color contribution depends on the material’s reflectivity.
When an object’s material is marked as transparent (opacity = true), rays are refracted as they enter and exit the object using the refractive index defined by DEFAULT_REFR_IND in minirt.h. Note that the current implementation has limitations: it does not handle nested transparent objects correctly and assumes a single refractive index transition (always from air to material).
This rendering mode visualizes the normal vectors of surfaces instead of standard shading. The X, Y, and Z components of the normal vector are mapped to the R, G, and B color channels, respectively. Values for R and G range from 0 to 255, while B ranges from 128 to 255, ensuring the scene is never completely dark.
To save rendered scenes as image files, pressing the p key will export the current window content as a .bmp file. This allows capturing snapshots of the scene outside of real-time viewing.