The Online POV-Ray Tutorial

Advanced POV-Ray Features

(Show Jump Points) (Hide Jump Points)

If you've made it this far, you're in good shape! This section covers the features of POV-Ray that are most most complex, but also the most powerful. Once you complete this section, you'll be ready a certified ray-tracing master.

Quick Index:

  1. #declare
  2. CSG
    1. Union
    2. Difference
    3. Intersection
    4. Merge
    5. Inverse
  3. Advanced Objects

#declare

Up until now, creating large numbers of similar objects has been an excersize in cut-and-paste editor features. POV-Ray provides a very powerful, very flexible way to create many similar objects with a statement called #declare. #declare essentially creates a new type of object (or pigment, or texture, or almost anything) that you can use and re-use whenever you like. Take a look at the following code:
#declare my_sphere =
sphere {
  <0, 0, 0>, 5
  finish {
    pigment rgbf <.5, .2, .4, .667>
  }
}
What this does, essentially, is declare a new type of object called "my_sphere" which you can now use later on in your source code, like this:
object {
  my_sphere
  translate <-2, 0, 0>
}
The object statement tells POV-Ray to create an object of type "my_sphere." Theoretically, you can put object statements around every object you use (including primitives, like spheres) but POV-Ray only requires it for #declared objects.

Note that any attributes you place inside the object statement override those in the #declare statement -- in this example, our sphere is moved from its original location at <0,0,0> to <-2,0,0>. This hold true for pigments, finishes, etc.

VRML programmers should take note that this #declare differs somewhat from VRML's DFN node. #declare does not create an instance of the object (which DFN does), only the definition. In other words, the above #declare statement would not add any objects to your scene on its own. You need to instantiate the objects (with the object keyword) to do that.

Now, why would you want to use #declare? Say, for example, you're making a Greek temple. You would want many pillars in your object, so you would create a pillar object with #declare, like this:

#declare pillar =
cylinder {
  <0, -5, 0>, <0, 5, 0>
  texture { White_Marble }
}
Then, you would create however many of these you needed, translating to your heart's content. Say, however, that you decide the columns in your temple should be made out of red marble, not white. All you have to do is change the one #declare statement, and all the pillars change! If you had created those pillars without #declare, you'd have to change each one by hande -- a major hassle, especially if you had 40 pillars in your temple.

So you can see one immediate benefit to #declare -- updating your scene becomes a lot easier. But wait, there's more! You can also use #declare to create your own colors and textures. In fact, the colors.inc and textures.inc files are basically long lists of #declared colors and textures, respectively. The syntax is intuitive:

#declare blue_green_filter = rgbf <0, .5, .5, .5>

#declare red_glass =
texture {
  finish {
    refraction 1.0
    reflection 0.1
    ior 1.5
  }

  pigment {
    color rgbf <1, .7, .7, .7>
  }
}
As you can most likely guess, these define a new color, called "blue_green_filter" and a new texture, called "red_glass". You would use these like this:
sphere {
  <0, 0, 0>, 1
  pigment { blue_green_filter }
}

cone {
  <-2, -4, 16>, 5
  <0, -3, 1>, 1
  texture { red_glass }
}
Not too difficult! You can use #declare to create custom finish, normal, and pigment statements... you can even use it with vectors and single numbers, like this:
#declare PI = 3.1415926545338327950288
This will save you a bit of typing if you reference PI frequently in your scene file! (Please remember that you don't need to put an object statement around anything you #declare other than objects).

C and C++ programmers should not be mislead by #delare's superficial similarity to the C/C++ pre-processor macro #define. Their behaviour is quite different. #define actually changes the source code before it gets compiled (why is why it's called a pre-processor macro). POV-Ray does not have a pre-processor, and so #declare, although misleadingly labeled, will not do source-code substitution.

At any rate, you can get the complete syntax for object and #declare in the Language Reference. They are both powerful tools, and if you create anything other than very simple scenes, you will find them invaluable.


CSG

CSG stands for Constructive Solid Geometry, a powerful technique in POV-Ray for creating new objects from combinations of other objects. So far, you have been limited to POV-Ray's primitives, which, while nice, aren't always what you need. POV-Ray lets you use the primitives in a much more constructive (har har) way with CSG: you can carve away parts of objects, you can stick objects together, and other exciting stuff.

There are five operators in CSG: union, intersection, merge, difference, and inverse. The syntax of all the operators (except inverse) is very simple: it's the operator, followed by a list of two or more objects enclosed by braces, like this:

CSG_operator {
  object_1
  object_2
  etc.
}
You actually don't have to put any objects at all between the braces, but it doesn't make sense to have less than two objects (remember, CSG creates new objects from combinations of other objects) and POV-Ray will warn you when you trace the file. The syntax for inverse is even easier: it's just the word "inverse."

We'll go over these operators one by one, because they're all important. A complete reference can be found in the CSG Section of the Language Reference.


Union

A union is the easiest CSG operator to understand. It simply takes a bunch of objects, and "sticks them together." It doesn't actually move the objects at all, but it creates a common bond between the objects, kind of like they've joined a special club for important primitives. (We'll politely ignore the similarities to certain political parties). The source code to a sample union looks like this:
union {
  sphere { <0, 1, 2>, 3 }
  box { <-77, 6, 5>, <2, 3, 55> }
  sphere { <-2, -3, -4>, 5 }
}
Now rendering the scene doesn't look any different whether you have the union keyword there or not. So why bother? Two reasons: first, you can assign attributes to the entire union of objects very easily:
union {
  sphere { <0, 1, 2>, 3 }
  box { <-77, 6, 5>, <2, 3, 55> }
  sphere { <-2, -3, -4>, 5 }
  
  pigment { color Blue } // applies to the entire union
}
In this case, the attribute pigment { color Blue } is applied to every object in the union. As always, this works with any attribute you care to try: pigment, translations, normal, etc.

The second, and perhaps even more useful reason for using unions, is when you combine CSG and the #declare keyword, like this:

#define two_spheres = 
union {
  sphere { <0, 0, 0>, 3 }
  sphere { <-1, -5, -1>, 3 }
}
From now on, you can reference the object two_spheres (which is, amazingly enough, two separate spheres) just as you would any other #declared object:
object {
  two_spheres
  pigment { color Pink }
  rotate <0, 180, 0>
}
Let's go through one more example, to make sure you understand -- this is a very important concept. Say you wanted to ray-trace a car. You'd create the wheels, then an axle, and then use union to stick them together. You could then re-use this wheel and axle combination however many times you wanted (depending on how many sets of wheels your car has). Your code might look something like this:
#declare wheels_n_axle =
union {
  object {  // left wheel
    wheel   // assuming we have already created a wheel object
    translate <-3, 0, 0>
  }

  object {  // axle
    axle    // assuming we have already created an axle object
  }

  object {  // right wheel
    wheel   // assuming we have already created a wheel object
    translate <3, 0, 0>
  }
}

#declare car = 
union {
  object { // front wheels and axle
    wheel_n_axle
    translate <0, 0, 5>
  }

  object {  // rear wheels and axle
    wheels_n_axle
    translate <0, 0, -5> 
  }

  // other car parts go here 
}
Note that the order you place objects in a union is unimportant -- objects within a union don't really care about the other objects. This is different from the objects in a difference -- they are very caring, almost loving, objects, as you will see in the next section.

A complete description of the union operator can be found in the CSG Section of the Language Reference.


Difference

A CSG difference is much like a mathematical difference -- it subtracts objects from one another. More specifically, it takes chunks out of the first object, each chunk being defined by the other objects in the difference statement. For example, say we wanted to make a wall that we would add a door to. The simplest way to do this is with a difference:
#declare wall =
difference {
  box { <0, 0, 0>, <10, 10, 1> } // 10x10x1 wall
  box { <2, 0, -1>, <6, 8, 2> } // minus a doorway
  texture { Wall_Texture } // assuming we have already created a Wall_Texture
}
The first cube serves as the wall, and the second cube describes what, exactly, we want to take out from the wall. The two objects without the difference statement look like this:

When we add the difference statement, we get:

Note that we made the doorway cube thicker than the wall. Why? This is because, occasionally, POV-Ray will get confused when you have two objects that overlay exactly the same space. So, we made the doorway cube a little thicker, avoiding a potentially weird image, and at no loss to anything else.

One important thing to remember about differences is that all objects are subtracted from the first one. If, for example, we wanted to add a few window holes to the wall above, we could just add a few more cubes at the very end, and voila! Once again, any attributes placed at the end of the difference statement will apply to the entire object.

A complete reference for the difference keyword is located in the CSG Section of the Language Reference.


Intersection

Much as a difference removes the insides of objects, a intersection removes the outsides of objects. The result of using the intersection operator is that the only thing remaining is the parts which all the objects within the operator had in common. Let's say that you want to make a single, colored, sugar-coated chocolate candy that won't melt in your hands (not nameing any names). Furthermore, it must be a mathematically perfect candy. The easiest way to do this in POV-Ray is with an intersection, like this:
#include "colors.inc"

camera {
  location <0, 0, -5>
  look_at <0, 0, 0>
}

light_source { <10, 10, -10> color White }

intersection {
  sphere { <0, -1, 0>, 2 }
  sphere { <0, 1, 0>, 2 }

  pigment { color Yellow }
}
This code takes two spheres that overlap, like this:

Then, it uses the intersection operator to remove everything that isn't overlapping, leaving an a remarkably sweet-looking goody, like this:

Although intersections are a little more difficult to imagine than some of the other CSG operators, they can be a very powerful tool. You can find a complete reference in the intersection section of the Language Reference.


Merge

Merge is very similar to union. In fact, the only difference between the two is that, if the objects actually overlap, merge will make the interior a smooth, continuous unit. Now, obviously, this won't make a difference to you if your objects aren't opaque. But if you have transparent, overlapping objects in your scene, the original object boundaries will be shown if you use a union (or no CSG at all); to get around this, you muts use merge.

A complete reference for the merge operator can be found in the CSG Section of the Language Reference.


Inverse

Inverse is not used very often, but there are times when it must be used. Inverse will take your object and reverse what POV-Ray considers to be its "inside" and "outside." This will make no difference to the way your object looks, but it makes a great deal of difference to the wayyour object acts when you use it in CSG. Consider the intersection of a sphere and a box. If the sphere is inverted (by placing the keyword invert in its definition), then POV-Ray will take the intersection of the box and an object defined as "the entire universe except this sphere." If you think about it for a while (probaby a long while), you'll realize that that's the same as a difference. In other words, this:
intersection {
  box { <0,0,0>,<1,1,1> }
  sphere {
    <1,1,1>, 1
    inverse
  }
}
is the same as this:
difference {
  box { <0,0,0>,<1,1,1> }
  sphere {
    <1,1,1>, 1
  }
}
In fact, POV-Ray calculates differences using this same method. A complete reference to the inverse keyword can be found in the CSG Section of the Language Reference.


Advanced Objects

There are times when POV-Ray's geometric primitives aren't going to be enough for you. Face it, if you want to ray-trace something as complex as a human being, even CSG won't help you. In this case, there are two options left to you:

The first is to specify your object in mathematical terms. Obviously, this will only work if

  1. Your object can be described by an n-dimensional polynomial in 3-space;
  2. You know what the heck I'm talking about; and
  3. You like pain
What we're trying to say here is that we're not about to teach you the math necessary to specify these objects, and, furthermore, we recommend against it, unless you really know what you're doing. Of course, if you'd like to read about the objects involved (namely, quadrics, cubics, quadrics and polys), the go right ahead. And if you can use them, so much the better. But if you don't have the math behind it, then don't worry about it; you'll probably sleep better at night. We have found these objects to be of limited use.

The second option you have is to use a modelling program. What a modelling program can do is generate extremely complex objects in POV-Ray by specifying them as a whole bunch of really simple objects, normally blobs, triangles, smooth triangles. or bicubic patches. These objects, much like the the mathematical ones above, are not generally meant for human consumption -- in other words, don't bother trying to create objects with these by hand, because unless you really know what you're doing, you'll probably just waste a lot of time.

Instead, find a good modelling program (there are many free and shareware ones out there; try the Resource Library), create the complex object in there (usually the modelling programs will have a very nice, graphical interface) and run POV-Ray on the file it creates. You will save a lot of time and effort.


Top of Document Main Page Step 3: Creating Simple Scenes Step 5: Conclusion

The Online POV-Ray Tutorial © 1996 The Online POV-Ray Tutorial ThinkQuest Team