WebGL met Three.js texturen & deeltjes

Sinds de introductie is 3D-afbeeldingen in de browser een populair onderwerp. Maar als u uw apps zou maken met eenvoudige oude WebGL, zou dit erg lang duren. Maar nu hebben we een aantal behoorlijk bruikbare bibliotheken waar we gebruik van kunnen maken, zoals Three.js. Dus in deze serie laat ik je zien hoe je verbluffende 3D-ervaringen voor de browser kunt maken.

Ik verwacht dat je een basiskennis van de 3D-ruimte hebt voordat je deze tutorial begint te lezen, omdat ik geen dingen zoals coördinaten, vectoren enz. Zal uitleggen.


Voorbereiding

We beginnen met de code uit het vorige deel van deze serie. Pak ook de items die ik heb aangeleverd en plaats deze in dezelfde map als uw app. Nu, aangezien we hier afbeeldingen zullen gebruiken, moet je je app op een vaste server plaatsen (mogelijk lokaal), tenzij je de browser start met ingeschakelde bestandstoegang vanuit bestanden (bijvoorbeeld met behulp van de --allow-file-access-from-files vlag in Chrome) CORS laat je hem niet laden vanuit een bestand. Dat is alles wat u hoeft te doen voordat u doorgaat.


Stap 1: de textuur laden

Als je je ooit zo hebt verveeld dat je met het maken van iets met pure OpenGL bent begonnen, herinner je je waarschijnlijk hoeveel pijn het is om een ​​textuur te laden. Gelukkig heeft Three.js een leuke functie die de textuur voor ons laadt en instelt. Voeg deze regel toe vóór de definitie van het materiaal van onze kubus:

 var cubeTexture = THREE.ImageUtils.loadTexture ('./ box.png');

Het is echt alles wat je hoeft te doen om je textuur geladen te krijgen.

In een real-world app zou je de textuur moeten voorladen zoals elke normale afbeelding en de gebruikers een mooie laadbalk tonen om hen te laten weten dat je aan het laden bent (Three.js gebruikt dan de gecachte afbeelding).


Stap 2: De kubus schilderen

Nu zullen we de textuur toepassen op onze kubus. Dit is ook gemakkelijk, je hoeft alleen maar de kleurdefinitie in het materiaal van de kubus te vervangen om er zo uit te zien:

 var cubeMaterial = nieuw THREE.MeshLambertMaterial (map: cubeTexture);

De kaart kenmerk stelt de textuur in. Nu kunt u de browser openen en zou u een roterende, getextureerde kubus moeten zien:


Je kunt de textuur ook inkleuren, voeg gewoon de kleur definitie in de opties van het materiaal, zoals dat:

 var cubeMaterial = nieuw THREE.MeshLambertMaterial (map: cubeTexture, color: 0x28c0ec);

En nu wordt de kubus blauw:


Op deze manier kunt u meerdere verschillende objecten met dezelfde textuur hebben als alleen de kleur verandert.


Stap 3: Meerdere materialen

U kunt verschillende materialen instellen voor elk vlak van de kubus. Om dit te bereiken, moet je de definitie van het hele materiaal wijzigen. Definieer eerst de materialen matrix. Elk element in de array komt overeen met het materiaal van één vlak. Ze gaan in deze volgorde: rechts, links, boven, onder, voor en achter:

 var materialen = []; materials.push (nieuw THREE.MeshLambertMaterial (map: cubeTexture, color: 0xff0000)); // right face materials.push (nieuw THREE.MeshLambertMaterial (map: cubeTexture, color: 0xffff00)); // left face materials.push (nieuw THREE.MeshLambertMaterial (map: cubeTexture, color: 0xffffff)); // top face materials.push (nieuw THREE.MeshLambertMaterial (map: cubeTexture, color: 0x00ffff)); // bottom face materials.push (nieuw THREE.MeshLambertMaterial (map: cubeTexture, color: 0x0000ff)); // front face materials.push (nieuw THREE.MeshLambertMaterial (map: cubeTexture, color: 0xff00ff)); // achterkant

Zoals je kunt zien, heeft elk gezicht zijn eigen materiaal, dus je kunt verschillende structuren, kleuren en andere attributen instellen voor elk vlak. Wijzig vervolgens het type van het kubusmateriaal in THREE.MeshFaceMaterial:

 var cubeMaterial = new THREE.MeshFaceMaterial (materialen);

U hoeft alleen de materialen array als de parameter. In de browser moet je zien dat elke kant van de kubus een andere kleur heeft:



Stap 4: deeltjes!

Stel dat u een effect wilt maken van het spinnen van sneeuwvlokken in uw app. Als je elke sneeuwvlok als een mesh rendert, krijg je hele lage fps. Dat is waar deeltjes in het spel komen. Ze zijn veel minder ingewikkeld en als ze als een geheel deeltjessysteem worden getekend, zijn ze echt efficiënt.

Begin met het maken van een geometrie voor onze deeltjes:

 var particles = new THREE.Geometry;

THREE.Geometry is een basisgeometrieobject, zonder enige vorm. Nu moeten we de positie van elk deeltje in het systeem bepalen. Laat het helemaal willekeurig zijn:

 voor (var p = 0; p < 2000; p++)  var particle = new THREE.Vector3(Math.random() * 500 - 250, Math.random() * 500 - 250, Math.random() * 500 - 250); particles.vertices.push(particle); 

Deze lus zal 2000 willekeurig geplaatste deeltjes creëren en ze allemaal in de geometrie plaatsen. Vervolgens moet je deeltjesmateriaal definiëren:

 var particleMaterial = new THREE.ParticleBasicMaterial (color: 0xeeeeee, size: 2);

Merk op dat we gebruiken THREE.ParticleBasicMaterial, wat alleen voor deeltjes is. In opties definiëren we alleen de kleur en de grootte van elk deeltje. Eindelijk, je kunt het deeltjessysteem maken en het aan de scène toevoegen:

 var particleSystem = nieuw THREE.ParticleSystem (particles, particleMaterial); scene.add (particleSystem);

Om de scène er nu beter uit te laten zien, draaien we de deeltjes in de richting tegengesteld aan die waarin de kubus draait (verander de geven functie om er zo uit te zien):

 function render () requestAnimationFrame (render); var delta = clock.getDelta (); cube.rotation.y - = delta; particleSystem.rotation.y + = delta; renderer.render (scène, camera); 

We hebben het clock.getDelta naar de variabele, want als je het zo zou gebruiken:

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

Het deeltjessysteem zou niet roteren, omdat de tweede oproep een getal dicht bij nul zal retourneren (onthoud dat het de tijd krijgt van de laatste oproep).

Open nu de browser en je zou een kubus en roterende deeltjes moeten zien:


Laten we beide dingen combineren die je in deze tutorial hebt geleerd en die lelijke witte vierkanten in echte sneeuwvlokken veranderen. Laad eerst de sneeuwvloktextuur:

 var particleTexture = THREE.ImageUtils.loadTexture ('./ snowflake.png');

Verander nu het deeltjesmateriaal om de textuur te gebruiken. Zorg ook voor transparantie en maak de deeltjes groter zodat we de vorm kunnen zien:

 var particleMaterial = new THREE.ParticleBasicMaterial (map: particleTexture, transparent: true, size: 5);

Als u de browser opent, ziet u enkele leuke sneeuwvlokken rond de kubus stromen:



Stap 5: Rook

Het rookeffect is vrij eenvoudig te bereiken en het ziet er goed uit. Begin met het maken van de geometrie, net zoals bij de sneeuwvlokken:

 var smokeParticles = new THREE.Geometry; for (var i = 0; i < 300; i++)  var particle = new THREE.Vector3(Math.random() * 32 - 16, Math.random() * 230, Math.random() * 32 - 16); smokeParticles.vertices.push(particle); 

Het enige verschil hier is dat we de positie kiezen uit een rechthoekig prisma met afmetingen 32x32x230. Laten we nu de textuur laden en het materiaal definiëren:

 var smokeTexture = THREE.ImageUtils.loadTexture ('./ smoke.png'); var smokeMaterial = new THREE.ParticleBasicMaterial (map: smokeTexture, transparent: true, blending: THREE.AdditiveBlending, size: 50, colour: 0x111111);

In materiële definitie is er een blending keuze. Het vertelt de renderer hoe het een object op een ander moet weergeven. Met THREE.AdditiveBlending overlappende kleurwaarden zullen aan elkaar worden toegevoegd, wat zal resulteren in een helderdere rook in de gebieden met hogere deeltjesdichtheid. We hebben ook de kleur ingesteld op bijna zwart, zodat de rook er natuurlijker uitziet.

Maak tenslotte het particle-systeem, verplaats het een beetje naar links en voeg het toe aan de scène:

 var smoke = new THREE.ParticleSystem (smokePodicles, smokeMaterial); smoke.sortParticles = true; smoke.position.x = -150; scene.add (rook);

Je moet ook instellen smoke.sortParticles naar waar. Wanneer het fout is, kan de achtergrond van de sprite als zwart worden getekend. Als u de browser opent, ziet u naast de kubus nog steeds een rookpijler:


Om de rook te animeren moeten we alle deeltjes doorlopen en ze een beetje omhoog bewegen. Voeg deze code toe aan de geven functie:

 var particleCount = smokeParticles.vertices.length; while (particleCount--) var particle = smokeParticles.vertices [particleCount]; particle.y + = delta * 50; if (particle.y> = 230) particle.y = Math.random () * 16; particle.x = Math.random () * 32 - 16; particle.z = Math.random () * 32 - 16;  smokeParticles .__ dirtyVertices = true;

In de lus voegen we toe delta * 50 naar de y-positie van het deeltje. Vervolgens controleren we of het deeltje hoger is dan 230, zo ja, we kiezen willekeurig zijn nieuwe positie ergens in de bodem van de rookpilaar. Eindelijk het belangrijkste: het instellen van de geometrie's __dirtyVertices vlag naar waar.

Om de prestaties te verbeteren, plaatst Three.js de objecten in de cache om te voorkomen dat alle WebGL-oproepen elk frame opnieuw worden opgebouwd. Als we iets in de geometrie van het object wijzigen, moeten we de renderer laten weten dat deze is gewijzigd. Kortom, de __dirtyVertices vlag zal het element net bereiken.

Als u nu de browser opent, ziet u naast de kubus een vloeiend geanimeerde rook.


Conclusie

In deze tutorial heb je geleerd hoe je texturen en deeltjes gebruikt. Wees zoals voorheen niet bang om een ​​beetje met uw app te experimenteren. Als je problemen hebt, bekijk dan de documentatie. In het volgende artikel zal ik je leren modellen te laden en te animeren.