Developing ray tracing render from scratch.
- Using k-d tree for fast traversal of 3D scene objects
- Using Surface Area Heuristic for building optimal k-d tree
- Rendering entire scene in parallel (using OpenMP)
- Texture mapping (using libpng)
- Saving rendered image to file (using libpng)
- Loading 3D models from *.obj format
- Phong shading
- Phong reflection model
- Two types of primitives: triangle and sphere
- Reflections, shadows, fog effect, multiple light sources
Requires libpng to be installed.
Tested on Mac OS 10.8 with gcc 4.2 and gcc 4.7.
All rendering routines are performing by this render, not OpenGL. Just using GLUT to display rendered image.
make run_demo_gl- Use controls ← ↑ → ↓ to rotate camera
- Use CTRL + ↑ or CTRL + ↓ to move camera forward or backward
- Use SHIFT + ↑ or SHIFT + ↓ to move camera up or down
- Use SHIFT + ← or SHIFT + → to move camera left or right
- Use ALT + ↑ or ALT + ↓ to change focus of camera
- Use ESC to exit
Lets create example application from scratch :) You will get following image:
#include<stdio.h>#include<canvas.h>#include<render.h>#include<obj_loader.h>#defineCANVAS_W 400
#defineCANVAS_H 400
// Boost by rendering in parallel#defineTHREADS_NUM 4
#defineBACKGROUND_COLOR rgb(255, 255, 255)
#defineMAX_OBJECTS_NUMBER 10000
#defineMAX_LIGHT_SOURCES_NUMBER 5
intmain(void) {
// Allocating sceneScene*scene=new_scene(MAX_OBJECTS_NUMBER,
MAX_LIGHT_SOURCES_NUMBER,
BACKGROUND_COLOR);
// Allocating new sphereFloatradius=100;
Point3dcenter=point3d(0, 0, 0);
Colorsphere_color=rgb(250, 30, 30);
Materialsphere_material=material(1, 5, 5, 10, 0, 10);
Object3d*sphere=new_sphere(center,
radius,
sphere_color,
sphere_material);
// Adding sphere to the sceneadd_object(scene,
sphere);
// Allocating new triangleObject3d*triangle=new_triangle(point3d(-700, -700, -130), // vertex 1point3d( 700, -700, -130), // vertex 2point3d( 0, 400, -130), // vertex 3rgb(100, 255, 30), // colormaterial(1, 6, 0, 2, 0, 0) // surface params
);
// Adding triangle to the sceneadd_object(scene,
triangle);
// Loading 3D model of cow from *.obj file// defining transformations and parameters of 3D model// TODO: must be refactored...SceneFaceHandlerParamsload_params=new_scene_face_handler_params(scene,
// scale:40,
// move dx, dy, dz:-150, -100, 30,
// rotate around axises x, y, z:0, 0, 0,
// colorrgb(200, 200, 50),
// surface paramsmaterial(2, 3, 0, 0, 0, 0)
);
load_obj("./demo/models/cow.obj",
// default handler which adding polygons of 3D model to scene:scene_face_handler,
&load_params);
// This function is requried (bulding k-d tree of entire scene)prepare_scene(scene);
printf("\nNumber of polygons: %i\n", scene->last_object_index+1);
// Allocating new light sourceColorlight_source_color=rgb(255, 255, 255);
Point3dlight_source_location=point3d(-300, 300, 300);
LightSource3d*light_source=new_light_source(light_source_location,
light_source_color);
// Adding light source to the sceneadd_light_source(scene,
light_source);
// Adding fogFloatdensity=0.002;
set_exponential_fog(scene, density);
// Allocating camera// TODO: It's a pity, but quaternions are not implemented yet :(Point3dcamera_location=point3d(0, 500, 0);
Floatfocus=320;
Floatx_angle=-1.57;
Floaty_angle=0;
Floatz_angle=3.14;
Camera*camera=new_camera(camera_location,
x_angle,
y_angle,
z_angle,
focus);
// Rotate camera if needed// rotate_camera(camera, d_x_angle, d_y_angle, d_z_angle);// Move camera if needed// move_camera(camera, vector3df(d_x, d_y, d_z));// Alocate new canvas, to render scene on itCanvas*canvas=new_canvas(CANVAS_W,
CANVAS_H);
render_scene(scene,
camera,
canvas,
THREADS_NUM);
// Saving rendered image in PNG formatwrite_png("example.png",
canvas);
release_canvas(canvas);
release_scene(scene);
release_camera(camera);
return0;
}Launch it
make example && ./exampleDefine different values of maximal depth of Kd-tree and track average number of ray intersections per pixel:
make DEF="-DRAY_INTERSECTIONS_STAT -DMAX_TREE_DEPTH=25" run_demo_glmake DEF="-DRAY_INTERSECTIONS_STAT -DMAX_TREE_DEPTH=25" example && ./exampleIllustration of kd-tree boosting:
- Without kd-tree, and without bounding box:
make clean > /dev/null
make DEF="-DRAY_INTERSECTIONS_STAT -DNO_BOUNDING_BOX -DMAX_TREE_DEPTH=0" benchmark > /dev/null &&
./benchmark
make clean > /dev/null- Without kd-tree, but with bounding box:
make clean > /dev/null
make DEF="-DRAY_INTERSECTIONS_STAT -DMAX_TREE_DEPTH=0" benchmark > /dev/null &&
./benchmark
make clean > /dev/null- With kd-tree, but without bounding box:
make clean > /dev/null
make DEF="-DRAY_INTERSECTIONS_STAT -DNO_BOUNDING_BOX -DMAX_TREE_DEPTH=20" benchmark > /dev/null &&
./benchmark
make clean > /dev/null- With id-tree, and with bounding box:
make clean > /dev/null
make DEF="-DRAY_INTERSECTIONS_STAT -DMAX_TREE_DEPTH=20" benchmark > /dev/null &&
./benchmark
make clean > /dev/null