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.
Contents:
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.
This is free/open-source software. Get the code from GitHub.
Basic syntax to call rayhunter
is
rayhunter classic <recursion-depth> <image-width> <image-height> <input-filename> <output-filename>
or
rayhunter path <recursion-depth> <non-primary-samples-count> <image-width> <image-height> <input-filename> <output-filename>
First option, classic
or path
,
says which ray-tracing algorithm to use.
classic
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 Material
has transparency
> 0) and reflected ray
(when Material
has mirror
> 0).
Wikipedia has
a nice article about ray-tracing that describes
Whitted-style ray-tracing.
path
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.
Actually rayhunter
for every pixel
checks <primary-samples-count>
of primary
rays, and then each primary ray that hits something splits into
<non-primary-samples-count>
.
So in total we check <primary-samples-count>
*
<non-primary-samples-count>
paths.
This is a sensible optimization, because usually there
is no need to take many <primary-samples-count>
,
since all primary rays hit more-or-less the same thing,
since they have very similar direction.
<non-primary-samples-count>
is
set using the 3rd required command-line option,
and <primary-samples-count>
is set
using optional option --primary-samples-count
(by default it's 1).
<recursion-depth>
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-continue
option) 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!).
<non-primary-samples-count>
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.
<image-width> <image-height>
Width and height of resulting image.
<input-filename>
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.
<output-filename>
Filename where to write final image. Image format will be automatically derived from filename extension, known image formats and extensions are
rgbe
(or pic
)
png
jpg
(or jpeg
)
ppm
bmp
If you will use --write-partial-image
features
(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.
You can process RGBE images using Radiance programs. Also my Castle Image Viewer can be used to view RGBE images.
Options below may be placed anywhere at command-line (before, between or after required options listed above).
See also notes about command-line options for all my programs.
Only for 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
way and ambientIntensity
is not available in standard VRML 1.0).
We handle all X3D light nodes — DirectionalLight
,
SpotLight
and PointLight
. Also the headlight
is used, configurable by NavigationInfo.headlight
and NavigationInfo.headlightNode.
For <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
cases emission
color is just black so the whole rendered
image would be black. That's why I decided to use diffuse
color instead of emission
. Everyone understands that setting
<recursion-depth>
to zero is only for testing purposes
anyway.
Mostly for classic
ray-tracer :
Use mirror
field of Material
node to create mirrors.
Only for path
tracer :
We don't use point and directional lights,
so VRML DirectionalLight
, SpotLight
and
PointLight
nodes are completely ignored.
Only the surface lights are used. Every object with
a non-black emissiveColor
is a light source.
Implemented BRDF is Phong's BRDF.
See fields describing physical properties (Phong's BRDF) for Material
node.
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 rayhunter
and real-time OpenGL rendering inside
castle-model-viewer:
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.
Actually 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
floating-point errors).
The same ray-tracer code as is used by rayhunter
is also used inside
castle-model-viewer.
While using ray-tracer from
castle-model-viewer
is more comfortable, using command-line rayhunter
has also
some advantages:
The obvious advantage is that you can use rayhunter
in batch mode,from scripts etc.
rayhunter
can produce images in RGBE format.
--first-row
and
--write-partial-rows
to 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.
Options --r-roul-continue
,
--direct-illum-samples-count
,
--primary-samples-count
that allow you to better control
path tracing are not available in view3dscene
.
rayhunter
may work a little faster since it doesn't
display the image while rendering. Although using
--write-partial-rows
you can force rayhunter
to write partial result from time to time.