Verderop in deel 1, waar we de kneepjes van de wereld hebben met Papervision3D, neemt deel 2 ons tafereel wat verder op. In dit afsluitende gedeelte leer je hoe je ronddraaiende kubussen met een 3D-bril naar de kijker springen.
Ik weet dat het daarboven staat dat deze tutorial gaat over Papervision3D in Flash, maar eigenlijk gaat het om het bedwelmen van je hersenen. We zullen je hersenen laten denken dat het naar een echt 3D-object kijkt, terwijl het feitelijk een 2D-afbeelding is.
Als u bekend bent met Papervision3D, kunt u dit volgen door elk project te gebruiken dat een scène, een camera en een kijkvenster heeft. Als dat niet het geval is, bekijk dan eerst deel 1 van deze tutorial, want ik ga verder vanaf waar we zijn gebleven. Dit is het soort ding waar we naartoe zullen werken:
Richt je vinger in de lucht en houd hem voor je neus op.
Bekijk het met alleen je rechteroog open, dan met alleen je linker. Zie hoe het van links naar rechts lijkt te springen, terwijl alles wat zich op de achtergrond bevindt nauwelijks lijkt te bewegen?
Je brein ziet deze verschillen tussen wat elk van je ogen ziet en gebruikt het om een volledige 3D-simulatie van de wereld om je heen te genereren. In jouw hoofd. Direct. Erg indrukwekkend!
Als we je hersens voor de gek houden, moeten we ervoor zorgen dat elk van je ogen een ander beeld ziet. Dus om te beginnen, laten we nog een "oog" (een andere camera) aan de scène toevoegen. Dit wordt gebruikt om de afbeelding voor uw rechteroog te maken, terwijl de afbeelding van de bestaande camera naar uw linkeroog wordt gevoerd.
Maak een nieuwe openbare variabele genaamd camera2...
public var camera2: Camera3D;
... en initialiseer het in de constructorfunctie Main ():
camera = nieuwe Camera3D ();
We hebben een andere viewport nodig om de uitvoer van de camera te maken, dus voeg het volgende toe:
public var viewport2: Viewport3D;
viewport2 = nieuwe Viewport3D (); viewport2.autoScaleToStage = true; // dit maakt de viewport zo groot als de stage addChild (viewport2);
(Ik haast me hier doorheen, omdat we het de laatste keer hebben behandeld.)
Onthouden, viewport2 zal leeg zijn totdat we er iets aan teruggeven. We hoeven hiervoor geen nieuwe renderer te maken; gebruik gewoon de bestaande twee keer. Dus, in Main (), neem deze code:
renderer = nieuwe BasicRenderEngine (); renderer.renderScene (scène, camera, viewport);
... en voeg een nieuwe regel toe om de tweede camera naar de tweede viewport te renderen, zoals zo:
renderer = nieuwe BasicRenderEngine (); renderer.renderScene (scène, camera, viewport); renderer.renderScene (scène, camera2, viewport2);
Doe hetzelfde in uw onEnterFrame () -functie, ook:
renderer.renderScene (scène, camera, viewport); renderer.renderScene (scène, camera2, viewport2);
Als je dit nu uitprobeert, dan zal het er hetzelfde uitzien als voorheen:
Maar dat is geen verrassing: enerzijds bevinden de twee camera's zich op exact dezelfde plaats!
Standaard worden camera's geplaatst op (x = 0, y = 0, z = -1000) - u kunt controleren door te doen trace (camera.x, camera.y, camera.z).
Van bovenaf gezien ziet de scène er als volgt uit:
Van de zijkant gezien, is het zo:
Om onze eigen ogen goed na te bootsen, zouden we onze tweede camera een klein beetje rechts van onze eerste moeten plaatsen:
Laten we het 50 pixels naar rechts verplaatsen en kijken wat er gebeurt. Zet dit in Main (), ergens nadat je de tweede camera hebt gemaakt:
camera2.x = camera.x + 50;
Test het nu en kijk wat je krijgt:
Het ziet er raar uit, maar het werkt duidelijk! Het gebied rond de kubussen is transparant in elke viewport, dus de eerste kan achter de tweede worden bekeken.
Het is handig om te kunnen kijken naar wat elke camera afzonderlijk ziet, dus laten we de ooganalogie verder nemen door ze "knipogen" te maken wanneer we klikken. Voeg eerst een gebeurtenislistener toe aan elk venster om de muisklikken te detecteren:
viewport.addEventListener (MouseEvent.CLICK, onClickViewport); viewport2.addEventListener (MouseEvent.CLICK, onClickViewport2);
Zet dat aan het einde van de Main () functie. Vergeet niet MouseEvent te importeren:
import flash.events.MouseEvent;
Voeg deze nieuwe functies toe aan uw code, buiten de functie Main () maar binnen de hoofdklasse:
openbare functie onClickViewport (mouseEvt: MouseEvent): void public function onClickViewport2 (mouseEvt: MouseEvent): void
Wanneer we op de eerste viewport klikken, moeten we deze onzichtbaar maken, terwijl de tweede zichtbaar wordt (en andersom wanneer we op de tweede klikken). Dus pas je event handlers aan zoals:
openbare functie onClickViewport (mouseEvt: MouseEvent): void viewport.visible = false; viewport2.visible = true; public function onClickViewport2 (mouseEvt: MouseEvent): void viewport.visible = true; viewport2.visible = false;
Probeer het:
Merk op dat je op een van de kubussen moet klikken; de transparante gebieden vuren niet af van een KLIK MouseEvent.
Je hebt een 3D-bril met "anaglyph" nodig; het soort waarbij elke lens een andere kleur heeft. Het paar dat ik gebruik heeft een gele lens in het linkeroog en een blauwe lens in het rechteroog (het ColorCode3D-systeem genoemd), maar andere kleurencombinaties zijn ook populair, zoals rood en cyaan.
Je kunt deze bril voor een paar dollar op eBay vinden: zoek gewoon naar 3D bril
U kunt er ook zelf een maken! André plaatste een opmerking bij het eerste deel van deze tutorial waarin hij uitlegde dat hij Tic-Tac-dozen met verschillende kleuren gebruikt om de zijne te maken. Genie!
Hoewel mijn voorbeelden worden gemaakt voor een gele en blauwe bril, zal ik proberen de principes uit te leggen, zodat je de jouwe kunt laten werken met de kleuren die je hebt. Het is een beetje lastig, dus plaats een reactie hieronder als dit verwarrend wordt!
Elke pixel op uw computer is als een groep van drie gloeilampen: één rood, één groen en één blauw.
Door de helderheid van elke "gloeilamp" aan te passen, kunnen we de kleur van die pixel wijzigen:
De lenzen in 3D-bril houden het licht van sommige van die lampen tegen. De blauwe lens in mijn bril blokkeert bijvoorbeeld het rode en groene licht van het bereiken van mijn oog.
Dus als ik dit beeld via mijn blauwe lens bekijk, kan ik het niet lezen:
Er komt geen licht uit het zwarte gebied omdat alle drie de lampen zijn uitgeschakeld. En geen licht bereikt mijn oog vanuit het groene gebied, omdat alleen de groene lamp is ingeschakeld en de blauwe lens dat filtert. Dus alles wat ik zie is een zwarte rechthoek.
Oké, als je dit zelf probeert, zou je merken dat dit niet helemaal waar is. Je lens is waarschijnlijk niet 100% puur blauw, dus het laat een beetje groen en rood licht door. Of misschien zijn de kleuren van uw monitor anders gekalibreerd dan de mijne, zodat de groene tekst een kleine hoeveelheid rood en blauw bevat. Om eerlijk te zijn, geldt hetzelfde voor mij - maar het maakt niet uit, zolang de tekst maar is hard lezen.
Ons doel is om het moeilijk te maken voor uw rechteroog om het beeld van de linkercamera te zien, en evenzo voor uw linkeroog en de juiste camera.
De blauwe lens is over mijn rechteroog, dus in theorie als ik al het blauw van de afbeelding van de linkercamera verwijder, kan ik het niet met mijn rechteroog zien.
Laten we in deze stap vervolgens het beeld van de linker viewport alleen rood en groen laten uitstralen; helemaal geen blauw licht. We kunnen dit doen met een ColorTransform. Deze zijn eenvoudig in te stellen; importeer eerst de klas:
import flash.geom.ColorTransform;
Maak vervolgens een nieuwe openbare variabele die een instantie van de klasse bevat:
public var leftViewportColorTransform: ColorTransform;
Maak nu deze nieuwe instantie in Main ():
leftViewportColorTransform = new ColorTransform ();
Vertel ten slotte aan Flash om deze ColorTransform op het kijkvenster van de linkercamera toe te passen:
viewport.transform.colorTransform = leftViewportColorTransform;
(Die laatste regel moet zijn nadat u de viewport en de kleurtransformatie hebt gemaakt. Het is waarschijnlijk het gemakkelijkst om het recht te zetten aan het einde van Main ().)
De SWF ziet er nog niet anders uit, omdat de ColorTransform standaard de afbeelding helemaal niet wijzigt.
We kunnen kiezen welke fractie van het licht van elke lamp we willen laten doorgaan door de blueMultiplier, greenMultiplier en redMultiplier eigenschappen van onze ColorTransform.
Een van deze instellen op 1 vertelt Flash om het met rust te laten, terwijl het dit instelt 0 vertelt Flash om het volledig uit te schakelen. En natuurlijk, 0.5 zal het de helft van de normale hoeveelheid opleveren, 2.0 zal het verdubbelen, enzovoort.
Dus om al het blauw uit de linker viewport te verwijderen, kunnen we dit doen:
leftViewportColorTransform.blueMultiplier = 0;
U moet dat vóór de lijn zetten die de transformatie op de viewport toepast, zoals deze:
leftViewportColorTransform.blueMultiplier = 0; viewport.transform.colorTransform = leftViewportColorTransform;
Als uw bril een rode of groene lens boven het rechteroog heeft, moet u de redMultiplier of greenMultiplier naar 0, in plaats van het blauw. Voor alle andere kleuren moet je een combinatie van rood, groen en blauw gebruiken - meer hierover in stap 15.
Test de SWF:
Het is moeilijk om de "a" van het logo te onderscheiden door de blauwe lens, maar het is helemaal niet moeilijk om de vorm van de kubussen tegen die witte achtergrond te onderscheiden!
Als u de achtergrond van uw SWF wijzigt, ziet u het probleem. Omdat het "witte" gebied rond de kubussen niet echt wit is, maar eerder transparant en de witte achtergrond van de SWF laat zien, wordt het niet beïnvloed door de ColorTransform.
Om dit te verhelpen, moeten we de viewport een effen witte achtergrond geven waarop de kubussen worden weergegeven. Dat is gemakkelijk genoeg; ga gewoon terug naar waar je de viewport hebt gemaakt:
viewport = nieuwe Viewport3D (); viewport.autoScaleToStage = true; // dit maakt de viewport zo groot als het podium
... en voeg een paar lijnen toe om een witte rechthoek te tekenen die zo groot is als het podium:
viewport = nieuwe Viewport3D (); viewport.autoScaleToStage = true; // dit maakt de viewport zo groot als de stage viewport.graphics.beginFill (0xffffff); // 0xffffff is white viewport.graphics.drawRect (0, 0, stage.stageWidth, stage.stageHeight);
Test het opnieuw:
Het beeld moet echt dof, dof en moeilijk door de rechterlens te zien zijn, maar net zo eenvoudig als het gewone beeld om door de linkerlens te kijken.
We moeten nu hetzelfde doen voor de juiste viewport. Maak dus je nieuwe ColorTransform aan:
public var rightViewportColorTransform: ColorTransform;
rightViewportColorTransform = nieuwe ColorTransform ();
Pas deze nieuwe transformatie nu toe op de juiste viewport:
viewport2.transform.colorTransform = rightViewportColorTransform;
Omdat mijn linkerlens geel is, moet ik al het geel uit dit venster leegmaken.
(Als uw linkerlens rood is, is deze stap eenvoudig - stel gewoon de redMultiplier van uw nieuwe ColorTransform op 0.)
Maar hoe krijgen we geel uit rood, groen en blauw?
Als we verven gebruikten, konden we dat niet; geel is in dat geval een primaire kleur. Maar wanneer het om licht gaat, zijn de dingen anders. Kijk hier eens even naar:
Afbeelding van Wikimedia Commons. Bedankt, Mike Horvath en jacobolus!
Zoals u kunt zien, mengen rood en groen samen om geel te maken (wat verklaart waarom de achtergrond van de linker viewport geel werd toen we al het blauw verwijderden). Dus om al het geel uit onze afbeelding te verwijderen, moeten we al het rood en al het groen verwijderen!
We kunnen dit als volgt doen:
rightViewportColorTransform = nieuwe ColorTransform (); rightViewportColorTransform.redMultiplier = 0; rightViewportColorTransform.greenMultiplier = 0; viewport2.transform.colorTransform = rightViewportColorTransform;
O ja, we moeten ook de achtergrond van deze viewport invullen.
Doe dit op dezelfde manier als eerder:
viewport2 = nieuwe Viewport3D (); viewport2.autoScaleToStage = true; // dit maakt de viewport zo groot als de stage viewport2.graphics.beginFill (0xffffff); // 0xffffff is white viewport2.graphics.drawRect (0, 0, stage.stageWidth, stage.stageHeight);
Test het uit:
De gele lens op mijn bril laat eigenlijk een behoorlijke hoeveelheid blauw licht door, maar het is nog steeds veel donkerder wanneer het door die lens wordt bekeken dan wanneer het door de blauwe lens wordt bekeken, en dat is waar het om gaat.
Dus we hebben onze twee afbeeldingen ingesteld en van kleur getransformeerd. Het probleem is dat we op dit moment slechts één van hen tegelijk kunnen zien.
De meest voor de hand liggende manier om ons beide tegelijk te laten zien, is door de alpha (de transparantie) van de viewport aan de voorzijde te verminderen, zoals:
viewport2.alpha = 0,5;
Test dit uit:
Ah. OK, geen opwindend succes. Alpha is duidelijk niet het juiste hulpmiddel voor de klus; wat hebben we nog meer??
Flash geeft ons de keuze uit verschillende overvloeimodi, methoden om twee weergave-objecten samen te voegen. Er staat hier een volledige lijst, maar ik ga me alleen concentreren op degene die wordt genoemd toevoegen.
De toevoegen de mengmodus gaat door elke pixel van de twee afbeeldingen en voegt de helderheid van elk van de drie lampen bij elkaar.
Dus als een bepaalde pixel in de eerste afbeelding de groene lamp volledig heeft ingeschakeld en de andere twee volledig uit, en dezelfde pixel in de tweede afbeelding heeft de blauwe lamp volledig aan en de andere twee volledig uit, dan zijn bij samenvoeging de groene en blauwe lampen zijn volledig ingeschakeld en de rode lamp is helemaal uit.
Als de eerste en de tweede afbeelding allebei de rode lamp halverwege hebben en de andere twee volledig uit, heeft de gemengde afbeelding de rode lamp volledig op, terwijl de andere twee uit blijven.
Verkrijg de foto? Geweldig, laten we het gebruiken. Verwijder de regel die we net hebben geschreven en die de alpha heeft aangepast en vervang deze door deze:
viewport2.blendMode = "toevoegen";
(We hoeven de overvloeimodus niet toe te passen op beide viewports, alleen degene boven in de displaylijst.)
Test het uit:
Dat lijkt er meer op!
Als je ernaar kijkt met één oog per keer, zou je moeten opmerken dat elk oog een ander kijkvenster promintently ziet. Je zult waarschijnlijk ook een vage geest van de andere viewport kunnen zien, maar dat is geen probleem; je brein kan dat negeren.
De afbeelding ziet er echter nog niet helemaal uit als 3D. Laten we dat uitzoeken.
Hoewel je ogen verschillende beelden zien, is dit niet voldoende om je hersenen voor de gek te houden. Je brein is behoorlijk slim, zie je; sommigen zouden zelfs zeggen dat het het slimste orgaan in je lichaam is. Het weet dat het andere aanwijzingen moet gebruiken om uit te zoeken of een object 3D is of niet. Perspectief, bijvoorbeeld: hoe klein een object eruit moet zien op basis van hoe ver weg het is.
Het grootste probleem is dat onze twee camera's veel verder uit elkaar staan dan onze eigen ogen. Dat is niet verrassend, omdat ik willekeurig het nummer 50 heb gekozen.
De daadwerkelijke scheidingsafstand die we zouden moeten gebruiken, zal afhangen van een aantal dingen, zoals hoe ver weg je bent van de monitor en hoe groot je scherm is, dus ik kan je niet gewoon een magisch nummer geven om te gebruiken. We zullen het handmatig moeten uitvogelen.
We zouden dit kunnen doen door verschillende nummers een voor een uit te proberen, maar dit is vervelend en zal voor altijd duren. Ik heb een beter idee.
Voeg deze regel toe aan uw functie onEnterFrame ():
camera2.x = camera.x + (mouseX * 0.1);
Verander nu uw onClickViewport- en onClickViewport2-functies naar het volgende:
openbare functie onClickViewport (mouseEvt: MouseEvent): void trace (camera2.x - camera.x); public function onClickViewport2 (mouseEvt: MouseEvent): void trace (camera2.x - camera.x);
Voer de SWF uit en beweeg de muis naar links en rechts. Het ziet er als volgt uit:
Zet je bril op, doe het licht uit en blijf bewegen tot je de "sweet spot" vindt waar het beeld stevig lijkt te worden. Klik met de muis op dit punt, en het zal een aantal traceren. Noteer het!
Zodra je de optimale scheiding hebt gevonden, verwijder je de regel die we zojuist aan de functie onEnterFrame () hebben toegevoegd:
camera2.x = camera.x + (mouseX * 0.1);
Zoek nu de regel in Hoofd () waar je de afstand tussen de camera's instelt:
camera2.x = camera.x + 50;
... en vervang de 50 door het nummer dat u hebt genoteerd. Ik vond dat 18 een goed aantal was om te gebruiken voor mijn setup.
Test ten slotte de SWF:
Ta-da!
Goed gedaan - je hebt een 3D-scène gemaakt in Flash en hebt wat mind-bedrog gebruikt om het naar een 3D-scène in je hoofd over te brengen;)
Als je alles begrepen hebt wat je hebt doorgemaakt, zou je dezelfde techniek moeten kunnen gebruiken om 3D anaglyph-afbeeldingen te maken met andere 3D-engines.
Ik heb in het eerste deel genoemd dat je misschien zou willen proberen om het voor de gebruiker mogelijk te maken om de camera met de muis te bewegen. Nu je het anaglyph-effect hebt toegevoegd, ziet het er erg indrukwekkend uit om de camera's naar voren en naar achteren te verplaatsen.
Bedankt voor het lezen van deze tutorial. Ik hoop dat je het nuttig hebt gevonden. Zoals altijd, als je vragen hebt, stel ze dan in de reacties hieronder.