Z Ray Tracer



Z Ray Tracer (ZRT) is a physically based general-purpose ray tracer developed by Hongzhi Wu as an effort to learn the theories and practices of physically based rendering. Z stands for "zhui", a Chinese character which means "trace". Currently I am using it as a test-bed for rendering research (by writing plugins for it).



Architecture: Multi-threading, Flexible C-like script language*, Highly customizable Plugins, Instances, Variuous debugging options (partial rendering, debugging shader, etc)
Geometry: Basic Primitives, .OBJ meshes with materials, kd-tree based intersection routines
Textures: Popular texture formats, Mipmap construction, HDR, Environment maps, Normal maps
Shadering Models: Lambertian, Ward, Cook-Torrance, Measured BRDF(MERL Database)
Rendering Techniques: Path tracing, Photon-mapping, Multiple Importance Sampling, Quasi Monte-Carlo



Please click on the thumbnails to see the original pictures.

Two mirror balls

perfect mirror and global diffuse illumination shader, area light, 4 shadow rays,  mirror reflectance = 0.9.

Mirror bunny and diffuse ball

perfect mirror and global diffuse illumination shader,  area light, 4 shadow rays, mirror reflectance = 0.9.

Silver bunny and orange ball

measured isotropic BRDF global illumination shader, 4 shadow rays, 
BRDFs[2]: silver-metallic-paint, orange-paint
Textured scene

global diffuse illumination shader,  4 shadow rays
Diffuse scene in a lightprobe

global diffuse illumination shader, uffizi light probe, 64 shadow rays
Bronze bunny and a silver ball on a plane with blue- metallic-paint BRDF Tainted screws on a table

screws using measured silver-metallic-paint BRDF modulated with a texture. Note the anisotropicity on the body of the screws due to the small-scale varaitions in geometry

Silver-metallic-paint  ball

measured isotropic BRDF global illumination shader, 64 shadow rays

global diffuse illumination shader


global diffuse illumination shader



R&D Log

07/13/2007    Implemented tone mapping using bilateral filtering [3]. Some of the pictures below are adjusted using tone-mapping.

05/06/2007    Used flex and bison to generate a parser for our own scene description. Now ZRT is a completely data-driven command line tool.

04/29/2007    Added 2d MIP-MAPed textures and cube map.

04/24/2007    Added isotropic BRDF shaders for both analytical(Ward) and measured-data (MERL dataset) models.

04/03/2007    Added support for triangular meshes; Added a BSP tree based intersection accelerator for meshes and a kd tree acceleration structure for the entire scene.

03/27/2007    Summary of previous progress: Established the overall general purpose offline renderer architecture. Features area light, soft shadows, indirect lighting (global illumination) shader and perfect mirror shader.


Sample Scene Configuration File

cam = pinhole_camera(vector3(0, 1, 3.25), vector3(0, 1, -3), vector3(0, 1, 0), 0.1, 0.1, 0.1)


cam_sampler = super_camera_sampler(cam, subpixel = 2, 0)


// init light

lt_scale = 0.5

lt = env_light(

  spectrum(lt_scale, lt_scale, lt_scale),







// init shaders

sh = global_diffuse_shader()

matr_white = material (

  "diffuse_reflectance" = RGB(0.9, 0.9, 0.9)



matr_red = material (

  "diffuse_reflectance" = RGB(0.9, 0.1, 0.1)



matr_green = material (

  "diffuse_reflectance" = RGB(0.1, 0.9, 0.1)



linkmap = shader_link_map (

  "reflectance" = "diffuse_reflectance",

  "reflectance_mapping" = "mapping",

  "reflectance_texture" = "texture",

  "reflectance_sampler" = "sampler"



rect  = rectangle_shape(2.0, 2.0)

sphere= sphere_shape(0.25)

plane = kd_tri_mesh_shape("Data\airplane.obj", 0.01, 6)



obj_bottom = simple_object(rect,



    translate(0.0, 0.0, 0.0)


  matr_white, sh, linkmap)



obj_back = simple_object(rect,


    translate(0.0, 1.0, -1.0)


  matr_white, sh, linkmap)



obj_left = simple_object(rect,



    translate(-1.0, 1.0, 0.0)


  matr_red, sh, linkmap)



obj_ball = simple_object(sphere,


    translate(-0.65, 0.25, 0.4)


  matr_white, sh, linkmap)



obj_plane = simple_object(plane,


    scale(0.8, 0.8, 0.8),



    translate(-0.1, 0.6, -0.05)


  matr_white, sh, linkmap)


// init scene

s = photon_mapped_scene(num_photons = 1000000, 0, kd_scene_isaccelerator(0.01, 4))

s += (lt,







// let's get started...

imaging(s, cam_sampler,

  width = 256, height = 256,


    num_shadow = 512, //shadow rays

    num_gather = 256, //gather rays

    num_lookup = 8000,

    radius = 0.025,

    gather = 1, // gather for L_i or use photon estimation directly

    trace = 1 // direct raytrace L_d or use photon estimation directly





shell("raw2png boxenvp.raw /o boxenvp.png")



[1] Matt Pharr and Greg Humphreys. Physically based rendering. Morgan Kaufmann Press, 2004

[2] Wojciech Matusik, Hanspeter Pfister, Matt Brand, and Leonard McMillan. A data-driven reflectance model. ACM Trans. Graph. 22(3):759-769, 2003

[3] Fredo Durand and Julie Dorsey. Fast Bilateral Filtering for the Display of High-Dynamic-Range Images. Proceedings of the 29th annual conference on Computer graphics and interactive techniques : 257-266, 2002


Back to Cool Stuff

Last Updated  2009-02-05 23:34:05