More sample images in rayhunter gallery.
rayhunter is a command-line program that takes
a 3D model (like a VRML, X3D or Collada file) and renders an image that
would be visible from given camera looking at given scene.
Two ray-tracing algorithms
may be used: deterministic (classic Whitted-style ray-tracer)
and Monte Carlo path tracing.
You can take a look at the gallery of images rendered using rayhunter as a demonstration of rayhunter's capabilities.
No installation is required. Just download and unpack these archives wherever
you want, and run the program inside. The documentation
(this web page) is also included inside
(look in the
documentation/ subdirectory) for offline viewing.
Basic syntax to call
rayhunter classic <recursion-depth> <image-width> <image-height> <input-filename> <output-filename>
rayhunter path <recursion-depth> <non-primary-samples-count> <image-width> <image-height> <input-filename> <output-filename>
says which ray-tracing algorithm to use.
This is normal Whitted-style deterministic ray-tracer.
All normal VRML lights are handled (point, spot, directional,
including the headlight).
No area lights, so no soft shadows.
Algorithm sends one primary ray for each pixel.
Ray-tracing is recursive, where the ray casts on some
surface we check rays to light sources and eventually
we recursively check refracted ray (when
transparency > 0) and reflected ray
mirror > 0).
a nice article about ray-tracing that describes
This is path tracer. Every surface with non-zero
emissiveColor is a light emitter. For each
pixel many random paths are checked and final pixel color
is the average color from all paths.
rayhunter for every pixel
<primary-samples-count> of primary
rays, and then each primary ray that hits something splits into
So in total we check
This is a sensible optimization, because usually there
is no need to take many
since all primary rays hit more-or-less the same thing,
since they have very similar direction.
set using the 3rd required command-line option,
<primary-samples-count> is set
using optional option
(by default it's 1).
This is interpreted differently by different ray-tracing algorithms:
0 means that each object will have only his own color. 1 means that light rays can light the surface, and ray may be once reflected or refracted. Greater values allow rays to be reflected and/or refracted more times along the way.
--r-roul-continueoption) will be 0.5 (the default value), then 1/2 of all paths will have length 3, 1/4 of all paths will have length 4, 1/8 of all paths will have length 5 etc.
Russian-roulette makes sure that the result is unbiased, i.e. the expected value is the correct result (i.e. the perfect beautiful realistic image). However, Russian-roulette introduces also a large variance, visible as a noise on the image.
That's where forcing some minimal path length helps. Sensible values for this are 1 or 2. Of course, the greater the better, but it will also slow down the rendering. 0 means that Russian-roulette will always be used to decide about path termination (expect a lot of noise on the image!).
Only for path tracer. Together with
<primary-samples-count>, this specifies
how many paths will be checked at each pixel.
Various scenes may require different numbers here to look
nice — you can start with 10, then 100, then even 1000.
But beware — this value directly affects rendering speed.
Width and height of resulting image.
3d model filename.
Anything that my code can read (see view3dscene docs) is accepted here. X3D and VRML are the best formats, we also read Collada and 3DS lights, for all other formats: only the headlight will shine over the scene.
- (single dash) as a filename means stdin.
Filename where to write final image. Image format will be automatically derived from filename extension, known image formats and extensions are
If you will use
(see below), then partial images will be also written to this file.
Moreover, if you will use
--first-row features (see below),
then initial image contents will be read from this file.
Notes about RGBE format: This format was developed by Greg Ward, and is used e.g. by Radiance. Colors in RGBE images are written with a very good precision, while not wasting a lot of disk space. Good precision means that you may be able to expose in the image some details that were not initially visible for the human eye, e.g. by brightening some areas. Also color components are not clamped to [0; 1] range — each component can be any large number. This means that even if resulting image is too bright, and some areas look just like white stains, you can always correct the image by darkening it or applying gamma correction etc.
Options below may be placed anywhere at command-line (before, between or after required options listed above).
classic ray-tracer :
Implemented light model is as close as possible to the light model outlined in VRML 2.0 / X3D specification. Some modifications were needed because I have recursive ray-tracing (while VRML 97 specifies only local light model). Also VRML 1.0 models require different treating in some cases (e.g.
SpotLight focus is specified using a different
ambientIntensity is not available in standard VRML 1.0).
We handle all X3D light nodes —
PointLight. Also the headlight
is used, configurable by
<recursion-depth> equal zero we use only
diffuse material color. According to VRML 97 light model,
emission color would be more correct but in 99% of real
emission color is just black so the whole rendered
image would be black. That's why I decided to use
color instead of
emission. Everyone understands that setting
<recursion-depth> to zero is only for testing purposes
classic ray-tracer :
mirror field of
Material node to create mirrors.
path tracer :
We don't use point and directional lights, so VRML
PointLight nodes are completely ignored.
Only the surface lights are used. Every object with
emissiveColor is a light source.
Implemented BRDF is Phong's BRDF.
See fields describing physical properties (Phong's BRDF) for
Some things not handled (yet): textures, interpolating normal vectors (i.e. we're of course calculating pixel color at every surface point separately, but our surfaces are flat with regards to normal vectors).
This concerns actually most 3d engines, including
ray-tracer algorithms inside
and real-time OpenGL rendering inside
3d model's geometry must be correct. Which means that:
No T-Intersections allowed. Otherwise you may see cracks.
If two faces cross each other, the intersection may be a line, not a plane. I.e. they shouldn't be coplanar in such case. Otherwise they will fight which one is nearer than the other and which one casts the shadow over the other.
rayhunter should be able to handle such
bad case of coplanar surfaces (i.e. result will look OK
as long as surfaces have the same material), but there
is never 100% warranty for such things (because it involves
The obvious advantage is that you can use
in batch mode,from scripts etc.
rayhunter can produce images in RGBE format.
--write-partial-rowsto be able to kill rayhunter process at any time and then later resume rendering from last point. You can also use the same options to render various parts of the image simultaneously on multiple systems. These advantages may be crucial if you want to do some serious rendering using path tracer, since they may take a lot of time.
--primary-samples-count that allow you to better control
path tracing are not available in
rayhuntermay work a little faster since it doesn't display the image while rendering. Although using
--write-partial-rowsyou can force
rayhunterto write partial result from time to time.