WebGL met Three.js basisprincipes

3D-afbeeldingen in de browser zijn een hot topic sinds het voor het eerst werd geïntroduceerd. Maar als u uw apps zou maken met gewone WebGL, zou dit eeuwen duren. Dit is precies waarom recentelijk enkele echt bruikbare bibliotheken zijn ontstaan. Three.js is een van de meest populaire en in deze serie laat ik je zien hoe je het het beste kunt gebruiken om verbluffende 3D-ervaringen voor je gebruikers te creëren.

Voordat we beginnen, verwacht ik dat je een basiskennis van de 3D-ruimte hebt voordat je deze tutorial begint te lezen, omdat ik niet dingen als coördinaten, vectoren, enz. Zal uitleggen.


Stap 1: voorbereiding

Maak eerst drie bestanden: index.html, main.js en style.css. Download nu Three.js (volledig zipbestand met voorbeelden en broncode, of alleen het JavaScript-bestand, naar keuze). Nu open index.html en voeg deze code in:

          

Dat is alles wat u nodig heeft in dit bestand. Gewoon een verklaring van scripts en stylesheet. Alle magie zal gebeuren in main.js, maar voordat we daar aan toe zijn, hebben we nog een truc nodig om de app er goed uit te laten zien. Open style.css en voeg deze code in:

 canvas positie: vast; boven: 0; links: 0; 

Hierdoor wordt het canvas in de linkerbovenhoek geplaatst, omdat standaard het canvas lichaam zal 8px marge hebben. Nu kunnen we doorgaan met de JavaScript-code.


Stap 2: The Scene and the Renderer

Three.js maakt gebruik van het concept van een weergavelijst. Dit betekent dat alle objecten in de lijst worden opgeslagen en vervolgens naar het scherm worden getrokken.

Three.js maakt gebruik van het concept van een weergavelijst. Dit betekent dat alle objecten in de lijst worden opgeslagen en vervolgens naar het scherm worden getrokken. Hier is dit een THREE.Scene voorwerp. U moet elk object dat u wilt laten tekenen op het scherm toevoegen aan de scène. U kunt zoveel scènes als u wilt hebben, maar één renderer kan slechts één scène tegelijkertijd tekenen (u kunt natuurlijk de scène wijzigen die wordt weergegeven).

De renderer tekent eenvoudig alles van de scène tot het WebGL-canvas. Three.js ondersteunt ook tekenen op SVG of 2D Canvas, maar we zullen ons richten op WebGL.

Laten we om te beginnen de breedte en hoogte van het venster opslaan in variabelen, we zullen het later gebruiken:

 var width = window.innerWidth; var height = window.innerHeight;

Definieer nu de renderer en de scène:

 var renderer = nieuw THREE.WebGLRenderer (antialias: true); renderer.setSize (breedte, hoogte); document.body.appendChild (renderer.domElement); var scene = new THREE.Scene;

De eerste regel definieert de WebGL-renderer. U kunt de opties van de renderer in het eerste argument doorgeven als een kaart. Hier hebben we de antialias waar, omdat we willen dat de randen van objecten glad zijn, niet gekarteld.

De tweede regel stelt de weergavegrootte in op de grootte van het venster en in de derde lijn voegen we de renderer toe canvas element van het document (je kunt dit ook doen met een bibliotheek, zoals jQuery: $ ( 'Body'). Append (renderer.domElement)).

De laatste definieert de scène, er zijn geen argumenten nodig.


Stap 3: De kubus

Laten we nu iets toevoegen om getekend te worden. Laat het een kubus zijn, want het is het eenvoudigste 3D-object. In Three.js worden de objecten die op het scherm worden getekend meshes genoemd. Elke mesh moet zijn eigen geometrie en materiaal hebben. Geometrie is een verzameling punten die moeten worden verbonden om het object te maken. Materiaal is gewoon de verf (of het schilderen, maar dat is niet het onderwerp van deze tutorial) die het object zal bedekken. Dus laten we onze kubus maken. Gelukkig zijn er voor ons enkele helperfuncties in Three.js voor het maken van primitieven (eenvoudige vormen):

 var cubeGeometry = nieuwe THREE.CubeGeometry (100, 100, 100); var cubeMaterial = nieuw THREE.MeshLambertMaterial (color: 0x1ec876); var cube = new THREE.Mesh (cubeGeometry, cubeMaterial); cube.rotation.y = Math.PI * 45/180; scene.add (kubus);

Zoals je kunt zien, maken we eerst de geometrie aan. De argumenten definiëren een grootte van de kubus: de breedte, hoogte en diepte.

Vervolgens definiëren we het materiaal van de kubus. Er zijn een paar materiaalsoorten in Three.js, maar deze keer gebruiken we de THREE.MeshLambertMaterial, omdat we later wat verlichting willen hebben (dit materiaal gebruikt Lambert's algoritme voor lichtberekeningen). U kunt de opties in het eerste argument als een kaart doorgeven, net als bij de renderer - dit is vrijwel een regel voor complexere objecten in Three.js. Hier gebruiken we alleen kleur, die wordt doorgegeven als een hexadecimaal getal.

Op de derde regel maken we een maas met behulp van de eerder gemaakte geometrie en materiaal. Vervolgens roteren we de kubus 45 graden op de Y-as, zodat deze er beter uitziet. We moeten de graden in radialen veranderen, wat wordt afgehandeld door de vergelijking die je waarschijnlijk kent van je fysica klas op de middelbare school: Math.PI * 45/180. Ten slotte wordt de kubus aan de scène toegevoegd.

Nu zou je kunnen openen index.html in je browser om de resultaten te zien, maar je ziet niets omdat de scène nog niet is gerenderd.


Stap 4: Camera!

Om iets te renderen, moeten we eerst de camera aan de scène toevoegen, zodat de renderer vanuit welk gezichtspunt dingen moet weergeven. Er zijn een paar typen camera's in Three.js, maar die zult u waarschijnlijk alleen gebruiken THREE.PerspectiveCamera. Dit type camera presenteert de scène terwijl we onze wereld zien. Laat er een maken:

 var camera = nieuwe THREE.PerspectiveCamera (45, width / height, 0.1, 10000);

"Om iets te renderen, moeten we eerst de camera aan de scène toevoegen, dus de renderer weet uit welk oogpunt hij dingen moet weergeven."

Het maken van de camera is een beetje ingewikkelder dan de rest van de dingen die we tot nu toe gedaan hebben. Het eerste argument definieert de FOV (gezichtsveld), de hoek die kan worden gezien van waar de camera zich bevindt. Een gezichtsafstand van 45 graden ziet er natuurlijk uit. Vervolgens bepalen we de verhouding van de camera. Dit is altijd de breedte van de renderer gedeeld door de hoogte, tenzij u bepaalde speciale effecten wilt bereiken. De laatste twee getallen bepalen hoe dichtbij en hoe ver het object kan zijn om de camera te laten tekenen.

Nu moeten we de camera iets naar achteren en naar boven verplaatsen, omdat alle objecten die in Three.js zijn gemaakt, standaard zijn gepositioneerd in het midden van de scène (x: 0, y: 0, z: 0):

 camera.position.y = 160; camera.position.z = 400;

De z coördinaat is positief in de richting van de toeschouwer, dus objecten met een hogere z positie zal dichterbij je verschijnen (in dit geval, omdat we de camera hebben verplaatst, zullen alle objecten verder van je verwijderd zijn).

Laten we nu de camera aan de scène toevoegen en deze weergeven:

 scene.add (camera); renderer.render (scène, camera);

Je voegt de camera toe net zoals je de kubus hebt toegevoegd. De volgende regel geeft de scène weer met deze camera. Nu kunt u de browser openen en zou u het volgende moeten zien:


Je zou alleen de bovenkant van de kubus moeten kunnen zien. Dit komt omdat we de camera hebben verplaatst en het stil is op zoek direct ervoor. Dit kan worden opgelost door de camera te laten weten op welke positie dit moet kijken. Voeg deze regel toe nadat de lijnen de positie van de camera hebben ingesteld:

 camera.lookAt (cube.position);

Het enige binnengekomen argument is een positie waarop de camera zal kijken. Nu ziet de scène er beter uit, maar de kubus is nog steeds zwart, ongeacht de kleur die u hebt ingesteld bij het maken van de scène:



Stap 5: Lichten!

De kubus is zwart, omdat er geen licht op de scène is, dus het is als een volledig zwarte kamer. Je ziet een witte achtergrond omdat er niets is om uit de kubus te tekenen. Om dat te voorkomen, gebruiken we een techniek genaamd skybox. Kortom, we zullen een grote kubus toevoegen die de achtergrond van de scène weergeeft (meestal wat ver terrein als het open ruimte is). Dus laten we de box maken. Deze code zou vóór moeten gaan renderer.render bellen:

 var skyboxGeometry = nieuwe THREE.CubeGeometry (10000, 10000, 10000); var skyboxMaterial = nieuw THREE.MeshBasicMaterial (color: 0x000000, side: THREE.BackSide); var skybox = nieuwe THREE.Mesh (skyboxGeometry, skyboxMaterial); scene.add (skybox);

Deze code lijkt op de code die de kubus maakt. Maar deze keer is de geometrie veel groter. We hebben ook gebruikt THREE.MeshBasicMaterial omdat we de skybox niet hoeven aan te steken. Let ook op het aanvullende argument dat aan het materiaal is doorgegeven: kant: THREE.BackSide. Omdat de kubus van binnenuit wordt weergegeven, moeten we de kant wijzigen die wordt getekend (normaal trekt Three.js alleen buitenmuren).

Nu is de gegenereerde scène volledig zwart. Om dat te verhelpen, moeten we licht toevoegen aan de scène. We zullen gebruiken THREE.PointLight, die het licht als een gloeilamp uitzendt. Voeg deze regels toe na de skybox:

 var pointLight = new THREE.PointLight (0xffffff); pointLight.position.set (0, 300, 200); scene.add (pointLight);

Zoals je kunt zien, hebben we het puntlicht met witte kleur gemaakt, daarna stellen we zijn positie in om een ​​beetje op en neer te gaan, om de voorkant en de bovenkant van de kubus te verlichten. Eindelijk wordt het licht als elk ander object aan de scène toegevoegd. Open de browser en je zou een gekleurde, gearceerde kubus moeten zien:


Maar de kubus is nog steeds behoorlijk saai. Laten we er wat beweging aan toevoegen.


Stap 6: Actie!

Nu voegen we wat beweging toe aan de scène. Laat de kubus rond de Y-as draaien. Maar eerst moeten we de manier veranderen waarop we de scène weergeven. een renderer.render Oproep, geeft de huidige status van de scène één keer weer. Dus zelfs als we de kubus op de een of andere manier animeren, zullen we hem niet zien bewegen. Om dat te veranderen, moeten we de render-loop aan onze app toevoegen. Dit kan worden bereikt met behulp van de renderAnimationFrame functie, die speciaal voor dat doel is gemaakt. Het wordt ondersteund in de meeste van de grote browsers en voor degenen die dit niet ondersteunen, wordt Three.js geleverd met een eigen polyfill. Dus laten we dit veranderen:

 renderer.render (scène, camera);

hieraan:

 function render () renderer.render (scène, camera); requestAnimationFrame (te maken);  render ();

Er zit eigenlijk geen lus in, omdat het de browser zou bevriezen. De requestAnimationFrame functie gedraagt ​​zich een beetje als setTimeout, maar het roept de functie zo snel door als de browser klaar is. Er is dus niets echt veranderd in de weergegeven scène en de kubus beweegt nog steeds niet. Laten we dat oplossen. Three.js wordt geleverd met THREE.Clock die kan worden gebruikt om een ​​vloeiende animatie van objecten te bereiken. Eerst initialiseren voor de geven functiedefinitie:

 var clock = new THREE.Clock;

Nu, elke keer dat u belt clock.getDelta het geeft de tijd sinds de laatste oproep terug, in milliseconden. Dit kan worden gebruikt om de kubus als volgt te draaien:

 cube.rotation.y - = clock.getDelta ();

Voeg deze regel toe tussen de renderer.render en de requestAnimationFrame roept de geven functie. Het is eenvoudigweg het aftrekken van de tijd voorbij de rotatie van de kubus op de Y-as (onthoud dat het in radialen is) om de kubus met de klok mee te draaien. Open nu de browser en je ziet je kubus met de wijzers van de klok mee draaien.


Conclusie

In dit deel van de serie heb je geleerd hoe je de scène moet voorbereiden, objecten en lichten kunt toevoegen en hoe je dingen kunt animeren. Je kunt met de app experimenteren, meer of verschillende objecten toevoegen, lichten. Het is aan jou. De volgende keer zal ik je laten zien hoe je texturen gebruikt en hoe je leuke effecten met deeltjes kunt creëren. Vergeet niet om de documentatie te bekijken als u problemen ondervindt.