Three.js - 阴影(十三)

阴影

  • three.js中使用的是阴影贴图,阴影贴图的工作方式就是具有投射阴影的光能对所有能被投射阴影的物体从光源渲染阴影
  • 注意事项:
  1. 每多一个能投射阴影光源,就会重复绘制一次场景。阴影的计算是一个光源一个光源的依次计算的。
  2. 要展示阴影需要,渲染器开启阴影渲染、灯光投开启投射阴影、物体开启接收阴影
  3. 只有DirectionalLightPointLightRectAreaLightSpotLight这4种光源才能投谁阴影。
  4. MeshLambertMaterial材质是不能接受投射阴影的。

展示阴影

  • 基础模版
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>学习</title>
  </head>
  <body>
    <canvas id="c2d" class="c2d" width="1000" height="500"></canvas>
    <script type="module">
      import * as THREE from 'https://threejs.org/build/three.module.js'
      import { OrbitControls } from 'https://threejsfundamentals.org/threejs/resources/threejs/r132/examples/jsm/controls/OrbitControls.js'

      const canvas = document.querySelector('#c2d')
      // 渲染器
      const renderer = new THREE.WebGLRenderer({ canvas })

      const fov = 40 // 视野范围
      const aspect = 2 // 相机默认值 画布的宽高比
      const near = 0.1 // 近平面
      const far = 1000 // 远平面
      // 透视投影相机
      const camera = new THREE.PerspectiveCamera(fov, aspect, near, far)
      camera.position.set(0, 50, 50)
      camera.lookAt(0, 0, 0)
      // 控制相机
      const controls = new OrbitControls(camera, canvas)
      controls.update()

      // 场景
      const scene = new THREE.Scene()

      // 渲染
      function render() {
        renderer.render(scene, camera)
        requestAnimationFrame(render)
      }

      requestAnimationFrame(render)
    </script>
  </body>
</html>

开启阴影想过配置

// 开启阴影渲染
renderer.shadowMap.enabled = true;

添加灯光并开启投射阴影

      {
        // 灯光
        const color = 0xffffff
        const intensity = 2
        const light = new THREE.DirectionalLight(color, intensity)
        light.castShadow = true // 投射阴影
        light.position.set(10, 10, 10)
        light.target.position.set(-4, 0, -4)
        scene.add(light)
        scene.add(light.target)

        const helper = new THREE.DirectionalLightHelper(light)
        scene.add(helper)
      }

绘制物体开启接收阴影

      {
        // 平面几何
        const groundGeometry = new THREE.PlaneGeometry(50, 50)
        const groundMaterial = new THREE.MeshPhongMaterial({ color: 0xcc8866, side: THREE.DoubleSide })
        const groundMesh = new THREE.Mesh(groundGeometry, groundMaterial)
        groundMesh.rotation.x = Math.PI * -0.5
        groundMesh.receiveShadow = true // 接受阴影
        scene.add(groundMesh)
      }
      {
        // 几何体
        const cubeSize = 4
        const cubeGeo = new THREE.BoxGeometry(cubeSize, cubeSize, cubeSize)
        const cubeMat = new THREE.MeshPhongMaterial({ color: '#8AC' })
        const mesh = new THREE.Mesh(cubeGeo, cubeMat)
        mesh.castShadow = true // 投射阴影
        mesh.receiveShadow = true // 接受阴影
        mesh.position.set(cubeSize + 1, cubeSize / 2, 0)
        scene.add(mesh)
      }

image.png

  • 从结果中看,阴影少了一部分。是因为光源阴影相机决定了阴影投射的区域。使用.CameraHelper(light.shadow.camera)来获取光源的阴影相机的辅助线。
    const cameraHelper = new THREE.CameraHelper(light.shadow.camera)
    scene.add(cameraHelper)

image.png

设置阴影相机

  • 通过设置light.shadow.camera修改阴影相机的区域。
    const d = 50
    light.shadow.camera.left = -d
    light.shadow.camera.right = d
    light.shadow.camera.top = d
    light.shadow.camera.bottom = -d
    light.shadow.camera.near = 1
    light.shadow.camera.far = 60

image.png

总结

  • 需要注意,每添加一个光源到场景中,都会降低 three.js 渲染场景的速度,所以应该尽量使用最少的资源来实现想要的效果。
  • 还有一种实现阴影的效果就是使用光照贴图或者环境光贴图,预先计算离线照明的效果。根据物体里地面的高低来控制光照贴图的透明度实现阴影变化,这种方式能加快three.js 渲染场景的速度。后面在详细讲解。
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值