Najvažnije iz članka
- Three.js i React Fiber predstavljaju moćnu kombinaciju za kreiranje interaktivnih 3D web aplikacija.
- React Three Fiber (R3F) omogućuje deklarativno pisanje Three.js scena kao React komponenti, pojednostavljujući razvoj i upravljanje stanjem.
- Osnovna 3D scena uključuje `Canvas`, svjetla, kameru i objekte definirane geometrijom i materijalom, s mogućnošću animacije putem `useFrame` hooka.
- Paketi poput `@react-three/drei` i `@react-three/postprocessing` nude gotove komponente za kontrolu kamere, učitavanje modela (glTF) i napredne vizualne efekte poput sjena i post-processinga.
- Optimizacija performansi je ključna za 3D web aplikacije, uključujući tehnike poput instancinga, optimizacije geometrije i tekstura, te pravilnog upravljanja resursima.
Sadržaj članka
U današnjem digitalnom dobu, web aplikacije sve više teže pružanju bogatijih i interaktivnijih korisničkih iskustava. Dok smo se nekada zadovoljavali statičnim stranicama, danas je trend prema dinamičnim, vizualno privlačnim sučeljima koja ne samo informiraju, već i angažiraju korisnika. Jedan od najuzbudljivijih smjerova u ovom razvoju je integracija 3D grafike direktno u preglednik. Zahvaljujući napretku web tehnologija, posebice WebGL-a i moćnih JavaScript biblioteka, stvaranje interaktivnih 3D scena nikada nije bilo dostupnije.
Ovaj članak služi kao sveobuhvatan vodič za kreiranje takvih iskustava, fokusirajući se na kombinaciju Three.js i React Fiber. Three.js je de facto standard za 3D grafiku na webu, pružajući apstrakciju nad složenim WebGL API-jem, čineći ga pristupačnijim developerima. S druge strane, React Fiber (ili točnije, React Three Fiber – R3F) je React renderer za Three.js koji omogućuje deklarativno stvaranje 3D scena unutar React komponenti, donoseći sve prednosti React ekosustava – od upravljanja stanjem, do komponentne arhitekture i reaktivnosti – u svijet 3D grafike.
Zašto Three.js i React Fiber?
Three.js se ističe svojom bogatom paletom značajki, uključujući različite tipove geometrija, materijala, svjetala, kamera, post-processing efekata, te podršku za učitavanje raznih 3D modela (glTF, OBJ, FBX, itd.). Njegova aktivna zajednica i opsežna dokumentacija čine ga idealnim izborom za svakoga tko se želi baviti 3D grafikom na webu.
Međutim, direktno korištenje Three.js-a u većim projektima može postati izazovno, pogotovo kada se radi o upravljanju stanjem, reaktivnom ažuriranju scene i integraciji s postojećim React aplikacijama. Tu na scenu stupa React Three Fiber (R3F). R3F nije samo “wrapper” oko Three.js-a; to je kompletan React renderer. To znači da možete pisati Three.js objekte kao obične React komponente, što značajno pojednostavljuje razvoj, poboljšava čitljivost koda i omogućuje korištenje React hookova i konteksta za upravljanje 3D scenom. Konačno, R3F omogućuje da React upravlja životnim ciklusom Three.js objekata, uključujući stvaranje, ažuriranje i brisanje, što smanjuje boilerplate kod i omogućuje modularniji pristup.
Postavljanje projekta
Za početak, trebat će nam standardna React aplikacija. Možemo je stvoriti pomoću Create React App ili Vitea. Za ovaj tutorial koristit ćemo Vite zbog njegove brzine i jednostavnosti.
npm create vite my-3d-app --template react-ts
cd my-3d-app
npm install
Nakon što je projekt inicijaliziran, instaliramo potrebne biblioteke:
npm install three @react-three/fiber @react-three/drei
three: Osnovna Three.js biblioteka.@react-three/fiber: React Three Fiber renderer.@react-three/drei: Skup korisnih, apstrahiranih komponenti i hookova za R3F, koje olakšavaju rad s kamerama, kontrolama, shadereima i drugim uobičajenim zadacima.
Struktura osnovne 3D scene
Svaka 3D scena u Three.js-u sastoji se od nekoliko ključnih elemenata:
- Scena (
Scene): Kontejner za sve objekte, svjetla i kamere. - Kamera (
Camera): Određuje perspektivu iz koje se scena promatra. - Renderer (
WebGLRenderer): Preko kojeg se scena prikazuje na platnu (canvasu). - Objekti (
Meshes): Sastoje se od geometrije (oblik) i materijala (kako objekt izgleda). - Svjetla (
Lights): Osvjetljavaju scenu.
S R3F-om, sve ove koncepte prevodimo u React komponente. Stvorimo Canvas komponentu iz @react-three/fiber koja će biti naš glavni ulaz u 3D svijet:
// src/App.tsx
import React from 'react';
import { Canvas } from '@react-three/fiber';
function App() {
return (
<div width: '100vw', height: '100vh' }}>
<Canvas>
{/* Ovdje će ići naši 3D objekti i svjetla */}
</Canvas>
</div>
);
}
export default App;
Canvas komponenta automatski postavlja WebGL renderer, scenu i defaultnu kameru. Možemo konfigurirati kameru i druge postavke pomoću propova.
Dodavanje prvog objekta: Kocka
Dodajmo jednostavnu rotirajuću kocku u našu scenu. Definirat ćemo novu komponentu Box:
// src/components/Box.tsx
import React, { useRef, useState } from 'react';
import { useFrame } from '@react-three/fiber';
import { Mesh } from 'three';
interface BoxProps {
position?: [number, number, number];
}
const Box: React.FC<BoxProps> = ({ position }) => {
const meshRef = useRef<Mesh>(null!); // Referenca na Three.js mesh objekt
const [hovered, setHover] = useState(false);
const [active, setActive] = useState(false);
// useFrame je hook koji se pokreće u svakom "frame-u" animacije
useFrame((state, delta) => {
if (meshRef.current) {
meshRef.current.rotation.x += delta;
meshRef.current.rotation.y += delta * 0.5;
}
});
return (
<mesh
position={position}
ref={meshRef}
scale={active ? 1.5 : 1}
=> setActive(!active)}
=> setHover(true)}
=> setHover(false)}
>
<boxGeometry args={[1, 1, 1]} /> {/* Geometrija kocke */}
<meshStandardMaterial color={hovered ? 'hotpink' : 'orange'} /> {/* Materijal */}
</mesh>
);
};
export default Box;
Sada integriramo ovu komponentu u App.tsx:
// src/App.tsx
import React from 'react';
import { Canvas } from '@react-three/fiber';
import Box from './components/Box';
function App() {
return (
<div width: '100vw', height: '100vh' }}>
<Canvas camera={{ fov: 75, position: [0, 0, 5] }}>
{/* Ambijentalno svjetlo koje osvjetljava scenu ravnomjerno */}
<ambientLight intensity={0.5} />
{/* Direkcionalno svjetlo koje simulira sunce */}
<directionalLight position={[0, 5, 5]} intensity={1} />
<Box position={[0, 0, 0]} />
</Canvas>
</div>
);
}
export default App;
Pokrenite aplikaciju (npm run dev) i trebali biste vidjeti rotirajuću narančastu kocku. Klikom na nju, promijenit će veličinu, a prelaskom miša preko nje promijenit će boju u ružičastu. To demonstrira kako R3F omogućuje interaktivnost i upravljanje stanjem unutar 3D scene na React način.
Dodavanje kamera kontrola i pomoćnih alata s drei
@react-three/drei je iznimno koristan paket koji pruža pregršt gotovih rješenja. Jedna od najčešćih potreba je mogućnost rotiranja scene i zumiranja pomoću miša. To se postiže pomoću OrbitControls.
// src/App.tsx (djelomična izmjena)
import { OrbitControls } from '@react-three/drei';
// ...unutar Canvas komponente...
<Canvas camera={{ fov: 75, position: [0, 0, 5] }}>
<ambientLight intensity={0.5} />
<directionalLight position={[0, 5, 5]} intensity={1} />
<Box position={[0, 0, 0]} />
<OrbitControls /> {/* Dodajemo kontrolu kamere */}
</Canvas>
Sada možete koristiti miš za rotiranje i zumiranje scene. drei nudi mnoge druge korisne komponente kao što su Stars, Html (za postavljanje HTML elemenata u 3D prostor), GizmoHelper i još mnogo toga.
Učitavanje 3D modela
Učitavanje kompleksnijih 3D modela, poput onih eksportiranih iz Blendera ili drugih 3D alata, ključno je za stvaranje bogatih scena. Najpopularniji format za web je glTF (GL Transmission Format) zbog svoje učinkovitosti i svestranosti.
@react-three/drei pruža hook useGLTF za jednostavno učitavanje glTF modela.
Pretpostavimo da imate model.gltf datoteku u public/models direktoriju.
// src/components/Model.tsx
import React from 'react';
import { useGLTF } from '@react-three/drei';
interface ModelProps {
url: string;
}
const Model: React.FC<ModelProps> = ({ url }) => {
const { scene } = useGLTF(url); // Učitavanje modela
// scene.clone() je važno ako želite koristiti isti model više puta
// kako bi svaki bio neovisan i imao vlastitu transformaciju
return <primitive object={scene.clone()} scale={0.5} position={[0, -1, 0]} />;
};
export default Model;
I dodajte ga u App.tsx:
// src/App.tsx (djelomična izmjena)
import Model from './components/Model';
// ...unutar Canvas komponente...
<Canvas camera={{ fov: 75, position: [0, 0, 5] }}>
<ambientLight intensity={0.5} />
<directionalLight position={[0, 5, 5]} intensity={1} />
<Box position={[2, 0, 0]} />
<Model url="/models/model.gltf" /> {/* Učitavanje našeg modela */}
<OrbitControls />
</Canvas>
Važna napomena za postavljanje modela: Ako se model ne vidi, provjerite putanju do datoteke, veličinu modela (scale prop) i poziciju (position prop) te jesu li svjetla dovoljno jaka. Također, modeli često imaju vlastitu orijentaciju, pa će možda biti potrebno rotirati ih (rotation prop).
Naprednije tehnike: sjenke i post-processing
Za realističniji izgled, sjenke su neophodne. Three.js ih podržava, ali je potrebno ih eksplicitno omogućiti na rendereru, svjetlima i objektima.
// src/App.tsx (djelomične izmjene)
import { Canvas } from '@react-three/fiber';
function App() {
return (
<div width: '100vw', height: '100vh' }}>
<Canvas
shadows // Omogućava sjene na rendereru
camera={{ fov: 75, position: [0, 0, 5] }}
>
<ambientLight intensity={0.5} />
<directionalLight
position={[0, 5, 5]}
intensity={1}
castShadow // Svjetlo baca sjene
shadow-mapSize-width={1024} // Rezolucija sjena
shadow-mapSize-height={1024}
shadow-camera-far={50}
shadow-camera-left={-10}
shadow-camera-right={10}
shadow-camera-top={10}
shadow-camera-bottom={-10}
/>
{/* Podloga koja prima sjene */}
<mesh receiveShadow position={[0, -2, 0]} rotation={[-Math.PI / 2, 0, 0]}>
<planeGeometry args={[10, 10]} />
<meshStandardMaterial color="lightgray" />
</mesh>
<Box position={[0, 0, 0]} castShadow receiveShadow /> {/* Kocka baca i prima sjene */}
{/* Vaš model, ako ga želite da baca/prima sjene, također mora imati te propove */}
{/* <Model url="/models/model.gltf" castShadow receiveShadow /> */}
<OrbitControls />
</Canvas>
</div>
);
}
export default App;
Post-processing efekti dodatno poboljšavaju vizualni dojam. Biblioteka @react-three/postprocessing (koja je također dio drei ekosustava) olakšava njihovu implementaciju. Efekti poput Bloom, SSAO, Depth of Field mogu transformirati scenu.
npm install @react-three/postprocessing
// src/App.tsx (djelomične izmjene)
import { EffectComposer, Bloom } from '@react-three/postprocessing';
// ...unutar Canvas komponente...
<Canvas>
{/* ...vaši objekti i svjetla... */}
<EffectComposer>
<Bloom luminanceThreshold={0} luminanceSmoothing={0.9} height={300} />
{/* Dodajte i druge efekte ovdje */}
</EffectComposer>
</Canvas>
Optimizacija performansi
3D grafika može biti vrlo resursno intenzivna. Nekoliko savjeta za optimizaciju:
- Koristite instancing: Kada imate mnogo istih objekata,
InstancedMeshiz Three.js-a (dostupan i krozdrei/InstancedMeshkomponentu) može značajno smanjiti draw calls. - Optimizirajte geometriju i teksture: Smanjite broj poligona u 3D modelima. Koristite komprimirane teksture (npr. KTX2) i smanjite njihovu rezoluciju gdje god je to moguće.
- Frustum Culling: Three.js automatski ne renderira objekte koji nisu u vidnom polju kamere, ali pazite na objekte koji su preveliki ili imaju složene bounding boxeve.
- Level of Detail (LOD): Prikazujte manje detaljne verzije objekata kada su udaljeni od kamere.
- Debounce/Throttle
useFrame: Ako imate skupe izračune unutaruseFrame, razmislite o njihovom smanjivanju ili pokretanju rjeđe. Npr. možete koristitiuseRefza pohranu stanja izvan re-render petlje. - Koristite
useMemoiuseCallback: Memoizirajte skupe objekte i funkcije kako biste izbjegli nepotrebno ponovno stvaranje Three.js instanci. - Pravilno zbrinjavanje resursa: R3F se brine o većini toga, ali kod kompleksnijih scena s custom Three.js objektima, pazite na brisanje geometrije, materijala i tekstura iz memorije kada više nisu potrebni kako biste spriječili "memory leaks".
Zaključak
Kombinacija Three.js-a i React Fiber-a otvara nevjerojatne mogućnosti za razvoj interaktivnih i vizualno impresivnih web iskustava. Od jednostavnih animacija do kompleksnih 3D vizualizacija, ova tehnološka sinergija pruža moćan i deklarativan alat za svakog web developera. Iako je putovanje u 3D svijet strmo, R3F značajno ublažava krivulju učenja, omogućujući developerima da se fokusiraju na kreativni aspekt, umjesto na složenosti WebGL API-ja. Eksperimentirajte s različitim geometrijama, materijalima, svjetlima i post-processing efektima, i otkrit ćete neograničen potencijal 3D grafike na webu. Sretno kodiranje i kreiranje!
Komentari