Home Creatief met POVRay Hoofdzaken Toch maar Versie 3 gebruiken?
 

Het uiterlijk der dingen

In de vorige aflevering ben ik in vogelvlucht langs de belangrijkste hoofdzaken gemanoeuvreerd.In deze cursus hebben we tot nu toe wel wat gepraat, een hoop dingen op eigen gelegenheid bekeken, maar nog niks zelf gemaakt. Daar gaan we wat aan doen. We maken een testopstelling om met eigen ogen te zien wat er allemaal met de oppervlakte van virtuele voorwerpen te doen is.

Een oppervlakte moet natuurlijk een kleur hebben want anders valt er niets te zien. Maar er zijn meer eigenschappen aan een oppervlak te onderscheiden dan een kleur. In de eerste plaats hoeft een kleur niet egaal te zijn: marmer en hout zijn voor de hand liggende voorbeelden. In de tweede plaats hoeft het oppervlak niet mathematisch plat te zijn. Bubbeltjes in allerlei vormen en maten kunnen voorkomen, denk maar aan een perzik en een citroen. Dit laatste visuele voorbeeld brengt een derde eigenschap aan het licht: hoe glimmend is het oppervlak? Een citroen heeft een glimmend waslaagje. Ook gevernist hout en, in mindere mate, gepolijst marmer glimmen de wereld toe.

Eigenschappen van voorwerpen verbinden we ook wel aan het materiaal. Je hebt metalen voorwerpen zoals glimmend chroom of geslagen roodkoper met hun typische 'metalen' uiterlijk. Dan is er de categorie van steenachtigen zoals beton, graniet en marmer en ook is het zinvol om de doorzichtige voorwerpen apart te zetten. Bij deze laatste denken we aan glazen bollen of lenzen, heldere of gekleurde gelatinepuddingen, waterijs enz. die iets met lichtbreking doen en/of licht doorlaten, verstrooien e.d.

Gewoon alle voorwerpen eventjes een verfje geven zondere toeters en bellen is heel eenvoudig en zo is het berekenen ook: het plaatje is vlug klaar. Maar heb je met veel moeite een lens gemaakt van doorzichtig marmer met rode aders, dan is dat ook voor Povray een hele toer om door te rekenen: geduld dient bewaard te worden. Maar dat had je al want anders was je nooit aan die ingewikkelde precieze constructie begonnen, nietwaar?

Testopstelling

We gaan niet al te veel vormgeven. Met wat basale vormen moeten de kenmerkende verschillen tussen oppervlakten zichtbaar gemaakt worden.

Ik stel me het volgende voor: links in beeld ligt een doos met een paar happen eruit. Dan kan je zien dat 'solid finite primitives' ook een inhoud hebben. Ook kan je de verschillen door de invalshoek van het licht beoordelen. Het is ook handig om een hol oppervlak te hebben voor het creëren van spiegelende effecten. Verder ligt er op de voorgrond een bol voorwerp, zeg om het simpel te houden, een bol met een cylindervormige holte. Dat is leuk voor het zien van de effecten van lichtbreking. Tot slot is een geleidelijk verlopend oppervlak handig: een kegel is in dit opzicht inzetbaar.

Constructie

We beginnen ons de goede gewoonte eigen te maken om alles eerst in het nulpunt op te bouwen en daarna met rotatie gevolgd door translatie op de juiste plaats te zetten. Tegelijk gaan we ons wennen aan het zo veel mogelijk declareren van dingen. Zeker in een testopstelling is dat handig, maar ook zonder dat is het aan te bevelen.

Aangezien we ons met kleur en oppervlaktestructuur gaan bezig houden doen we een 'include' van twee files die veel kant en klare zaken bevatten. Ik zou zeggen, zoek ze maar eens op in de folder geheten 'include' en bekijk in een editor wat er allemaal in zit.

Listing 1

#include "colors.inc"
#include "textures.inc"


#declare box0 =
 difference {
    box { <0, 0, 0>, <4, 1, 2> }
    cylinder { <0.2, -0.1, -0.2>,
                 <0.2, 1.1, -0.2>, 1}
  }


#declare prisma =  intersection {
   plane {-x, 0 rotate <0, 60, 0>}
   plane { x, 1 rotate <0, -60, 0>}
   plane {-z, 0}
   plane { y, 1.1}
   plane {-y, -0.1}
  }


#declare box1 = difference {
   object {box0 }
   object {prisma translate <3,0,-0.3>}
 }


#declare bolhol = difference {
   // Sphere object
   sphere {< 0, 0, 0>, 0.5}
   cylinder {<0,-0.1, 0>,<0,1.1,0>,0.3}
 }


// het uiterlijk der dingen
// en soms ook het innerlijk
#declare bolkleur = texture {
    pigment { Green }
    finish { ambient 0.5 }
    }
#declare kegelkleur = texture {
    finish { ambient 0.5 }
    pigment { Red }
    }
#declare dooskleur = texture {
    finish { ambient 0.5 }
    pigment { Blue }
    }


cone { <0, 0, 0>, 0.7
       <0, 1.5, 0>, 0
      translate  <3, 0, 3>
      texture { kegelkleur }
 }


//bol plaatsen
object { bolhol
        translate <2, 0.5, 2 >
        texture { bolkleur}
 }


//doos plaatsen
object { box1 rotate <0, -50, 0>
    translate <0, 0, 3>
    texture { dooskleur }
    }


camera {
   location  <2, 2, -3>
   direction <0, 0, 2>
   up <0, 1, 0>
   right <1.33, 0, 0>
   look_at   <2, 1, 3>
 }


light_source { <8, 4, 3>
             color White
 }


// grondvlak
plane { <0, 1, 0>, 0
   pigment {checker
    color Red color Blue}
}


background { color SkyBlue }


In listing 1 is te zien hoe we aan onze doos beginnen te bouwen. De grootte (l x b x h) is 4 bij 2 bij 1. Voor het gemak zetten we de linker onderhoek in de oorsprong. Vervolgens gaan we met een cylinder een ronde hap uit die hoek nemen. We doen dat met een 'difference' waarbij in de beschrijving dus het tweede voorwerp wordt afgetrokken zullen we maar zeggen van het eerste (de doos). De volgende stap is een driehoekige hap uit de doos te nemen; een soort taartpunt. Ik heb gekozen voor een prisma.

Maar ja, ik kon die nergens vinden in de verzameling van voorgekookte vormen, dus ben ik maar gaan spieken bij anderen. Zo vond ik wat voorbeelden van veelvlakken. Aan de hand daarvan heb ik de definitie van het prisma gemaakt. Ik zal het verduidelijken.

Vlakgebruik

Een vlak heeft een voorkant en een achterkant of een bovenkant en een onderkant. Een vlak is oneindig groot maar je kan je wiskundig indenken dat het toch nog sluitend gebogen is. Je kan dan spreken van een binnenkant en een buitenkant. Dat is wat we in Povray ook doen. Uit onze schooltijd kunnen we ons allemaal wel herinneren dat er drie punten nodig waren om een vlak vast te leggen. Vandaar dat 3-potige tafetjes nooit wankelen maar dit ter zijde. Bij eenzelfde vlak kan je een heleboel groepjes van 3 punten verzinnen die ook in het vlak liggen. Er is dus emplooi voor een genormaliseerde definitie van de positie van een vlak. En, hoe kan het ook anders, dat doen we met een wiskundige 'normaal'. Die normaal kan je zien als een fictieve pijl die loodrecht staat op het vlak. Wil je nu een vlak hebben dat horizontaal loopt op een hoogte van 1 dan beschrijf je die als:

plane { <0, 1, 0>, 1 }

De normaal (de pijl, weet je wel) wijst in de positieve richting van de y-as. Er bestaat een afkorting voor: de naam 'y' in Povray. Om nu een prisma af te grenzen moet je dus zorgen dat de buitenkanten van de vlakken goed liggen. Doe je dat verkeerd dan krijg je geen gesloten voorwerp.

Dus plane {y,1} is het bovenvlak, plane {-y,0} is het ondervlak en plane {-z,0} is de ene zijkant. Er moeten dan nog twee vlakken gezet worden die op de juiste manier gedraaid moeten worden. Ook hier weer: even nadenken over waar de buitenkant zit en hoe de draairichting moet zijn. Pak in gedachte de y-as met de linkerhand beet en met duim naar boven in de positieve richting. De rest van je vingers kromt zich in de positieve draairichting. Het eerste vermelde vlak keert zijn buitenkant naar links (negatieve x-richting) en krijgt een positieve draai om de y-as. Het tweede vlak heeft zijn buitenkant in de positieve x-richting wijzen en krijgt ook een draai om de y-as maar nu in tegengestelde richting. De opdracht 'intersection' knoopt de vlakken zo bij elkaar dat je een prisma overhoudt. In de declaratie van box1 zien we het verschoven prisma een hap nemen uit box0. Hier zien we ook hoe we vooraf gedefinieerde voorwerpen gebruiken. We zeggen 'object {naam}'. Let erop dat ik tijdens het samenstellen de objecten die een hap uit de doos nemen, net een beetje groter (lopend van -0.1 naar 1.1) heb gemaakt dan de hoogte van de doos (0.0 naar 1.0). Dat is gedaan, omdat er anders rare effecten kunnen optreden. Tijdens berekeningen wordt afgerond (of liever gezegd met eindige nauwkeurigheid gewerkt) en dan kan het voorkomen dat punten op een 'gezamenlijk' oppervlak de ene keer aan de ene en de andere keer aan de andere deelnemer wordt toegerekend. En dat geeft ongewenste resultaten.

Nog 2 objecten

Om zaken als glimlichten, lichtbreking door transparante vormen e.d. te bekijken is een bol een handig ding. Om ook het effect van holle ruimten te bestuderen is er een holle cylinder in de bol gezet op de bekende manier: met een 'difference'. Nu hebben we met de simpele kegel meegeteld drie objecten die we gaan gebruiken om te experimenteren met oppervlaktestructuren (textures).

Met een #declare kunnen we veel meer dingen doen dan objecten beschrijven; eigenlijk kunnen we van alles declareren. Maar bedenk wel dat onze Povray declaratie een ander ding is dan een declaratie in de computertaal C. Daar is een declaratie een soort makro die tekst-expansie doet. Met een declaratie geef je in C als het ware een verkorte schrijfwijze op. Dat is in Povray echt niet het geval! Hier zijn declaraties echt om het met een mooi woord te zeggen 'object-georiënteerd'. Zie maar in de volgende declaraties waarin we het oppervlak van elke figuur apart vastleggen. Wat je declareert krijgt een type mee. Dat is hier 'texture'. Ga je de naam later gebruiken dan moet je weer 'texture' opgeven want anders komt er protest. Je wordt dus bewaakt, zodat een verkeerd gebruik niet kan. Als het ware ligt het 'type' vast.

De enige uitzondering is bij het declareren van virtuele voorwerpen. Daar gebruik je 'object': terwijl box0 bijvoorbeeld als een difference is geconstrueerd spreek je bij gebruik toch over 'object {box0}. Wat nadenken zal de onderliggende logica wel begrijpelijk maken, maar nadenken hoeft niet: gewoon het recept opvolgen is een acceptabele handeling.

Textures

In deze listing heb ik het minimaal nodige opgenomen voor de texture van de 3 vormen. Ze hebben allemaal een egaal verfje in een simpele kleur en bovendien hebben ze redelijk veel 'ambient'. Dit zal ik uitleggen. In de normale wereld komt licht van overal vandaan: we spreken over diffuus licht. Als de zon schijnt dan is het niet totaal duister in de schaduw. Helaas is dit lichteffect niet met raytracing te verwezelijken. We nemen onze toevlucht tot een truc. Met 'ambient' zorgen we dat elk oppervlak is het ware toch licht uitstraalt. Geven we niks op dan is er een default actief: ambient 0.1 en dat is weinig.

We kunnen onze defaults ook veranderen met b.v.

#default texture { finish { ambient 0.5}}

wat ons drie apart van elkaar staande regels tekst bespaart. Veel makkelijker is het verspreide licht te behandelen in Povray versie 3. Daar bestaat een

global_settings { ambient_light 0.5}

waardoor het effect schijnbaar is losgekoppeld van de voorwerpen en als een lichtbron wordt behandeld.

Posities

Ik heb de camera en de voorwerpen zo geplaatst dat alles in beeld is. Ook valt een stukje van de kegel achter het bolletje. Natuurlijk is iedereen vrij om alles anders neer te zetten maar ik zou om niet in verwarring te geraken alleen maar de camera verzetten. Vaak zal je details willen zien en dan moet je er wel als het ware met je neus bovenop gaan zitten. Handig is het ook om op schaal een plattegrond te hebben want elke keer dat je de camera verkeerd plaatst ben je een hoop rekentijd kwijt aan een onbruikbaar beeld.

De scenebeschrijving van listing 1 is in afbeelding 1 te zien. Helaas in z/w, wat het niet al te duidelijk maakt.

Experimenteren

We kunnen nu gaan proberen hoe diverse textures er uit zien. Bedenk wel dat wat we ervan zien afhangt van de belichting. Laat ik elk geval, wat je ook doet met de belichting, de kleur wit zijn. Desnoods wat minder fel want Grey50 mag ook best; het is maar om het principe aan te geven.

Eenvoudige oppervlakten worden in zijn algemeenheid beschreven als

  texture {
    TEXTURE_IDENTIFIER
    pigment {..}.
    normal {..}.
    finish {..}.
    halo {..}.
    TRANSFORMATIONS
  }

Ik weet dat dit niet volledig is want in Povray versie 3 komen er heel wat meer mogelijkheden bij. Maar laten we het eenvoudig houden en eerst even naar het verfje gaan kijken. Ik vertaal 'pigment' met 'verfje' maar dat is onjuist. Een verfje zit aan de buitenkant en waar het hier om gaat is dat een pigment door en door is. Het zit ook binnenin voorwerpen. Dat blijkt b.v. bij de happen die uit onze doos zijn genomen. Die hebben ook kleur. Maar een egaal pigment is nogal saai en doods. Dat vond ik in eerste instantie ook van ons grondvlak en die heb ik als

// Floor plane
plane { <0, 1, 0>, 0
   pigment {checker
            color Red color Blue}
}

opgegeven wat een goed perspectief effect geeft. Je ziet trouwens ook dat ik een beetje gesmokkeld heb. De 'texture {...' is er niet. Dat kan omdat Povray tamelijk tolerant is bij het weglaten van evidente dingen. Maar je ziet: ik gebruik hier een texture identifier, nl. checker, waardoor ik een vierkant geblokt vlak krijg met scherpe overgangen tussen de twee gebruikte kleuren. Er zijn nog een paar anderen: brick b.v. ook met twee kleuren en hexagon met drie kleuren. Maar vergis je niet in deze patroontjes: ze zijn niet plat maar 'gevuld'. Zo bestaat checker uit een oneindige ruimte die gevuld is met kubussen die afwisselend een ander pigment hebben. Hier zien we weer een slordigheidje van Povray: in mijn voorbeeld geef ik 'colors' op terwijl ik eigenlijk 'pigment { color...' bedoel. Laat ik mijn vlak door die ruimte lopen dan krijgt het oppervlak het pigment dat heerst in de snijpunten met die ruimte. Voor een horizontaal vlak worden dat dus vierkantjes. Hoe ziet het oppervlak van een bol eruit, als ik die in de 'checkers-ruimte' zou plaatsen?

Wil je een horizontaal vlak met parallellogrammen dan moet het vlak dus het ruimtelijk patroon onder een hoek gaan snijden. Daartoe kan je het patroon zelf gaan verdraaien met

 rotate < ax, by, cz>

in elke gewenste richting.

We kunnen het grondvlak ook van een metselwerkje voorzien met

 pigment { brick
          pigment { Jade } ,
          pigment { Black_Marble }
         }

Je ziet dat je voor de vulling een pigment op geeft en niet een kleur. Ook dat is mogelijk. Wat betreft de afmetingen: steen met metselwerk is < 8, 3, 4.5 > en het cement heeft een dikte van 0.5. Om bruikbaar te worden moet er wat geschaald worden (met scale <0.01, 0.01, 0.01 > om alles 100 keer kleiner te maken) anders hebben we in onze afbeelding waanzinnig grote metselstenen. De eerst opgegeven kleur wordt voor het cement gebruikt en de tweede voor de steen zelf.

Natuurlijk hoeft het vullen van de ruimte niet op zo'n simpele manier te gebeuren. Er is heel wat over afgedacht en veel formules zijn ingebruik. Trouwens, de algemene mogelijkheden van een pigment zijn:

  pigment {
    PIGMENT_IDENTIFIER
    PATTERN_TYPE
    PIGMENT_MODIFIERS...
  }

Ook hier weer zijn een aantal veel gebruikte zaken voorgedefineerd voor ons. Zo bestaat er 'agaat' en 'bozo' en een heleboel hout- en steensoorten. Veel kant en klare steensoorten zijn te vinden in de file stones.inc.

Stel nu dat onze doos van massief hout is en in zijn lengterichting uit een stam is gezaagd. Op de kopse kant moet dan een concentrisch ringenpatroon (jaarringen) te zien zijn en op de andere zijden moeten nerven zichtbaar zijn. Nu zal de cursist vast wel begrijpen waarom ik happen uit de doos heb genomen.

Kleurovergangen

Vaak wil je de ruimte niet verdeeld hebben in scherp afgegrensde stukjes. Regelmatige kleurverlopen in 3 dimensies krijg je met b.v.

 pigment {
   gradient x
     color_map {
       [0.1 color Red]
       [0.2 color Yellow]
       [0.4 color Yellow]
       [0.6 color Blue]
       [0.6 color Green]
       [0.8 color Cyan]
       [0.9 color Brown]
      }
   }
 }

het type van het patroon dat we hebben gekozen heet 'gradient'. Die functie evalueert in de positieve richting van de x-as van 0.0 naar 1.0 en de kleur wordt dan als volgt bepaald: van 0.0 tot 0.1 is alles rood, van 0.1 tot 0.2 verloopt de kleur naar geel, tusssen 0.2 en 0.4 blijft de kleur hetzelfde (geel), de kleur verloopt verder van 0.4 naar 0.6 naar blauw toe en zodra we over 0.6 heen komen, verspringt de kleur plotseling naar groen die dan geleidelijk aan overgaat naar cyaan op 0.8. Het verloop gaat vervolgens naar bruin en blijft van 0.9 tot 1.0 dezelfde kleur. Eigenlijk is het veel beter om de 'color_map' gewoon te vergeten. Ook de kop boven dit stukje is foute boel. Het moet worden:

Pigment patronen

We moeten de verwarring tussen 'kleur in licht' en 'kleur van voorwerpen' zien te vermijden. Licht bestaat uit een aantal kleuren maar voorwerpen bevatten een pigment. Voortaan doen we dus dingen zoals:

 pigment {
   gradient x
   pigment_map {
     [0.3 wood scale 0.2]
     [0.3 Jade]
     [0.6 Jade]
     [0.9 marble turbulence 1]
   }
 }

Je ziet, zo kan je veel meer maar er is niks op tegen om gewoon eigenwijs 'color Brown' en zo te gebruiken. Helaas was men met versie 2 van Povray nog niet zover gevorderd in het onderscheidend vermogen van het verstand, dus daar is pigment_map nog onbekend.

Glimmer en glitter

Een oppervlak heeft heel wat meer nodig dan alleen maar een verdeling van pigmenten in patronen, verlopen enz. Maar raytracing staat juist bekend, omdat er zulke mooie realistische glimlichtjes, weerkaatsingen enz. mogelijk zijn. Hoe voegen we glimmer aan het oppervlak toe?

De simpelste is in de vorm:

 texture { pigment { color Yellow }
           finish { phong 1 }
         }

Het Engelse woord 'finish' betekent hier niet eindpunt maar glans. En wat is de phong van een oppervlak? Die bestaat niet want het was een meneer Phong die de rekenmethode bedacht heeft. Probeer het maar eens uit met de bol. Staan lichtbron en camera goed dan kan je een 'highlight' zien in de kleur van de lichtbron (en die is wit). Tegelijk lijkt de bol ook wat gladder. De sterkte van het glimlicht kan tussen 0.0 en 1.0 liggen. Er zijn ook andere manieren om blinkende gladheid en glans aan oppervlakten te geven. Daar kom ik later nog wel op terug.

Hobbeligheid

Het Engelse woord hiervoor is 'bumpiness'. Je begrijpt wel dat als je bobbels op het oppervlak wil aanbrengen, dat je dan heel wat wiskundige formules moet gebruiken en dat Povray heel wat af te rekenen heeft. Soms kom je daar niet onderuit als je b.v. een wateroppervlak met golvingen e.d. wil. Maar in de meeste gevallen voldoet een simpele methode die ons oog gewoon voor de gek houdt. Dit is de

 normal { bumps 0.1 scale 0.05 }

die je aan het texture toevoegt. Het eerste getal geeft de diepte van de hobbels. In ons geval 0.1 wat redelijk is op een bol met een radius van 0.5. De schaling geeft de bobbels een breedte van 0.05. Je begrijp wel dat er met de 'normaal' (zie een eindje terug in dit artikel) gestoeid gaat worden. Zet je hersens in wiskunde-mode en denk dat je een raakvlak aan een punt op het oppervlak maakt. Dat vlak heeft een 'normaal' in het raakpunt. Die staat als het ware ook 'loodrecht' op het gekromde vlak. Ga nu met de richting van die normaal knoeien, wanneer je gaat berekenen hoe het licht in het raakpunt moet worden. Doe dat veranderen van de normaal volgens een passende formule en je krijgt een bobbeleffect.

Gereserveerde woorden

adaptive        height_field      rgbf
agate           hexagon           right
agate_turb      iff               ripples
all             image_map         rotate
alpha           include           roughness
ambient         interpolate       scale
area_light      intersection      sky
background      inverse           smooth
bicubic_patch   ior               smooth_triangle
blob            jitter            specular
blue            lambda            sphere
bounded_by      leopard           spotlight
box             light_source      spotted
bozo            location          sturm
brilliance      looks_like        texture
bumps           look_at           tga
bump_map        mandel            threshold
bump_size       map_type          tightness
camera          marble            tile2
checker         material_map      tiles
clipped_by      max_intersections torus
clock           max_trace_level   translate
color           merge             triangle
color_map       metallic          turbulence
colour          normal            type
colour_map      no_shadow         union
component       object            up
composite       octaves           use_color
cone            omega             use_colour
crand           once              use_index
cubic           onion             u_steps
cylinder        open              version
declare         phase             v_steps
default         phong             water_level
dents           phong_size        waves
difference      pigment           wood
diffuse         plane             wrinkles
direction       point_at          x
disc            poly              y
distance        pot               z
dump            quadric

fallloff        quartic
filter          quick_color
finish          quick_colour
flatness        radial
fog             radius
frequency       raw
gif             red
gradient        reflection
granite         refraction
green           rgb




Volgende keer

De redactie vindt dit epistel nu wel lang genoeg. Het is weer mijn oude probleem: ik wil meer schrijven maar de ruimte in dit blad is voor mij beperkt. De volgende keer zal ik verder ingaan op het gebruik van nog meer complexe textures want we zijn er nog lang niet over uitgepraat. Ik zal verder een rondvraag doen bij de cursisten (m/v) om te zien hoe noodzakelijk het is om in deze cursus Povray versie 2 te gebruiken. Mijn eigen studie van de nieuwe mogelijkheden van Povray versie 3 maken mij steeds enthousiaster: soms loopt het kwijl mij in de bek.

Mocht blijken dat de meeste cursisten een harddisk hebben dan is de noodzaak om de oude versie te gebruiken niet meer zo dringend aanwezig. In dit verband wil ik nog wel eventjes een tip geven aan mensen die 4 Mb intern geheugen aan boord hebben maar die geen harddisk hebben of willen gebruiken: maak een RAM-disk aan! Dan kan je tijdens nachtenlange rekenklussen de harddisk (en de monitor) afzetten. Even ter verduidelijking: als je een harddisk die af staat, aan de ST hebt hangen dan kan je natuurlijk niet lezen/schrijven naar de harddisk maar, omdat de DMA-poort toch nog belast blijft, wil het gebruik van de floppydrive ook niet goed gaan (bij vele ST's). Maar lezen/schrijven naar een interne RAM-disk blijft goed functioneren!

Een heel belangrijke reden om versie 3 niet voor deze cursus te gebruiken is: de povray.gtp past niet op een gewone dubbelzijdige DD-floppydisk. Maar er bestaat al heel lang een comprimeerder DCSquish geheten die programma's kan comprimeren als uitvoerbare files. Tijdens het activeren pakt het programma zich dan in het geheugen uit. Op die manier is povray.gtp van ruim 880 Kb terug te brengen tot 444 Kb. En dan is alleen werken met een floppydisk geen onmogelijkheid. Ik heb niet getest hoeveel geheugen er tijdens dat uitpakken wordt gebruikt dus de methode kan nog tegenvallen als je maar 1 Mb aan intern geheugen hebt!

Piet Vogelaar


Copyright © Rein Bakhuizen van den Brink
Last updated on 1 september 1999
Home Creatief met POVRay Hoofdzaken Toch maar Versie 3 gebruiken?