Compiling POV-Ray 2.2 from Source
07/31/23, updated 10/17/24Notice
This guide was tested with Debian 12 & FreeBSD 13.2, exact instructions may vary depending on your operating system. However, if you have even a basic understanding of software compilation you should be able to follow along without issue.
Table of Contents
- Intro
- Why POV-Ray 2?
- Preparation
- Build Setup
- Fixing Random Number Generation
- Enabling Extra Optimization
- Increasing Max Constants
- Compiling POV-Ray 2.2
- Rendering a Scene
- Conclusion
Intro
Over 30 years have passed since POV-Ray 2 was first released, in that time computer hardware and software has evolved considerably, 3D graphics being no exception. For most 3D programs of that vintage, any life still left in them is confined to virtual machines, emulators, or perhaps period appropriate hardware if you happen to be a collector. Often times this scenario comes about because source code is either lost, or kept locked away, it's much harder to keep software running when all you have is an ancient binary for even more ancient systems.
Of course, having source code doesn't automatically mean you can create a working executable. Development practices have changed alongside everything else, the popular tools, languages and libraries ebb and flow as projects come and go. Without maintenance, old software that manages to avoid code rot and continue working long into the future is generally more self-contained, fewer dependencies means fewer parts of the whole can be lost or become unusable over time.
This brings us to POV-Ray 2, specifically version 2.2 from 1994, the final release in the 2.x series. Although you can't immediately compile it straight out of the archive, the source tree has almost everything you need to build the program today, a few small tweaks and a C toolchain are the only things separating you from retro ray tracing goodness!
Why POV-Ray 2?
You might be wondering why it's worth bothering with such an old version of POV-Ray, when its current incarnation is much more advanced and actively developed? Well there are two primary reasons why 2.2 is still useful today. First is that there are many scene files out there which were written for the 2.x series, modern POV-Ray can render old projects but as my 2.2 vs 3.7 comparison demonstrates, there's various inaccuracies and errors with the backwards compatibility feature. The other reason is that if like me you want to create retro 3D art, POV-Ray 2.2 is an excellent period appropriate tool for doing just that, which unlike many of its contemporaries can run just fine on modern operating systems.
Preparation
So before we can start building we need to sort out some prerequisites. First of all we'll grab the source code from POV-Ray's website: https://www.povray.org/ftp/pub/povray/Old-Versions/Official-2.2/
The files we need are:
Linux, BSD | Windows |
---|---|
POVDOC.TAR.Z | POVDOC.ZIP |
POVSCN.TAR.Z | POVSCN.ZIP |
POVSRC.TAR.Z | POVSRC.ZIP |
These archives will provide us with documentation, example scenes and of course the program sources, download and extract them to a destination of your choosing.
Now that we have the code, we need something to compile it with, on Debian GNU/Linux and derivatives (for example Ubuntu, Linux Mint, Pop!_OS) this is as easy as installing the "build-essential" package. To do that you can run the following command in a terminal (make sure you have root privileges):
apt install build-essential
This will pull in the GNU Compiler Collection (GCC) & GNU Make (BSD users should install and use "gmake" for this guide), our compiler and build tool respectively. With that we have everything we need, so it's time to get ready to build!
Build Setup
As mentioned earlier, POV-Ray 2.2 can't be compiled straight away, this is because some important files aren't yet where they should be. If you navigate to the place where you extracted "POVSRC" you will see two folders (Windows users note that the ZIP archives contain upper case filenames), "machine" & "source". "machine" has more folders with system specific source files covering various platforms of the time period, whereas "source" contains the actual source code for POV-Ray, we need to copy the correct "machine" files to "source" in order to make our executable.
Inside "machine" you will see a folder called "unix", in there you will find the files we need. Copy all of the files from "unix" (but not the "unix" directory itself) to the "source" folder from before (note that despite being for UNIX-compatible systems, these files will work for Windows users too, as long as you use the MinGW development environment when compiling). With the system files in place we need to rename the file "unixconf.h" to "config.h" or the build tool won't find it, so do that now.
With all that out of the way it's now possible to build POV-Ray 2.2! However, before we do that we're going to make a couple of changes to the source code, one of which will make sure that we don't have a certain issue later on.
Fixing Random Number Generation
So what's the problem? Well, POV-Ray uses random numbers in various parts of the rendering process, most notably in procedural texture generation. In the 2.x series these random numbers are by default sourced from your system RNG, which is usually a good idea (especially in scenarios involving cryptography where you want things to be as random as possible) but in this context it creates a couple of issues for us. The first is that when you render the same scene on different operating systems, the final image can vary considerably, as seen here with "Planet" (planet.pov) by Ville Saari:
System RNG (Debian 12) | System RNG (FreeBSD 13.2) |
---|---|
1.35s | 1.36s |
This is quite a problem if aspects of a scene were designed around the way a procedural texture was generated. The other even worse issue is that sometimes, your system RNG will cause POV-Ray 2.2 to fail during rendering and abort, demonstrated here with "Pawns" (pawns.pov) by Douglas Otwell:
System RNG (Debian 12) | Fixed RNG (Debian 12) |
---|---|
N/A | 52.43s |
Fortunately, the POV-Ray developers were aware of these consistency issues and mention it in the documentation, their suggested fix is to incorporate a deterministic RNG found in the IBM-compatible "machine" files. Head to the "machine" folder and this time look inside the "ibmpc" directory, there you will see a file called "ibm.c", open it in your editor of choice. Navigate to line 2784 or so and you should find the following block of code:
/* ANSI Standard pseudo-random number generator */
int rand(void);
void srand(int);
static unsigned long int next = 1;
int rand()
{
next = next * 1103515245L + 12345L;
return ((int) (next / 0x10000L) & 0x7FFF);
}
void srand(seed)
int seed;
{
next = (unsigned long int)seed;
}
This is what we need to fix our RNG, so copy it to your clipboard. In the "source" folder open "unix.c" in your editor, then paste the code at the end of the file, don't forget to save your changes and voila! That's all we have to do to fix the problem, there's just one more file to edit before building.
Enabling Extra Optimization
Ray tracing is a computationally expensive process. Although modern computers are orders of magnitude faster than the '90s machines POV-Ray 2 was written for, more complex scenes can still take quite some time to render. Fortunately though there's a free performance boost that we can employ with just a small edit, the benefits of which will definitely add up as you design and continuously render a scene.
When a compiler turns source code into an executable, you often have the option to automatically optimize the build. This process will attempt to make the various routines of a program more efficient, so that less CPU time is spent making those calculations. Optimizing a build does make compilation take longer however, so different levels of optimization are usually available, which is what we'll be changing now.
In the "source" folder open "unix.mak", at line 21 you should see the following:
CFLAGS= -c -O
LFLAGS = -o povray -O
These are parameters (flags) that will be given to our compiler. By default our build will only have basic optimization, we're going to change this so that we create a level 2 optimized build (level 3 also exists but can sometimes cause bugs or even sacrifice performance compared to level 2, depending on the program). All you have to do is change the "-O" parameter on both lines so that it reads "-O2":
CFLAGS= -c -O2
LFLAGS = -o povray -O2
Now save the file but keep it open for the next section.
Increasing Max Constants
As your scenes increase in complexity you may find yourself exceeding POV-Ray's default limits, some of these settings can be changed at the command-line but others are hard-coded. One such parameter is "MAX_CONSTANTS", which determines how many slots to allocate for identifiers created with the "#declare" feature. By default you can have 1000 of these declarations in a scene, trying to render a scene with more will result in this error:
Too many constants "DECLARED"
To overcome this we need to increase the maximum number of constants, fortunately the source code is already set up to accept a user-defined value during compilation. Let's add a new flag for our compiler which will replace the default value, first go to line 21 again:
CFLAGS= -c -O2
Now we need to create a macro, the name of which will be replaced by the value we specify. The "-D" option creates macros in the form of "-D<name>=<definition>", in the following example I've set "MAX_CONSTANTS" to 2000:
CFLAGS= -c -O2 -DMAX_CONSTANTS=2000
You can set yours as you see fit but keep in mind that higher values will use more memory when running POV-Ray. Save your changes and close the file, that's all there is to it! Finally having done the necessary code changes it's time for...
Compiling POV-Ray 2.2
The moment you've been waiting for, time to actually compile our build! This is the easiest part of the process, just run this command in the "source" folder:
make -f unix.mak
If you would like to speed things up and have a multi-core CPU, you can add "-jX" to the end of that command, where X is the number of jobs to run simultaneously, set this to the number of cores & threads you have for a faster compilation time. Note that while compiling you will see a number of warnings displayed on the terminal, these can be ignored as they don't cause any issues with the program.
Once the build has finished you should have a file called "povray", this is our program. To run it, first we'll make sure it's marked as an executable:
chmod +x povray
That changes the file permissions so that we can actually run it. Now let's see if it works:
./povray
You should see some authorship and basic usage information printed to your terminal, if so then congratulations, you've just built POV-Ray 2.2!
Rendering a Scene
Now we have a binary it's time to put it through its paces! Navigate to where you extracted "POVSCN", inside there you will see a folder called "povscn" (not present in the ZIP archive) and under that you'll find the folder "scenes", descend into it and from there head into the "level2" directory. Here we have lots of files, most of them with the ".pov" extension, these are scene files written in POV-Ray 2's Scene Description Language (SDL). When we render a scene we need to provide our executable with one of these scene files, the program will then read the file and follow the instructions contained within, resulting in an image file showing the result of the render.
To do this we can either copy our "povray" binary to the "level2" folder or add it to our PATH, programs in our PATH can be run from any location on the system, allowing us to simply type "povray" in a terminal to execute it. On Debian and derivatives, if the folder structure ".local/bin/" exists in our home directory it will be added to the PATH when we login, if it doesn't exist you can create it like so (logout and in after creating it to update your PATH):
mkdir -p ~/.local/bin/
Copy "povray" to "bin" and optionally rename it to "povray2" so it doesn't conflict with a system-wide POV-Ray installation, such as if you have the "povray" package installed.
One last thing before rendering, we need to provide POV-Ray with the location of a folder called "include" to avoid some missing file errors. Head to where you extracted "POVDOC" and look inside, enter the "povdoc" folder (not present in the ZIP archive) and you'll see the "include" directory we're looking for. This folder contains files with the ".inc" extension, which can be included by scenes to gain access to things like default colors, textures and extra shapes. Make a note of where "include" is located and continue on.
It's finally time! We'll be rendering "planet.pov" from earlier, this time with the RNG fixed. Run the following command in the "level2" folder (make sure you provide the location of "include") and let POV-Ray 2.2 do its thing!
povray2 +L<Location of "include" directory> +Iplanet.pov +Oplanet.tga +FT +W640 +H480 +A0.1 +V
Here's a description of each parameter:
Parameter | Description |
---|---|
+L | Directory to search when including additional source files (e.g colors.inc). |
+I | Scene file to render. |
+O | File to save resulting image to. |
+F | Image format to use (in this case T for TARGA). |
+W | Image width. |
+H | Image height. |
+A | Level of anti-aliasing. |
+V | Display verbose messages. |
Once the render has finished you should have a "planet.tga" file, open it with your preferred image viewer, if it looks like these examples then you've successfully followed the guide:
Fixed RNG (Debian 12) | Fixed RNG (FreeBSD 13.2) |
---|---|
1.33s | 1.31s |
Conclusion
If you followed along then you should now have a working build of POV-Ray 2.2 with deterministic rendering, if so then congratulations! So what's next? Well, if you're looking to make scenes of your own then I have two resources to recommend:
- "Taming POV-Ray" by Greco Moran
- "povray.doc" (found in the "docs" folder in the same location as the "include" directory)
That's really all you need to get started with retro ray tracing, so dive on in and make some renders! I wish you good luck on your future POV-Ray adventures!