web-dev-qa-db-fra.com

Comment créer une ombre directionnelle dans Three.JS?

Est-il possible de créer des ombres à partir d'un DirectionalLight?

Si j'utilise SpotLight alors je vois une ombre, mais si j'utilise DirectionalLight cela ne fonctionne pas.

23
eqiproo

Oui, vous avez certainement pouvez utiliser des lumières directionnelles pour projeter des ombres. Vous devez vous assurer que vous n'utilisez pas MeshBasicMaterial car ils ne prennent pas en charge les ombres. Utilisez à la place MeshLambertMaterial ou MeshPhongMaterial.

Vous devez activer les ombres pour le rendu avec quelque chose comme ceci:

renderer.shadowMapEnabled = true;
renderer.shadowMapSoft = true;

renderer.shadowCameraNear = 3;
renderer.shadowCameraFar = camera.far;
renderer.shadowCameraFov = 50;

renderer.shadowMapBias = 0.0039;
renderer.shadowMapDarkness = 0.5;
renderer.shadowMapWidth = 1024;
renderer.shadowMapHeight = 1024;

Et puis vous devez activer la projection d'ombres et la réception d'ombres par objet et par lumière pour avoir

dirLight.castShadow = true;
object.castShadow = true;
otherObject.receiveShadow = true;

Ensuite, si la lumière et les objets sont placés aux positions appropriées. dirLight entraînera l'ombre de object contre otherObject.

[EDIT]: Voici un démo de travail pour quiconque cherche à faire quelque chose de similaire.

36
Cory Gross

Sachez que les cartes d'ombre dépendent de l'échelle. Je travaille sur une scène où la distance unitaire représente un mètre et mes objets mesurent environ 0,4 mètre. C'est assez petit par rapport aux normes Three.js. Si vous avez également cette situation, vous pouvez prendre quelques mesures importantes:

  • Assurez-vous que les plans proche/éloigné de la caméra cachée sont raisonnables compte tenu des dimensions de votre scène.
  • Assurez-vous que les valeurs haut/gauche/bas/droite de la caméra d'ombre ne sont pas trop grandes, sinon chaque pixel d'ombre peut être si grand que vous ne remarquerez même pas l'ombre dans votre scène.

Voyons comment procéder.

Débogage

Assurez-vous d'activer le rendu de débogage par lumière via CameraHelper :

scene.add(new THREE.CameraHelper(camera)) 

Ou dans les anciennes versions de Three.js:

light.shadowCameraVisible = true;

Cela vous montrera le volume sur lequel l'ombre est calculée. Voici un exemple de ce à quoi cela pourrait ressembler:

Remarquez les plans proche et lointain (avec des croix noires) et le haut/gauche/bas/droit de la caméra d'ombre (murs extérieurs de la boîte jaune.) Vous voulez que cette boîte soit serrée autour des objets que vous allez avoir dans ombre - peut-être encore plus serré que ce que je montre ici.

Code

Voici quelques extraits de code qui pourraient être utiles.

var light = new THREE.DirectionalLight(0xffffff);
light.position.set(0, 2, 2);
light.target.position.set(0, 0, 0);
light.castShadow = true;
light.shadowDarkness = 0.5;
light.shadowCameraVisible = true; // only for debugging
// these six values define the boundaries of the yellow box seen above
light.shadowCameraNear = 2;
light.shadowCameraFar = 5;
light.shadowCameraLeft = -0.5;
light.shadowCameraRight = 0.5;
light.shadowCameraTop = 0.5;
light.shadowCameraBottom = -0.5;
scene.add(light);

Assurez-vous que certains objets projettent des ombres:

object.castShadow = true;

Assurez-vous que certains objets reçoivent des ombres:

object.receiveShadow = true;

Enfin, configurez quelques valeurs sur WebGLRenderer:

renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(canvasWidth, canvasHeight);
renderer.shadowMapEnabled = true;
renderer.shadowMapSoft = true;
50
Drew Noakes