von:Carlos Calzada Grau
|
Zusammenfassung:
Die Firma Pixar hat RenderMan, einen Rendering Interface Standard,
entwickelt. RenderMan erlaubt es Modellierern zu spezifizieren, was
gerendert werden muß, ohne genau festzulegen, welcher Algorithmus benutzt
werden soll. Dieser Artikle gibt einen Einblick in dieses fantastische Programm.
Der erste Animationsfilm, der einen Oskar erhielt war Tin Toy (1988); Pixar modellierte das Gesicht eines Babys mit über 40 Muskeln, die ein Animator kontrollieren konnte.
Knick Knack, die Geschichte eines Schneemanns, der in einer Kristallkugel lebt, erschien 1989. Der Film wurde ursprünglich als 3D Film produziert, später aber in einer ``normalen'' Fassung herausgegeben.
Wenig später kamen eine Reihe von erfolgreichen Filmen wie z.B. Toy Story, einer der ersten Filme voller Länge, die vollständig auf einem Computer produziert wurden. Die PixarHomepage enthält eine Menge interessanter Informationen, darunter auch das Erscheinungsdatum für Toy Story 2, der 1999 erscheinen soll.
Pixar entwickelte RenderMan um "Modeler" und "Renderer" voneinander zu trennen und unabhängig voneinander zu warten. Ein Modeler wird dazu benutzt, Szenen zu zeichnen und Animationen zu entwerfen. Die einzige Aufgabe eines Renderers ist es, die mit dem Modeler entworfenen Szenen so realistisch wie möglich zu zeichnen (oder rendern, wie die Angelsachsen sagen); der Renderer ist für die lebensechte Erzeugung von Schatten, Lichtfall und Texturen verantwortlich.
RenderMan erlaubt es, die Angaben, was darzustellen ist, vom wie des Renderns zu trennen. Ein Modeler sollte sich nicht um das Rendern kümmern müssen. Ein Renderer, der den von RenderMan spezifizierten Standard erfüllt, kann, unabhängig von RenderMan, eine Vielfalt von Methoden zum ``Zeichnen'' der Objekte benutzen, wie z.B. Z-Buffer, Scan-Line, Ray-Tracing oder Radiosity. Man kann das Interface, das RenderMan bereitstellt, als ein Format zum Beschreiben von Szenen ansehen, genauso wie PostScript ein Format zum Beschreiben (in zweierlei Hinsicht) von Seiten ist. Dieser Standard hängt weder vom Betriebssystem noch von der zugrundeliegenden Architektur ab.
Wir werden in diesem Artikel versuchen, eine kleine Einführung in RenderMan mit Hilfe der Blue Moon Rendering Tools zu geben, die komplett von Larry Gritz geschrieben wurden. Dieses Paket ist ein frei verfügbarer Renderer (nur die Binärdateien für persönlichen Gebrauch), der für viele verschiedene Systeme erhältlich ist, unter anderem auch für Linux, für das er in der Tat zuerst implementiert wurde. Er benutzt sowohl Ray-Tracing als auch Radiosity und läßt im Vergleich zu Pixars kommerziellem Photorealistic RenderMan (PRMan) wenig zu wünschen übrig.
Das Welt- und Kamerakoordinatensystem sind anfänglich identisch, nämlich ein linkshändiges System wie in PovRay; der Ursprung befindet sich in der Mitte des Bildschirms, die X Achse verläuft nach rechts, die Y Achse nach oben und die Z Achse geht in den Bildschirm hinein. Ein rechtsändiges Koordinatensystem unterscheidet sich dadurch, daß die Z Achse aus dem Bildschirm herauskommt.
Die folgende Abbildung zeigt die Standardkamera (die X Achse ist rot, die Y Achse grün und die Z Achse blau; der Sourcecode kann durch einen Klick auf das Bild erhalten werden)
Das Weltkoordinatensystem in PovRay ist fest, was zur Folge hat, daß man die Kamera durch die Welt bewegt und Objekte durch Transformationen positioniert. RenderMan verhält sich genau umgekehrt: die Kamera befindet sich an einer festen Stelle und man verändert das Weltkoordinatensystem, um unterschiedliche Ansichten zu erhalten. All das wird verständlicher werden, wenn wir ein Beispiel "sezieren".
RenderMan hat viele eingebaute Funktionen, sowohl zur Definition von Objekten als auch für Lichter usw. Wir werden uns jetzt als Beispiel einige Quadriken anschauen. Andere eingebaute Objekte (Primitive) wären Bezier-patches oder Polygone.
Scheibe
Höhe Radius
Thetamax
Scheibe 5 10 300 |
Kegel
Höhe
Radius Thetamax
Kegel 15 10 300 |
Zylinder Radius
zmin
zmax thetamax
Zylinder 10 -5 10 300 |
Kugel Radius
zmin
zmax thetamax
Kugel 10 -4 8 300 |
Torus gr Rad kl
Rad
phimin phimax thetamax
Torus 10 &nbs p; 4 &nb sp; 90 320 300 |
Paraboloid Radius
zmin
zmax thetamax
Paraboloid 10 4 15 300 |
Hyperboloid
Punkt1
Punkt2 thetamax
Hyperboloid 0 10 -5 10 5 15 300 |
Es mag dem aufmerksamen Leser schon aufgefallen sein, daß das Format dieser Primitive nicht gerade einfach ist, was aber nicht allzu schlimm ist, da die RIB Datei von einem Modeler erzeugt wird; für diese Schnittstelle ist das Dateiformat knapp genug und angemessen.
rabit:~/$ gzip -d BMRT2.3.6.linux.tar.gz rabit:~/$ tar xvf BMRT2.3.6.linux.tar
Das Auspacken erzeugt das Verzeichnis BMRT2.3.6. Es enthält ausführbare Programme (in bin/), Beispiele (in examples/) und die Anleitung, sowohl als PostScript als auch als HTML (in doc/), Die README Datei enthält zusätzliche Hinweise für die Installation.
Um uns an RenderMans Benutzung zu gewöhnen, gehen wir Schritt für Schritt durch ein typisches Beispiel (../../common/May1998/disptest.rib). Die folgende Abbildung kann mit dem Befehl rendrib -v ../../common/May1998/disptest.rib erzeugt werden (ein Klick auf das Bild liefert es in 1024x768 Auflösung und mit 2x2 anti-aliasing).
../../common/May1998/disptest.rib ist eines der vielen Beispiele im Verzeichnis examples von BMRT. Der Leser wird feststellen, daß die Datei, aus der es erzeugt wurde, nicht sehr groß ist. Das Erzeugen von Animationen läßt die Dateigröße natürlich beträchtlich wachsen.
Das Verzeichnis bin enthält mehrere Programme: rendrib, rendribv und rgl. rendrib ist der eigentliche Renderer, rendribv funktioniert ähnlich, nur daß es Objekte als "Wireframes" zeichnet, und rgl rendert Polygone. Die beiden letzten Renderer werden dazu verwendet, schnell eine Grobversion der Szene (preview) zu erhalten, wohingegen rendrib für das endgültige Rendern benutzt wird.
Das RIB Format (Renderman Interface Bytestream) ist einfach, ohne dadurch an Ausdruckskraft einzubüßen. RIB Dateien werden als einfache ASCII Dateien gespeichert, genau wie die entsprechenden Dateien für PovRay. Eine ordentliches RIB Datei enthält die folgenden Elemente:
Der Graphikzustand enthält alle Informationen, die benötigt werden, um Primitive zu zeichnen. Er besteht aus zwei Teilen: einem globalen Zustand, der allen Primitiven gemeinsam ist und einem aktuellen Zustand, individuell für jedes primitive Objekt. Die Parameter des globalen Zustands heißen Optionen, und die des aktuellen Zusatnds heißen Attribute.
Wir werden jetzt Zeile für Zeile das folgende Beispiel analysieren
und so besser verstehen, wie die verschiedenen Optionen und Attribute
verwendet werden und wie Szenen mit RenderMan beschrieben werden.
1.- ##RenderMan RIB-Structure 1.0
2.- version 3.03
3.-
4.-
###########################################################################
5.- #
6.- # Diese RIB Datei zeigt einige komplexe prozedurale Texturen.
7.- # Zwei Kugeln zeigen, wie "stucco" und "dented" displacement shaders
benutzt werden.
8.- # Der Boden zeigt den gmarbtile_polish shader, polierte grüne
Marmorkacheln.
9.- # Der Shader erzielt die Reflektionen durch Aufruf der
10.- # Funktion trace() function, statt reflection mapping zu benutzen.
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
Kommentare in einer RIB Datei werden mit # begonnen und gehen bis zum Ende der Zeile (genau wie // Kommentare in C++). Kommentare können überall in der Datei verwendet werden.
Zeile 2 zeigt ein Beispiel der version Anweisung. Es gibt an, das die Version des benutzten Interfaces 3.03 ist; die neueste Version ist 3.1 vom September 1989 (ja, 1989, kein Fehler), obwohl es eine Revision vom Mai 1995 gibt.
Die Anweisungen searchpath und shader in Zeile 14 definieren den Pfad für die "Shader"; das sind Objekte, die dem Renderer mitteilen, wie ein bestimmtes Objekt zu rendern ist (als Solid, transparent, usw.), da die Texturen der Objekte als Plug-Ins implementiert sind, was das Interface sehr mächtig macht und das Hinzufügen neuer Texturen und Effekte sehr erleichtert. Diese Einstellungen werden gewöhnlich mit der Environment-Variablen SHADER vorgenommen.
Die Option Display erscheint auf Zeile 15. Sie legt fest, daß die Ausgabe in die Datei "balls2.tiff" erfolgt, und vom Typ "file" "rgb" sein soll.
Zeile 16 definiert die Auflösung des Bildes mit der Option Format. Die Auflösung für unser Beispiel ist 400x300, die -1 definiert das Seitenverhältnis (der Wert sollte +1 sein, ich bin nicht sicher, warum hier -1 verwendet wurde).
Die nächste Zeile gibt an, wieviele Rays für jedes Pixel verwendet werden sollen. Jedes Pixel wird dabei in horizontale und vertikale Richtung in die angegebene Anzahl von Subpixeln unterteilt. Die Angabe PixelSamples 2 2 resultiert in 4 Rays durch jedes Pixel, was die Bildqualität erheblich verbessern kann, natürlich unter Vergrößerung der Rechenzeit. Unser Beispiel kann mit 1 x 1 = 1 Rays pro Pixel in zufridenstellender Qualität und Geschwindigkeit gezeichnet werden.
Zeile 19 definiert den Eintrag prmanspecular vom Typ integer. prmanspecular ist jetzt ein Token, das von einer ganzen Zahl gefolgt werden muß.
Zeile 21 gibt an, daß eine Zentralprojektion verwendet werden soll und daß die Größe des Sichtfelds ("fov") 25 Grad beträgt.
Die Zeilen 22 und 23 definieren die Kameraposition durch eine Verschiebung gefolgt von einer Drehung. Transformationen werden immer in "von rechts nach links" angewendet: hier, zuerst die Drehung, dann die Verschiebung (Anm. des Übers: das ist dasselbe wie in mathematischer Notation). Die Transformationen werden erst ausgeführt, wenn RenderMan den Eintrag WorldBegin findet. Die Drehung ist eine Drehung um -100 Grad um die X Achse. (eine 45 Grad Drehung um die Y Achse kann durch Rotate 45 0 1 0 erzielt werden) Die Verschiebung erfolgt um -0.55 Einheiten entlang der Y-Achse und um 8 Einheiten entlang der Z-Achse. Es ist wichtig, daß nicht die Kamera sondern das Weltkoordinatensystem transformiert wird. (Anm. des engl. Übers.: OpenGL benutzt dasselbe Schema) Die folgenden Abbildungen zeigen verschiedene Zustände während der Transformationen:
Die drei Objekte, die die Szene ausmachen, werden jedes zwischen einem AttributeBegin und AttributeEnd deklariert, da jedes Objekt seine eigenen Eigenschaften hat (sowohl Position als auch Erscheinung). Wenn sich nur die Position von Objekt zu Objekt ändern würde, könnte man die Textur global deklarieren und die Objekte dann mittels TransformBegin und TransformEnd definieren. Das erste Objekt (Zeilen 34 bis 42) ist ein patch. Patches können auf unterschiedliche Weise konstruiert werden: uniform oder nicht-uniform, rational oder polynomial und bilinear oder bikubisch usw. Bikubische patches führen zu Bezier und B-Spline patches; näheres dazu kann man in den meisten Büchern über Computergraphik finden. Unser Beispiel enthält einen bilinearen patch durch vier Punkte; die Geometrie des patches wird durch ein "P" gefolgt von den (x,y,z)-Koordinaten der Punkte definiert. Die Textur des Objektes wird durch den Befehl Surface gezeichnet; das erste Argument ist eine shader-Datei und die restlichen Argumente sind spezifisch für den gewählten shader. Das nächste Bild zeigt die Szene, die wir bis jetzt konstruiert haben.
Die Zeilen 44 bis 52 definieren etliche Objekte in der Szene: eine Kugel (Zeile 51), deren Farbe mit der Angabe Color [R G B] festgelegt wird. Die Kugel wird verschoben und erhält eine Oberfläche vom Typ matte. Als nächstes kommt die wichtigste Eigenschaft von BMRT: die Displacement shaders. Sie funktionieren analog zu bump-maps in PovRay, nur daß in BRMT die "bumps" nicht simuliert sind, sondern echt. Der erzielte Effekt ist, daß sowohl die Oberfläche als auch die Ränder der Kugel rauh erscheinen. Displacement shaders sind denen für Texturen sehr ähnlich, sie werden stets durch den Namen des gewünschten shaders gefolgt von den zugehörigen Parametern deklariert. Die Spezifikation der Kugel ist etwas gewöhnungsbedürftig: zuerst kommt der Radius, dann zmin und zmax, die die Kugel in Richtung der z-Achse abschneiden (z.B., die Werte -1 und 1 würden keine Änderungen der Kugel zur Folge haben, wohingegen die Werte 0 und 1 die Kugel halbieren würden), der letzte Wert gibt den Winkel (in Grad) an, den die Kugel umfaßt (360 ist die ganze Kugel, 180 eine Halbkugel, usw.) Hier ist ein Bild der Kugel in ihrer Position:
Das nächste Bild unterscheidet sich vom letzten nur dadurch, daß die Textur- und Displacementparameter geändert wurden. Es ist daher unnötig, daß ich dieselben Erklärungen nochmals gebe; wir können einfach den Code benutzen und erhalten das folgende:
Damit ist unsere Beschreibung der Eingabedatei vollständig. Es sollte klargeworden sein, daß das Entwerfen von Szenen nicht komplex ist, daß aber eine komplizierte Szene oder Animation die Datei sehr komplex machen kann. Um dem zu entgehen, genügt es, einen Modeler zu verwenden, der RenderMan unterstützt (jeder Modeler, der etwas auf sich hält, kann RIB Dateien exportieren); alternativ kann die Animation in C programmiert werden. Die Distribution der BMRT enthält ein include Verzeichnis und die nötigen Bibliotheken. Sie enthalten Funktionen, die die RIB Datei auf der Standardausgabe erzeugen. Beide Methoden sind identisch: dem WorldBegin in einer RIB Datei entspricht der Aufruf RiWorldBegin() in einem C Programm. (Um mehr darüber zu lernen, sollte man RenderMan for Poets im doc/ Verzeichnis lesen.)
Im nächsten Artikel werden wir ein kleines Objekt modellieren. Wir werden dazu C verwenden; das hat den Vorteil, daß es später einfacher ist, Animationen zu erzeugen und wird uns natürlich auch die Programmier-Bibliothek näher bringen. Das Objekt, das wir animieren werden, könnte ein Linux-Pinguin sein, oder vielleicht Bill Gates (oder beide; wir könnten vielleicht auch den Pinguin dazu bringen, sich einen Bill Gates zu braten... :)
Webpages maintained
by Miguel Ángel Sepúlveda
© Carlos Calzada Grau 1998 Übersetzt von:David Lutterkort LinuxFocus 1998 |