Skip navigation

Árnyékolás

Működése

Igen látványos, bár nagyon számításigényes funkció a tárgyak által vetett árnyék generálása. A Three.js az úgynevezett árnyéktérképes algoritmust használja.

A gyorsabb működés végett nekünk kell jeleznünk a forráskódban, hogy mely fényforrások fényei vetnek árnyékot és melyek nem (ez az alapértelmezés), valamint mely tárgyak vetnek árnyékot, és mely tárgyak felszínen jelenik meg árnyék. Ha mindent bekapcsolunk, sok tárgy esetén akadozhat az animáció.

A sebességet növelhetjük az árnyéktérkép méretének csökkentésével, a minőség rovására.

Vigyázzunk!

Az árnyékoló kódrészt a 2015. októberi r73 kiadással átalakították!

A Learning Three.js (2. kiadás) könyv, és nagyon sok interneten található kódrészlet a régebbi kódbázishoz tartozik, így azok nem mindig fognak megfelelően működni!

Használata

A renderer-nél kapcsoljuk be az árnyéktérkép generálást:

renderer.shadowMap.enabled = true;

Ha szeretnénk, hogy egy tárgy vessen árnyékot, akkor kapcsoljuk ezt be a castShadow kapcsolóval. Ha szeretnénk árnyékot megjeleníteni egy tárgy felszínén, akkor a receiveShadow kapcsolót kell beállítani. Példaprogramunkban egy kockát világítunk meg, amely vet árnyékot, viszont rajta árnyék nem jelenik meg. Egy objektum természetesen vethet árnyékot, és ugyanakkor rajta is jelenhet meg árnyék.

geometry = new THREE.BoxGeometry( 4, 4, 4 );
material = new THREE.MeshLambertMaterial( { color: 0xffffff, wireframe: false } );
cubeMesh = new THREE.Mesh( geometry, material );
cubeMesh.castShadow = true;
cubeMesh.receiveShadow = false;
scene.add( cubeMesh );

Azon tárgyak esetén, amelyekre árnyékot szeretnénk vetíteni, Lambert vagy Phong anyagot kell választani. Példánkban egy síkot modellezünk, amit a kocka alá pozicionálunk.

planeGeometry = new THREE.PlaneGeometry( 30, 30, 30, 30 );
var material2 = new THREE.MeshPhongMaterial( { color: 0xffffff } );
planeMesh = new THREE.Mesh( planeGeometry, material2 );
planeMesh.rotation.x = -1.0 * Math.PI / 2.0;
planeMesh.position.y = -8;
planeMesh.receiveShadow = true;
planeMesh.castShadow = false;
scene.add( planeMesh );

Az árnyékot akkor látjuk jól, ha a kamera a fényforráshoz és a tárgyakhoz képest megfelelő helyen van. Példánkban a kamerát oldal irányból a kockára irányítjuk.

camera = new THREE.PerspectiveCamera( 75, aspectRatio, 0.1, 1000 );
camera.position.z = 30;
camera.lookAt( cubeMesh.position );

A következő lépés a fényforrás definiálása és elhelyezése a térben. A castShadow-t engedélyezzük, valamint figyeljünk arra, hogy a fényforrás hatása elérjen azokig a tárgyakig, amelyekre az árnyék vetül (distance)!

var sLight = new THREE.SpotLight( 0x00ffff, 1 );
sLight.position.set( 0, 15, 0 );
sLight.angle = Math.PI / 6;
sLight.target = cubeMesh;
sLight.penumbra = 0.8;
sLight.distance = 80;
sLight.castShadow = true;
scene.add( sLight );

A fényforrás paramétereinek jobb átláthatósága végett hozzáadunk egy segéd geometriát.

var spotLightHelper = new THREE.SpotLightHelper( sLight );
scene.add( spotLightHelper );

Példaprogramok

  • Az oldal alján megjelenő demó elérhető külső ablakban megjelenítve is. A kamera az egérrel interaktívan körbemozgatható, zoomolható!
  • Egy egyszerű, de nagyon látványos példaprogram érhető el a hivatalos Three.js példák között webgl_shadowmap_pointlight.html néven. Itt is változtatható a kamera elhelyezkedése.