Povray Tutorial
Povray Tutorial
The beginning tutorial explains step by step how to use POV-Ray’s scene de-
scription language to create your own scenes. The use of almost every feature
of POV- Ray’s language is explained in detail. We will learn basic things like
placing cameras and light sources. We will also learn how to create a large
variety of objects and how to assign different textures to them.
Here is presented only the beginning of the whole ”Beginning tutorial”. This
should be well enought to make your computer graphics assignment. For full
tutorial and also for other documentation please refer the official POV-Ray site
at http://www.povray.org.1
1
Contents
1 Our First Image 3
1.1 Understanding POV-Ray’s Coordinate System . . . . . . . . . . 3
1.2 Adding Standard Include Files . . . . . . . . . . . . . . . . . . . 4
1.3 Adding a Camera . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.4 Describing an Object . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.5 Adding Texture to an Object . . . . . . . . . . . . . . . . . . . . 6
1.6 Defining a Light Source . . . . . . . . . . . . . . . . . . . . . . . 7
2 Basic Shapes 8
2.1 Box Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.2 Cone Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.3 Cylinder Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.4 Plane Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.5 Torus Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3 CSG objects 18
3.1 What is CSG? . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
3.2 CSG Union . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
3.3 CSG Intersection . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3.4 CSG Difference . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
3.5 CSG Merge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
3.6 CSG Pitfalls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
3.6.1 Co-incident Surfaces . . . . . . . . . . . . . . . . . . . . . 23
2
1 Our First Image
We will create the scene file for a simple picture. Since ray-tracers thrive on
spheres, that is what we will render first.2
3
Figure 2: ”Computer graphics aerobics”
up our left hand and point our thumb in the positive direction of the axis of
rotation. Our fingers will curl in the positive direction of rotation. Similarly if
we point our thumb in the negative direction of the axis our fingers will curl in
the negative direction of rotation.
In the figure 2, the left hand is curling around the x-axis. The thumb points
in the positive x direction and the fingers curl over in the positive rotation
direction.
If we want to use a right-handed system, as some CAD systems and modelers
do, the right vector in the camera specification needs to be changed. See the
detailed description in ”Handedness”. In a right-handed system we use our right
hand for the ”Aerobics”.
There is some controversy over whether POV-Ray’s method of doing a right-
handed system is really proper. To avoid problems we stick with the left-handed
system which is not in dispute.
The first include statement reads in definitions for various useful colors. The
second include statement reads in a collection of stone textures. POV-Ray comes
with many standard include files. Others of interest are:
4
#include "shapes.inc"
#include "glass.inc"
#include "metals.inc"
#include "woods.inc"
They read pre-defined textures, shapes, glass, metal, and wood textures. It is a
good idea to have a look through them to see a few of the many possible shapes
and textures available.
We should only include files we really need in our scene. Some of the include
files coming with POV-Ray are quite large and we should better save the parsing
time and memory if we don’t need them. In the following examples we will only
use the colors.inc, and stones.inc include files.
We may have as many include files as needed in a scene file. Include files may
themselves contain include files, but we are limited to declaring includes nested
only ten levels deep.
Filenames specified in the include statements will be searched for in the current
directory first. If it fails to find your .inc files in the current directory, POV-
Ray searches any ”library paths” that you have specified. Library paths are
options set by the +L command-line switch or Library_Path option. See the
chapter ”Setting POV-Ray Options” for more information on library paths.
Because it is more useful to keep include files in a separate directory, standard
installations of POV-Ray place these files in the c:\povray3\include directory
(replace ’c:\povray3’ with the actual directory that you installed POV-Ray in).
If you get an error message saying that POV-Ray cannot open ”colors.inc” or
other include files, make sure that you specify the library path properly.3
camera {
location <0, 2, -3>
look_at <0, 1, 2>
}
3
5
Briefly, location <0, 2, -3> places the camera up two units and back three
units from the center of the ray-tracing universe which is at <0, 0, 0>. By
default +z is into the screen and −z is back out of the screen.
Also look_at <0,1,2> rotates the camera to point at the coordinates <0, 1, 2>.
A point 1 unit up from the origin and 2 units away from the origin. This makes
it 5 units in front of and 1 unit lower than the camera. The look_at point
should be the center of attention of our image.
sphere {
<0, 1, 2>, 2
texture {
pigment { color Yellow }
}
}
The first vector specifies the center of the sphere. In this example the x coor-
dinate is zero so it is centered left and right. It is also at y = 1 or one unit up
from the origin. The z coordinate is 2 which is five units in front of the camera,
which is at z = −3. After the center vector is a comma followed by the radius
which in this case is two units. Since the radius is half the width of a sphere,
the sphere is four units wide.
6
the amount of red, green and blue to be mixed. For example a nice shade of
pink can be specified by:
Note: the international - rather than American - form ”colour” is also accept-
able and may be used anywhere that ”color” may be used.
The values after each keyword should be in the range from 0.0 to 1.0. Any of
the three components not specified will default to 0. A shortcut notation may
also be used. The following produces the same shade of pink:
In many cases the color keyword is superfluous, so the shortest way to specify
the pink color is:
to the scene file to get our first complete POV-Ray scene file as shown below.
#include "colors.inc"
background { color Cyan }
camera {
location <0, 2, -3>
look_at <0, 1, 2>
}
sphere {
<0, 1, 2>, 2
texture {
pigment { color Yellow }
}
}
light_source { <2, 4, -3> color White}
The vector in the light_source statement specifies the location of the light as
two units to our right, four units above the origin and three units back from
the origin. The light source is an invisible tiny point that emits light. It has no
physical shape, so no texture is needed.
That’s it! We close the file and render a small picture of it using whatever
methods you used for your particular platform. (Figure 3) If you specified a
preview display it will appear on your screen. If you specified an output file
(the default is file output on), then POV-Ray also created a file.
7
Figure 3: Our first image
Note: if you do not have high color or true color display hardware then the
preview image may look poor but the full detail is written to the image file
regardless of the type of display.
The scene we just traced isn’t quite state of the art but we will have to start
with the basics before we soon get to much more fascinating features and scenes.
2 Basic Shapes
So far we have just used the sphere shape. There are many other types of shapes
that can be rendered by POV-Ray. The following sections will describe how to
use some of the more simple objects as a replacement for the sphere used above.
box {
<-1, 0, -1>, // Near lower left corner
< 1, 0.5, 3> // Far upper right corner
texture {
T_Stone25 // Pre-defined from stones.inc
scale 4 // Scale by the same amount in all
// directions
}
rotate y*20 // Equivalent to ’’rotate <0,20,0>’’
}
In the example we can see that a box is defined by specifying the 3D coordinates
of its opposite corners. The first vector is generally the minimum x-, y- and z-
8
Figure 4: The box
coordinates and the 2nd vector should be the maximum x-, y- and z- values
however any two opposite corners may be used. (Figure 4)Box objects can only
be defined parallel to the axes of the world coordinate system. We can later
rotate them to any angle.
Note: we can perform simple math on values and vectors. In the rotate param-
eter we multiplied the vector identifier y by 20. This is the same as <0,1,0>*20
or <0,20,0>.
cone {
<0, 1, 0>, 0.3 // Center and radius of one end
<1, 2, 3>, 1.0 // Center and radius of other end
texture { T_Stone25 scale 4 }
}
The cone shape is defined by the center and radius of each end. In this example
one end is at location <0, 1, 0> and has a radius of 0.3 while the other end
is centered at <1, 2, 3> with a radius of 1. (Figure 5) If we want the cone to
come to a sharp point we must use radius = 0. The solid end caps are parallel
to each other and perpendicular to the cone axis. If we want an open cone with
no end caps we have to add the keyword open after the 2nd radius like this:
cone {
<0, 1, 0>, 0.3 // Center and radius of one end
<1, 2, 3>, 1.0 // Center and radius of other end
open // Removes end caps
texture { T_Stone25 scale 4 }
}
9
Figure 5: The cone
cylinder {
<0, 1, 0>, // Center of one end
<1, 2, 3>, // Center of other end
0.5 // Radius
open // Remove end caps
texture { T_Stone25 scale 4 }
}
(Figure 6)
10
Figure 7: Our first image with checkered plane
The object defined here is an infinite plane. The vector <0, 1, 0> is the surface
normal of the plane (i.e. if we were standing on the surface, the normal points
straight up). The number afterward is the distance that the plane is displaced
along the normal from the origin – in this case, the floor is placed at y = −1 so
that the sphere at y = 1, radius = 2, is resting on it. (Figure 7)
plane { y, -1
11
pigment { ... }
}
#include "colors.inc"
camera {
location <0, .1, -25>
look_at 0
angle 30
}
background { color Gray50 } // to make the torus easy to see
light_source { <300, 300, -1000> White }
torus {
4, 1 // major and minor radius
rotate -90*x // so we can see it from the top
pigment { Green }
}
We trace the scene. Well, it’s a donut alright. Let’s try changing the major and
minor radius values and see what happens. We change them as follows:
12
Figure 8: Tori
difference {
torus {
4, 1
rotate x*-90 // so we can see it from the top
}
box { <-5, -5, -1>, <5, 0, 1> }
pigment { Green }
}
Interesting... a half-torus. (Figure 9) Now we add another one flipped the other
way. Only, let’s declare the original half-torus and the necessary transformations
so we can use them again:
union {
object { Half_Torus }
object { Half_Torus
rotate Flip_It_Over
translate Torus_Translate*x
}
}
This makes an S-shaped object, but we can’t see the whole thing from our
present camera. Let’s add a few more links, three in each direction, move the
object along the +z-direction and rotate it about the +y-axis so we can see
more of it. We also notice that there appears to be a small gap where the half
13
Figure 9: Samplepictures for tordemo.pov Phases 1, 3 and 4
Tori meet. This is due to the fact that we are viewing this scene from directly
on the xz- plane. We will change the camera’s y-coordinate from 0 to 0.1 to
eliminate this. (Figure 9)
union {
object { Half_Torus }
object { Half_Torus
rotate Flip_It_Over
translate x*Torus_Translate
}
object { Half_Torus
translate x*Torus_Translate*2
}
object { Half_Torus
rotate Flip_It_Over
translate x*Torus_Translate*3
}
object { Half_Torus
rotate Flip_It_Over
translate -x*Torus_Translate
}
object { Half_Torus
translate -x*Torus_Translate*2
}
object { Half_Torus
rotate Flip_It_Over
translate -x*Torus_Translate*3
}
object { Half_Torus
translate -x*Torus_Translate*4
}
rotate y*45
translate z*20
}
14
easily modeled using two half tori and two cylinders. We create a new file. We
can use the same camera, background, light source and declared objects and
transformations as we used in tordemo.pov:
#include "colors.inc"
camera {
location <0, .1, -25>
look_at 0
angle 30
}
background { color Gray50 }
light_source{ <300, 300, -1000> White }
#declare Half_Torus = difference {
torus {
4,1
sturm
rotate x*-90 // so we can see it from the top
}
box { <-5, -5, -1>, <5, 0, 1> }
pigment { Green }
}
#declare Flip_It_Over = x*180;
#declare Torus_Translate = 8;
union {
object { Half_Torus }
object { Half_Torus rotate Flip_It_Over }
}
This may seem like a wasteful way to make a complete torus, but we are really
going to move each half apart to make room for the cylinders. First, we add the
declared cylinder before the union:
We then add two Chain_Segments to the union and translate them so that they
line up with the minor radius of the torus on each side:
union {
object { Half_Torus }
object { Half_Torus rotate Flip_It_Over }
object { Chain_Segment translate x*Torus_Translate/2 }
object { Chain_Segment translate -x*Torus_Translate/2 }
}
15
Figure 10: Samplepictures for tordemo.pov Phases 5, 7 and 8
Now we translate the two half tori +y and −y so that the clipped ends meet the
ends of the cylinders. (Figure 10) This distance is equal to half of the previously
declared Torus_Translate:
union {
object {
Half_Torus
translate y*Torus_Translate/2
}
object {
Half_Torus
rotate Flip_It_Over
translate -y*Torus_Translate/2
}
object {
Chain_Segment
translate x*Torus_Translate/2
}
object {
Chain_Segment
translate -x*Torus_Translate/2
}
}
We render this and voila! A single link of a chain. (Figure 10) But we aren’t
done yet! Whoever heard of a green chain? We would rather use a nice metallic
color instead. First, we remove any pigment blocks in the declared tori and
cylinders. Then we add the following before the union:
16
We then add the texture to the union and declare the union as a single link:
Now we make a union of two links. The second one will have to be translated
+y so that its inner wall just meets the inner wall of the other link, just like the
links of a chain. This distance turns out to be double the previously declared
Torus_Translate minus 2 (twice the minor radius). This can be described by
the expression:
Torus_Translate*2-2*y
In the object block, we will use this declared value so that we can multiply
it to create other links. Now, we rotate the second link 90*y so that it is
perpendicular to the first, just like links of a chain. Finally, we scale the union
by 1/4 so that we can see the whole thing:
union {
object { Link }
object { Link translate y*Link_Translate rotate y*90 }
scale .25
}
We render this and we will see a very realistic pair of links. If we want to make
an entire chain, we must declare the above union and then create another union
of this declared object. We must be sure to remove the scaling from the declared
object:
17
#declare Link_Pair =
union {
object { Link }
object { Link translate y*Link_Translate rotate y*90 }
}
We render this and we should see a very realistic gold chain stretched diagonally
across the screen like in the figure 11.
3 CSG objects
Constructive Solid Geometry, or CSG, is a powerful tool to combine primitive
objects to create more complex objects as shown in the following sections.4
4
18
3.1 What is CSG?
CSG stands for Constructive Solid Geometry. POV-Ray allows us to con-
struct complex solids by combining primitive shapes in four different ways.
In the union statement, two or more shapes are added together. With the
intersection statement, two or more shapes are combined to make a new
shape that consists of the area common to both shapes. The difference state-
ment, an initial shape has all subsequent shapes subtracted from it.
And last but not least merge, which is like a union where the surfaces inside the
union are removed (useful in transparent CSG objects). We will deal with each
of these in detail in the next few sections.
CSG objects can be extremely complex. They can be deeply nested. In other
words there can be unions of differences or intersections of merges or differences
of intersections or even unions of intersections of differences of merges. . . ad
infinitum. CSG objects are (almost always) finite objects and thus respond to
auto-bounding and can be transformed like any other POV primitive shape.
#include "colors.inc"
camera {
location <0, 1, -10>
look_at 0
angle 36
}
light_source { <500, 500, -1000> White }
plane { y, -1.5
pigment { checker Green White }
}
Let’s add two spheres each translated 0.5 units along the x-axis in each direction.
We color one blue and the other red.
We trace this file and note the results. Now we place a union block around the
two spheres. This will create a single CSG union out of the two objects.
19
union{
sphere { <0, 0, 0>, 1
pigment { Blue }
translate -0.5*x
}
sphere { <0, 0, 0>, 1
pigment { Red }
translate 0.5*x
}
}
We trace the file again. The union will appear no different from what each
sphere looked like on its own, but now we can give the entire union a single
texture and transform it as a whole. Let’s do that now.
union{
sphere { <0, 0, 0>, 1
translate -0.5*x
}
sphere { <0, 0, 0>, 1
translate 0.5*x
}
pigment { Red }
scale <1, .25, 1>
rotate <30, 0, 45>
}
We trace the file again. As we can see, the object has changed dramatically.
We experiment with different values of scale and rotate and try some different
textures.
There are many advantages of assigning only one texture to a CSG object instead
of assigning the texture to each individual component. First, it is much easier
to use one texture if our CSG object has a lot of components because changing
the objects appearance involves changing only one single texture. Second, the
file parses faster because the texture has to be parsed only once. This may be
a great factor when doing large scenes or animations. Third, using only one
texture saves memory because the texture is only stored once and referenced by
all components of the CSG object. Assigning the texture to all n components
means that it is stored n times.
intersection {
sphere { <0, 0, 0>, 1
20
translate -0.5*x
}
sphere { <0, 0, 0>, 1
translate 0.5*x
}
pigment { Red }
}
We trace the file and will see a lens-shaped object instead of the two spheres.
This is because an intersection consists of the area shared by both shapes, in
this case the lens-shaped area where the two spheres overlap. We like this lens-
shaped object so we will use it to demonstrate differences.
intersection{
sphere { <0, 0, 0>, 1
translate -0.5*x
}
sphere { <0, 0, 0>, 1
translate 0.5*x
}
pigment { Red }
rotate 90*y
}
Let’s create a cylinder and stick it right in the middle of the lens.
We render the scene to see the position of the cylinder. We will place a
difference block around both the lens-shaped intersection and the cylinder
like this:
difference {
intersection {
sphere { <0, 0, 0>, 1
translate -0.5*x
}
sphere { <0, 0, 0>, 1
translate 0.5*x
}
pigment { Red }
21
rotate 90*y
}
cylinder { <0, 0, -1> <0, 0, 1>, .35
pigment { Blue }
}
}
We render the file again and see the lens-shaped intersection with a neat hole in
the middle of it where the cylinder was. The cylinder has been subtracted from
the intersection. Note that the pigment of the cylinder causes the surface of the
hole to be colored blue. If we eliminate this pigment the surface of the hole will
be black, as this is the default color if no color is specified.
OK, let’s get a little wilder now. Let’s declare our perforated lens object to give
it a name. Let’s also eliminate all textures in the declared object because we
will want them to be in the final union instead.
Let’s use a union to build a complex shape composed of copies of this object.
union {
object { Lens_With_Hole translate <-.65, .65, 0> }
object { Lens_With_Hole translate <.65, .65, 0> }
object { Lens_With_Hole translate <-.65, -.65, 0> }
object { Lens_With_Hole translate <.65, -.65, 0> }
pigment { Red }
}
We render the scene. An interesting object to be sure. But let’s try something
more. Let’s make it a partially-transparent object by adding some filter to the
pigment block.
union {
object { Lens_With_Hole translate <-.65, .65, 0> }
object { Lens_With_Hole translate <.65, .65, 0> }
object { Lens_With_Hole translate <-.65, -.65, 0> }
object { Lens_With_Hole translate <.65, -.65, 0> }
pigment { Red filter .5 }
}
22
We render the file again. This looks pretty good... only... we can see parts of
each of the lens objects inside the union! This is not good.
merge {
object { Lens_With_Hole translate <-.65, .65, 0> }
object { Lens_With_Hole translate <.65, .65, 0> }
object { Lens_With_Hole translate <-.65, -.65, 0> }
object { Lens_With_Hole translate <.65, -.65, 0> }
pigment { Red filter .5 }
}
POV-Ray uses inside/outside tests to determine the points at which a ray inter-
sects a CSG object. A problem arises when the surfaces of two different shapes
coincide because there is no way (due to the computer’s floating-point accuracy)
to tell whether a point on the coincident surface belongs to one shape or the
other.
Look at the following example where a cylinder is used to cut a hole in a larger
box.
difference {
box { -1, 1 pigment { Red } }
cylinder { -z, z, 0.5 pigment { Green } }
}
Note: that the vectors -1 and 1 in the box definition expand to <-1, -1, -1>
and <1, 1, 1> respectively.
If we trace this object we see red speckles where the hole is supposed to be. This
is caused by the coincident surfaces of the cylinder and the box. One time the
cylinder’s surface is hit first by a viewing ray, resulting in the correct rendering
of the hole, and another time the box is hit first, leading to a wrong result
where the hole vanishes and red speckles appear. This problem can be avoided
by increasing the size of the cylinder to get rid of the coincidence surfaces. This
is done by:
23
difference {
box { -1, 1 pigment { Red } }
cylinder { -1.001*z, 1.001*z, 0.5 pigment { Green } }
}
In general we have to make the subtracted object a little bit larger in a CSG dif-
ference. We just have to look for coincident surfaces and increase the subtracted
object appropriately to get rid of those surfaces.
The same problem occurs in CSG intersections and is also avoided by scaling
some of the involved objects.
24