Three.js Scena base

Gianluca Lomarco
9 min readApr 20, 2023

--

Three.js è una libreria JavaScript che ci permette di creare ambientazioni tridimensionali nelle nostre pagine web, con le quali è possibile interagire in diversi modi.

Mescolando elementi 3D con contenuti html più standard; come titoli, paragrafi, immagini e pulsanti è possibile dare vita ad esperienze davvero pazzesche, aumentando l'immersivita e il coinvolgimento degli utenti.

Ne sono un esempio i tantissimi siti web che ogni giorni vengono premiati su awwwards e simili. I siti che beneficiano maggiormente di queste tecnologie sono quelli basati sullo storytelling, ma questa libreria può essere usata in diversi modi su qualsiasi sito web, persino per creare veri e propri videogiochi. Puoi trovare molti esempi anche sul sito web della libreria stessa:

In questo articolo vediamo come iniziare ad utilizzare three.js creando la nostra prima scena 3D.

Di cosa abbiamo bisogno?

Immaginiamo di dover girare la scena di un film, di cosa avremmo bisogno?

Innanzi tutto ci serve un set, un luogo che contenga tutti gli oggetti di scena: sfondi, una serie di elementi per comporre l’ambientazione da ricreare, ecc. Oltre alla scenografia, ci saranno gli attori che recitano interagendo tra di loro e con gli oggetti di scena.

Tutto questo verrà ripreso da una telecamera, anche più di una a volte. Ma non potremmo riprendere niente se non avessimo un insieme di luci, ben posizionate, che illuminano tutto.

Three.js ci permette di creare virtualmente tutto questo e renderizzare ogni fotogramma ripreso dalla camera all’interno di un elemento html: la canvas. La canvas si comporta come una tela in cui possiamo disegnare quello che vogliamo. Three.js quindi non fa altro che generare le immagini dei singoli fotogrammi della scena che poi vengono trasferite sulla canvas, e di conseguenza nella pagina web.

Ma come funziona tutto questo?

Three.js sfrutta delle API di javascript chiamate webGL, che ci permettono di comunicare direttamente con la GPU del nostro computer e di eseguire due programmi chiamati SHADERS. Nello specifico un Vertex shader e un Fragment shader.

Senza entrare troppo nel tecnico limitiamoci a dire che questi due programmi hanno il compito di trasformare le informazioni contenute nelle geometrie che compongono la scena (il vertex shader) in una serie di pixel colorati che compongono i fotogrammi (il fragment shader) che, alla fine, finiscono nella canvas.

Occorre però specificare che gli shaders calcolano un solo pixel alla volta e in maniera del tutto indipendente l'uno dall'altro. Di conseguenza per generare un singolo fotogramma con risoluzione 1920x1080 (full HD), dobbiamo eseguire gli shader un bel po' di volte.

Fortunatamente a svolgere queste operazioni se ne occupa la GPU.

A differenza della CPU, composta da pochi processori ma molto potenti, la GPU è invece costituita da migliaia si microprocessori e ciò le permette di eseguire moltissime operazione simultaneamente. In questo modo riesce a calcolare migliaia di pixel contemporaneamente. Grazie a questa velocità di calcolo siamo in grado di renderizzare scene anche molto complesse in tempo reale arrivando fino a 60fps (60 frame per secondo).

The Book of Shaders- che cos'è uno shader

Finita questa introduzione passiamo al codice e creiamo il nostro progetto.

Struttura del progetto

Per semplicità non utilizzeremo un bundler manager, ne dipendenze npm o moduli JavaScript. Lavoreremo con dei semplici file HTML e un po di JavaScript.

Alla fine di questo articolo trovi il link alla guida su come creare una scena base con three.js usando Vite.

Creiamo quindi un file index.html con la struttura base:

e un file app.js con un semplice log:

Importiamo three.js

Abbiamo diverse possibilità per importare la libreria all’interno del progetto e possiamo trovare tutte queste possibilità nella sezione installazione della documentazione.

Per adesso ci limiteremo a scaricare i file della libreria e collegarli al nostro file index.html utilizzando il tag <script>.

A questo link https://threejs.org/ sarà sufficiente cliccare su download per scaricare il file zip con il codice sorgente. Unzippate il file ed entrando nella cartella build copiate il file three.min.js ed incollatelo nella cartella del vostro progetto.

A questo punto dovremo collegare il file alla fine del tag <body> in questo modo, assicurandoci di inserirlo prima del file app.js come si vede nell'immagine.

A questo punto, dentro al file app.js, avremo accesso ad una variabile chiamata THREE che contiene tutte le classi e le utilities che tra poco andremo ad utilizzare per realizzare il progetto.

Modifichiamo il file app.js per stampare in console questa variabile e controllare che esista.

Scene

Siamo pronti per creare la scena. La scena è il nostro set cinematografico. Non è altro che un contenitore in cui metteremo gli oggetti, le luci che riprenderemo con una videocamera.

Per creare la scena ci basterà creare una istanza della classe Scene in questo modo.

Oggetti

Creiamo alcuni oggetti da inserire nella scena.

Gli oggetti prendono il nome di Mesh e sono sempre composti da due elementi:

  • geometria
  • materiale

A grandi linee possiamo affermare che la geometria definisce la forma dei nostri oggetti mentre il materiale determina l’aspetto finale (il colore dei pixel). In realtà è un po’ più complesso di cosi, ma per adesso è più che sufficiente.

Creiamo per il momento un semplice cubo colorato. Useremo la classe BoxGeometry per la geometria del cubo in questo modo:

e successivamente creiamo un materiale. Three.js ci mette a disposizione molti tipo di materiali diversi, già pronti all'uso. Per cominciare useremo la classe MeshBasicMaterial alla quale passeremo un parametro contenente il colore del nostro cubo in questo modo:

Possiamo specificare il colore in diversi modi, in questo caso ho usato un numero con la notazione esadecimale, ma possiamo passare una stringa in modo molto simile a come faremmo nel CSS, '#00ff00' sempre esadecimale o anche semplicemente 'green'. Three.js ci fornisce anche una classe Color molto utile soprattutto se dobbiamo fare delle conversioni delle nostre tonalità cromatiche.

Adesso che abbiamo la geometria e il materiale creiamo la nostra Mesh e aggiungiamola alla scena usando il metodo add(…):

Camera

La camera è di fatto la nostra videocamera, l'elemento che riprende tutto ciò che succede nella scena. La camera non va inserita nella scena e quindi non è un elemento visibile ma identifica il nostro punto di vista.

Possiamo avere anche più di una camera, posizionate in punti diversi, e passare da una all'altra come avviene in un set cinematografico.

Three.js ci mette a disposizione principalmente due tipo di camere:

  • PerspectiveCamera (per viste prospettica)
  • OrtographicCamera (per viste assonometriche)

Oggi useremo la prima per creare il nostro punto di osservazione. Per creare questo tipo di camera abbiamo bisogno di passare due parametri.

Field of view

Corrisponde alla larghezza dell'angolo della visuale. Più questo angolo è grande più elementi entreranno in camera, ma risulteranno molto distorti ai bordi, come succede in una visuale appunto "grandangolare". Più e piccolo, meno cose verranno riprese dalla camera risultando di conseguenza molto zoomate come avviene in una visuale "telescopica".

Essendo un angolo useremo un valore di 75 gradi valore che circa corrisponde al campo visivo dei nostri occhi.

Il secondo parametro è l'aspect ratio, ovvero il rapporto tra larghezza e altezza dell'inquadratura.

Aspect Ratio

Nella maggior parte dei casi questo valore è il risultato della divisione tra la larghezza della canvas e la sua altezza. In questo momento non abbiamo ancora questo elemento, quindi temporaneamente useremo in oggetto con altezza e larghezza generiche.

Non è necessario aggiungere la camera alla scena, ma se acneh volessimo aggiungerla non creerà nessun problema in quando non sarà comunque visibile.

Creiamo al camera

Il Renderer

Il renderer è appunto l'elemento che occupa di renderizzare le nostre scene. Usa la camera come punto di vista e genera i fotogrammi che finiscono nella canvas.

Creando il renderer verrà creata anche la canvas che successivamente dobbiamo inserire nel DOM all'interno del <body>.

Con il metodo setSize(…) stiamo impostando la dimensione dei fotogrammi che verranno generati del renderer e quindi anche la dimensione della <canvas>, che successivamente appendiamo al <body>. Per fare ciò usiamo le stesse dimensioni adottare per calcoare l'aspect-ratio della camera.

NB.

È fondamentale che l'aspect-ratio della camera sia identico all'aspect-ratio della canvas, altrimenti le immagine renderizzate risulteranno distorte. Nei prossimi capitoli vedremo come rendere la nostra scena responsive.

Abbiamo quasi finito, ci manca soltanto di renderizzare la nostra scena invocando il metodo render(…) del renderer al quale passeremo due parametri: la scena da renderizzare e la camera da utilizzare come punto di vista.

Fatto ciò dovremmo vedere nella nostra pagina un riquadro completamente nero. Sta funzionando tutto ma c'è un problema.

Abbiamo creato il cubo e la camera, ma non abbiamo definito come sono posizionati nello spazio. Entrambi hanno una proprita position che ci permetto di modificare la posizione nello spazio indicando le coordinate x, y, e z, come in un piano cartesiano.

Di default camera ed oggetti vengono creati al centro dello spazio, alle coordinate x = 0, y = 0, e z = 0. Quindi la nostra camera si trova dentro al nostro cubo. Sarà sufficiente spostarla un po indietro per riuscire a vedere il cubo correttamente.

Ma in che direzione bisogna spostarla?

Sistema di riferimento X, Y e Z

Il sistema di riferimento dello spazio 3D è composto da 3 assi X, Y e Z.

Inizialmente l'asse X è disposto orizzontalmente ed è orientato verso destra, quindi valori positivi sposteranno i nostri oggetti verso destra, mentre valori negativi li sposteranno verso sinistra.

L'asse Y è disposto verticalmente ed è orientato verso l'alto. Di conseguenza valori positivi sposteranno gli oggetti verso l'alto, e quelli negativi verso il basso.

L'asse Z è disposto perpendicolarmente alla schermo del monitor orientato verso l'osservatore. Di default la camera è oreintata lungo l 'asse Z ma con verso opposto come mostrato in figura.

Quindi per spostare indietro la camera dobbiamo assegnare un valore positivo alla coordinata z.

Ricarichiamo la pagina per vedere un risultato di questo tipo:

Il quadrato colorato al centro della scena è il nostro "verde cubo" che stiamo osservando frontalmente.

Conclusioni

Non è certamente la scena più entusiasmante del web, ma è il primo passo, ed è un passo necessario perchè abbiamo visto quasi tutti gli elementi necessari a qualunque scena 3D. Nei prossimi articoli vedremo meglio come manipolare e animare gli oggetti. Aggiungeremo qualche luce nella scena e sostituiremo il materiale base con qualcosa ti più realistico.

Qui sotto il link per creare la stessa scena con Vite.

E le luci?

Ti sarai accorto che non abbiamo messo nessuna luce, eppure siamo in grado di vedere il cubo. Come mai?

Questo è dovuto al fatto che il MeshBasicMaterial non è influenzato dalla luce. Assegnando un colore a questo materiale, ad ogni pixel appartenente alla geometria del cubo verrà applicato quel preciso colore, senza variazioni legate all’ illuminazione.

Questo infatti è un materiale un po’ particolare e torna molto comodo in situazioni ben precise. Nella stragrande maggioranza dei casi ci serve che il nostri materiali siano influenzati dalle luci presenti nella scena, allora useremo gli altri materiale che three.js ci mette a disposizione.

Congratulazioni

Per la tua prima scena 3D realizzata con three.js.

Ti invito a modificare la posizione del cubo o della camera sperimentando con soluzioni diverse per vedere come cambia l'immagine.

Come potrai immaginare, oltre alla posizione possiamo modificare anche la rotazione e la scala dei nostri oggetti per ottenere risultati diversi.

Sentiti libero anche di aggiungere altri oggetti alla scena provando con altre geometrie come:

  • sfera
  • cilindro
  • cono
  • toro

Le trovi sulla documentazione.

Puoi anche creare diversi materiali per dare vita a Mesh con geometrie e colori diversi.

--

--

Gianluca Lomarco

I am a creative developer working with webGL and fullstack Main teacher at Boolean Academy. Now I’am starting a new experience as content creator in YouTube