iT邦幫忙

0

Three JS - 燈光設定產生 Glb 模型陰影

  • 分享至 

  • xImage

我想做成像 sketchfab 這樣類似陽光透過窗框打在建築物地板上的效果。

以下是我的 code

import './style.css'
import * as THREE from 'three'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'

function main () {
  const canvas = document.querySelector('#c');
  const renderer = new THREE.WebGLRenderer({
    canvas: canvas,
    antialias: true,
  });

  renderer.setPixelRatio(window.devicePixelRatio)
  renderer.setClearColor(0xAAAAAA);
  renderer.shadowMap.enabled = true;

  const camera =new THREE.PerspectiveCamera(75, canvas.offsetWidth / canvas.offsetHeight, 0.1, 2000);
  camera.position.set(80, 40, 100);
  camera.lookAt(0, 0, 0);

  const scene = new THREE.Scene();

  {
    const light = new THREE.DirectionalLight(0xffffff, 1);
    light.position.set( 300, 200, 100 );
    light.target.position.set( 0, 0, 0 );

    light.castShadow = true;
    light.shadow.mapSize.width = canvas.offsetWidth;
    light.shadow.mapSize.height = canvas.offsetHeight;
    light.shadow.bias = 0.01;

    light.shadow.camera.left = -500;
    light.shadow.camera.right = 500;
    light.shadow.camera.top = 500;
    light.shadow.camera.bottom = -500;

    scene.add( light );

    const lightHepler = new THREE.DirectionalLightHelper(light)
    scene.add(lightHepler);

    const cameraHelper = new THREE.CameraHelper(light.shadow.camera)
    scene.add(cameraHelper)
  }

  {
    const planeGeo = new THREE.PlaneBufferGeometry(1000, 1000, 1, 1);
    const planeMet = new THREE.MeshLambertMaterial({ color: 0x999999, side: THREE.DoubleSide });
    const plane = new THREE.Mesh(planeGeo, planeMet);
    plane.receiveShadow = true;
    plane.rotateX(Math.PI / 2);
    scene.add(plane);
  }

  /*
    Load 3D model
  */
  const loader = new GLTFLoader();

  // loader.load( './shiba/scene.gltf', gltf => {
  //   scene.add( gltf.scene );
  // }, undefined, error => {
  //   console.error( error );
  // })

  // loader.load('./horse/Horse.glb', gltf => {
  //   const mesh = gltf.scene.children[ 0 ];
  //   mesh.scale.set(0.1, 0.1, 0.1);
  //   mesh.castShadow = true;
  //   mesh.receiveShadow = true;
  //   scene.add( mesh );
  // }, undefined, error => {
  //   console.error( error );
  // })

  loader.load('./showroom/scene.gltf', gltf => {
    gltf.scene.scale.set(0.01, 0.01, 0.01);
    gltf.scene.traverse(child => {
      child.receiveShadow = true;
    })
    console.log(gltf.scene);
    scene.add( gltf.scene );
  }, undefined, error => {
    console.error( error );
  })

  /*
    Add OrbitControl
  */
  const controls = new OrbitControls(camera, renderer.domElement)

  function resizeRendererToDisplaySize(renderer) {
    const canvas = renderer.domElement;
    const width = canvas.clientWidth;
    const height = canvas.clientHeight;
    const needResize = canvas.width !== width || canvas.height !== height;
    if (needResize) {
      renderer.setSize(width, height, false);
    }
    return needResize;
  }

  function render() {
    if (resizeRendererToDisplaySize(renderer)) {
      const canvas = renderer.domElement;
      camera.aspect = canvas.clientWidth / canvas.clientHeight;
    }

    controls.update()

    renderer.render(scene, camera);

    requestAnimationFrame(render);
  }

  requestAnimationFrame(render);
}

main()

https://ithelp.ithome.com.tw/upload/images/20220331/2012388913MfIoSm4X.png
不確定還缺少哪些東西,沒辦法做的像 sketchfab 那樣有陰影。

圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 個回答

0
淺水員
iT邦大師 6 級 ‧ 2022-04-02 14:42:46

每個 Object3D 物件都有 castShadowreceiveShadow
castShadow 被設定為 true 的物件才會產生陰影
receiveShadow 被設定為 true 的物件才能在這上面顯示別人的陰影

所以你可能要在所有牆壁都設定 castShadow

另外 Material 那邊有 shadowSide 屬性
這會決定平面的哪一邊可以產生陰影
若不確定哪一邊可以把 shadowSide 設定為 THREE.DoubleSide
代表從兩邊都會產生陰影

我要發表回答

立即登入回答