Particelle
Le particelle sono un ottimo modo per aggiungere vita alla tua scena. Possono essere utilizzate in vari modi, come neve, pioggia, fuoco, fumo o effetti magici. Spesso vengono utilizzate per creare effetti atmosferici, come nebbia, polvere o scintille.
In questa lezione, esploreremo diversi modi per creare particelle usando Threejs e React Three Fiber per creare questa scena notturna con un cielo stellato ed effetto nevicata:
Osserva come i fiocchi di neve cadono e le stelle brillano nel cielo. ❄️✨
Stelle
Il nostro codice iniziale contiene questa "Scena Invernale Low Poly" di EdwiixGG sopra un cubo e una sorgente luminosa animata.
Sembra bello ma possiamo renderlo più interessante aggiungendo stelle al cielo.
Iniziamo aggiungendo stelle al cielo. Il modo più semplice con React Three Fiber è utilizzare il componente Stars dalla libreria drei.
In components/Experience.jsx
:
// ... import { Stars } from "@react-three/drei"; export const Experience = () => { // ... return ( <> <Stars /> {/* ... */} </> ); };
E voilà, il nostro cielo è ora pieno di belle stelle splendenti!
Possiamo giocare con i suoi parametri come factor
per regolare la dimensione in base alla distanza o speed
per regolare il timing dell'effetto fade.
Consulta la documentazione per tutti i parametri disponibili.
Vediamo come funziona dietro le quinte esplorando il codice sorgente del componente Stars.
Possiamo vedere che per renderizzare le stelle vengono utilizzati points riempiti con tre attributi sulla geometria:
position
: per determinare la posizione di ciascuna stellacolors
: per determinare il colore di ciascuna stellasize
: per determinare la dimensione di ciascuna stella
Poi un ShaderMaterial personalizzato chiamato StarfieldMaterial
è responsabile di visualizzare i punti correttamente basati su quei valori degli attributi e l'uniform time per l'effetto di fading.
In primo luogo, questo approccio è ottimo, è leggero e completamente elaborato sulla GPU, il che significa che potresti potenzialmente inserire un numero molto elevato di stelle.
Ma visivamente vedo due cose che potrebbero essere migliorate:
- Le stelle sono rappresentate come quadrati.
- L'effetto di fading è sincronizzato tra tutte le stelle risultando in un effetto di lampeggiamento.
Poiché non abbiamo controllo su questi aspetti con il componente Stars
, creiamo il nostro sistema di stelle!
Stelle personalizzate
Per avere un controllo più facile sulle stelle, gestiremo la loro logica sul lato CPU utilizzando l'istanziazione.
Non preoccuparti se non è il modo più ottimizzato, per un numero ragionevole di stelle andrà bene ed è molto più flessibile. Impareremo come gestire le nostre particelle sul lato GPU quando costruiremo il nostro semplice motore VFX e quando impareremo TSL più avanti in questo capitolo.
PS: L'istanziazione è comunque un modo efficiente per rendere un grande numero di oggetti con la stessa geometria, come visto nella lezione sull'ottimizzazione.
Istanze
Cominciamo creando il nostro componente StarrySky
in un nuovo file components/StarrySky.jsx
:
import { Instance, Instances } from "@react-three/drei"; import { useMemo, useRef } from "react"; import { randFloatSpread } from "three/src/math/MathUtils.js"; export const StarrySky = ({ nbParticles = 1000 }) => { const particles = useMemo( () => Array.from({ length: nbParticles }, (_, idx) => ({ position: [ randFloatSpread(20), randFloatSpread(20), randFloatSpread(20), ], })), [] ); return ( <Instances range={nbParticles} limit={nbParticles} frustumCulled={false}> <planeGeometry args={[1, 1]} /> <meshBasicMaterial /> {particles.map((props, i) => ( <Particle key={i} {...props} /> ))} </Instances> ); }; const Particle = ({ position }) => { const ref = useRef(); return <Instance ref={ref} position={position} />; };
Stiamo creando un InstancedMesh utilizzando una plane geometry combinata con un mesh basic material.
Grazie al componente <Instance />
di Drei, siamo in grado di creare istanze di questo mesh e di controllare ciascuna particella (istanza) individualmente.
Ora sostituiamo il componente Stars
con il nostro personalizzato in components/Experience.jsx
:
// ... import { StarrySky } from "./StarrySky"; export const Experience = () => { // ... return ( <> <StarrySky /> {/* ... */} </> ); };
Ora abbiamo questo cielo caotico:
È un buon punto di partenza!
Regoliamo le dimensioni delle stelle. Nel useMemo
responsabile dell'impostazione delle posizioni delle particelle, possiamo aggiungere un attributo size
:
import { randFloat, randFloatSpread } from "three/src/math/MathUtils.js"; // ... const particles = useMemo( () => Array.from({ length: nbParticles }, (_, idx) => ({ position: [randFloatSpread(20), randFloatSpread(20), randFloatSpread(20)], size: randFloat(0.1, 0.25), })), [] );
E nel componente Particle
, possiamo passare questo attributo size
al componente Instance
:
const Particle = ({ position, size }) => { const ref = useRef(); return <Instance ref={ref} position={position} scale={size} />; };
Ora è meglio, abbiamo stelle di diverse dimensioni:
Ma abbiamo un problema, le stelle sono posizionate tra -20
e 20
usando randFloatSpread(20)
, ma vogliamo che le stelle siano posizionate lontano nel cielo.
Per fare ciò, manteniamo la z
sempre a 0
e regoliamo la posizione x
tra 5
e 15
.
Le nostre stelle saranno posizionate casualmente tra 5
e 15
sull'asse x
.
E per essere tutto intorno al centro, ruotiamo la posizione y
tra 0
e 2 * Math.PI
.
Il centro non conterrà mai stelle e le stelle saranno sparse in tutte le direzioni.
Nel useMemo
responsabile dell'impostazione delle posizioni delle particelle, possiamo regolare l'attributo position
e aggiungere un attributo rotation
:
const particles = useMemo( () => Array.from({ length: nbParticles }, (_, idx) => ({ position: [randFloat(5, 15), randFloatSpread(20), 0], rotation: [0, randFloat(0, Math.PI * 2), 0], size: randFloat(0.1, 0.25), })), [] );
React Three Fiber: The Ultimate Guide to 3D Web Development
✨ You have reached the end of the preview ✨
Go to the next level with Three.js and React Three Fiber!
Get full access to this lesson and the complete course when you enroll:
- 🔓 Full lesson videos with no limits
- 💻 Access to the final source code
- 🎓 Course progress tracking & completion
- 💬 Invite to our private Discord community
One-time payment. Lifetime updates included.