如何在threeJs中投射/接收阴影

时间:2021-05-12 12:15:05

标签: javascript three.js

我对 ThreeJS 还很陌生,我想让圆环体的阴影投射到它后面的 PlaneGeometry 上。

我尝试使用 .castShadow.receiveShadow 但没有结果

你能解释一下我做错了什么吗?

const canvas = document.getElementById("torus");
// ____RENDERER ___
const renderer = new THREE.WebGLRenderer({
  canvas: canvas,
  antialias: true,
  alpha: true
});
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
renderer.setSize(window.innerWidth, window.innerHeight);

const camera = new THREE.PerspectiveCamera(
  45,
  window.innerWidth / window.innerHeight,
  1,
  500
);
camera.position.set(0, 0, 30);
camera.lookAt(0, 0, 0);

const textureLoader = new THREE.TextureLoader();
const normalTexture = textureLoader.load(
  "https://thumbs.dreamstime.com/b/normal-map-old-rough-loose-concrete-surface-normal-map-old-rough-loose-concrete-surface-texture-use-d-programs-d-195202276.jpg"
);

const scene = new THREE.Scene();

// _____Torus____
const geometry = new THREE.TorusGeometry(4, 1, 16, 100);
const material = new THREE.MeshStandardMaterial({
  metalness: 0.7,
  roughness: 0.2,
  color: new THREE.Color(0xf1f1f1),
  normalMap: normalTexture
});
const torus = new THREE.Mesh(geometry, material);
torus.castShadow = true; //default is false
torus.receiveShadow = false;
scene.add(torus);

// _____Plane______
const planeGeometry = new THREE.PlaneGeometry(20, 20, 32);
const planeMaterial = new THREE.MeshBasicMaterial({
  color: 0xF0F0F0,
  side: THREE.DoubleSide
});
const plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.position.z = -4;
plane.receiveShadow = true;
scene.add(plane);

//______Light
const pointLight = new THREE.PointLight(0xffffff, 1, 100);
pointLight.position.set(0, 5, 6);
pointLight.intensity = 2;
pointLight.castShadow = true;

pointLight.shadow.mapSize.width = 512;
pointLight.shadow.mapSize.height = 512;
pointLight.shadow.camera.near = 0.5;
pointLight.shadow.camera.far = 500;

scene.add(pointLight);
const pointLightHelper = new THREE.PointLightHelper(pointLight, 1);
scene.add(pointLightHelper);




function createGUI() {
  const lightColor = { color: "#ffffff" };
  var gui = new dat.GUI();

  var gui = gui.addFolder("PointLight 1");

  gui.add(pointLight.position, "x").min(-10).max(10).step(0.01);
  gui.add(pointLight.position, "y").min(-10).max(10).step(0.01);
  gui.add(pointLight.position, "z").min(-10).max(10).step(0.01);
  gui.add(pointLight, "intensity").min(0).max(10).step(0.01);
  gui.addColor(lightColor, "color").onChange(function () {
    pointLight.color.set(lightColor.color);
  });

  gui.open();

}

const animate = function () {
  requestAnimationFrame(animate);

  torus.rotation.x += 0.01;

  renderer.render(scene, camera);
};

renderer.setAnimationLoop(() => {
  renderer.render(scene, camera);
});

window.addEventListener("load", init, false);
function init() {
  createGUI();
  animate();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.7/dat.gui.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<canvas id="torus"></canvas>

1 个答案:

答案 0 :(得分:2)

您已将 MeshBasicMaterial 用于平面网格,它是一种不发光的材质。所以它不会收到 shadpws。使用像 MeshStandardMaterial 这样的发光材料可以解决这个问题。

const canvas = document.getElementById("torus");
// ____RENDERER ___
const renderer = new THREE.WebGLRenderer({
  canvas: canvas,
  antialias: true,
  alpha: true
});
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
renderer.setSize(window.innerWidth, window.innerHeight);

const camera = new THREE.PerspectiveCamera(
  45,
  window.innerWidth / window.innerHeight,
  1,
  500
);
camera.position.set(0, 0, 30);
camera.lookAt(0, 0, 0);

const textureLoader = new THREE.TextureLoader();
const normalTexture = textureLoader.load(
  "https://thumbs.dreamstime.com/b/normal-map-old-rough-loose-concrete-surface-normal-map-old-rough-loose-concrete-surface-texture-use-d-programs-d-195202276.jpg"
);

const scene = new THREE.Scene();

// _____Torus____
const geometry = new THREE.TorusGeometry(4, 1, 16, 100);
const material = new THREE.MeshStandardMaterial({
  metalness: 0.7,
  roughness: 0.2,
  color: new THREE.Color(0xf1f1f1),
  normalMap: normalTexture
});
const torus = new THREE.Mesh(geometry, material);
torus.castShadow = true; //default is false
scene.add(torus);

// _____Plane______
const planeGeometry = new THREE.PlaneGeometry(20, 20, 32);
const planeMaterial = new THREE.MeshStandardMaterial({
  color: 0xF0F0F0,
  side: THREE.DoubleSide
});
const plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.position.z = -4;
plane.receiveShadow = true;
scene.add(plane);

//______Light
const pointLight = new THREE.PointLight(0xffffff, 1, 100);
pointLight.position.set(0, 5, 6);
pointLight.intensity = 2;
pointLight.castShadow = true;

pointLight.shadow.mapSize.width = 512;
pointLight.shadow.mapSize.height = 512;
pointLight.shadow.camera.near = 0.5;
pointLight.shadow.camera.far = 500;

scene.add(pointLight);
const pointLightHelper = new THREE.PointLightHelper(pointLight, 1);
scene.add(pointLightHelper);




function createGUI() {
  const lightColor = { color: "#ffffff" };
  var gui = new dat.GUI();

  var gui = gui.addFolder("PointLight 1");

  gui.add(pointLight.position, "x").min(-10).max(10).step(0.01);
  gui.add(pointLight.position, "y").min(-10).max(10).step(0.01);
  gui.add(pointLight.position, "z").min(-10).max(10).step(0.01);
  gui.add(pointLight, "intensity").min(0).max(10).step(0.01);
  gui.addColor(lightColor, "color").onChange(function () {
    pointLight.color.set(lightColor.color);
  });

  gui.open();

}

const animate = function () {
  requestAnimationFrame(animate);

  torus.rotation.x += 0.01;

  renderer.render(scene, camera);
};

renderer.setAnimationLoop(() => {
  renderer.render(scene, camera);
});

window.addEventListener("load", init, false);
function init() {
  createGUI();
  animate();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.7/dat.gui.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<canvas id="torus"></canvas>