threejs学习1-点光源-webgl_lights_physical

32 阅读2分钟
<template>
  <view class="content">
    <view id="webgl" class="content"></view>
  </view>
</template>

<script>
import * as THREE from "three";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
export default {
  data() {
    return {
      title: "Hello",
      camera: null,
      scene: null,
      bulbLight: null,
      hemiLight: null,
      floorMat: null,
      cubeMat: null,
      ballMat: null,
      renderer: null,
      animateId: "",
    };
  },
  onLoad() {},
  mounted() {
    this.init();
    this.animate();
  },
  methods: {
    init() {
      const that = this;
      const dom = document.getElementById("webgl");
      console.log("dom", dom);
      // const stats = new Stats(); // 性能检测插件
      // dom.appendChild(stats.dom);

      // 相机
      this.camera = new THREE.PerspectiveCamera(
        50,
        dom.offsetWidth / dom.offsetHeight,
        0.1,
        100
      );
      this.camera.position.set(-4, 4, -2); // 设置相机位置

      this.scene = new THREE.Scene();

      // 添加辅助坐标轴
      const axesHelper = new THREE.AxesHelper(5);
      this.scene.add(axesHelper);

      // 点光源
      const bulbGeometry = new THREE.SphereGeometry(0.02, 16, 8);
      this.bulbLight = new THREE.PointLight(0xffee88, 1, 100, 2);
      const bulbMat = new THREE.MeshStandardMaterial({
        emissive: 0xffffee,
        emissiveIntensity: 1,
        color: 0x000000,
      });
      // 点光源用一个物体表示
      this.bulbLight.add(new THREE.Mesh(bulbGeometry, bulbMat));
      this.bulbLight.position.set(0, 2, 0);
      this.bulbLight.power = 800; // 光源的功率。单位为流明(lm)。

      this.bulbLight.castShadow = true;
      this.scene.add(this.bulbLight);

      // 点光源的辅助
      const pointLightHelper = new THREE.PointLightHelper(this.bulbLight);
      this.scene.add(pointLightHelper);

      // 半球光
      this.hemiLight = new THREE.HemisphereLight(0xddeeff, 0x0f0e0d, 0.02);
      this.hemiLight.intensity = 50; // 光源的强度。默认值为 1。
      this.scene.add(this.hemiLight);

      // 增加半球光的辅助
      const HemisphereHelper = new THREE.HemisphereLightHelper(
        this.hemiLight,
        5
      );
      this.scene.add(HemisphereHelper);

      // 地板的材质
      this.floorMat = new THREE.MeshStandardMaterial({
        roughness: 0.8,
        color: 0xffffff,
        metalness: 0.2,
        bumpScale: 0.0005,
      });
      // 加载图片
      const textureLoader = new THREE.TextureLoader();
      textureLoader.load("../../static/hardwood2_diffuse.jpg", function (map) {
        map.wrapS = THREE.RepeatWrapping;
        map.wrapT = THREE.RepeatWrapping;
        map.anisotropy = 4;
        map.repeat.set(10, 24);
        map.colorSpace = THREE.SRGBColorSpace;
        that.floorMat.map = map;
        that.floorMat.needsUpdate = true;
      });
      textureLoader.load("../../static/hardwood2_bump.jpg", function (map) {
        map.wrapS = THREE.RepeatWrapping;
        map.wrapT = THREE.RepeatWrapping;
        map.anisotropy = 4;
        map.repeat.set(10, 24);
        that.floorMat.bumpMap = map;
        that.floorMat.needsUpdate = true;
      });
      textureLoader.load(
        "../../static/hardwood2_roughness.jpg",
        function (map) {
          map.wrapS = THREE.RepeatWrapping;
          map.wrapT = THREE.RepeatWrapping;
          map.anisotropy = 4;
          map.repeat.set(10, 24);
          that.floorMat.roughnessMap = map;
          that.floorMat.needsUpdate = true;
        }
      );

      // 箱子
      this.cubeMat = new THREE.MeshStandardMaterial({
        roughness: 0.7,
        color: 0xffffff,
        bumpScale: 0.002,
        metalness: 0.2,
      });
      textureLoader.load("../../static/brick_diffuse.jpg", function (map) {
        map.wrapS = THREE.RepeatWrapping;
        map.wrapT = THREE.RepeatWrapping;
        map.anisotropy = 4;
        map.repeat.set(1, 1);
        map.colorSpace = THREE.SRGBColorSpace;
        that.cubeMat.map = map;
        that.cubeMat.needsUpdate = true;
      });
      textureLoader.load("../../static/brick_bump.jpg", function (map) {
        map.wrapS = THREE.RepeatWrapping;
        map.wrapT = THREE.RepeatWrapping;
        map.anisotropy = 4;
        map.repeat.set(1, 1);
        that.cubeMat.bumpMap = map;
        that.cubeMat.needsUpdate = true;
      });

      // 球
      this.ballMat = new THREE.MeshStandardMaterial({
        color: 0xffffff,
        roughness: 0.5,
        metalness: 1.0,
      });
      textureLoader.load("../../static/earth_atmos_2048.jpg", function (map) {
        map.anisotropy = 4;
        map.colorSpace = THREE.SRGBColorSpace;
        that.ballMat.map = map;
        that.ballMat.needsUpdate = true;
      });
      textureLoader.load(
        "../../static/earth_specular_2048.jpg",
        function (map) {
          map.anisotropy = 4;
          map.colorSpace = THREE.SRGBColorSpace;
          that.ballMat.metalnessMap = map;
          that.ballMat.needsUpdate = true;
        }
      );

      // 地板
      const floorGeometry = new THREE.PlaneGeometry(20, 20); // 生成一个平面
      const floorMesh = new THREE.Mesh(floorGeometry, this.floorMat);
      floorMesh.receiveShadow = true; // 材质是否接收阴影。默认值为false
      floorMesh.rotation.x = -Math.PI / 2.0; // 物体的局部旋转,以弧度来表示
      this.scene.add(floorMesh);

      // 球体
      const ballGeometry = new THREE.SphereGeometry(0.25, 32, 32); // 生成一个球体
      const ballMesh = new THREE.Mesh(ballGeometry, this.ballMat);
      ballMesh.position.set(1, 0.25, 1); // 表示对象局部位置的Vector3
      ballMesh.rotation.y = Math.PI;
      ballMesh.castShadow = true; // 对象是否被渲染到阴影贴图中。默认值为false。
      this.scene.add(ballMesh);

      // 箱子 1、2、3
      const boxGeometry = new THREE.BoxGeometry(0.5, 0.5, 0.5);
      const boxMesh = new THREE.Mesh(boxGeometry, this.cubeMat);
      boxMesh.position.set(-0.5, 0.25, -1);
      boxMesh.castShadow = true; // 增加光照下的阴影
      this.scene.add(boxMesh);

      const boxMesh2 = new THREE.Mesh(boxGeometry, this.cubeMat);
      boxMesh2.position.set(0, 0.25, -5);
      boxMesh2.castShadow = true; // 增加光照下的阴影
      this.scene.add(boxMesh2);

      const boxMesh3 = new THREE.Mesh(boxGeometry, this.cubeMat);
      boxMesh3.position.set(7, 0.25, 0);
      boxMesh3.castShadow = true; // 增加光照下的阴影
      this.scene.add(boxMesh3);

      this.renderer = new THREE.WebGLRenderer(); // 渲染器
      this.renderer.shadowMap.enabled = true; // 如果使用,它包含阴影贴图的引用。
      // 这个属性用于在普通计算机显示器或者移动设备屏幕等低动态范围介质上,模拟、逼近高动态范围(HDR)效果
      this.renderer.toneMapping = THREE.ReinhardToneMapping;
      this.renderer.setPixelRatio(window.devicePixelRatio); // 设置设备像素比。通常用于避免HiDPI设备上绘图模糊
      this.renderer.setSize(dom.offsetWidth, dom.offsetHeight); // 将输出canvas的大小调整为(width, height)并考虑设备像素比
      dom.appendChild(this.renderer.domElement);

      // Orbit controls(轨道控制器)可以使得相机围绕目标进行轨道运动。
      const controls = new OrbitControls(this.camera, this.renderer.domElement);
      controls.minDistance = 1;
      controls.maxDistance = 20;
    },

    animate() {
      this.animateId = requestAnimationFrame(this.animate);
      this.render();
    },
    cancelAnimate() {
      cancelAnimationFrame(this.animateId);
    },
    render() {
      this.renderer.toneMappingExposure = Math.pow(0.68, 5.0); // 色调映射的曝光级别,以拍摄非常明亮的场景
      const time = Date.now() * 0.0005;
      this.bulbLight.position.y = Math.cos(time) * 0.75 + 1.25;
      this.renderer.render(this.scene, this.camera);
    },
  },
};
</script>

<style>
.content {
  height: 750rpx;
  width: 100%;
  margin: 0 auto;
}

.logo {
  height: 200rpx;
  width: 200rpx;
  margin: 200rpx auto 50rpx auto;
}

.text-area {
  display: flex;
  justify-content: center;
}

.title {
  font-size: 36rpx;
  color: #8f8f94;
}
</style>