Carlos Calzada Grau Über den Autor:
Inhalt: |
Zusammenfassung:
Dies ist der dritte
Artikel der Serie über Renderman (I
, II). In diesem Teil wird eines der wichtigsten Themen
beleuchtet: die Möglichkeit, Szenen mittels den Programmiersprachen C
oder C++ zu modellieren und zu rendern.
Durch die frühere Installation von Blue Moon Rendering Werkzeugen sind
zwei neue Verzeichnisse erzeugt worden: lib und inlcude.
Diese beinhalten vier Dateien, von denen momentan aber nur zwei relevant
sind: ri.h, eine Headerdatei, und libribout.a ,
die die Funktionsbibliothek darstellt. Die Headerdatei sollte in das Verzeichnis
/usr/local/include
und ribout.a nach /usr/local/lib (der etwas erfahrene
Leser kann sie auch in andere Verzeichnisse installieren) kopiert werden. Nach der Installation
der Bibliothek wird es nun Zeit für ein erstes Beispielprogramm.
gcc myprogram.c -o myprogram -lribout -lmHier ist ein Makefile , durch welches man sich Tipparbeit unter der Konsole ersparen kann:
LIBS = -lm -lribout PROGNAME = primero all: $(PROGNAME) $(PROGNAME).o: $(PROGNAME).c gcc -c $(PROGNAME).c $(PROGNAME): $(PROGNAME).o gcc -o $(PROGNAME) $(PROGNAME).o $(LIBS) |
Im ersten Beispiel werden einige Koordinatenachsen, sowie ein Ball in ihrem Schnittpunkt erstellt. Hier ist der Quelltext der Datei primero.c:
1 #include <stdio.h> 2 #include <math.h> 3 #include <ri.h> 4 5 void main(void) 6 { 7 int i; 8 int x,y,z; 9 int nf; 10 float slopex,slopey,slopez; 11 12 RtColor Rojo={1,0,0}; 13 RtColor Verde={0,1,0}; 14 RtColor Azul={0,0,1}; 15 RtColor Blanco={1,1,1}; 16 17 RtPoint p1={30,0,10}; /* Posicicion inicial de la pelota */ 18 RtPoint p2={0,20,10}; /* Posicion final de la pelota */ 19 20 RtPoint from={0,100,100}; /* Direccion de la luz */ 21 RtPoint to={0,0,0}; 22 23 char name[]="primero.tif"; 24 RtFloat fov=45; 25 RtFloat intensity1=0.1; 26 RtFloat intensity2=1.5; 27 RtInt init=0,end=1; 28 29 RiBegin(RI_NULL); 30 RiFormat(320,240,1); 31 RiPixelSamples(2,2); 32 RiShutter(0,1); 33 RiFrameBegin(1); 34 RiDisplay(name,"file","rgb",RI_NULL); 35 name[7]++; 36 RiProjection("perspective","fov",&fov,RI_NULL); 37 RiTranslate(0,-5,60); 38 RiRotate(-120,1,0,0); 39 RiRotate(25,0,0,1); 40 RiWorldBegin(); 41 RiLightSource(ämbientlight","intensity",&intensity1,RI_NULL); 42 RiLightSource("distantlight","intensity",&intensity2,"from",from,"to",to,RI_NULL); 43 RiColor(Azul); 44 RiTransformBegin(); 45 RiCylinder(1,0,20,360,RI_NULL); 46 RiTranslate(0,0,20); 47 RiCone(2,2,360,RI_NULL); 48 RiTransformEnd(); 49 RiColor(Verde); 50 RiTransformBegin(); 51 RiRotate(-90,1,0,0); 52 RiCylinder(1,0,20,360,RI_NULL); 53 RiTranslate(0,0,20); 54 RiCone(2,2,360,RI_NULL); 55 RiTransformEnd(); 56 RiColor(Rojo); 57 RiTransformBegin(); 58 RiRotate(90,0,1,0); 59 RiCylinder(1,0,20,360,RI_NULL); 60 RiTranslate(0,0,20); 61 RiCone(2,2,360,RI_NULL); 62 RiTransformEnd(); 63 RiColor(Blanco); 64 RiSphere(5,-5,5,360,RI_NULL); 65 RiWorldEnd(); 66 RiFrameEnd(); 67 RiEnd(); 68 }; |
Die ersten drei Zeilen binden wichtige Headerdatei ein, unter denen sich auch ri.h, die Headerdatei für die Prototypen der Renderman Bibliothek, befindet. Jedes Kommando von Renderman besitzt eine äquivalente C Funktion in der Datei ri.h, so hat etwa TransformBegin die Funktion RiTransformBegin() als entsprechendes Gegenstück, usw. Das Programm primero wird durch einen Durchlauf von make generiert. Der Aufruf des Beispielprogrammes erzeugt durch Umleiten der Standardausgabe (primero > primero.rib) eine Szenen-Datei. Wird dagegen die Ausgabe mittels einer Pipe zur Eingabe von rendrib (primero | rendrib), so rendert dieses Programm ein entsprechendes Bild (primero.tif).
Die Aufrufe der Bibliotheksfunktionen müssen zwischen einem RiBegin(RI_NULL) und einem RiEnd() Aufruf stehen. Der Parameter, der an RiBegin übergeben wird, ist im allgemeinen RI_NULL. Damit keine RIB Ausgabe an die Standardausgabe geht, könnte man den Namen einer Ausgabedatei ("myfile.rib") oder sogar den Namen eines Prozesses (zum Beispiel renderib) übergeben. Das Programm wird dann die Renderman Befehle an den Renderer weiterleiten, ohne daß eine RIB Datei für das Zwischenspeichern erzeugt wird.
Die Quelldatei des ersten Beispielprogrammes verwendet sowohl typische C Anweisungen, als auch Typen und Funktionen des Renderman Interfaces: Der Typ Rtcolor ist ein Vektor mit drei Komponenten vom Type Real, für die Farbwerte für Rot, Grün und Blau (zwischen 0.0 und 1.0). RtPoint beschreibt eine Position im Raum, RtFloat und RtInt sind die entsprechenden Typen.
In Zeile 29 wird RiBegin(RI_NULL) aufgerufen. Dadurch wird
das Renderman Interface initialisiert. Von hier an folgen die Funktionen
der Kommandos, die in einer typischen RIB Datei zu finden sind. Ein Beispielaufruf
des Programmes und die Umleitung dessen Ausgabe in eine Datei (./primero
> primero.rib) sollte wie folgt aussehen:
##RenderMan RIB-Structure 1.0 version 3.03 Format 320 240 1 PixelSamples 2 2 Shutter 0 1 FrameBegin 1 Display "camara.tif" "file" "rgb" Projection "perspective" "fov" [45 ] Translate 0 -5 60 Rotate -120 1 0 0 Rotate 25 0 0 1 WorldBegin LightSource ämbientlight" 1 "intensity" [0.1 ] LightSource "distantlight" 2 "intensity" [1.5 ] "from" [0 100 100] "to" [0 0 0] Color [0 0 1] TransformBegin Cylinder 1 0 20 360 Translate 0 0 20 Cone 2 2 360 TransformEnd Color [0 1 0] TransformBegin Rotate -90 1 0 0 Cylinder 1 0 20 360 Translate 0 0 20 Cone 2 2 360 TransformEnd Color [1 0 0] TransformBegin Rotate 90 0 1 0 Cylinder 1 0 20 360 Translate 0 0 20 Cone 2 2 360 TransformEnd Color [1 1 1] Sphere 5 -5 5 360 WorldEnd FrameEnd |
Dieses erste Beispiel war nicht sehr brauchbar. Das nächste Programm
ähnelt dem ersten Beispiel. Es demonstriert die Mächtigkeit der Bibliothek
in Sachen Animation. Wurde im ersten Beispiel nur ein einzelnes Bild
erzeugt, so wird das nächste den Ball in Bewegung versetzen.
1 #include <stdio.h> 2 #include <math.h> 3 #include <ri.h> 4 #include "filename.h" 5 6 void main(void) 7 { 8 int i; 9 int x,y,z; 10 int nf; 11 float slopex,slopey,slopez; 12 13 RtColor Rojo={1,0,0}; 14 RtColor Verde={0,1,0}; 15 RtColor Azul={0,0,1}; 16 RtColor Blanco={1,1,1}; 17 18 RtPoint p1={30,0,10}; /* Posicicion inicial de la pelota */ 19 RtPoint p2={0,20,10}; /* Posicion final de la pelota */ 20 21 RtPoint from={0,100,100}; /* Direccion de la luz */ 22 RtPoint to={0,0,0}; 23 24 char base[]="camara_"; 25 char ext[]="tif"; 26 char name[50]; 27 RtFloat fov=45; 28 RtFloat intensity1=0.1; 29 RtFloat intensity2=1.5; 30 RtInt init=0,end=1; 31 32 nf=100; /* Numero de frames */ 33 slopex=(p2[0]-p1[0])/nf; 34 slopey=(p2[1]-p1[1])/nf; 35 slopez=(p2[2]-p1[2])/nf; 36 37 RiBegin(RI_NULL); 38 RiFormat(320,240,1); 39 RiPixelSamples(2,2); 40 RiShutter(0,1); 41 for (i=1;i <= nf;i++) 42 { 43 RiFrameBegin(i); 44 filename(base,ext,sizeof(base)+4,i-1,name); 45 RiDisplay(name,"file","rgb",RI_NULL); 46 name[7]++; 47 RiProjection("perspective","fov",&fov,RI_NULL); 48 RiTranslate(0,-5,60); 49 RiRotate(-120,1,0,0); 50 RiRotate(25,0,0,1); 51 RiWorldBegin(); 52 RiLightSource(ämbientlight","intensity",&intensity1,RI_NULL); 53 RiLightSource("distantlight","intensity",&intensity2,"from",from,"to",to,RI_NULL); 54 RiColor(Azul); 55 RiTransformBegin(); 56 RiCylinder(1,0,20,360,RI_NULL); 57 RiTranslate(0,0,20); 58 RiCone(2,2,360,RI_NULL); 59 RiTransformEnd(); 60 RiColor(Verde); 61 RiTransformBegin(); 62 RiRotate(-90,1,0,0); 63 RiCylinder(1,0,20,360,RI_NULL); 64 RiTranslate(0,0,20); 65 RiCone(2,2,360,RI_NULL); 66 RiTransformEnd(); 67 RiColor(Rojo); 68 RiTransformBegin(); 69 RiRotate(90,0,1,0); 70 RiCylinder(1,0,20,360,RI_NULL); 71 RiTranslate(0,0,20); 72 RiCone(2,2,360,RI_NULL); 73 RiTransformEnd(); 74 RiColor(Blanco); 75 RiTransformBegin(); 76 RiTranslate(p1[0]+slopex*(i-1),p1[1]+slopey*(i-1),p1[2]+slopez*(i-1)); 77 RiSphere(5,-5,5,360,RI_NULL); 78 RiTransformEnd(); 79 RiWorldEnd(); 80 RiFrameEnd(); 81 } 82 RiEnd(); 83 }; |
Als nächstes sollte dieses zweite Beispiel wie zuvor kompiliert und ausgeführt werden, wobei seine Ausgabe zum Beispiel an rendribv weitergeleitet werden kann. Dies ist ein einfacher Weg, eine Vorschau auf die Animation schnell und bei einer akzeptablen Framerate zu bekommen. Um sich die RIB Ausgabedatei anzuschauen, muß man nur die Standardausgabe in eine neue Datei umleiten. Der Leser kann sich davon überzeugen, daß die erzeugte Datei recht groß ist (segundo.rib belegt 70 KB), da die gleiche Szene hundertmal definiert ist (einmal für jeden Frame).
Folgende Abbildung zeigt einige Zwischenbilder der Animation:
Natürlich kann jedes Objekt animiert, seine Position und Größe
verändert werden. Ebenso kann man die Intensität des Lichtes und die Kamera
variieren, Gegenstände auftauchen und verschwinden lassen, uvm.
float rebote (int i, int nframes, int max) { float min, z; while (i > nframes) i-=nframes; min=sqrt(max); z=i-((float)nframes/2.0); z=(z*min)/((float)nframes/2.0); z=(float)max - (z*z); return(z); } |
Durch ein paar einfache Berechnungen wird die typische Parabelkurve (y=x^2) auf die Zahl der Frames und die maximale Höhe angewendet. Folgende Abbildung zeigt wieder einige Zwischenbilder. Diese werden durch das Programm tercero.c pro Prellbewegung erzeugt:
Hier sind noch ein paar animierte GIF Dateien zu finden, die die Animationen veranschaulichen sollen.Auch wenn sie (zumindest unter Netscape) langsam sind, sollten sie unter xanim mit brauchbarer Geschwindigkeit laufen.
Geradlinige Bewegung: segundo_anim.gif
Parabelförmige Bewegung: tercero_anim.gif
Mit diesem letzten Beispiel endet die Vorstellung der grundlegenden
Nutzung der C Schnittstelle zu Renderman und seiner Programmierung. Die
Programmierung von Shadern stellt hierbei die größte Herausforderung
und die spektakulärste Anwendung dar. Durch diese erhät der Benutzer
die totale Kontrolle über den letztendlichen Rendervorgang der Szene,
da durch sie Texturen, Beleuchtung, usw. gesteuert werden können.
Páginas
web mantenidas por Miguel Ángel Sepúlveda
© Carlos Calzada Grau 1998 LinuxFocus 1998 |