original in es Carlos Calzada Grau
es to en Miguel Angel Sepulveda
Graduate in computer science and fun of computer graphics since my first Spectrum. I am very enthusiastic about Linux, its development philosophy and anything that has nothing to do with micro$oft. Other of my non-screen related hobbies are bonsais and aquaria.
In 1987, Red's Dream won several prizes in the World Animation Festival at Zagreb and in the San Francisco International Film Festival.
The first animation that won an Oscar was Tin Toy (1998), Pixar designed a model for the face of a baby defining more than 40 muscles to controled by the animator.
In 1989 they released Knick Knack, this is the story of a snowman that lives inside the crystal ball. The movie was initially produced to be viewed in 3D althout they also released a normal version.
Following soon after came a number of succeses like the recent movie Toy Story. This is one of the first long feature films completely produced by computer. In the home page of Pixar many more interesting things can be found, for example the Toy Story 2 film release date is some time in 1999.
Pixar developed the interface RenderMan to separate and maintain "modelers" and "renderes" independently . A modeler is a tool used to draw scenes, design animations, etc. The renderer's only purpose is to take the description of the modeler and render it with shadows, lights, textures, etc..
RenderMan lets 3D artists to specify what to render but not how to do it. In other words, a modeler should not be concerned with the rendering step. Similarly a renderer that complies with the standard specifications of RenderMan can use Z-buffer, scan-line, ray-tracing, radiosity or any other method to "draw" the objects, and this step is independent of RenderMan. We can view the interface of RenderMan as a format for the description of scenes in the same way PostScript is a format for the description of pages. This standard is independent of architectures and operating systems.
In this article we will attempt to give a small introduction to RenderMan, we will use Blue Moon Rendering Tools, completely written by Larry Gritz. This package is a renderer of free distribution (only binaries and for personal use), there are versions for many systems among which you will find Linux ( in fact this was one of the first implementations), it uses ray-tracing and radiosity and has little to envy to a Photorealistic RenderMan (PRMan), the commercial product of Pixar.
At the beginning the system of coordinates for the world and the camera are the same, they are left-hand rule coordinate systems (as Pov-Ray), with the origin at the center of the screen, the X axis to the right, the Y axis upwards and the Z axis going to the inside of the screen. The following figure shows the camera used by default (the X axis is red, Y axis is green and Z axis blue, to see the source code click on the image). A right-hand rule coordinate system is identical but for the Z axis that points in the opposite direction.
In Pov-Ray the system of world coordinates is fixed, meaning one can move the camera through the world and set objects using transformations. In RenderMan the opposite is true, the camera is fixed and what gets transformed to obtained various points of view is the world system of coordinates. All this will become clear when we "desmantle" an example.
RenderMan has many primitives, both for object definition as for ligths, etc... Now we will see as an example the format of the most famous cuadrics, although there are others (like bezier patches, polygones, ...).
Disk
height radius
thetamax
Disk 5 10 300 |
Cone
height radius
thetamax
Cone 15 10 300 |
Cylinder
radius zmin
zmax thetamax
Cylinder 10 -5 10 300 |
Sphere
radius zmin
zmax thetamax
Sphere 10 -4 8 300 |
Torus major
rad min rad
phimin phimax
thetamax
Torus 10 4 90 320 300 |
Paraboloid
radius zmin
zmax thetamax
Paraboloid 10 4 15 300 |
Hyperboloid
point1
point2
thetamax
Hyperboloid 0 10 -5 10 5 15 300 |
The reader may already notice that the format of some of these primitives is not precisely simple, but taking into account that the file RIB must be supplied by a modeler as output, this format is actually appropriate because of its conciseness and performance.
rabit:~/$ gzip -d BMRT2.3.6.linux.tar.gz rabit:~/$ tar xvf BMRT2.3.6.linux.tar
After uncompressing and unpacking the tar-file we get a new directory named BMRT2.3.6 It contains the executables (in bin/), the examples (in examples/) and the documentation in both PostScript and HTML (under doc/), there is also a README file with additional information about the program. Look within the README file for the installation section, it is simple and should not give trouble to anyone.
Let us become familiar with RenderMan's specification by examining a typical example (disptest.rib). The image is generated by the command rendrib -v disptest.rib (click the image to view it in 1024x768 resolution and with anti-aliasing 2x2).
This is one of the many samples that can be found in the examples/ directory of BMRT (Blue Moon Rendering Tools) and as the reader can appreciate the file that generated it is not very long (when writing animations you will see the file growing considerably).
There are several executables under bin/: rendrib, rendribv and rgl. Rendrib is the renderizer properly speaking, rendribv is similar but it renders objects in wire mode, only with lines; finally rgl renders using polygons. The last three renderers are used to preview positions, animations, etc.. and the final rendering must always be done with rendrib.
The format of the file RIB (Renderman Interface ByteStream) is very simple, although not necessarely less powerful. They are saved as plain text files (exactly like Pov-Ray). A well-writen RIB file contains the following:
The graphical state contains all the information needed to render a primitive. It is divided in two parts: a global that remains constant from primitive to primitive and a current state that changes with primitives. The parameters of the global state are known as options and the current states are named attributes
To better understand options and attributes, and to have an idea of how to specify scenes with RenderMan, let us review the preview example line by line. This would be a good tutorial on what can be done and how to get it done.
1.- ##RenderMan RIB-Structure 1.0
2.- version 3.03
3.-
4.- ###########################
5.- #
6.- # This RIB file demonstrates some more complex procedural textures.
7.- # Two spheres show the use of "stucco" and "dented" displacement shaders.
8.- # The floor shows the gmarbtile_polish shader, which is polised green
9.- # marble tiles. Note that the reflection is accomplished by the shader
10.- # actually calling the trace() function, rather than reflection mapping.
11.- #
12.- ###########################
13.-
14.- Option "searchpath" "shader" [".:../shaders:&"]
15.- Display "balls2.tif" "file" "rgb"
16.- Format 400 300 -1
17.- PixelSamples 1 1
18.-
19.- Declare "prmanspecular" "integer"
20.- Option "render" "prmanspecular" [0]
21.- Projection "perspective" "fov" 35
22.- Translate 0 -0.55 8
23.- Rotate -110 1 0 0
24.-
25.-
26.- WorldBegin
27.-
28.- LightSource "ambientlight" 1 "intensity" 0.02
29.-
30.- Declare "shadows" "string"
31.- Attribute "light" "shadows" "on"
32.- LightSource "distantlight" 1 "from" [0 1.5 4] "to" [0 0 0] "intensity" 0.6
33.-
34.- AttributeBegin
35.- Declare "txtscale" "float"
36.- Declare "Kr" "float"
37.- Declare "darkcolor" "color"
38.- Declare "lightcolor" "color"
39.- Declare "veincolor" "color"
40.- Surface "gmarbtile_polish" "Ka" 1 "txtscale" 0.5 "Kr" .25 "Kd" 0.3 "Ks" 0.2 "roughness" 0.02
41.- Patch "bilinear" "P" [ -5 -5 0 5 -5 0 -5 5 0 5 5 0 ]
42.- AttributeEnd
43.-
44.- AttributeBegin
45.- Color [ .6 .6 .6 ]
46.- Translate -1.5 0 1
47.- Surface "matte"
48.- Declare "frequency" "float"
49.- Declare "Km" "float"
50.- Displacement "stucco" "frequency" 20 "Km" 0.3
51.- Sphere 1 -1 1 360
52.- AttributeEnd
53.-
54.- AttributeBegin
55.- Translate 1.5 0 1
56.- Color 1 .45 .05
57.- Declare "Kr" "float"
58.- Declare "Km" "float"
59.- Surface "shiny" "Kd" 0 "Kr" 0.25 "roughness" 0.15 "specularcolor" [1 .5 .06]
60.- Displacement "dented" "Km" 0.5
61.- Sphere 1 -1 1 360
62.- AttributeEnd
63.-
64.- WorldEnd
Comments can be included in the file using the # symbol, see line 1 and from lines 4 to 12. A # symbol may appear in any place of the file and they occupy a full line (like // comments in C++ ). Comments should be used when editing these files manually because they help us understand the inner workings of the scene.
Line 2 shows an example of the version directive. It merely declares the version of interface being used (3.03); the most recent version is 3.1 released september 1989 (yes 1989, it is not a mistake), although there are revisions of May 1995.
The directives searchpath and shader on line 14 defines the path for the "shaders", these are objects that inform the renderer how to reder a given object (as a plastic, transparent, etc..), this is one of the features that makes the interface very powerful because the textures of an object behave as Plug-Ins, therefore it is easy to implement new textures, effects,... not having to wait for a more powerful release of the renderer. Usually there is an environment variable (SHADER) that indicates the location of these files, therefore it is not often necessary to declare the path explicitly.
The Display option appears on line 15. It declares the output filename as "balls2.tiff" and its type as "file" "rgb", that ism an RGB file.
In line 16 we define the resolution for rendering (size of the image) through the Display option. The resolution of our example is 400x300, the -1 defines the aspect ratio of the pixel (actually it should be +1, I am not sure why they used -1 here).
Next comes the horizontal and vertical sampling for every pixel, i. e., the number of rays launched to render a pixel. An stament PixelSamples 2 2 translates into 4 rays launched per pixel, prividing a great quality for the image (this is the anti-aliasing), but unfortunately a larger time for rendering. In our case, a sampling of 1 x 1 = 1 provides a faster rendering time but only one ray per pixel.
Line 19 declares the integer variable prmanspecular , actually prmanspecular gets defined as a token and when the renderer finds this token it will take as an integer whatever number follows.
Next comes the declaration of a 3D proyection, with the key
"perspective" we are requesting a perspective projection
and "fov" 35 sets the field of view to 35
degrees.
Lines 22 and 23 then defined the position of the camera. First we write a translation followed by a rotation, but since all transformations are performed through a stack the first transformation to be applied is the last one in, rotation followed by a translation (in this case the transformations get executed once renderman finds the statement WorldBegin ). In this example the system rotates -100 degrees around the X axis (to rotate around the Y axis one would have written Rotate 45 0 1 0), next it is translated -0.55 units along the Y axis and 8 units along the Z axis. Please take into account that what gets transformed (rotated and translated) is not really the camera but the center of world coordinates (translator's note: OpenGL uses exactly the scheme for transformations). The following figures show different stages during the two transformations.
After the previous preliminaries definitions comes the scene itself. Any scene (a declaration of lighting, objects, etc..) always begins with WorldBegin and ends with WorldEnd (lines 26 and 64 respectively). The first few lines in the scene of our example declares the lightning (lines 28 to 32); every light has a number and in theory they must be distinct, the first one is the ambient light and it has 0.02 intensity. After lighting the variable shadows is declared as a character string and then the lighting option for casting shadows is activated. Line 32 adds a light source of the type distantlight (a light source infinitely far a way like the sun) using number 1 again; as mentioned before this light source should be different (say 2), it still works becuase BMRT appears to ignore the light numbering, however to keep compatibility (for example with Pixar's PRMan) we should be stricter with the interface. The intensity of the secound source of light is identical to the first one (these are common attributes) and the direction vector defined by the fields from and to, send the rays in parallel, as if it was a distant source.
Now we have the three elemental objects that constitute the scene, each object is enclosed by a pair AttributeBegin AttributeEnd because each has its own characteristics (both position and appearance). If the only feature that changed from object to object was the position one could declare the texture outside and then define the objects using TransformBegin and TransformEnd. The first object (lines 34 to 42) is a patch, and patches can be: uniform or non-uniform, rational or non rational and bilinear or bicubic (which leads to Bezier and BSplines patches) etc. (any book on computer graphics will help to really understand this features). In our example we have a bilinear patch with four points, these are defined with a "P" followed by the coordinates (x,y,z) of the points. The texture of the object is rendered by the statement Surface, the first argument is a shader file and the following arguments are specific of each shader. In the following image we have the the resulting scene
Lines 44 to 52 define several objects within the scence: an sphere (line 51) whose color is specified with the directive Color [R G B]. This sphere is translated and given a surface type, matte in this present case. Next comes the most important feature of BMRT, the displacement shaders. They are analogous to the bump-maps of Pov-Ray except that under BMRT these "bumps" are not simulated but they are real. The final effect is that the surface and borders of the sphere appear rough. shaders for displacement are similar to those for textures, always go declare as a name for a particular shader followed by its parameters. The specification of the sphere is a bit strange; first goes the radius, then zmin and zmax clip the sphere along the z-axs (for example values -1 and 1 would leave the sphere intact while values 0 and 1 would cut it in half), the last value are the degrees covered by the sphere (360 is the whole sphere, 180 half, etc..). Here is an image of the first sphere in position:
The following object is similar to the first one except for different texture and displacement characteristics, therefore I will not repeat the same explanation here, and let us simply run the code and see what we get:
This completes the file. At this point it should be clear that the development of scenes is not complex, but a complicated scene or an animation can make the file very complex. To avoid this, is enough to use a modeler that supports RenderMan (any modeler of estime exports RIB files) or alternatively to program the animacion in C. In the distribution of BMRT come the include directory and the necessary libraries. They contain functions that send to standard output the RIB file. Both methods are completely indentical: WorldBegin in a RIB file corresponds to RiWorldBegin() in a C program (to learn more about it read RenderMan for Poets which is located in the doc/ directory).
In the next article we will model a little object, it will be done in C so that it can be animated easier later on and also in order to become familiar with the library. The small object for the animation could be the Linux penguin or maybe Bill Gates (or both and we make the penguin fry the other.. :)