Ray Tracer
Development
I implemented the project together with my fellow student Basil Fierz for the ?Introduction to Computer Graphics? course at ETH during the autumn semester 2007.
Detailed Description
The features that we had to implement for the course include several different primitive types, intersection acceleration using kD-trees, reflection/refraction, different lighting models, texturing and other things that nearly every ray tracer has. Apart of this the ray tracer features some more special things.
First of all the architecture of the ray tracer has been built around shaders. To determine the colour of an object hit by a ray a shader is run. The shader to be run is determined by the material attached to the object. Shaders can feature ordinary lighting models or more complex stuff like ocean shading or normal mapping. In order to improve the data driven design the ray tracer allows those shaders to be implemented in a scripting language provided by the kaos Engine. This way an object?s appearance can be customized without changing the source code of the ray tracer.
To allow the rendering of animated scenes the ray tracer has to implement a sophisticated animation and camera model. Since rendering a movie can take possibly hours it is desirable to cache generated frames on the hard disc. The ray tracer can also be configured to either generate a series of images or to write directly a movie file.
For the end of semester contest we had to implement something special. Our entry, using this ray tracer, consisted of three different types of new scenes. First the rendering of an ocean using the statistical ocean model, second the rendering of a Doom 3 cut scene and third the rendering of a television playing a movie inside.
Technical Details
- Additional Developers: Basil Fierz
- Programming Language: C++
- Development Environment: Visual Studio 2005
- Project Size: 236 files, 19637 code lines, 5907 comment lines, 5814 blank lines, 915 KiB code
- Project Duration: 14 Weeks as a course project
- Technology used: -
Feature List
- Several different primitives like planes, triangles, quadrics or arbitrary 3d models
- Fractals
- Refraction, Reflection and Shadows
- Lambert Diffuse and Blinn/Phong Lighting
- Image textures, procedural textures and movie textures
- Supersampling
- Normal Mapping
- kD-Trees to accelerate intersection queries
- Different types of light sources. Including area lights
- Animation and creation of movies
- Instancing
- many more
Challenges
One of the challenges with the ray tracer was that the work had to be done besides the rest of all the studies. The far bigger challenge was that we did not focus on the performance of the ray tracer. We preferred to implement cool features. In the end we realised that we had to remove features (for example the area light) from our end of semester contest demos because we did not had the time to render the movies using them. We also had to constrain the movie to some low resolution like 480 times 320 pixels. Even using this low resolution we had a total rendering time of totally about thirty hours distributed to three 2.4 core 2 duo machines.
Screenshots
A reflecting sphere inside a room of "infinitely" reflecting mirrors |
||
Videos
Viewing the procedurally textured wooden horse from different angles |
A film we created for the end of semester contest of the course. It was made using only the ray tracer and an audio editing tool |
Code Sample
The code piece shown represents the main render loop. This is the place where all the pixels are colored.
//main renderloop that raytraces the given scene
void Renderer::render(Scene* scene){
if (scene) {
scene->getCamera()->getFilm()->AppendPicture();
scene->getCamera()->getFilm()->BeginFrame();
// Initialize Sampler
Point p = scene->getCamera()->getFilm()->GetResolution();
m_sampler->init(p.x, p.y);
// Initialize fields
Ray ray;
std::vector<Ray> shadowRays;
IntersectionData* iData = 0;
Sample* sample = new Sample(0,0);
//reset film in camera
sample->setSize( (p.x > p.y? p.x : p.y) );
scene->getCamera()->setSample(*sample);
// Renderloop
while (m_sampler->getNextSample(sample)) {
// generate camera ray and intersect it with the scene
ray = scene->getCamera()->generateRay(*sample);
sample->setColor(traceColor(ray, scene, 0));
// write back the sample color
scene->getCamera()->setSample(*sample);
// observer update
if (m_sampler->cycleComplete()) {
notifyObservers();
}
}
//cleanup
scene->getCamera()->getFilm()->EndFrame();
delete sample;
}
}
Related Links
- Introduction to Computer Graphics Course page
- Results of the course contest
- Contest video on YouTube