Three.js - 光源(九)

899 阅读3分钟

「这是我参与2022首次更文挑战的第9天,活动详情查看:2022首次更文挑战

光源

为了模拟物体在不同情况下的样式,three.js中提供了多种光源。需要注意光源和材质是相互的,简单来说物体表面的颜色是光源材质的乘积。在材质中的基础材质是不受灯光影响的。

创建基本场景

      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, 10, 20)
      camera.lookAt(0, 0, 0)

      // 控制相机
      const controls = new OrbitControls(camera, canvas)
      controls.update()

      // 场景
      const scene = new THREE.Scene()
      scene.background = new THREE.Color('white')

      {
        // 地面 平铺
        const planeSize = 20
        const loader = new THREE.TextureLoader()
        const texture = loader.load('https://threejs.org/manual/examples/resources/images/checker.png')
        // THREE.RepeatWrapping 纹理重复
        texture.wrapS = THREE.RepeatWrapping
        texture.wrapT = THREE.RepeatWrapping
        // 当一个纹素覆盖大于一个像素时,贴图将如何采样。 THREE.NearestFilter,它将使用最接近的纹素的值。
        texture.magFilter = THREE.NearestFilter
        const repeats = planeSize / 2
        // 重复次数
        texture.repeat.set(repeats, repeats)
        const planeGeo = new THREE.PlaneGeometry(planeSize, planeSize)
        // Phong材质
        const planeMat = new THREE.MeshPhongMaterial({
          map: texture,
          side: THREE.DoubleSide
        })
        const mesh = new THREE.Mesh(planeGeo, planeMat)
        mesh.rotation.x = Math.PI * -0.5
        scene.add(mesh)
      }

      {
        // 方块
        const cubeSize = 4
        const cubeGeo = new THREE.BoxGeometry(cubeSize, cubeSize, cubeSize)
        // Phong材质
        const cubeMat = new THREE.MeshPhongMaterial({ color: '#8f4b2e' })
        const mesh = new THREE.Mesh(cubeGeo, cubeMat)
        mesh.position.y = 2
        scene.add(mesh)
      }

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

      requestAnimationFrame(render)
  1. 这里使用了纹理重复创建地板,要了解具体使用可以去看前面的文章。
  2. 使用Phong材质,在没有灯光的情况下,渲染的物体都是黑色。

image.png

环境光 AmbientLight

  • 只是简单地将材质的颜色与光源颜色进行相乘,再乘以光照强度。所以只使用环境光,场景内的物体看起来没有立体感。
  • 环境光,它没有方向,无法产生阴影,场景内任何一点受到的光照强度都是相同的。
      {
        const color = 0xffffff
        const intensity = 1
        const light = new THREE.AmbientLight(color, intensity)
        scene.add(light)
      }

image.png

半球光 HemisphereLight

  • 颜色是从天空到地面两个颜色之间的渐变,与物体材质的颜色相乘后得到最终的颜色效果。
  • 一般都是与其他光源一起使用。
      {
        const skyColor = 0xb1e1ff // 天空 蓝色
        const groundColor = 0xffffff // 地面白色
        const intensity = 1
        const light = new THREE.HemisphereLight(skyColor, groundColor, intensity)
        scene.add(light)
      }

image.png

方向光 DirectionalLight

  • 方向光表示的是来自一个方向上的光,并不是从某个点发射出来的,而是从一个无限大的平面内,发射出全部相互平行的光线。
  • 一般用于模仿太阳光。
      {
        const color = 0xffffff
        const intensity = 1
        const light = new THREE.DirectionalLight(color, intensity)
        light.position.set(0, 10, 10)
        scene.add(light)

        // 光源辅助线
        const helper = new THREE.DirectionalLightHelper(light)
        scene.add(helper)
      }

1.gif

  • 为了能更好的观看光源,这里修该背景为黑色,使用.DirectionalLightHelper()生成方向光辅助线。

点光源 PointLight

  • 表示的是从一个点朝各个方向发射出光线的一种光照效果。
  • 一般用于模拟电灯。

      {
        const color = 0xffffff
        const intensity = 1
        const light = new THREE.PointLight(color, intensity)
        light.position.set(0, 5, 10)
        scene.add(light)

        // 光源辅助线
        const helper = new THREE.PointLightHelper(light)
        scene.add(helper)
      }

1.gif

  • 使用.PointLightHelper()生成点光源辅助线。

光源强度

  • WebGLRenderer中有一个设置项 .physicallyCorrectLights。开启后可设置随着离光源的距离增加光照如何减弱。点光源和聚光灯等灯光受其影响。
  • 在光源上有两个属性。.power以"流明(光通量单位)"为单位的光功率,.decay沿着光照距离的衰退量,默认值1。
renderer.physicallyCorrectLights = true

// 点光源修改
light.power = 800
light.decay = 2

1.gif

总结

本节介绍了一些常用的光源,在开发中光源是配合使用的。不过需要注意每添加一个光源到场景中,都会降低 three.js渲染的速度,所以要根据需求来判断添加多少光源实现最好的效率。