original in es Carlos Calzada Grau
es to en Miguel Angel Sepulveda
en to nl Guus Snijders
Afgestudeerd in computer wetenschappen en heb plezier met computer graphics sinds mijn eerste Spectrum. Ik ben erg enthousiast over Linux, de ontwikkelings-filosofie en alles dat niets te maken heeft met micro$oft. Andere niet-scherm gerelateerde hobbies zijn bonsais en aquaria.
IN 1987 won Red's Dream verschillende prijzen op het "World Animation Festival" in Zagreb en het "San Francisco International Film Festival".
De eerste animatie die een Oscar won, was Tin Toy (1998), Pixar ontwierp een model voor het gezicht van een baby met meer dan 40 spieren die door de animator werden bediend.
In 1989 werd Knick Knack vertoond, dit was het verhaal van een sneeuwman die in een kristallen bol leeft. De film was in de eerste instantie geproduceerd voor 3D weergave, al werd er ook een normale versie uitgebracht.
Kort daarna volgden een aantal successen zoals de recente film Toy Story. Dit is een van de eerste langere films die volledig geproduceerd is met computers. Op de homepage van Pixar kunnen nog veel meer interessante dingen worden gevonden, zo wordt Toy Story 2 ergens in 1999 uitgebracht.
Pixar ontwikkelde de interface "RenderMan" apart en onderhield "modelers" en "renderers" los daarvan. Een modeler is een tool die wordt gebruikt om scenes te tekenen, animaties te ontwerpen, enz. Het enige doel van een renderer is om de beschrijving van de modeler te nemen en deze te renderen met schaduwen, lichten, texturen, enz..
RenderMan laat 3D artiesten opgeven wat te renderen, maar niet hoe dat moet. In andere woorden, een modeler zou zich niets moeten aantrekken van de rendering stap. Zo kan een renderer die voldoet aan de standaard specificaties van RenderMan gebruik maken van Z-buffer, scan-line, ray-tracing, radiosity en een andere methode om de objecten te "tekenen", deze stap is onafhankelijk van RenderMan. Je kunt de interface van RenderMan zien als een formaat voor de beschrijving van scenes, op dezelfde manier als waarop PostScript een formaat is voor de beschrijving van pagina's. Deze standaard is niet afhankelijk van architecturen en besturingssystemen.
In dit artikel proberen we een korte introductie in RenderMan te geven, hiervoor zullen we de Blue Moon Rendering Tools van Larry Gritz gebruiken. Dit pakket is een renderer voor vrije distributie (alleen binaries en voor persoonlijk gebruik) en er zijn versies voor vele systemen, waaronder Linux (in feite was dit een van de eerste implementaties). Er wordt gebruik gemaakt van ray-tracing en radiosity en doet niet of nauwelijks onder voor een Fotorealistische RenderMan (PRMan), het commerciële product van Pixar.
In het begin zijn het systeem van coördiaten voor de wereld en de camera gelijk, het zijn links-handige coördiaten-systemen (als Pov-Ray), met de origine in het midden van het scherm, de X-as naar rechts, de Y-as naar boven en de Z-as naar de binnenkant van het scherm. De volgende figuur laat de default camera zien (de X-as is rood, Y-as is groen en Z-as is blauw, voor de broncode, klik op de afbeelding). Een rechts-handig coördinaten-systeem is identiek maar dan wijst de Z-as in de andere richting.
In Pov-Ray is het systeem van wereld coördinaten vast, dat wil zeggen dat men de camera door de wereld kan bewegen en objecten zetten met transformaties. In RenderMan geldt het tegenovergestelde, de camera is vast en wat wordt getransformeerd voor de verschillende gezichtspunten is het wereld-systeem van coördinaten. Dit alles zal duidelijker worden als we een voorbeeld "ontmantelen".
RenderMan kent veel primitieven, voor object definities, lichten, enz... Nu gaan we een voorbeeld bekijken van het formaat van de bekenste cuadrics (NL:?), hoewel er ook andere zijn (zoals bezier patches, polygonen, ...).
Schijf
hoogte radius
thetamax
Disk 5 10 300 |
Kegel
hoogte radius
thetamax
Kegel 15 10 300 |
Cylinder
radius zmin
zmax thetamax
Cylinder 10 -5 10 300 |
Bol
radius zmin
zmax thetamax
Bol 10 -4 8 300 |
Donut major
rad min rad
phimin phimax
thetamax
Donut 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 |
De lezer heeft wellicht al gemerkt dat het formaat van sommige van deze primitieven niet echt gemakkelijk is, maar gelet op het feit dat het bestand RIB door een modeler als uitvoer moet worden gegeven, is dit formaat toepasselijk vanwege de doordachtheid en snelheid.
rabit:~/$ gzip -d BMRT2.3.6.linux.tar.gz rabit:~/$ tar xvf BMRT2.3.6.linux.tar
Na het uitpakken van de tar-ball hebben we een nieuwe directory met de naam BMRT2.3.6 . Deze bevat de uitvoerbare bestanden (in bin/, de voorbeelden (in examples/ en de documentatie in zowel PostScript asl HTML (onder doc/, ook is er een README bestand met aanvullende informatie over het programma. Lees het README bestand voor het installatie gedeelte, het is vrij simpel en zou niemand problemen moeten geven.
Om bekend te worden met de RenderMan's specificaties, gaan we een typisch voorbeeld bekijken (disptest.rib). De afbeelding is gegenereerd met het commando rendrib -v disptest.rib (klik op de afbeelding om hem in 1024x768 met anti-aliasing 2x2 te bekijken).
Dit is een van de vele voorbeelden die gevonden kunnen worden in de examples directory van BMRT (Blue Moon Rendering Tools), de lezer zal waarschijnlijk kunnen waarderen dat het genereren niet lang duurt (als je met animaties gaat werken, zul je zien dat de bestanden behoorlijk gaan groeien).
Er zijn verschillende executables onder bin/: rendrib, rendribv en rgl. Rendrib is de eigenlijke renderer, rendribv is vergelijkbaar maar rendert objecten in draad-mode, met alleen lijnen; rgl tenslotte rendert met behulp van polygonen. De laatste drie renders worden gebruikt voor de weergave van posities, animaties, enz.. Het uiteindelijke renderen gaat altijd met rendrib.
Het formaat van het RIB bestand (Renderman Interface ByteStream) is erg simpel, hoewel niet minder krachtig. Ze worden opgeslagen als platte-tekst bestanden (net asl Pov-Ray). Een goed-geschreven RIB bestand bevat het volgende:
De grafische staat bevat alle informatie die nodig is om een primitief te renderen. Het bestaat uit twee delen: een globale die die constant blijft van primitieve naar primitieve en een huidige staat die met de primitieven veranderd. De parameters van de globale staat, zijn bekend als opties en de huidige staten worden attributen genoemd.
Voor een beter begrip van opties en attributen en om een idee te hebben hoe scenes worden gespecificeerd met RenderMan, gaan we het voorbeeld regel voor regel bekijken. Dit zou een goede tutorial kunnen worden over wat er mogelijk is en hoe het doen.
1.- ##RenderMan RIB-Structure 1.0
2.- version 3.03
3.-
4.- ###########################
5.- #
6.- # Dit RIB bestand demonstreert enkele complexere procedurele texturen.
7.- # Twee ballen tonen het gebruik van "stucco" en "dented"
misplaatsing shaders.
8.- # De vloer toont de gmarbtile_polish shader, dit zijn gepolijste, groene
9.- # marmeren tegels. Let op dat de reflectie via de aanroep van de trace()
10.- # functie door de shader gaat, in plaats van reflectie 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
commentaren kunnen in het bestand worden opgenomen met het # symbool, zoals in regel 1 en de regels 4 tot 12. Een # symbool mag overal in het bestand voorkomen en ze mogen een volledige regel gebruiken (net als // commentaren in C++). Commentaren zijn handig wanneer deze bestanden met de hand worden bewerkt, omdat ze hulp bieden bij het begrijpen van de interne werkingen van de scene.
Regel 2 laat een voorbeeld van de version directive zien. Deze declareert alleen de versie van de gebruikte interface (3.03); de meest recente versie is 3.1, uitgebracht in september 1989 (ja 1989, dit is geen vergissing), hoewel er revisies van Mei 1995 zijn.
De directives searchpath en shader op regel 14 definiëren het pad voor de "shaders", dit zijn objecten die de renderer informeren hoe een bepaald object gerenderd moet worden (zoals een plastic, transparant, enz...), dit is een van de features die de interface erg krachtig maken, doordat de texturen van een object zich gedragen als plug-ins. Zo is het eenvoudig om nieuwe texturen, effecten,... te implementeren, zonder te wachten op een krachtiger versie van de renderer. Meestal is er een omgevingsvariabele (SHADER) die de locatie van deze bestanden aangeeft, vaak hoef je het pad dus niet expliciet op te geven.
De Display optie verschijnt op regel 15. Deze declareert de bestandsnaam voor de uitvoer als "balls2.tiff" met als type "file" "rgb", oftewel een RGB bestand.
Op regel 16 definiëren we de resolutie voor het renderen (grootte van de afbeelding) met de Display opties. De resolutie van ons voorbeeld is 400x300, de -1 definieert de aspect ratio van de pixel (eigenlijk zou het +1 moeten zijn, ik weet niet zeker waarom ze hier -1 hebben gebruikt.
Vervolgens komen de horizontale en verticale sampling voor iedere pixel, het aantal "rays" dat wordt gestart om een pixel te renderen. Een statement PixelSamples 2 2 wordt vertaald naar 4 rays per pixel, wat een geweldige kwaliteit voor de afbeelding opleverd (dit is de anti-aliasing), maar helaas duurt het renderen dan langer. In ons geval geeft een sampling van 1 x 1 = 1 een snellere rendering, maar slechts een ray per pixel.
Regel 19 declareerd de integer variabele prmanspecular, eigenlijk wordt prmanspecular gedefinieerd als een token en zodra de renderer dit token tegenkomt, zal het het daaropvolgende nummer als een integer nemen.
Vervolgens komt de declaratie van een 3D projectie, met de sleutel
"perspective" vragen we om een perspectief projectie en "fov
35" stelt het weergave veld in op 35 graden.
De regels 22 en 23 definiëren de positie van de camera. Eerst schrijven we een vertaling (translation), gevolgd door een rotatie. Maar omdat alle transformaties eerst op een stack worden geplaatst, is de eerste transformatie die wordt uitgevoerd, degene die het laatste op de stack is geplaatst, rotatie gevolgd door een vertaling (in dit geval worden de transformaties uitgevoerd zodra renderman het statement WorldBegin vindt). In dit voorbeeld roteerd het systeem -100 graden rond de X-as (om te roteren rond de Y-as gebruik je Rotate 45 0 1 0), vervolgens wordt het vertaald -0,55 eenheden langs de Y-as en 8 eenheden langs de Z-as. Let vooral op wat er wordt getransformeerd (geroteerd en vertaald) niet echt de camera is, maar het centrum van de wereld coördinaten (opmerking van de Engelse vertaler : OpenGL gebruikt exact hetzelfde schema voor transformaties). De volgende figuren laten verschillende stadia tijdens de twee transformaties zien.
Na de inleidende definities komt de scene zelf. Iedere scene (een declaratie van lichten, objecten, enz...) begint altijd met WorldBegin en eindigt met WorldEnd (regels 26 en 64, respectievelijk). De eerste paar regels in de scene van ons voorbeeld declareren de belichting (regel 28 tot 32); ieder licht heeft een nummer en in theorie moeten ze zich onderscheiden, de eerste is het omgevingslicht en heeft een intensiteit van 0,02. Na het belichten wordt de variabele shadows gedeclareerd als een karakter string en dan wordt de licht optie voor schaduwen geactiveerd. Regel 32 voegt een lichtbron van het type distantlight (een lichtbron die zich ver weg bevindt, zoals de zon) toe, weer met nummer 1: zoals eerder genoemd, zou de lichtbron anders moeten zijn (zeg 2), het werkt echter nog steeds omdat BMRT blijkbar de licht-nummering negeert, voor compatibiliteit (bijvoorbeeld met Pixar's PRMan) zouden we echter stricter moeten zijn met de interface. De intensiteit van de tweede lichtbron is gelijk aan de eerste (dit zijn algemene attributen) en de richtingsvector, gedefinieerd met from en to, stuurt de lichtbundels parallel, alsof het een lichtbron op afstand was.
Nu hebben we de drie elementaire objecten die de scene vormen, ieder object is omsloten met een paar AtributeBegin en AttributeEnd omdat ieder zijn eigen karakteristieken heeft (zowel positie als uiterlijk). Als de positie de enige eigenschap was die van object tot object veranderde, zou een TransformBegin en TransformEnd volstaan. Het eerste object (regels 34 tot 42) is een patch, patches kunnen zijn: uniform of non-uniform, rationeel of niet-rationeel en bilinear of bicubic. (wat leidt tot Bezier en Bsplines patches) enz. (een boek over computer graphics helpt om deze features echt te begrijpen). In ons voorbeeld hebben we een bilineare patch met vier coördinaten (x,y,z) van punten. De textuur van het object wordt gerenderd met het statement Surface, het eerste object is een shader bestand en de volgende argumenten zijn specifiek voor iedere shader. In de volgende afbeelding zie je de resulterende scene:
De regels 44 tot 52 definiëren meerdere objecten in de scene: een bol (regel 51), waarvan de kleur wordt opgegeven met de directive Color [R G B]. Deze bol wordt vertaald en krijgt een oppervlak-type matte, in het huidige geval. Vervolgens komt de belangrijkste feature van BMRT, de displacement (verplaatsing) shaders. Deze zijn vergelijkbaar met de bump-maps van Pov-Ray, behalve dat onder BMRT deze "bumps" niet gesimuleerd zijn, maar echt. Het laatste effect is dat het oppervlak en de grenzen van de bol ruw lijken. shaders voor verplaatsingen zijn vergelijkbaar met die voor texturen, declareer altijd als een naam voor een bepaald shader, gevolgd door zijn parameters. De specificatie van de bol is een beetje vreemd; eerst de radius, dan plaatsen de zmin en zmax de bol op de z-as (de waarden -1 en 1 zouden de bol intact laten, terwijl de waarden 0 en 1 hem doormidden zouden snijden), de laatste waarden zijn de graden die worden gedekt door de bol (360 is de volledige bol, 180 half, enz...) Hier is een afbeelding van de eerste bol in positie:
het volgende object is vergelijkbaar met de eerste, op de verschillende textuur na en de verplaatsing karakteristieken, daarom zal ik de uitleg hier niet herhalen, laten we gewoon de code uitvoeren en kijken wat we krijgen:
Dit maakt het bestand compleet. Op dit punt zou het duidelijk moeten zijn dat het ontwikkelen van scenes niet moeilijk is, hoewel een complexe scene of een animatie het bestand erg complex kunnen maken. Om dit voorkomen, volstaat een modeler die RenderMan ondersteund (vrijwel alle bekende modelers exporteren RIB bestanden), eventueel kun je de animatie in C programmeren. In de distributie van BMRT zit ook de include directory en de nodige libraries. Deze bevatten functies om het RIB bestand naar stdout (standaard uitvoer) te sturen. Beide methoden zijn volledig identiek: WorldBegin in een RIB bestand komt overeen met RiWorldBegin() in een C programma (om hier meer over te leren, zie Renderman for Poets, deze is te vinden in de doc/ directory.
In het volgende artikel gaan we een klein object modelleren, dit zullen we doen in C, zodat het later makkelijk geanimeerd kan worden en zo worden we gelijk een bekend met de library. Het kleine object voor de animatie zou de Linux pinguïn kunnen zijn, of Bill Gates (of beide en laten we de pinguïn de andere roosteren... :)
:)