Introduction
Who has never heard of Pixar?,
Who has never seen the movie Toy Story?.
Pixar Animation Studios is known since a long time ago for its work on computer
animations. Luxo Jr. (1986) is the first movie with 3d graphics
nominated for an Oscar, it also won more than 20 prizes in international
film festivals.
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.
The RenderMan@ Interface Procedures and RIB Protocol are:
Copyright 1988, 1989, Pixar.
All Rights Reserved.
RenderMan@ is a registered trademark of Pixar
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.
Installation
As a first step let us go to the home page of Blue Moon Rendering Tools
and download the program. At this instance the current version os 2.3.4 and to
uncompress it we proceed as usual:
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.
First Steps
Let us become familiar with RenderMan's specification by examining a
typical example (../../common/May1998/disptest.rib). The image is generated
by the command rendrib -v ../../common/May1998/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:
-
Global options for all the frames
(resolution, anti-akiasing, etc...)
-
FrameBegin
-
Initialization of the options for the graphical state of such
frame (like the output filename, level of detail, etc...)
-
Attributes of the graphical state for the frame (like
lights, type of projection, etc...)
-
WorldBegin
-
Modifications of the graphical state and declarations fo the geometry of the
actual frame.
-
WorldEnd. With the following side effects: the frame is rendered and
saved, all the geometry and the lights declared in (6) are destroyed, the graphical
state returns to the one existing at (5).
-
FrameEnd. This returns the graphical state back to its
situation in (2).
-
Steps (2) to (8) are repeated in case of additional frames.
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.
A partir de aquí tenemos los tres objetos que forman la
escena, cada objeto está encerrado en un par
AttributeBegin, AttributeEnd, ya que cada uno tiene
sus propias características, tanto de posición como de
apariencia, si lo único que cambiaramos de un objeto a otro
fuera su posición, podríamos declarar la textura fuera y
a continuación definir los objetos con TransformBegin
y TransformEnd. El primer objeto (lineas 34 a 42) es un
parche, los parches pueden ser: uniformes o no-uniformes, racionales o
no-racionales y bilineares o bicúbicos, con esto se consiguen
parches Bezier, BSplines etc. (un libro sobre
gráficos por ordenador ayudaría bastante a comprender
esto). En este caso tenemos un parche bilinear con cuatro puntos,
estos se definen con "P" y luego se ponen las coordenadas
(x,y,z) de los puntos que queramos. La textura del objeto se
consigue con la directiva Surface, el primer argumento es un
fichero shader, las siguientes son específicas de cada
shader. En la imagen siguiente tenemos como queda la escena
al añadir este cuadrado.
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).
Conclusions
RenderMan interface is very powerful and in fact Toy Story was made
using it (with a modeler called marionet). In
www.toystory.com there are some
articles about the movie and a few other things. The specification of
the interface can be found at
giga.cps.unizar.es.
Besides the specification there is manual for PRMan (Pixar's the renderer )
also some examples.
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.. :)
|