文章数量
36
访客量
4940
访问量
9798

threejs使用SpotLight实现聚光灯光照效果

阅读量:690
更新时间:2023-02-11 11:25:06

效果预览:效果预览
源码下载:关注公众号【RMRF】,回复【three5】可获取源码

一、安装

npm install three

二、App.vue

<template>
  <div class="index">
    <div id="container"></div>
  </div>
</template>
<script>
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
export default {
  data() {
    return {
      scene: null, // 场景
      camera: null, // 相机
      renderer: null, // 渲染器
      composer: null, // 效果合成器
      lightHelper: null
    };
  },
  mounted() {
    this.init();
  },
  methods: {
    // 初始化
    init() {
      const el = document.getElementById('container');
      this.initScene();
      this.initCamera();
      this.initRenderer(el);
      this.initCube();
      this.initPlane()
      this.initOrbitControls();
      this.initSpotLight()
      this.render();
      window.addEventListener('resize', this.onWindowResize);
    },
    // 场景
    initScene() {
      this.scene = new THREE.Scene();
    },
    // 相机
    initCamera() {
      this.camera = new THREE.PerspectiveCamera(
        35,
        window.innerWidth / window.innerHeight,
        1,
        2000
      );
      this.camera.position.set(46, 22, -21);
    },
    // 渲染器
    initRenderer(el) {
      this.renderer = new THREE.WebGLRenderer({
        antialias: true
      });
      this.renderer.setPixelRatio(window.devicePixelRatio);
      this.renderer.setSize(window.innerWidth, window.innerHeight);
      this.renderer.shadowMap.enabled = true;
      el.appendChild(this.renderer.domElement);
    },
    // 缩放
    initOrbitControls() {
      let controls = new OrbitControls(this.camera, this.renderer.domElement);
      controls.target.set(0, 7, 0);
      controls.maxPolarAngle = Math.PI / 2;
      controls.update();
    },

    // 渲染
    render() {
      this.renderer.render(this.scene, this.camera);
      if (this.lightHelper) {
        this.lightHelper.update()
      }
      requestAnimationFrame(this.render);
    },
    // 自适应
    onWindowResize() {
      this.camera.aspect = window.innerWidth / window.innerHeight;
      this.camera.updateProjectionMatrix();
      this.renderer.setSize(window.innerWidth, window.innerHeight);
    },
    // 立方体
    initCube() {
      const geometry = new THREE.BoxGeometry(3, 3, 3);
      const material = new THREE.MeshPhongMaterial();
      let cube = new THREE.Mesh(geometry, material);
      cube.castShadow = true;
      cube.receiveShadow = true;
      this.scene.add(cube);
    },
    // 地板
    initPlane() {
      let geometry = new THREE.PlaneGeometry(50, 50);
      let material = new THREE.MeshPhongMaterial({
        color: 0xffffff,
        dithering: true
      })
      let mesh = new THREE.Mesh(geometry, material);
      mesh.position.set(0, -3, 0);
      // 沿着X轴旋转
      mesh.rotation.x = -Math.PI * 0.5;
      // 接受阴影
      mesh.receiveShadow = true;
      this.scene.add(mesh);
    },
    // 聚光灯
    initSpotLight() {
      const light = new THREE.SpotLight(0xffff00, 1)
      // 投射阴影
      light.castShadow = true
      // 光照最大范围
      light.angle = 0.4
      // 半影衰减百分比
      light.penumbra = 0.2
      // 沿着光照距离的衰减量
      light.decay = 2
      // 光照最大距离
      light.distance = 50
      // 位置
      light.position.set(0, 20, 13)
      this.scene.add(light)
      // 光照锥形辅助
      this.lightHelper = new THREE.SpotLightHelper(light);
      this.scene.add(this.lightHelper)
      // 环境光
      const ambientLight = new THREE.AmbientLight(0x404040);
      this.scene.add(ambientLight);
    }
  }
};
</script>