The POV-Ray language is fairly easy to use, once you understand it. In
fact, if you have any experience with programming, you will find POV-Ray
very easy -- there are no variables, conditionals, loops, or anything else
that can make programming tricky. Basically, a POV-Ray source file (the
file you make and give to POV-Ray) is just a list of objects and their
descriptions. Of course, describing the scene you have in your mind to
POV-Ray is the tricky part, because you have to speak POV-Ray's language.
The building blocks of all POV-Ray objects and scenes are called
primitives. Primitives are objects that POV-Ray already
knows about, and all you have to do is describe a few attributes. POV-Ray
primitives are usually simple geometric shapes such as spheres, cubes, and
cones.
Describing primitives, in general, take this form in POV-Ray:
Deciphering what this does isn't too tricky. The code defines a sphere with
its center at the origin (that's <0,0,0>, remember?) and
with a radius of 5 (in other words, the distance from the center of the
sphere to any point on the edge of the sphere is exactly 5 units). The
phrase pigment { color rgb <1,0,0> } simply means that the
sphere's pigment (or color) attribute is described by the rgb vector
<1,0,0>, which is the color red. You could have just as
well used color Red, if you had #included the
correct file. The pigment attribute, by the way, is a complex attribute,
of which color is just one of the many attributes that
can go inside it.
There are two types of primitives in POV-Ray: finite
primitives and infinite primitives.
Finite primitives have well-defined limits. Examples of
finite primitives include spheres, cones, torii, and blobs. Infinite
primitives have components that can potentially stretch to infinity -- for example, a
plane is both infinitely thin and infinitely wide. Examples of infinite
objects include planes, quadrics and cubics. At any rate, describing
primitives in POV-Ray is only a matter of knowing the syntax for the
particular primitive you want to describe. You can find a complete syntax
reference in the finite object and infinite object language references.
By now, you're probably itching to make your first scene. Before you can do
that, however, you need to learn about two things: the camera and light sources.
The Camera
Before POV-Ray can generate the scene, it needs to know from where you are
looking. If you imagine your computer screen as the camera taking a
snapshot of the scene you're describing, you'll see POV-Ray needs to know a)
where the camera is in the scene, and b) which direction it's pointing. Such
data is given to POV-Ray through the camera object. As
you might imagine, the camera object is a rather important one: in fact,
POV-Ray requires that there be one and only one in each scene.
There are many attributes that the camera object can have; of these, we will
only concentrate on the two most useful: the location
and the look_at attributes. A complete reference of all
the camera attributes can be found in the Camera Reference.
A simple camera in POV-Ray looks like this:
camera {
location <2,5,-10>
look_at <0,0,0>
}
This example defines a camera located at <2,5,-10> and
pointing at the origin. This means that anything with a z
coordinate less than -10 will definately be invisible
-- it will be behind the camera!
You can put the camera anywhere you want in the scene, including inside of
objects (although you may not see very much), with one exception: you may
not place the camera directly over the origin and have it looking straight
down. For complex mathematical reasons, this will cause POV-Ray to generate an
error. If you need that type of setup, position the camera a little to the
left or the right -- your problem will be solved, and your scene will look
(almost) exactly the same.
Anyways, now that we have a way of receiving light, we need to have a way of
providing light.
Let there be light! (Light sources)
If you gave POV-Ray a file containing the camera definition above and the
sphere definition before that, the output image would be a lovely blank
picture. This would happen because you'd have no light in your scene. To
add light (thereby enabling you to actually see something), you
need to add a light source.
There are a few different types of light sources in POV-Ray. We will
concentrate here on the most simple (and useful): the point light
source. A point light source can be thought of as an infinitely
small object that emits light. Because they are infinitely small, point
light sources cannot be directly seen (so you don't have to worry about them
appearing in your scene). However, their effects can certainly be
seen: your scene lights up!
Point light sources as known as non-attenuating light sources: the emitted
light does not get weaker with distance. This means that you can illuminate
your entire scene with one point light source placed far away from the
scene. You can have as many light sources as you want, but they are
computationally expensive -- the more you have, the longer POV-Ray will take
to trace your scene.
An example of a simple point light source definition in POV-Ray looks like
this:
light_source {
<0,10,-10>
color rgb <1,1,1>
}
The first vector is a position vector specifying the location of the light
source. The second vector specifies the color (and brightness) of the
light. It is generally a good idea to use white or gray light, as using
colored light can have side effects that are not immediately obvious (for
example, green objects will not show up when exposed to pure red light).
Complete information for light sources can be found in the lights section of the Language Reference.
Anyways, now that we can add light, we're ready to construct our first full
scene.
The first example scene
Putting together all we have learned to far, we get a complete POV-Ray
source code file that looks like this:
// This is a simple red sphere
// first, the camera position
camera {
location <2,5,-10>
look_at <0,0,0>
}
// now, some light
light_source {
<0,-10,0>
color rgb <1,1,1>
}
// the sphere
sphere {
<0,0,0>, 5
pigment { color rgb <1,0,0> }
}
After running POV-Ray, the output image looks like this:
Finally! Your first image! Of course, this one is a little boring -- but
don't worry, we'll get to some fun stuff soon. For now, experiment! It's
the best way to learn. Try replacing the sphere with other objects and
seeing what happens. The objects that you should easily be able to use are
boxes, cones, cylinders, spheres, torii and planes.
Transformations
So now we can create some simple objecs. But wait! Some of these objects
can only be created around the origin (like the torus). What if we want to
put them somewhere else? What if we want to move them around? POV-Ray
provides answers to all these questions in the form of
transformations. Transformations, in ray-tracing terms,
are attributes that change the position, size or orientation of objects (and
of the various attributes of the objects). The most common types of
transformations, and the ones that POV-Ray supports, are
translations, rotations and
scalings.
A translation is a transformation that moves an object
relative to its current position. It is specified in POV-Ray by the phrase
translate <x,y,z>.
Translations are easy to visualize. Consider a cube sitting on the origin,
like this:
Our camera is positioned so that the x axis increases to the right, the y
axis increases upwards and the z axis increases towards us. A translation
of <-1,4,2> results in the cube being moved left one
unit, up four, and back two, like this:
A rotation is a transformation that changes the
orientation of an object (the way that it's facing). Rotations are the most
complex of the transformations. They are specified to POV-Ray by the string
rotation <x,y,z>, where
x, y, and z are the number of degrees (not
radians) around the respective axis. Consider the original cube up above. A
rotation of <0,0,45> rotates the cube 45 degrees around
the z axis, leaving us with a cube looking like this:
A quick way to remember which way the objects are going to rotate is by
usings the so-called "left hand rule." Hold out your left hand, fingers
clenched and thumb out. Point your thumb in the positive direction of the axis you
are rotating about (if you're rotating about more than one axis at a time,
this won't help you -- unless you have more than one thumb!) The direction
that your fingers curl is the direction an object will rotate when the
number of degrees is positive. (Negative degrees rotate the opposite
direction).
Another important thing to remember about rotations is that they are always
with respect to the coordinate axes -- in other words, unless your object is
located at the origin, it will orbit around the axis (or axes) you are
rotating it about. For example, this is what would happen if we translated
the cube first, and then rotated it:
To get around this, make sure you rotate your object when its
centered at the origin, and thentranslate it. Your
picture will end up like this:
Transformations are one of the few aspects of POV-Ray in which the order
matters, simply because transformations are always made with respect to the
object's current orientation.
The last translation you need to know about is scaling.
Simply enough, scaling changes the size of the object with respect to its
current size. Scaling is specified in POV-Ray via the string scale
<x,y,z>. The elements of the
vector specify the how much to scale the shape with respect to the
coordinate axis: a scale of 1.0 leaves the object the same, and
a scale of 0.0 or less is invalid. Going back to our original
cube, if we scaled the object with the string scale
<1,4,1>, we would get a result like this:
Because of vector promotion (if you don't remember what that is, you can re-read about it), scaling can also take a
single number rather than a vector. This causes the object to be scaled in
every direction by that number. For example, the phrase scale
2 is the same as the phrase scale <2,2,2>.
Transformations are placed like any other attribute. For example:
This code makes a yellow torus, slightly widened around the x axis, rotated
-45 degrees around the x axis and with its center at
<0,2,0>, like this:
Note that torus objects are created around the origin, so you are in fact
forced to use transformations to get them where you want... luckily
for you, you now know how. And to quote G. I. Joe, knowing is half the battle.
Texture
We admit it -- we lied to you. The pigment attribute is
actually a part of a bigger attribute called the texture
attribute. Every time you used pigment, it should have really
looked like this:
texture {
pigment { color Red }
}
The reason that POV-Ray is a little loose about the pigment
attribute and lets you use it outside of texture is because
pigment is so frequently used by itself that it becomes a pain
to type out the whole texture statement. In fact, most parts
of the texture { } block you can do the same thing with. Either
way, they have the same effect.
The texture attribute contains attributes describing the
outward appearance of the object: pigment, finish
and normal. The pigment attribute, as you know,
describes the color of the object (although it's a lot more
complicated than what we've shown you so far). The finish
attribute describes how the object "interacts with light" -- highlighting,
metallic luster, shinyness, reflectivity, etc. The normal
attribute describes some three-dimensional features of objects, such as
bumps, waves, and ripples. We'll cover these one by one.
Pigment
You've seen the use of the color attribute within the
pigment attribute (for example, pigment { color Blue
}). A more complete description that what we've given you so far can
be found in the Color section
of the Language Reference. A more flexibe
attribute, however, is color_map. color_maps are
used to do a wide variety of things. Basically, a color_map
defines bands of color on a "map" ranging from 0.0 to
1.0 Let's look at a simple example:
color_map {
[0.0 color Red]
[0.25 color Blue]
[0.9 color Green]
}
This defines three bands of color: red from 0.0 to
0.25, blue from 0.25 to 0.9, and
green from 0.9 to 1.0. The other commonly used
format looks like this:
color_map {
[0.0 0.25 color Red]
[0.25 0.9 color Blue]
[0.9 1.0 color Green]
}
They both do the same thing; the second one just contains information about
where you want the bands to stop as well as start.
The next step is tell POV-Ray what to do with this. This is done
by using of the many pigment types. A simple pigment
type is called gradient. Gradient creates bands of color based
on the color map. Using the source code from the first scene we created,
and replacing the color Red with our color map and pigment type, we get
this:
sphere {
<0,0,0>, 5
pigment {
gradient <0, 1, 0>
color_map {
[0.0 color Red]
[0.25 color Blue]
[1.0 color Green]
}
scale 3
}
}
This source code requires a bit of explaining. The vector following the
gradient keyword is the normal vector to the orientation of the
bands of color (you remember normal vectors, don't you? Or did you think we
were wasting our time telling you stuff you didn't need to know? Admit it!
You skipped over that section! Well, we're forgiving; you can go
back and read about it
again). The scale statement applies to the
pigment, not to the object (look carefully at where it's placed --
inside the pigment { } block).
Our sphere now looks like this:
A careful examination of this image yields some interesting facts. Starting
from the top down, you can see a slight bit of green (the rest of it was cut
off), which fades into the the large blue band, which in turn fades into the
small red band. The red band is abruptly cut off and the cycle repeats
itself again. However, the next time, the pattern has reversed! The red
band is on the top. This is because gradient patterns reverse
themselves at the origin. To get around this, you can translate the texture
away from the origin (you can apply all transformations to textures,
remember?). More information on gradients can be found in the
gradient section of the Language Reference.
Ok, now let's try something else. Add the phrase turbulence
0.5 after the gradient statement. The resulting picture
looks like this:
Whoah! The turbulence keyword, as you may have guessed, "mixes
stuff up." With this color map, we get a freakish plasma-like sphere.
Values for turbulence range from 0.0 to
1.0. A complete description can be found in the turbulence section of the Language Reference.
There are many other pigment types than gradient. For example,
there is a pigment type called marble. By itself, rather boring
and un-marble-like. However, with a high turbulence, it can create some
very realistic marble pigments. Here's some sample source code:
sphere {
<0,0,0>,5
pigment {
marble
turbulence 1 // full turbulence
color_map {
[0.0 color Gray90] // 90% gray
[0.8 color Gray60] // 60% gray
[1.0 color Gray20] // 20% gray
}
}
}
This high-turbulence marble pigment generates some very
nice-looking marble:
Not too shabby, huh? Other pigment types include wood, agate, bozo, and a host of others that can
be found in the pigment section of
the Language Reference. And although technically
not pigment types per se, you may want to check out the checker and hexagon pigment patterns, as
well as the image map
pattern (which lets you map an external image to an object), all found in
the same section as above. And remember, the best way to learn is to
experiment!
Finish
Finish describes how the objects interact with light:
how much they reflect, how they shine, how metallic they are, etc. All
finish attributes are enclosed in a finish { } block.
Perhaps the most used of the finish attributes is the phong
attribute. A phong is a highlight, or glare. It is specified, strangely
enough, by the phong attribute, followed by a number between
0.0 and 1.0 that specifies how bright the phong
is. There is also a phong_size that controlls how "tight" the
phong is -- in other words, the higher this number, the smaller in size the
phong is (this is a little misleading, yes). Here we have a green sphere
with a phong highlight of 1.0:
When lit by two light sources, the sphere looks like this:
As you can see, the phong adds a nice bit of realistic "shine" whenever a
light source directly hits part of the object. A more complete description
of phong can be found in the phong section of the Language Reference.
Another finish attribute that can produce stunning effects is the
reflection keyword. This causes objects to reflect their
surroundings to a certain degree. Reflection takes one number, ranging from
0.0 to 1.0, that specifies how reflective the
object is. Let's take a look at a more complex scene with a reflective
object.
#include "colors.inc"
camera {
location <-2, 3, -10>
look_at <0, 5, 0>
}
plane { // the floor
y, 0 // along the x-z plane (y is the normal vector)
pigment { checker color Black color White } // checkered pattern
}
sphere {
<0, 5, 0>, 2
pigment { color White }
finish {
reflection 0.9
phong 1
}
}
light_source { <10, 10, -10> color White }
light_source { <-10, 5, -15> color White }
The image this produces is:
As you can see, this generates a yellowish mirrored sphere floating above an
infinite checkerboard -- a variant of one of the standard ray-tracing
scenes. A more in-depth description of reflectivity can be found in the reflection section of the Reference manual.
The final attribute of the finish keyword we will describe here
is the refraction keyword. Refraction is
what happens when light rays passing through a translucent object get bent,
causing a distortion of everything seen through the object. For example, if
you look through a crystal ball, you will see a distorted view of whatever
is behind it.
The refraction keyword takes one value. This value should
either be 0.0 or 1.0, for refraction off and on,
respectively. Although you can specify values in between, it is not
recommended as it does not correspond to any known physical property. How
noticeably it refracts is controlled by the ior keyword (for
index of refraction),
which takes a number greater than 0. The default ior of "empty
space" is defined as 1.0. So, if we wanted to create the
crystal ball described above, we would use something like this:
Remember your RGBF vectors? A filter value
of 1.0 would mean this was an invisible sphere, certainly not
what we want. Our filter value of 0.8 gives the sphere enough
definition to be visible. The image generated looks like this:
Now we start seeing some of the true power of ray-tracing. The warped look
of the checkboard pattern is due to the refraction, the bright hightlighting
is due to a phong, and a bit of reflection makes this all the more
realistic. Tinting the glass would be easy: just change the color of the
sphere from <1,1,1> (or white) to whatever color you want
it tinted. Modify the filter value to make the ball more and less
translucent. It's fun!
There are many other finish attributes that you can play with,
including metallic, ambient, and crand. We've touched on a few; for
a complete reference, read the finish
section of the Language Reference. To get a good
feel for most of the finish attributes, you can experiment with the Finish Tool.
Normal
The normal attribute creates some simple 3D features on your
objects: bumps, ripples, waves, and the like. It does not actually change
the object; instead, it changes slightly the way light bounces off the
object and essentailly fools the eye into believing the object is a little
different than it really is. As such, the effects are not 100% true to real
life, but they are much, much faster than actually describing the changes
individually would be.
Let's try a bumps example. Bumps are created with (oddly enough) the
bumps keyword, followed by a single number, generally between
0.0 and 1.0, that specifies the relative size of
the bumps. Here's some source code:
This creates a green cone with a slightly bumpy appearance, like this:
Not to difficult, eh? Imagine how difficult it would be to model all those
bumps yourself. Now, here's a fun one to try -- ripples:
plane {
y, -2
texture {
pigment { color rgb <.1,.9,.9> }
normal {
ripples 0.5
}
}
}
The number following the ripples keyword specifies, again, the
relative size of the ripples. The image this produces is:
Pretty nifty! The ripples keyword and its close relative,
the waves keyword, can take a few modifiers that give a little
more control than we've shown you. A complete reference can be found in the
ripples section of the Language Reference. More normal
attributes, such a dents and wrinkles, can be found in the normal section of the same document. You
can also experiment with the Normal Tool
to get a feeling for the various attributes.
Including Textures
Much like you learned how to include colors beforehand, you can also include
textures. POV-Ray comes with a file full of some very good textures, called
textures.inc. Including this is the same as before:
#include "colors.inc"
#include "textures.inc"
Note that you must include colors.inc before you include
textures.inc, because textures.inc uses colors
from colors.inc.
Using an included texture is easy. To make a sphere that uses the Jade
textures, for example, you would say:
sphere {
<-2, 4, 6>, 5.6
texture { Jade }
}
Look through the file textures.inc for a list of the textures
included. You can also look through colors.inc for a list of
the colors in there.
Well, if you've managed this far, you're in good shape. Keep it up! The
next section gets in to the really fun stuff.