WebGL con Three.js Shader

La grafica 3D nel browser è stata un argomento di interesse sin dalla sua introduzione. Ma se dovessi creare le tue app usando semplicemente WebGL vecchio, ci vorrebbero anni. Di recente sono disponibili alcune librerie davvero utili. Three.js è uno dei più popolari e in questa serie ti mostrerò come utilizzarlo al meglio per creare incredibili esperienze 3D per i tuoi utenti.

Mi aspetto che tu abbia una conoscenza di base dello spazio 3D prima di iniziare a leggere questo tutorial, poiché non spiegherò cose come coordinate, vettori, ecc..


Una parola sugli shaders

Se sai già quali sono gli shader, puoi saltare questo passaggio. Gli shader sono fondamentalmente programmi scritti in GLSL (Graphics Layer Scripting Language), che vengono eseguiti sulla GPU. Ciò li rende estremamente utili, in quanto possiamo prendere un po 'di lavoro dalla CPU e metterlo sulla GPU per aumentare le prestazioni. Ci sono due tipi: vertex e framment shaders. Gli ombreggiatori di vertici vengono utilizzati per modificare la struttura dell'oggetto (spostare i vertici) e gli ombreggiatori di frammenti apportano modifiche ai pixel che vengono disegnati.


Passaggio 1: Vertex Shader

Inizieremo con quello più semplice. Questo shader modificherà la posizione dei vettori nella mesh, risultando in facce mobili. Inserisci questo codice in della tua app:

 

Il genere l'attributo di questo script non verrà compreso dal browser, quindi non verrà eseguito (passeremo il suo contenuto al materiale Three.js in seguito). Nelle prime due righe stiamo definendo due variabili. Il primo è uniforme tempo fluttuante. Le uniformi vengono passate sia a vertex che a framment shader. Successivamente, c'è varia vec2 vUv. Le varianti sono l'interfaccia tra il vertice e lo shader del frammento. tempo manterrà il tempo in millisecondi da quando è stata avviata l'app, che useremo per calcolare nuove posizioni dei vertici. Nel VUV memorizzeremo l'UV (vettore di trama) di ogni vertice, in modo che possiamo usarlo nello shader di frammenti.

Avanti, c'è il void main () dichiarazione. Tutti gli shader devono avere questa funzione. Qui passiamo l'UV del vertice al nostro VUV e calcolando la nuova posizione del vertice. Alla fine, impostiamo il GL_POSITION, che di fatto definisce la posizione del vertice. Ma anche, dobbiamo moltiplicare la posizione calcolata in precedenza dal projectionMatrix e modelViewMatrix, due matrici che Three.js ci fornisce. Questo è necessario perché se non lo facciamo, la GPU non prenderà in considerazione il punto dal quale stiamo guardando il vertice. Ora passiamo allo shader dei frammenti.


Step 2: Fragment Shader

Ora questo è il luogo in cui avviene tutta la magia. Gli shader dei frammenti sono responsabili di tutti quei giochi di bell'aspetto. Quello che useremo è piuttosto semplice, quindi non aspettarti di vedere una scena di Crysis 3 dopo averla usata. Inserisci il seguente codice sotto il vertex shader:

 

Come puoi vedere in cima allo shader, ci sono di nuovo le nostre due variabili. Devi tenere presente che tutte le variabili che usi (eccetto quelle da Three.js) devono essere definite in ogni shader utilizzato.

Nel void main () funzione, stiamo calcolando i colori in base al tempo e ai raggi UV del frammento (gli shader dei frammenti operano sui frammenti, che sono composti da vertici, quindi i valori di variando le variabili sono interpolate nello shader del frammento). Sentiti libero di pasticciare con quei numeri e funzioni (ricorda solo che i valori dei colori devono essere positivi).

Infine, stiamo impostando il gl_FragColor variabile che imposta il colore del frammento.

Se apri il browser ora, non cambierà nulla, perché dobbiamo modificare il materiale dell'oggetto in modo che utilizzi gli shader.


Passaggio 3: THREE.ShaderMaterial

Questo materiale speciale viene utilizzato ogni volta che è necessario utilizzare gli shader. Cambiamo il materiale dell'oggetto che abbiamo allegato al nostro modello nella parte precedente di questa serie. In primo luogo, definire il uniformi array che verrà usato per passare variabili agli shader:

 var uniforms = time: type: "f", valore: 0, risoluzione: tipo: "v2", valore: new THREE.Vector2, texture: tipo: "t", valore: THREE.ImageUtils. loadTexture ('./ box.png');

Successivamente, nel Loader.load definire il articoloil materiale e usalo:

 var itemMaterial = new THREE.ShaderMaterial (uniforms: uniforms, vertexShader: document.getElementById ('cubeVertexShader'). innerHTML, fragmentShader: document.getElementById ('cubeFragmentShader'). innerHTML); item = new THREE.Mesh (new THREE.CubeGeometry (100, 10, 10), itemMaterial);

Ora, se apri il browser, dovresti vedere che il raggio rosso ha cambiato i suoi colori:


Ma i colori non cambiano e anche la mesh non è animata. Per cambiare questo, dobbiamo aggiornare il tempo variabile negli shader ogni volta che viene disegnata una cornice. Vai al rendere funzione e aggiungere questa linea dopo il clock.getDelta () chiamata:

 uniforms.time.value + = delta * 10;

Ora se apri il browser, dovresti vedere un oggetto ben colorato e colorato:



Una parola sulle prestazioni

Se dovessimo creare un simile effetto texture usando, ad esempio, HTML5 Canvas, il processo richiederebbe troppo dei cicli della CPU, risultando in ritardi. Ma tutti gli shader vengono eseguiti sulla GPU, che è ottimizzata per tutte le operazioni sulla grafica e focalizzata solo su di essi. Separare i calcoli grafici e non grafici è la chiave per un'app di buona esecuzione.

Se vuoi creare qualcosa di reale usando WebGL, permettimi di assicurarti che dovrai spostare più lavoro possibile sulla GPU, per rendere la tua applicazione fluida e reattiva.


Conclusione

Come puoi vedere, l'uso di Three.js ci consente di creare grafica 3D nel browser molto facilmente e i risultati sono piuttosto buoni. Ma, possono essere ancora meglio, dai un'occhiata a questi esempi dal sito di Three.js:

  • Hyperlapse
  • Il TNT per due

Con abbastanza tempo, una mente creativa e Three.js, puoi creare app fantastiche come quelle. Sarò più che felice di vedere le tue creazioni Three.js. Grazie per aver letto.