Sneeuw, regen en nog meer ongemakHet was vandaag een echte zomerdag. Wiedes dus dat we dit keer voor de cursusavond een minder benauwde en koelere plek uitzoeken. We gaan buiten zitten en doen het dit keer maar zonder computer en beeldscherm. Aan het eind zal ik met iedereen tegelijk wel eventjes de demo's van deze keer bespreken in het bedompte zaaltje. Hoe komt het toch dat als het warm en zomers is men gaat werken aan winterse beelden zoals Tatjana deze week? Ze komt met de vraag: 'Hoe maak je sneeuw?'. Heel simpel zo'n vraag, maar beantwoorden dat is andere koek. Zoals altijd vraag ik mij in deze moderne tijden af: 'wie heeft dit al eerder bij de hand gehad?' want met behulp van Internet kan je de meest vreemde gegevens achterhalen. En ook dit keer dus. Zoekcriteria met 'povray' en 'snow' leverden op een verwijzing naar de site van Paul T. Dawson. Zoals wel vaker hoeven de cursisten niet onder de indruk te zijn van mijn brede kennis: gewoon weten waar en hoe je moet zoeken. De rest is: wat Engelse tekst lezen, wat voorbeelden nazien en wat zelf proberen. Dus Tatjana weet wat haar te doen staat: even aandachtig luisteren en dan thuis de rest van het materiaal bestuderen. (red.: de vermelde teksten en software zullen gezet worden op de disk behorende bij deze uitgave van het tijdschrift.) Sneeuw Laten we beginnen met het maken van sneeuwvlokken. Het eerste wat ons opvalt als we een sneeuwkristal bekijken is dat het zo wondermooi regelmatig is opgebouwd. Er is een duidelijk patroon, maar de uiteindelijke vorm die het patroon aanneemt kan heel wisselend zijn. De grondbeginselen van het construeren van een sneeuwkristal zie je een sneeuwvlok wordt opgebouwd uit driehoeken. Vijf driehoeken worden 6 maal geroteerd. Een set van 5 op 'random' manier geconstrueerde driehoeken worden 6 maal geroteerd. Dan krijg je een radiale figuur met maar liefst 30 driehoeken. Helaas zal men in het tijdschrift de kleuren van de driehoeken niet zien. Met grijstinten alleen is het lang zo goed niet zichtbaar. Met wat sleutelen aan de parameters en de startwaarde voor de randomreeks kan je kristallen krijgen zoals er wat zijn afgebeeld. Het is verbazingwekkend wat een verschillen je kan krijgen. Wat je nu moet doen is die sneeuwvlokken in je scene opnemen. Je moet ze dus een beetje distribueren. Er zijn voorbeelden beschikbaar waarbij je kan zien hoe dat moet. Leuk is het voorbeeld - lees de povray source er maar eens goed op na - van de sneeuwvlaag. Maar pas op: zo gedetailleerd gemaakte sneeuwvlokken in grote aantallen aanwezig in je scene vreet geheugen in de computer. Ik kan het niet nalaten om jullie te laten zien hoe de bedenker van dit sneeuw-pakket zelf een scene ermee heeft gemaakt. Je kan een probleem krijgen wanneer de camera midden in vallende sneeuw staat. Sneeuwvlokken dicht bij de lens zijn dan duidelijk zichtbaar en dan zal je zien dat ze gauw te groot zijn en best wel grof in elkaar zitten. Een andere zaak is dat een beetje scene al gauw 100.000 sneeuwvlokken kan tellen. Zou je een sneeuwvlok als een object behandelen dan loopt de rendertijd extreem op. De oplossing die hier gekozen is is: werken met driehoeken. Die kan je in een 'mesh' plaatsen waarin alleen de hoekpunten van driehoeken genoteerd worden. Dat spaart geheugenruimte en je kan b.v eerst een kleine mesh maken (ongeveer 1 Kb groot om in het geheugen te noteren) met een paar honderd sneeuwvlokken en zo'n mesh met wat draaien en schuiven herhaaldelijk gebruiken. Het gevolg is dat een complete scene zoals in dit voorbeeld na een dagje rekenen (640 x 480 pixels) klaar is. Zouden we een sneeuwvlok als een object behandelen dan zou het weken kunnen duren! Bomen Een vorige keer heb ik het gehad over het maken van bomen. Er waren toen diverse pakketten bekeken o.a. van Paul T. Dawson (van de sneeuw van daarnet). Na wat zelf uitgeprobeerd te hebben moet ik zeggen dat zijn bomen goed bruikbaar zijn. Op zijn homepage stond een afbeelding van een 'gewone' stereotype boom. Volgens zijn opgave waren er 102.400 bladeren aan 512 kleine takjes die elk op hun beurt een 'triangle mesh' dragen met 200 bladeren. Elk blad bestaat uit een driehoek en twee driehoeken die het blad verder verbinden. Hij had 4 Mb aan geheugen nodig voor de scene en met de anti-alias aan heel veel uurtjes rekentijd. U ziet het naar ik hoop een beetje een gewone boom met ruim 100.000 bladeren Voor de mensen die zich afvragen 'Hoe doe je dat nu?' is hier een listing: #declare One_Leaf = mesh { #declare A = 1 #while ( A <= TREE_MESH_SIZE ) // Calculate random location for first point. #declare X1 = ( rand (TREE_RAND) * 2 ) - 1 #declare Y1 = ( rand (TREE_RAND) * 2 ) - 1 #declare Z1 = ( rand (TREE_RAND) * 2 ) - 1 // Move a little way from *first* point. #declare X2 = X1 + ( rand (TREE_RAND) * 0.6 ) - 0.3 #declare Y2 = Y1 + ( rand (TREE_RAND) * 0.6 ) - 0.3 #declare Z2 = Z1 + ( rand (TREE_RAND) * 0.6 ) - 0.3 // Move a little way from *first* point. #declare X3 = X1 + ( rand (TREE_RAND) * 0.6 ) - 0.3 #declare Y3 = Y1 + ( rand (TREE_RAND) * 0.6 ) - 0.3 #declare Z3 = Z1 + ( rand (TREE_RAND) * 0.6 ) - 0.3 // Make the "leaf" triangle. triangle { <X1, Y1, Z1>, <X2, Y2, Z2>, <X3, Y3, Z3> } // Make the "branch" triangles. triangle { <X1, Y1, Z1>, <0, 0, 0>, <0, 0, 0.1> } triangle { <X1, Y1, Z1>, <0, 0, 0>, <0.1, 0, 0 > } #declare A = A + 1 #end } // End of mesh. Op deze manier krijg je een vorm die wel wat op een blad met steeltje lijkt. Je hebt een houvast (punt <0,0,0> en je kan bij gebruik het mesh verschuiven en roteren. Zo krijg je (van een afstand gezien) heel verschillende bladeren. Een heel groot voordeel van de PTD-tree manier is dat je door met driehoeken te werken i.p.v. met objecten als eindvormen aan takken je verschrikkelijk veel tijdwinst hebt bij het renderen. Maar beste mensen, moeten we nu zo nodig echt lijkende bomen hebben? Kunnen we de fantasie niet een ietsje verder oprekken in plaats van bezig blijven met wat we al eens gezien hebben? Ja toch? Een wat bijzondere boom maar toch best artistiek verantwoord dit plaatje gemaakt door P.T. Dawson zie je een boom die - je zou het niet zeggen - bijna hetzelfde is opgebouwd als de normale boom van daarnet. Maar inplaats van een mesh van driehoeken als bladeren zijn er nu bolvormige vormsels. Let op de manier hoe de takken zich vertakken. Om de fantasie wat te prikkelen geeft ik hier ook een afbeelding van Paul. Wat zou je zeggen van een landschap met dergelijke plantjes? Waarbij hij experimenteert met de aan/uit knop van de Branches_On_End_Flag. Zet je die nl. aan dan verschuiven alle zijtakken naar het eind van de tak. Je ziet dat in de linker boom gebeuren. Doe je dat niet dan worden de zijtakken afgesplits volgens een regelmaat: en soort wenteltrap-effect. De twee bomen in kwestie zitten alsvolgt in elkaar: een stam met daaraan een (1) grote zijtak en daar weer een zijtak aan. Dan zitten er 15 kleine takjes aan de laatste vast. Regen en drup Eigenlijk is het logisch: nu we een vraag over sneeuw gehad hebben krijgen we een vraag over regendruppels en hoe je de diverse effecten moet modelleren. Ik ga het niet hebben over speciale optische grappen zoals een regenboog of druppels die de omgeving liggen te weerspiegen, waar de lens doorheen kijkt enz., nee gewoon het effect van vallende regen. Normale druppels in een normaal tempo. Dat laatste is natuurlijk figuurlijk bedoeld want we doen in deze club niet aan animaties. Per slot van rekening hebben we op zijn hoogst een snelle TT tot onze beschikking en geen super-Intel 500MHz rekenmonster. Hebben we een scene met regen dan zijn er de volgende dingen te onderscheiden:
Stel dat we regendruppels een natuurlijke vorm geven: de druppelvorm of voor het gemak iets dat daar veel op lijkt: een bolvorm. De regen zal er dan raar uitzien: we zien bolletjes in de scene zweven als ze vlak voor de camera hangen. Als wij met ons oog naar regen kijken dan bewegen de druppels zo snel dat we ze niet zien: bewegingsonscherpte maakt dat we een streepje vallend water zien. Dat effect hebben we ook als we een waterval fotograferen: met een belichtingstijd van 1/1000 seconde is alles bevroren en ziet er raar uit: met een belichtingstijd van 1/30 seconde wordt bewegend water onscherp en ziet het er echter en bewegelijker uit op de foto. Op mijn vraag in de PovRay newsgroup of iemand al eens regen gemaakt had, of dat ik het zelf moest gaan uitvinden kwam een reactie van Glenn McCarter dat hij een scene gemaakt had waarin regen zat. Het heette 'cinema' en was enige tijd geleden een prijswinnaar in de doorlopende Povray wedstrijd voor mooie plaatjes. Ik zal zijn vondsten hier bespreken. Regendruppel Hoe maken we nu een regendruppel? Dat zien we in de listing #declare BT = 1.01 // Blob Threshold #declare BRF = 1.0 // Blob Radius Factor #declare BSF = 1.0 // Blob Strength Factor #declare RainDrop = blob { threshold BT sphere { // main body <0,0,0>, BRF*2.0,BSF*1.08 scale <1,1,2> translate <0,0,0> } cylinder { // upper pull <0,0,0>,<0,0,4> BRF*1.0, BSF*1.00 scale <1.0,1.0,1.0> translate <0,0,0> } // texture { IORWater } // texture { BWhite } texture { Water } scale .14 translate <0,0,0> } We werken met een blob die we verbinden aan een cylinder. Dat kan sinds we een nieuwe (versie 3.1) Povray hebben. Nog even voor de duidelijkheid: met een blob krijg je vloeiende organische vormen. Maar dan moet je wel de parameters goed instellen. Dat gebeurt hier. De 'treshhold' waarde wordt door PovRay gebruikt om uit te vinden waar het oppervlak is. Hoe hoger deze waarde hoe dichter het oppervlak naar het centrum van je bol of cylinder kruipt. Verder zien we dat de bol gezet wordt in de oorsprong en een radius krijgt van 2.0. De bol heeft een extra eigenschap erbij: de 'Strength' die aangeeft hoe sterk het centrum van het object het oppervlak naar zich toe trekt (negative waarde) of van zich afduwt (positief). Hoe het oppervlak eruit gaat zien hangt van een samenspel van drie factoren af: de threshold van de blob in zijn geheel en de eigenschappen radius en strength van zijn samenstellende onderdelen. Bovendien zien we dat er niets op tegen is om elke sphere of cylinder ook nog eens met een 'scale' op te zadelen. Onze regendruppel heeft dus een kop met een staart erachter. Zo'n vorm geeft de indruk van een vallende voorbij flitsende regendruppel. Bij gebruik moet je een heleboel regendruppels in je scene plaatsen. Dan loopt je rekentijd hard op met veel blob -objecten: regen kost rekentijd. Je doet er goed aan om rekening te houden met de windrichting: de druppels moeten in de goede richting wijzen. Het is onzin om je hele scene te vullen met regen want dankzij het coulissen-effect kan je gewoon eeen box vol regen voor de camera zetten. Vallende regendruppels veraf zie je niet individueel en door een mistig neveleffect kan je regen in de verte nadoen. Je moet bij toepassing van dit voorbeeld in de eigen scene wel eventje de schaal van het geheel aanpassen. Het is ook verstandig om de regen eerst apart in een scene te zetten. Vandaar die uit-gecommentarieerde 'texture {BWhite}'. #declare BWhite = texture { pigment { color rgb<1.3,1.3,1.3> } normal { bumps .5 scale <.4,.4,.6> } finish { ambient .1 } } Hang je een helder lichtje in de scene dan zie massief aandoende heldere regen, ideaal voor testdoeleinden maar weinig bruikbaar in echte scenes. Daartoe moet de druppel andere eigenschappen hebben zoals in de listing #declare Water = texture { pigment { color rgbf<1,1,1,.93> } // pigment { // color rgb<1,1,.1> } // test normal { bumps .5 scale <.4,.4,.7> } // finish { ambient .02 // refraction 1 ior 1.33 } // test with no reflection // finish { ambient .02 // refraction 1 ior 1.33 // reflection .08 } finish { ambient .02 specular .9 roughness .002 refraction 1 ior 1.33 reflection .08 } // added specular We zien dat er heel wat moet worden opgegeven om een beetje lijkend vallend water te krijgen. Het water moet van zichzelf geen kleur hebben en doorzichtig zijn. Vandaar die opgave van rgbf (f!!) met f voor filtering van doorvallend licht. Er wordt maar een beetje licht geabsorbeerd door het water. Het uiterlijk van de druppel wordt dus voor een groot deel bepaald door de eigenschappen van het oppervlak. Ten eerste wat bobbels (bumps) om via lichtreflectie het oppervlak te zien. Dan moet het oppervlak wat glimmende eigenschappen krijgen via een 'finish'. Met de hoge waarde van 'specular' krijgen we in het centrum van eventuele glimlichten veel helderheid en een glimlicht zal vanwege de lage waarde van roughness ook heel kompact en plaatselijk blijven. We zorgen dat al het opvallend licht (de refraction 1) evensterk wordt teruggekaatst (spiegeleffect). De brekingsindex ior geeft aan wanneer (onder welke hoek t.o.v. het oppervlak) een invallende lichtstraal nog volledig wordt gereflecteerd en wanneer die door het oppervlak heen breekt en het object binnen gaat. De lage waarde voor 'reflection' geeft aan dat objecten van de scene zelf zich nagenoeg niet weerspiegelen in de druppel. Een iets andere definitie voor ons vallend water kan zijn: #declare IORWater = texture { pigment { color rgbf<1,1,1,.7> } normal { bumps .5 scale <.4,.4,.6> } finish { ambient .02 refraction 1 ior 1.33 reflection .4 } } Deze vorm van water trekt zich vanwege 'reflection' wat meer aan van zijn omgeving. Maar pas op, want voordat je het weet lijkt het water sterk op roestvrij staal! In het blikveld van de camera hoeven deze luxe uitgevoerde regendruppels niet in grote getale aanwezig te zijn. Een handjevol statements om een handjevol druppels te krijgen is voldoende. Je kan ook het karakter van de regenbui een beetje bepalen. Zoals (weer een voorbeeld): // object { RainDrop // scale 4 // translate <0.6,-1,0> } // raining // object { RainDrop // scale 4 // translate <-2.6,-1,0> } // raining // object { RainDrop // scale <1,1,2> // translate <-1.2,-1,-1> } // pouring // object { RainDrop // scale <1,1,4> // translate <-1.9,-1,-2> } // sleeting Is de regen wat verder van de camera verwijderd dan kan men vaak prima regen krijgen met simpele druppels. Als volgt wordt het gedaan door Glenn McCarter. #declare RoundDrop = sphere { <0,0,0>,.1 texture { Water } } Maar je moet natuurlijk een flinke scheut van die druppels in de scene mixen. Daarvoor heb je programmalusjes nodig zoals b.v. #declare RS = seed(12345) // pick a random seed number #declare RainScale = 1 // elongation of the drops #declare RainXAngle = 10 // tilt of the rain #declare RainYAngle = 0 #declare RainX = 10*Feet // raindrops go in this box #declare RainY = 10*Feet // #declare RainZ = 10*Feet // #declare RainShower = union { #declare DropCount = 1 #while ( DropCount < NumDrops ) object { RainDrop scale <1,1,rand(RS)*RainScale+RainScale/2> rotate <RainXAngle,RainYAngle,0> translate <rand(RS)*RainX, rand(RS)*RainY, rand(RS)*RainZ> } #declare DropCount = DropCount + 1 #end } We zien dat de auteur een voorkeur heeft met het werken in oude Engelse maten. In de praktijk blijkt het lastig om deze doos met waterdruppels goed in je scene te zetten. De truc is dan om bij wijze van test te doen: #declare RainBlock = // for testing box { <0,0,0>, <RainX, RainY, RainZ> texture { pigment { color rgb<.5,.4,1.0> } finish { ambient .3 } } } En dit object in je scene te plaatsen. Om de druppels duidelijk massief zichtbaar te krijgen moet je ze even een ander texture geven. Trouwens, deze truc is handig voor meer dingen. Maar ik zie dat het langzamerhand tijd is geworden voor de koffie en dat een paar mensen nodig moeten plassen. Zometeen gaan we verder. Plassen Een volgende zaak waar we te maken mee krijgen is dat als het regent er plassen op de grond komen. Die versterken ook het 'het regent' - effect. Maar hoe maak je nu plassen? Laten we ons eerst om de vorm bekommeren. Die is plat en de rand verloopt meestal vloeiend. Dus een sphere die je plat drukt met een scale ontdoet al direct het plasje van zijn rondheid. Om het wat echter te maken (het blijft anders toch teveel herkenbaar als een ellips) moeten we naar de blob-vorm zoals b.v. #declare Puddle = blob { threshold BT sphere { // main <0,0,0>, BRF*9.0,BSF*2.0 scale <1,1,1> translate <0,0,0> } sphere { // big ext -Y <0,0,0>, BRF*3.0,BSF*2.0 scale <1,1,1> translate <-1,-4,0> } sphere { // little -y <0,0,0>, BRF*4.0,BSF*1.0 scale <1,1,1> translate <-4,-7,0> } sphere { // ext -x <0,0,0>, BRF*3.0,BSF*0.3 scale <1,1,1> translate <-5,1,0> } texture { Water } scale <1,1,.08> translate <0,0,0> } Hierin worden vier bollen genomen, iets ten opzichte van elkaar verschoven (zie maar: de translate van de bollen), en wat verschillend in grootte. De hele blob wordt ten slotte plat geslagen (zie scale <1,1, 0.08 > ) en als texture gebruiken we het eerder beschreven Water. Aangezien het uiterlijk van een plas zo sterk afhangt van de omgeving kan je zoals aangeven de 'finish' van de plas voor testdoeleinden veranderen. Moeilijker wordt het als de plas ook nog eens verstoord wordt door druppels die erin vallen of windvagen die rimpelingen veroorzaken. Je moet dan diverse textures tegelijk gaan gebruiken. Eentje b.v. met kleine bobbels en eentje met bobbels die een golvend karakter hebben. Ik geloof dat we voorlopig genoeg weten om met regen en plassen wat te doen. Er is natuurlijk nog veel meer te vertellen. Bijvoorbeeld hoe je druppels moet modelleren die in diverse staten van afdruipen zijn van een nat randje. Je kan dat prima modelleren met blobs: alsof die ervoor gemaakt zijn. Ik kan het niet nalaten om een listing te geven van een druppel die bijna los laat en op het punt staat om te vallen. #declare AboutToDrip = // just ready to separate blob { threshold BT sphere { // lower body <0,0,0>, BRF*1.6,BSF*1.6 scale <1,1,1.0> translate <0,0,0> } sphere { // upper body <0,0,0>, BRF*1.6,BSF*1.3 scale <1,1,1.0> translate <0,0,2> } texture { Water } scale <.2,.2,.3> translate <0,0,-.5> } Let wel: we werken nog steeds in hetzelfde Britse maatsysteem van daarnet. Maar het gaat om het principe. Voor een lang uitgerekte druppel kan je werken met twee bollen met er tussen een cylinder. Dat kan iedereen zelf uitvogelen. Brekingsindex Soms is het lastig voor gewone mensen om te weten te komen wat de brekingsindex van iets is. Toch moet je dat vaak weten in PovRay zeker als je met spiegelende en doorzichtige voorwerpen gaat werken. Ik geef hier een stel al vaker gevraagde stoffen. Eerst wat vaste stoffen en kristallen: Flint_Glass_Ior = 1.710 Amber_Ior_1 = 1.546 Calcite_Ior = 1.600 Crystal_Ior = 2.000 Diamond_Ior_1 = 2.470 Ice_Ior = 1.309 Olivin_Ior_1 = 1.670 Sapphire_Ior = 1.700 en wat vloeistoffen: Alcohol_Ior = 1.329 Water_20_C_Ior = 1.333 Carbondisulfide_Ior = 1.630 en tot slot Polystyrene_Ior = 1.550 Gum_arabic_Ior = 1.480 Gelatin_Ior = 1.520 Aloe_Ior = 1.619 Slotwoord De vorige keer heb ik gehad over 'spiral'. Ik fris het geheugen nog even op: we wilden een schoef maken en hoe moesten we de draad erop tappen? Toen stipte ik aan dat je met het patroon 'spiral' (ingebouwd in PovRay)) losgelaten op de oppervlaktenormaal je als het ware diepe groeven kon zien (die er niet echt zijn). Mooi gezichtsbedrog. Nu komt Jacob met een file met de naam 'spiral' maar dat gaat over iets heel anders. Namelijk hoe je wenteltrappen moet maken. Om de nieuwsgierigheid te bevredigen zal ik het op de disk erbij zetten. Vanwege het mooie weer houden we de cursuspraat vanavond kort. Gewoon lekker buiten zitten en luisteren naar de zingende vogels zou ik zeggen. Piet Vogelaar Copyright © Rein Bakhuizen van den Brink Last updated on 1 september 1999 |