TECH3

ONE FIBER AT A TIME...​​

04                                        2025-2026

In dit onderdeel herhalen we de basisprincipes van React Three Fiber, zodat we vertrouwd raken met de belangrijkste concepten van 3D-rendering in React. Zo bouwen we een stevig fundament om nadien zelf interactieve en visueel indrukwekkende 3D-ervaring te maken.

ONE FIBER AT A TIME

SETUP

01

01

SETUP

SETUP

Hoe zetten we React Three Fiber op? 

Voer volgende uit in de terminal 

npm create vite@latest

Volg deze stappen:

  • Kies een naam voor het project
  • Selecteer een framework (REACT)
  • Selecteer Typescript + Compiler
  • 'No' to rolldown-vite (experimental)
  • Install with npm and start (yes)

Vervolgens voer je deze install uit

npm install three @react-three/fiber

01

SETUP

FIBER

In het install-commando zie je een @ teken. Dit geeft aan dat de package deel uitmaakt van een groter geheel, namelijk React Three. De installatie is dus succesvol voltooid, en we kunnen nu verder met het opzetten van onze eerste scène.

ONE FIBER AT A TIME

SYNTAX

02

02

SYNTAX

FIBER SYNTAX

Three Fiber maakt het werken met 3D in React een stuk eenvoudiger: in plaats van alles zelf te moeten opbouwen zoals in native Three.js, kun je hier gewoon gebruikmaken van bestaande componenten.

Native Three.js

const mesh = new THREE.Mesh()
mesh.geometry = new THREE.BoxGeometry(1, 1, 1)
mesh.material = new THREE.MeshBasicMaterial({ color: 'red' })

scene.add(mesh)

R3F (React Three Fiber)

<mesh>
    <boxGeometry />
    <meshBasicMaterial color="red" />
</mesh>

Omdat de geometry en het materiaal binnen onze mesh zitten, koppelt Fiber ze automatisch aan elkaar. De syntax is bovendien korteren overzichtelijker.

02

SYNTAX

FIBER SYNTAX

In vanilla Three.js was het aanpassen van positie en rotatie wat ingewikkelder, maar in Fiber kunnen we dit gewoon rechtstreeks via props doen.

Native Three.js

const mesh = new THREE.Mesh()
mesh.position.set(1, 2, 3)
mesh.rotation.x = 0.5
mesh.geometry = new THREE.BoxGeometry(1, 1, 1)
mesh.material = new THREE.MeshBasicMaterial({ color: 'red' })

scene.add(mesh)

R3F (React Three Fiber)

<mesh position={ [ 1, 2, 3 ] } rotation-x={ 0.5 }>
    <boxGeometry />
    <meshBasicMaterial color="red" />
</mesh>

02

SYNTAX

FIBER SYNTAX

Het is nu ook veel eenvoudiger om objecten in elkaar te nesten of te groeperen, zodat je makkelijk complexe 3D-structuren kunt opbouwen.

Native Three.js

const group = new THREE.Group()
scene.add(group)

const mesh1 = new THREE.Mesh()
mesh1.geometry = new THREE.BoxGeometry(1, 1, 1)
mesh1.material = new THREE.MeshBasicMaterial({ color: 'red' })

const mesh2 = new THREE.Mesh()
mesh2.geometry = new THREE.SphereGeometry(0.5)
mesh2.material = new THREE.MeshBasicMaterial({ color: 'orange' })

group.add(mesh1, mesh2)

02

SYNTAX

FIBER SYNTAX

R3F (React Three Fiber)

<group>
    <mesh>
        <boxGeometry />
        <meshBasicMaterial color="red" />
    </mesh>
    <mesh>
        <sphereGeometry />
        <meshBasicMaterial color="orange" />
    </mesh>
</group>

Door de component-based aanpak zal je minder fouten maken of iets vergeten toe te voegen aan de scene.

02

SYNTAX

CONCLUSION

Werk je in React en wil je 3D toevoegen? Dan is R3F absoluut de makkelijkste keuze.
 

Gebruik je liever native Three.js, dan heb je wel meer vrijheid, maar ook veel meer werk — je moet namelijk alles zelf opbouwen.

ONE FIBER AT A TIME

OUR FIRST SCENE

03

03

OUR FIRST SCENE

CANVAS

Net zoals een schilder een canvas nodig heeft om zijn kunstwerk te creëren, hebben wij een Canvas nodig om onze 3D-ervaringen op te “schilderen”. Dit doen we met behulp van de Canvas-component.

Importeer Canvas via import en voeg daarna de component toe aan je index.tsx

import { Canvas } from '@react-three/fiber'

//...

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <Canvas></Canvas>
  </StrictMode>,
)

03

OUR FIRST SCENE

WHERE IS IT?

Mogelijks zie je nog niets (light mode) maar kijk eens naar de inspector?

We hebben effectief een html canvas-element in onze DOM-staan.

TIP: Bij het opstarten van een React project verwijder je best alle premade content en styling

03

OUR FIRST SCENE

CANVAS

Tijd om iets in onze canvas te plaatsen en te kijken of ze doet wat we verwachten!

Plaats tussen het Canvas element een mesh op volgende manier.

 <Canvas>
     <mesh>
        <torusKnotGeometry />
        <meshNormalMaterial />
    </mesh>
</Canvas>

03

OUR FIRST SCENE

RESIZE IT

We merken dat onze canvas niet het volledige scherm vult. Dit kunnen we oplossen met behulp van CSS.

Voeg volgende toe aan index.css 

html,
body,
#root
{
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    overflow: hidden;
}

Onze canvas neemt nu het volledige scherm in. Dit is ideaal wanneer je een volledige 3D-ervaring wilt creëren. Als dat niet het geval is, kun je de CSS aanpassen aan de behoeften van je applicatie.

03

OUR FIRST SCENE

REFACTOR

In plaats van alles in main.tsx te plaatsen, werken we met overzichtelijke componenten. Maak een Experience-component aan waarin onze 3D-ervaring zal komen.

In onze main.tsx zou je dus enkel volgende moeten zien.

import Experience from './Experience'


createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <Canvas>
      <Experience />  
    </Canvas>
  </StrictMode>,
)

03

OUR FIRST SCENE

REFACTOR

Plaats de 3D elementen in je Experience tussen een fragment (<> </>)

import './Experience.css'

function Experience() {
 

  return (
    <>
      <mesh>
        <torusKnotGeometry />
        <meshNormalMaterial />
      </mesh>
    </>
  )
}

export default Experience

Experience.tsx ziet er als volgt uit.

ONE FIBER AT A TIME

MESHES

04

04

MESHES

DIFFERENT TYPES

In Three.js (en dus ook in R3F) hebben we verschillende soorten geometries en materials. 

  • BoxGeometry
  • SphereGeometry
  • PlaneGeometry
  • CylinderGeometry
  • ConeGeometry
  • TorusKnotGeometry
  • ...

04

MESHES

SPHERE

We hoeven onze meshes niet telkens handmatig te importeren. Deze manier van werken heet declarative. React Three Fiber (R3F) begrijpt automatisch welk element we willen gebruiken en voegt het toe aan onze scene.

Verander de mesh van Torus naar Sphere in Experience.tsx

<mesh>
    <sphereGeometry />
    <meshBasicMaterial />
</mesh>

Weet je niet welke props deze geometry aanvaard? Bekijk dan zeker de documentatie

Met args kunnen we de eigenschappen van onze objecten aanpassen. Laten we bijvoorbeeld de sphere vergroten.

<mesh>
    <sphereGeometry args={ [ 1.5, 32, 32 ] } />
    <meshBasicMaterial />
</mesh>

De volgorde van de args zijn degene die in de originele three.js class staan.

04

MESHES

PROPERTIES

Een andere optie in R3F is om properties los van elkaar te definiëren. Dit maakt de code overzichtelijker: we geven simpelweg de propertynaam en de gewenste waarde op.

Verander de kleur van de material en activeer 'wireframe'.

<mesh>
    <sphereGeometry args={ [ 1.5, 32, 32 ] } />
    <meshBasicMaterial color="royalblue" wireframe />
</mesh>

Wanneer je wireframe toevoegt, wordt dit automatisch op true gezet. Wil je het uitschakelen, dan kun je false meegeven, maar dat is standaard al het geval en kan dus worden weggelaten.

<mesh>
    <sphereGeometry args={ [ 1.5, 32, 32 ] } />
    <meshBasicMaterial color="royalblue" wireframe={false} />
</mesh>

04

MESHES

BOX

We veranderen onze mesh naar een boxGeometry en bekijken hoe we de properties afzonderlijk kunnen instellen.

Verander de code in Experience.tsx naar volgende

<mesh>
    <boxGeometry />
    <meshBasicMaterial color="royalblue" wireframe />
</mesh>

Net zoals bij het aanpassen van de kleur of het inschakelen van wireframe, kunnen we ook de scale, position en rotation van onze mesh eenvoudig wijzigen.

<mesh scale={ [ 3, 2, 1 ] }>
    <boxGeometry />
    <meshBasicMaterial color="royalblue" wireframe />
</mesh>

04

MESHES

BOX

Als we een mesh uniform willen schalen, roteren of positioneren, hoeven we slechts één waarde op te geven. Deze wordt dan voor x, y en z gebruikt.

Verander de scale van de mesh naar volgende

<mesh scale={ 1.5 }>

Verander de position van de mesh door volgende uit te voeren

<mesh position={ [ 2, 0, 0 ] } scale={ 1.5 }>

Stel dat je enkel de x-as wil veranderen dan kan je volgende doen

<mesh position-x={ 2 } scale={ 1.5 }>

04

MESHES

ROTATION

Hetzelfde geldt voor rotation. Houd er rekening mee dat je bij rotaties altijd gebruikmaakt van Math.PI.

Roteer de Cube op de y-as door volgende aan te passen.

<mesh rotation-y={ Math.PI * 0.25 } position-x={ 2 } scale={ 1.5 }>

Hier komt uitleg over MATH.PI en de waarden (tabel?)

04

MESHES

PRACTICE (SQUID GAME)

Probeer nu zelf eens volgende scene te maken in R3F.

"Creëer een scene met drie planes. Op elke plane plaats je een verschillende vorm: bijvoorbeeld een cirkel, een driehoek en een vierkant — de keuze van de geometry is aan jou. Geef elke vorm een eigen kleur, maar houd de planes uniform van kleur."

ONE FIBER AT A TIME

ANIMATION

05

05

ANIMATION

ANIMATE

Een statische kubus is leuk, maar het wordt pas interessant als hij kan bewegen. Daarvoor gebruiken we de useFrame-hook van R3F.

React tekent elk frame, waardoor onze kubus zichtbaar blijft. In gamingtermen noemen we dit FPS (Frames per Second). Met de useFrame-hook kun je code uitvoeren bij elke frame, oftewel bij elke “tick”.

Voer volgende code uit in Experience.tsx en kijk naar de console.

import { useFrame } from '@react-three/fiber'

export default function Experience()
{
    useFrame(() =>
    {
        console.log('tick')
    })

    // ...
}

05

ANIMATION

USEREF

Omdat een tick bij elk frame loopt, kunnen we nu de kubus laten roteren. Om dit te doen, hebben we eerst een referentie naar de kubus nodig.

Plaats een ref op de mesh zodat we deze kunnen aanspreken

import { useRef } from 'react'
import * as THREE from 'three'

export default function Experience()
{
    const cubeRef = useRef<THREE.Mesh>(null)

    // ...
}

<mesh ref={ cubeRef } rotation-y={ Math.PI * 0.25 } position-x={ 2 } scale={ 1.5 }>

Vervolgens kunnen we onze ref gebruiken in de useFrame hook.

useFrame(() =>
{
    cubeRef.current.rotation.y += 0.01
})

05

ANIMATION

DELTA

Misschien valt het je op dat de kubus van je buur sneller of langzamer draait dan die van jou. Dat komt doordat apparaten verschillende framerates hebben. Door delta te gebruiken in plaats van een vaste rotatiewaarde, maak je de beweging framerate-onafhankelijk.

Voeg volgende code in Experience.tsx

useFrame((state, delta) =>
{
	console.log(delta)
    cubeRef.current.rotation.y += delta
})
  • state: Geeft informatie over de camera, scene, renderer, ...
  • delta: bevat de tijd die voorbij is ten opzichte van de vorige frame in seconden.

05

ANIMATION

GROUP

Je kunt niet alleen losse elementen animeren, maar ook hele groepen tegelijk. Zet de meshes in een group en maak een referentie naar die group om ze gezamenlijk te manipuleren.

Plaats de elementen in een group wrapper

<group>
    <mesh position-x={ - 2 }>
        <sphereGeometry />
        <meshBasicMaterial color="orange" />
    </mesh>

    <mesh ref={ cubeRef } rotation-y={ Math.PI * 0.25 } position-x={ 2 } scale={ 1.5 }>
        <boxGeometry />
        <meshBasicMaterial color="royalblue" />
    </mesh>
</group>

05

ANIMATION

GROUP

Maak een groupRef aan en plaats deze op de group.

export default function Experience()
{
    const cubeRef = useRef<THREE.Mesh>(null)
    const groupRef = useRef<THREE.Group>(null)

    // ...
    
    <group ref={ groupRef }>
}

Animeer nu de groupRef door ook zijn rotatie aan te spreken.

useFrame((_, delta) =>
{
 		if(!cubeRef.current || !groupRef.current) return
        cubeRef.current.rotation.y += delta
        groupRef.current.rotation.y += delta
})

ONE FIBER AT A TIME

CONTROLS

06

DREI

We stappen nu over op een package die ons extra “powers” geeft: Drei.

Voer volgende install in de terminal

npm install @react-three/drei

06

CONTROLS

CONTROLS

We zien onze scene verschijnen, maar voorlopig kunnen we er niet in rondbewegen of omheen draaien. Dat lossen we op met controls — en daarvan zijn er verschillende types:

  • OrbitControls: laat je met de muis rond een object of scène draaien, zoomen en pannen.
     
  • TransformControls: laat je objecten verplaatsen, roteren of schalen in de 3D-ruimte.
     
  • PivotControls: laat je het draaipunt (pivot) van een object aanpassen en verplaatsen.
     
  • en nog veel meer...

06

CONTROLS

ORBITCONTROLS

De OrbitControls laten ons met de muis vrij rondkijken in onze scene. Normaal gezien is dat best wat werk om zelf op te zetten, maar met Drei gaat het supersimpel.

Importeer OrbitControls en plaats het in de jsx rendering (bovenaan)

import { OrbitControls } from '@react-three/drei'

export default function Experience()
{
    return <>

        <OrbitControls />

        {/* ... */}

    </>
}

06

CONTROLS

DAMPING

Als je met de muis rond de scene draait en loslaat, merk je dat de beweging nog even zachtjes doorgaat. Dat effect heet damping. In de 3D-wereld zorgt het voor een vloeiendere ervaring, maar je kunt het ook uitschakelen als je liever directe controle hebt.

Verander volgende in de OrbitControls component.

<OrbitControls enableDamping={ false } />

06

CONTROLS

We houden damping aan, want we willen dat vloeiende gevoel behouden. De eigenschap enableDamping kunnen we gerust weglaten — die staat standaard al op true.

<OrbitControls />

TRANSFORM

Met dit soort controls kunnen we echt “spelen” met onze objecten in de 3D-omgeving. Het doet een beetje denken aan Blender, waar je objecten kunt verplaatsen langs de assen. Let op: je plaatst deze controls niet bovenaan in je scene, maar binnen de component die de objecten bevat die je wilt manipuleren.

Importeer de TransformControls en plaats hierin de mesh.

import { TransformControls, OrbitControls } from '@react-three/drei'

<TransformControls>
    <mesh position-x={ 2 } scale={ 1.5 }>
        <boxGeometry />
        <meshStandardMaterial color="mediumpurple" />
    </mesh>
</TransformControls>

06

CONTROLS

Er vallen meteen twee dingen op:

  1. De gizmo bevindt zich niet op ons object, maar in het midden van de scene.

  2. Bewegen is nogal onhandig, want de camera draait mee terwijl we het object willen verplaatsen.

TRANSFORM FIX

Er zijn twee manieren om dit probleem aan te pakken. De ene oplossing is iets eenvoudiger, de andere wat uitgebreider.

Oplossing 1: Plaats de offset van de mesh op de controls.

<TransformControls position-x={ 2 }>
    <mesh scale={ 1.5 }>
        <boxGeometry />
        <meshStandardMaterial color="royalblue" />
    </mesh>
</TransformControls>

06

CONTROLS

Oplossing 2: Gebruik ref's om zo de positie aan te passen (best). Plaats de position-x terug op de mesh en verplaats de TransformControls onderaan.

<mesh position-x={ 2 } scale={ 1.5 }>
    <boxGeometry />
    <meshStandardMaterial color="royalblue" />
</mesh>

<TransformControls />

TRANSFORM FIX

De tweede oplossing is om een ref toe te voegen aan onze mesh — wat we doorgaans toch al doen — en die vervolgens door te geven aan de controls als het focusobject.

Maak een reference aan en plaats deze op de mesh.

import { useRef } from 'react'

export default function Experience()
{
    const cube = useRef()

    // ...
}

<mesh ref={ cube } position-x={ 2 } scale={ 1.5 }>

06

CONTROLS

Assigneer nu de reference aan de TransformControls door de 'object' prop.

<TransformControls object={ cube } />

PROBLEM #2

Er is nog één klein probleem: terwijl we onze objecten verplaatsen, beweegt de camera nog steeds mee. Dankzij de handige functies van Drei kunnen we dat makkelijk oplossen. Door één control als default te markeren, krijgt die voorrang op de rest.

Geef onze OrbitControls de prop 'makeDefault'.

<OrbitControls makeDefault />

06

CONTROLS

Klik je nu op de TransformControls, dan schakelen de OrbitControls automatisch uit. Op die manier beweegt de camera niet meer mee wanneer je een object wilt manipuleren — veel handiger!

MODES

De TransformControls hebben meerdere modi. Standaard staat deze op translate, maar je kunt net als in Blender ook kiezen voor rotate of scale.

Verander de TransformControls naar rotate en test uit.

<TransformControls object={ cube } mode="rotate" />

06

CONTROLS

Verander de TransformControls naar scale en test uit.

<TransformControls object={ cube } mode="scale" />

We zullen de controls terug naar translate plaatsen (of we laten het weg)

<TransformControls object={ cube } mode="translate" />

PIVOT

Eigenlijk is PivotControls gewoon een alles-in-één versie van TransformControls. Het ziet er bovendien stijlvol uit, waardoor het minder “debugging-achtig” voelt en je het gerust in een productieproject kunt gebruiken.

Importeer de PivotControls en wrap onze sphere binnen deze controls.

import { PivotControls, TransformControls, OrbitControls } from '@react-three/drei'

<PivotControls>
    <mesh position-x={ - 2 }>
        <sphereGeometry />
        <meshStandardMaterial color="orange" />
    </mesh>
</PivotControls>

06

CONTROLS

PIVOT

Anders dan TransformControls, ondersteunt PivotControls geen groepen. Daarom verplaatsen we de origin naar het midden van de mesh door de anchor aan te passen.

Verander de anchor naar de sphere locatie.

<PivotControls anchor={ [ 0, 0, 0 ] }>
    {/* ... */}
</PivotControls>

06

CONTROLS

Ehh… niets te zien! Dat komt omdat de anchor binnen de sphere zit. Gelukkig kun je dit eenvoudig oplossen door depthTest={false} toe te voegen, zodat het object altijd zichtbaar is.

<PivotControls
    anchor={ [ 0, 0, 0 ] }
    depthTest={ false }
>
    {/* ... */}
</PivotControls>

PIVOT SETTINGS

Je kunt diverse eigenschappen van de controls aanpassen:

  • lineWidth: De dikte van de lijnen.

  • axisColors: Geef een array [x, y, z] op om de assen in eigen kleuren weer te geven.

  • scale: Bepaalt hoe groot de controls visueel zijn.

  • fixed: Normaal reageren controls op zoom; met fixed={true} blijven ze altijd even groot.

Speel even met de settings en kijk welke invloed die hebben.

<PivotControls
    anchor={ [ 0, 0, 0 ] }
    depthTest={ false }
    lineWidth={ 4 }
    axisColors={ [ '#9381ff', '#ff4d6d', '#7ae582' ] }
    scale={ 100 }
    fixed={ true }
>
 {/* ... */}
</PivotControls>

06

CONTROLS

ONE FIBER AT A TIME

LIGHTS

07

LIGHTS

In Three.js — en eigenlijk in elke 3D-software — bepaalt licht in grote mate hoe je objecten waarneemt. Vooral de combinatie van materiaaltype en lichtsoort heeft hier veel invloed op.
Binnen R3F heb je keuze uit verschillende materialen, zoals:

  • MeshBasicMaterial (No lights)
  • MeshStandardMaterial
  • MeshPhysicalMaterial
  • MeshLambertMaterial
  • MeshPhongMaterial
  • MeshToonMaterial
  • MeshNormalMaterial (No lights)

07

LIGHTS

LIGHTS

Net zoals je kunt kiezen uit diverse materialen, kun je in R3F ook uit verschillende soorten lichten kiezen, bijvoorbeeld:

  • AmbientLight: Gelijkmatige verlichting
  • DirectionalLight: Simulatie van zonlicht
  • PointLight: Straalt in alle richtingen vanaf een punt
  • SpotLight: Straalt in een kegelvorm (podiumspot)
  • HemisphereLight: simuleert hemisferisch licht (boven - lucht | onder - grond)
  • RectAreaLight: Rechthoeking vlak dat licht uitstraalt (softbox)
  • Environment

07

LIGHTS

Laten we beginnen met Ambient, Directional en PointLight. Andere lichtsoorten komen later waarschijnlijk nog voorbij. Voel je vrij om ze alvast zelf te ontdekken en uit te proberen!

LIGHTS

We starten met het zonlicht in onze scene, oftewel DirectionalLight.

Voeg een DirectionalLight toe

07

LIGHTS

export default function Experience()
{
    // ...

    return <>

        <directionalLight />

        {/* ... */}
    </>
}

We zien geen verandering in onze scene, hoe komt dit?

MATERIALS

Het effect van ons licht is nog niet zichtbaar omdat we MeshBasicMaterial gebruiken. Dit materiaal reageert niet op licht en blijft altijd zichtbaar, ongeacht de verlichting in de scene.

Verander de materials naar meshStandardMaterial (meest gebruikt)

07

LIGHTS

<group ref={ groupRef }>
    <mesh position-x={ - 2 }>
        <sphereGeometry />
        <meshStandardMaterial color="orange" />
    </mesh>

    <mesh ref={ cubeRef } rotation-y={ Math.PI * 0.25 } position-x={ 2 } scale={ 1.5 }>
        <boxGeometry />
        <meshStandardMaterial color="mediumpurple" />
    </mesh>
</group>

<mesh position-y={ - 1 } rotation-x={ - Math.PI * 0.5 } scale={ 10 }>
    <planeGeometry />
    <meshStandardMaterial color="grey" />
</mesh>

DIRECTIONAL

Bij het aanmaken van een licht wordt het standaard boven het midden van de scene geplaatst. Wil je dat het ergens anders schijnt? Pas dan de position aan.

Verander de position naar volgende.

07

LIGHTS

<directionalLight position={ [ 1, 2, 3 ] } />

We kunnen ook (de kleur) en intensiteit aanpassen als we dat willen.

<directionalLight position={ [ 1, 2, 3 ] } intensity={ 4.5 } />

AMBIENT

De schaduwen onderaan zijn nu vrij donker en niet zo realistisch. In de echte wereld wordt licht verspreid en weerkaatst door oppervlakken. Met een AmbientLight kunnen we dit effect in R3F eenvoudig simuleren.

Voeg een ambientLight toe aan de scene en pas de intensiteit ook aan.

07

LIGHTS

<directionalLight />
<ambientLight intensity={ 1 } />

Er valt nog veel te ontdekken over licht, zoals schaduwen, shadow maps, environment maps, en meer. Voorlopig is dit echter genoeg om verder te gaan met onze scene.

POINTLIGHT

Tot slot voegen we een PointLight toe. Dit licht verspreidt zich in alle richtingen en staat bekend als een “duur” licht, omdat het veel prestaties vraagt. Daarom gebruiken we het liever zo min mogelijk.

Zet de directionalLight in comment en plaats een pointLight om te zien wat voor effect we krijgen.

07

LIGHTS

<pointLight position={[0.5,2,0.5]} intensity={10}/>
<ambientLight intensity={ 1.5 } />

Dat een licht veel rekenkracht kost, betekent niet dat je het niet kunt gebruiken. Zorg er wel voor dat je scene niet overvol raakt met zware objecten en lichten, want een trage, haperende ervaring is voor niemand prettig.

ONE FIBER AT A TIME

SETTINGS (CANVAS)

08

CANVAS

Ons Canvas bevat meerdere onderdelen: de scene, camera, renderer, colorSpace, en meer. Af en toe willen we deze instellingen aanpassen. Laten we beginnen bij de camera.

Plaats in de camera prop een leeg object.

<Canvas camera={ {} }>
    <Experience />
</Canvas>

08

SETTINGS (CANVAS)

Wat we kunnen aanpassen in de camera is volgende:

  • fov (field of view): bepaalt hoe breed de kijkhoek van de camera is.

  • near: geeft de minimale afstand aan waarop de camera objecten nog kan zien.

  • far: geeft de maximale afstand aan waarop de camera objecten nog kan zien.

  • position: bepaalt de locatie van de camera in de 3D-ruimte.

CAMERA

Probeer eens verschillende waardes en kijk hoe dit de camera beïnvloedt in de scene.

Verander de camera settings naar volgende

<Canvas camera={ { fov: 45, near: 0.1, far: 200 } }>

De camera staat nu te dicht dus veranderen we de positie.

<Canvas camera={ { fov: 45, near: 0.1, far: 200, position: [ 3, 2, 6 ] } }>

08

SETTINGS (CANVAS)

Hoe meer props des te moeilijker het te lezen is op een lijn. Refactor dit naar volgende

<Canvas
   camera={ {
      fov: 45,
      near: 0.1,
      far: 200,
      position: [ 3, 2, 6 ]
        } }
    >
    <Experience />
</Canvas>

ORTHOGRAPHIC

Een orthografische camera laat geen perspectief zien. Gewoonlijk stel je hiervoor top, right, bottom en left in, maar in R3F wordt dit vaak automatisch afgehandeld.

Verander de camera naar orthographic.

<Canvas
    orthographic
    camera={ {
        ...
    } }
>
    <Experience />
</Canvas>

08

SETTINGS (CANVAS)

Fov is nu nutteloos maar bij een orthographic camera maken we gebruik van 'zoom'

  camera={ {
        fov: 45,
        zoom: 100,
        near: 0.1,
        far: 200,
        position: [ 3, 2, 6 ]
    } }

REFACTOR

Instellingen voor objecten zetten we vaak buiten de component, zodat de code overzichtelijk blijft en makkelijker te beheren is.

Maak een object aan met de settings.

const cameraSettings = {
    fov: 45,
    zoom: 100,
    near: 0.1,
    far: 200,
    position: [ 3, 2, 6 ]
}

Geef het object mee met de camera.

<Canvas
     orthographic
     camera={ cameraSettings }
>
     <Experience />
</Canvas>

08

SETTINGS (CANVAS)

Verwijder de orthographic alsook de zoom (hier gaan we niet mee verder)

ANIMATE

Onze camera kan weleens in beweging komen! Bijvoorbeeld door hem continu rond een object te laten draaien in een loop. Hiervoor gebruiken we een paar eenvoudige wiskundige berekeningen.

Comment de OrbitControls want we gaan de camera laten draaien.

{/* <orbitControls /> */}

08

SETTINGS (CANVAS)

Wil je dat de camera rond een object draait? Dan gebruiken we sin() en cos() voor de cirkelbeweging. De benodigde angle halen we uit de state met de methode getElapsedTime() of clock.elapsedTime.

ANIMATE

In onze useFrame zullen we eens zien wat in state zit.

useFrame((state, delta) =>
{
    console.log(state.clock)

    // ...
})

08

SETTINGS (CANVAS)

Sla nu de elapsedTime in een variable.

useFrame((state, delta) =>
{
    const angle = state.clock.elapsedTime
    console.log(angle)

    // ...
})

ANIMATE

Verander nu de x en z positie van de camera a.d.h.v de sin() en cos()

useFrame((state, delta) =>
{
    const angle = state.clock.elapsedTime
    state.camera.position.x = Math.sin(angle)
    state.camera.position.z = Math.cos(angle)

    // ...
})

08

SETTINGS (CANVAS)

Maak de cirkel nu groter door dit te vermenigvuldigen met een bepaald aantal

useFrame((state, delta) =>
{
    const angle = state.clock.elapsedTime
    state.camera.position.x = Math.sin(angle) * 8
    state.camera.position.z = Math.cos(angle) * 8

    // ...
})

ANIMATE

Onze camera draait netjes rond het object, maar richt zich nog niet op het object zelf. Met lookAt() zorgen we dat de camera continu naar het object kijkt.

useFrame((state, delta) =>
{
    const angle = state.clock.elapsedTime
    state.camera.position.x = Math.sin(angle) * 8
    state.camera.position.z = Math.cos(angle) * 8
    state.camera.lookAt(0, 0, 0)

    // ...
})

08

SETTINGS (CANVAS)

Onze camera cirkelt mooi rond en blijft gericht op het middelpunt van de scene — gaaf! Zet de animatie even in comment, zodat we terug met OrbitControls kunnen werken.

ANTI-ALIAS

<Canvas
    gl={ {
        antialias: false
    } }
    camera={ {
        fov: 45,
        near: 0.1,
        far: 200,
        position: [ 3, 2, 6 ]
    } }
>

08

SETTINGS (CANVAS)

Normaal staat antialiasing aan, maar laten we het eens uitzetten. Dat gebeurt via de gl-prop, die verwijst naar de onderliggende WebGLRenderer, waar je nog veel meer instellingen kunt aanpassen.

Anti-aliasing helpt om die vervelende kartelige randen weg te werken. Het doet dit door de kleuren van omliggende pixels te mengen, waardoor lijnen en vormen veel vloeiender ogen.

We zullen deze weer op true plaatsen of wegdoen, dat is veel mooier :)

TONE MAPPING

<Canvas
    flat
    gl={ {
        antialias: true
    } }
    camera={ {
        fov: 45,
        near: 0.1,
        far: 200,
        position: [ 3, 2, 6 ]
    } }
>

08

SETTINGS (CANVAS)

Om tonemapping weg te halen van de scene plaatsen we 'flat' op onze Canvas

In essentie zet tone mapping de brede variatie aan lichtintensiteiten in een HDR-beeld om naar een kleiner bereik, zonder belangrijke details in schaduwen of hooglichten te verliezen.

Dit plaatst 'NoToneMapping' op onze scene en dat ziet er ... lelijk uit.

TONE MAPPING

//Optie 1 
import * as THREE from 'three'

//Optie 2
import { CineonToneMapping } from 'three'

08

SETTINGS (CANVAS)

Importeer de CineonToneMapping van Three

Als je bepaalde tone mappings wilt gebruiken voor je scene, voeg je deze toe via gl. Vergeet niet eerst de juiste tone mapping uit Three.js te importeren.

Afhankelijk van de import die je gebruikt moet je nog THREE plaatsen vooraf.

TONE MAPPING

  gl={ {
        antialias: true,
        toneMapping: THREE.CineonToneMapping
    } }

08

SETTINGS (CANVAS)

Voeg de tonemapping toe aan gl.

Laten we twee tone mappings toevoegen en het effect ervan bekijken. Er zijn nog veel andere tone mappings beschikbaar, die je in de Three.js-documentatie kunt vinden.

Importeer nu ook ACESFilmicToneMapping en vervang de toneMapping met deze.

  gl={ {
        antialias: true,
        toneMapping: THREE.ACESFilmicToneMapping
    } }

ALPHA

html,
body,
#root
{
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    overflow: hidden;
    background: LightSkyBlue;
}

08

SETTINGS (CANVAS)

Voeg css toe om een achtergrond te geven en dit in actie te zien.

De achtergrond van het Canvas is standaard transparant, waardoor je elementen of styling achter de canvas kunt tonen en ze nog steeds zichtbaar blijven.

PIXEL RATIO

<Canvas
    dpr={ [ 1, 2 ] }
    gl={ {
        antialias: true,
        toneMapping: THREE.ACESFilmicToneMapping,
        outputColorSpace: THREE.LinearSRGBColorSpace
    } }
>

08

SETTINGS (CANVAS)

Voeg dpr toe aan de canvas (standaard staat deze al zo) [min,max]

Op high-DPI schermen past de renderer zich automatisch aan. Om te voorkomen dat je applicatie traag wordt op apparaten met een zeer hoge pixelratio, kun je beter zelf een limiet instellen via de dpr-prop van het <Canvas>.

ONE FIBER AT A TIME

HTML & TEXT

09

HTML

Met de HTML-component van Drei kun je gewoon HTML-elementen toevoegen die aan een mesh vastzitten en automatisch mee bewegen in de 3D-scene.

Importeer HTML component van drei 

import { Html } from '@react-three/drei'

09

HTML & TEXT

Gebruik nu HTML en schrijf iets 

export default function Experience()
{
    // ...

    return <>

        {/* ... */}

        <Html>Hello!</Html>

    </>
}

INSIDE MESH

Het HTML-element staat nu nog in het midden van de scene, maar door het in een mesh te plaatsen, volgt het automatisch de origin van dat object.

Plaats een nieuw Html element in onze mesh

<mesh position-x={ - 2 }>
    <sphereGeometry />
    <meshStandardMaterial color="orange" />
    <Html>This sphere is lit! 🔥</Html>
</mesh>

09

HTML & TEXT

We kunnen de offset veranderen door de position aan te passen.

<mesh position-x={ - 2 }>
    <sphereGeometry />
    <meshStandardMaterial color="orange" />
    <Html position={ [ 1, 1, 0 ] }>This sphere is lit! 🔥</Html>
</mesh>

STYLE IT

Nu staat er een DOM-element in de 3D-scene, maar hoe style je dat? Gewoon een class toewijzen en in je CSS de gewenste stijlen instellen.

Gebruik de prop wrapperClass en geef een class name mee

<Html
    wrapperClass="label"
>

09

HTML & TEXT

Nu kan je in index.css de gewenste stijl toevoegen.

.label > div
{
    font-family: Helvetica, Arial;
    position: absolute;
    background: #00000088;
    color: white;
    padding: 15px;
    white-space: nowrap;
    overflow: hidden;
    border-radius: 30px;
    user-select: none;
}

DISTANCE

Je kunt een HTML-element centreren op zichzelf en een distanceFactor instellen. Zo lijkt het alsof het element diepte heeft en mee schaalt als je in- of uitzoomt in de scene.

Plaats center en een distanceFactor van 6 op het HTML component

<Html
    position={ [ 1, 1, 0 ] }
    wrapperClass="label"
    center
    distanceFactor={ 6 }
>

09

HTML & TEXT

OCCLUDE

Wat betekent occlusion? Als je een HTML-element in de scene hebt en er een mesh vóór plaatst, zie je dat het element normaal gesproken gewoon erboven blijft. Met occlude zorg je ervoor dat het element achter de mesh verdwijnt, alsof het echt geblokkeerd wordt.

Om een occlude toe te voegen moet je eerst references plaatsen op de meshes en deze meegeven me in de array

<Html
    position={ [ 1, 1, 0 ] }
    wrapperClass="label"
    center
    distanceFactor={ 6 }
    occlude={ [ sphere, cube ] }
>

09

HTML & TEXT

TEXT

HTML in de scene werkt, maar voor echte 3D-tekst gebruiken we de Text-component. Die maakt het eenvoudig om tekst als onderdeel van je 3D-scene weer te geven.

Importeert de helper van drei in je project

import { Text } from '@react-three/drei'

09

HTML & TEXT

Voeg deze nu toe aan je project en plaats een stukje tekst ertussen.

export default function Experience()
{
    // ...

    return <>

        {/* ... */}

        <Text>TECH3 IS AWESOME!</Text>

    </>
}

FONT

Standaard krijg je een font bij de Text-component, maar je kunt net zo goed je eigen lettertypen toevoegen en gebruiken in de 3D-scene.

Kies een font, download het en zet het pad in de font-prop. De component ondersteunt .woff, .ttf en .otf, maar .woff is aan te raden omdat het minder zwaar is.

<Text
    font="./HussarBoldWeb.woff"
>
   TECH3 IS AWESOME!
</Text>

09

HTML & TEXT

Ook de fontSize als color zijn aanpasbaar.

<Text
    font="./HussarBoldWeb.woff"
    fontSize={ 2 }
    color="pink"
>
   TECH3 IS AWESOME!
</Text>

MATERIAL

Wil je de tekst een eigen look geven? Je kunt een custom material meegeven, precies zoals je dat bij een mesh zou doen.

Verander de material van de tekst naar een meshNormalMaterial

<Text
    font="./bangers-v20-latin-regular.woff"
    fontSize={ 2 }
    color="salmon"
>
   TECH3 IS AWESOME!
   <meshNormalMaterial />
</Text>

09

HTML & TEXT

Nu we weten dat dit mogelijk is zullen we terug keren zonder NormalMaterial.

SETTINGS

Net als andere objecten kun je een Text verplaatsen, van grootte veranderen en roteren om het precies te positioneren zoals je wilt.

Verander de positie naar boven (y-as) met 2

<Text
    font="./HussarBoldWeb.woff"
    fontSize={ 2 }
    color="pink"
    position-y={2}
>

09

HTML & TEXT

Een MaxWidth , TextAlign en dergelijke zijn ook allemaal mogelijk op een Text element.

<Text
    font="./HussarBoldWeb.woff"
    fontSize={ 1 }
    color="pink"
    position-y={ 2 }
    maxWidth={ 5 }
    textAlign="center"
    scale={ .5}
>

ONE FIBER AT A TIME

VARIA

10

FLOAT

Drei heeft een hoop leuke kant-en-klare componenten. Check de documentatie om ze allemaal te ontdekken!
Met Float laat je een element zachtjes zweven, net alsof het een ballon is. Het werkt als een wrapper rond je objecten.

Importeer Float van Drei en gebruik deze rond onze text.

<Float>
    <Text
        font="./bangers-v20-latin-regular.woff"
        fontSize={ 1 }
        color="salmon"
        position-y={ 2 }
        maxWidth={ 2 }
        textAlign="center"
    >
        TECH3 IS AWESOME!
    </Text>
</Float>

10

VARIA

FLOAT

De tekst zweeft al prachtig, maar we hebben nog meer controle! Pas de speed en float-intensity aan om het effect sneller, langzamer of sterker te maken.

Pas de speed en intenstity aan en speel wat met de waarden.

<Float
    speed={ 5 }
    floatIntensity={ 2 }
>
    {/* ... */}
</Float>

10

VARIA

REFLECTOR

Altijd al een 3D-spiegel willen maken? Dankzij Drei is het nu supermakkelijk: gewoon een MeshReflectorMaterial toepassen op je object en you're done!

Importeer MeshReflectorMaterial van Drei en vervang de material van de plane.

import { MeshReflectorMaterial } from '@react-three/drei'

//...

<mesh position-y={ - 1 } rotation-x={ - Math.PI * 0.5 } scale={ 10 }>
    <planeGeometry />
    <MeshReflectorMaterial />
</mesh>

10

VARIA

REFLECTOR

Het MeshReflectorMaterial heeft verschillende instelbare opties. Je kunt onder andere resolution, blur, mixBlur, mirror en color aanpassen om het gewenste effect te bereiken.

Plaats deze waarden in onze Material

<MeshReflectorMaterial
    resolution={ 512 }
    blur={ [ 1000, 1000 ] }
    mixBlur={ 1 }
    mirror={ 0.5 }
    color="grey"
/>

10

VARIA

NOICE!

Gefeliciteerd! Je eerste stap in React Three Fiber en Drei is gezet. Er valt nog veel meer te leren, maar hiermee heb je al een stevige basis.

10

VARIA

TECH3/4 - React Three Fiber

By Niels Minne

TECH3/4 - React Three Fiber

  • 123