Three.js开发必备:灯光详解附带案例

目录

前言

在学习和使用three.js的时候,灯光是非常重要的元素之一,灯光用于模拟现实世界中的光照,环境光,聚光灯,点光等,使3D场景更加逼真,下面是我在学习灯光的时候进行的一些总结及其夹杂案例强化对灯光的使用。

灯光介绍

环境光 (AmbientLight)

属性:

javascript 复制代码
const ambientLight = new THREE.AmbientLight({
 	color: 0xffffff, // color(颜色)
    intensity: 0.5, // intensity(强度)
});

color(颜色)、intensity(强度)

描述:

环境光均匀地照亮所有物体,不产生阴影。它用来模拟间接光照,给场景提供一个基本亮度。

适用场景:

适用于需要整体照明但不需要方向性光照效果的场景。

案例:平行光前后对比

未使用环境光之前 使用环境光之后

平行光 (DirectionalLight)

属性:

javascript 复制代码
const directionalLight = new THREE.DirectionalLight();
directionalLight.position.set(3, 3, 3);
directionalLight.color.set(0xffff00);
directionalLight.intensity = 0.1;
directionalLight.castShadow = true;
directionalLight.shadow.camera.top = 5;
directionalLight.shadow.camera.bottom = -5;
directionalLight.shadow.camera.left = -5;
directionalLight.shadow.camera.right = 5;
directionalLight.shadow.camera.near = 0.5;
directionalLight.shadow.camera.far = 20;
this.scene.add(directionalLight);
this.mesh.castShadow = true;

color、intensity、position(位置)、target(光照目标,默认是原点)castShadow(控制平行光是否能够投射阴影)

描述:

平行光模拟远处的大光源,如太阳。光线被认为是平行的,不会因为距离变化而衰减。 平行光可以产生阴影,为场景中的物体增加逼真的阴影效果。要启用平行光的阴影功能,需要将 castShadow 属性设置为 true,并且为场景中的接收阴影的物体设置receiveShadow 属性为 true。 均匀的光照: 平行光在整个场景中产生均匀的光照效果,类似于太阳光的照明。

适用场景

适合模拟户外日光或任何具有强烈方向性的光源。

案例:通过GUI控制平行光参数

javascript 复制代码
<template>
  <div id="container"></div>
</template>

<script>
import * as THREE from "three";
import { GUI } from "three/examples/jsm/libs/lil-gui.module.min.js";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import { CameraHelper } from "three";

export default {
  name: "three13Camera",
  components: {},
  mounted() {
    window.addEventListener("resize", () => {
      this.renderer.setSize(window.innerWidth, window.innerHeight);
      this.camera.aspect = window.innerWidth / window.innerHeight;
      this.camera.updateProjectionMatrix();
    });
    this.init();
  },
  data() {
    return {
      camera: null,
      scene: null,
      renderer: null,
      mesh: null,
      controls: null,
      gui: null,
      cameraHelper: null,
      cameraParams: {
        fov: 75,
        aspect: window.innerWidth / window.innerHeight,
        near: 0.1,
        far: 700,
        zoom: 1,
      },
    };
  },
  methods: {
    allView() {
      this.renderer.domElement.requestFullscreen();
    },
    backAllView() {
      this.renderer.domElement.exitFullscreen();
    },
    init() {
      this.gui = new GUI();
      const container = document.body;

      // 场景初始化
      this.scene = new THREE.Scene();

      // 相机初始化
      this.camera = new THREE.PerspectiveCamera(
        this.cameraParams.fov,
        this.cameraParams.aspect,
        this.cameraParams.near,
        this.cameraParams.far
      );
      this.camera.position.set(2, 2, 5);
      this.camera.lookAt(0, 0, 0);

      // 渲染器初始化
      this.renderer = new THREE.WebGLRenderer({ antialias: true });
      this.renderer.setSize(window.innerWidth, window.innerHeight);
      this.renderer.shadowMap.enabled = true;
      this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
      container.appendChild(this.renderer.domElement);

      // 创建立方体
      const geometry = new THREE.BoxGeometry(1, 1, 1);
      // { color: 0x00ff00 }
      const material = new THREE.MeshLambertMaterial();
      this.mesh = new THREE.Mesh(geometry, material);
      this.scene.add(this.mesh);
      this.scene.background = new THREE.Color(0x1f1f1f);

      const planeGeometry = new THREE.PlaneGeometry(10, 10);
      const planeMaterial = new THREE.MeshStandardMaterial({
        color: 0x888888,
        side: THREE.DoubleSide, // 添加这一行
      });
      const plane = new THREE.Mesh(planeGeometry, planeMaterial);
      plane.receiveShadow = true; // 必须开启
      plane.position.y = -1;

      plane.rotation.x = -Math.PI / 2; // 旋转成水平面
      plane.receiveShadow = true; // 接收阴影

      this.scene.add(plane);

      // 轨道控制器
      this.controls = new OrbitControls(this.camera, this.renderer.domElement);
      this.controls.enableDamping = true;
      this.controls.dampingFactor = 0.05;

      // // 环境光
      // const ambientLight = new THREE.AmbientLight({
      //   color: 0xffffff,
      //   intensity: 0.5,
      // });
      // this.scene.add(ambientLight);

      // 平行光
      const directionalLight = new THREE.DirectionalLight();
      directionalLight.position.set(3, 3, 3);
      directionalLight.color.set(0xffff00);
      directionalLight.intensity = 0.1;
      directionalLight.castShadow = true;
      directionalLight.shadow.camera.top = 5;
      directionalLight.shadow.camera.bottom = -5;
      directionalLight.shadow.camera.left = -5;
      directionalLight.shadow.camera.right = 5;
      directionalLight.shadow.camera.near = 0.5;
      directionalLight.shadow.camera.far = 20;
      this.scene.add(directionalLight);
      this.mesh.castShadow = true;

      // GUI 控制面板
      // -----------------------------
      const lightFolder = this.gui.addFolder("Directional Light");

      // 控制 position
      const lightPosition = {
        x: directionalLight.position.x,
        y: directionalLight.position.y,
        z: directionalLight.position.z,
      };

      lightFolder
        .add(lightPosition, "x")
        .min(-10)
        .max(10)
        .step(0.1)
        .onChange(() => {
          directionalLight.position.set(
            lightPosition.x,
            lightPosition.y,
            lightPosition.z
          );
          lightHelper.update(); // 更新 helper 显示
        });

      lightFolder
        .add(lightPosition, "y")
        .min(-10)
        .max(10)
        .step(0.1)
        .onChange(() => {
          directionalLight.position.set(
            lightPosition.x,
            lightPosition.y,
            lightPosition.z
          );
          lightHelper.update();
        });

      lightFolder
        .add(lightPosition, "z")
        .min(-10)
        .max(10)
        .step(0.1)
        .onChange(() => {
          directionalLight.position.set(
            lightPosition.x,
            lightPosition.y,
            lightPosition.z
          );
          lightHelper.update();
        });

      // 在 lightFolder 中添加 intensity 控制
      lightFolder
        .add(directionalLight, "intensity")
        .min(0)
        .max(5)
        .step(0.1)
        .name("Intensity");

      // 添加颜色控制
      lightFolder
        .addColor(
          { color: "#" + directionalLight.color.getHexString() },
          "color"
        )
        .name("Light Color")
        .onChange((value) => {
          directionalLight.color.set(value);
        });
      // 添加 DirectionalLightHelper
      const lightHelper = new THREE.DirectionalLightHelper(directionalLight, 5); // 参数2是helper的大小
      this.scene.add(lightHelper);

      // 动画循环
      this.animate();
    },
    animate() {
      requestAnimationFrame(this.animate);
      this.controls.update();
      this.renderer.render(this.scene, this.camera);
      // this.cameraHelper.update();
    },
  },
};
</script>

<style scoped></style>

点光源 (PointLight)

属性

color、intensity、distance(影响半径)、decay(衰减因子,默认值为2,符合物理规律)、position

描述

点光源从空间中的一点向四周发出光线,类似于灯泡的效果。随着距离增加,光照强度会按照设置的衰减方式减弱。

适用场景

适用于室内照明或需要局部高亮区域的场合。

案例:通过GUi控制点光的参数

案例代码:

javascript 复制代码
<template>
  <div id="container"></div>
</template>

<script>
import * as THREE from "three";
import { GUI } from "three/examples/jsm/libs/lil-gui.module.min.js";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
export default {
  name: "three13Camera",
  components: {},
  mounted() {
    window.addEventListener("resize", () => {
      this.renderer.setSize(window.innerWidth, window.innerHeight);
      this.camera.aspect = window.innerWidth / window.innerHeight;
      this.camera.updateProjectionMatrix();
    });
    this.init();
  },
  data() {
    return {
      camera: null,
      scene: null,
      renderer: null,
      mesh: null,
      controls: null,
      gui: null,
      cameraHelper: null,
      cameraParams: {
        fov: 75,
        aspect: window.innerWidth / window.innerHeight,
        near: 0.1,
        far: 700,
        zoom: 1,
      },
      pointLightPosition: { x: 2, y: 1, z: 2 }, // 初始化点光源的位置
      sphereLight: null, // 球体光源对象
    };
  },
  methods: {
    allView() {
      this.renderer.domElement.requestFullscreen();
    },
    backAllView() {
      this.renderer.domElement.exitFullscreen();
    },
    init() {
      this.gui = new GUI();
      const container = document.body;

      // 场景初始化
      this.scene = new THREE.Scene();

      // 相机初始化
      this.camera = new THREE.PerspectiveCamera(
        this.cameraParams.fov,
        this.cameraParams.aspect,
        this.cameraParams.near,
        this.cameraParams.far
      );
      this.camera.position.set(2, 2, 5);
      this.camera.lookAt(0, 0, 0);

      // 渲染器初始化
      this.renderer = new THREE.WebGLRenderer({ antialias: true });
      this.renderer.setSize(window.innerWidth, window.innerHeight);
      this.renderer.shadowMap.enabled = true;
      this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
      container.appendChild(this.renderer.domElement);

      // 创建立方体
      const geometry = new THREE.BoxGeometry(1, 1, 1);
      const material = new THREE.MeshLambertMaterial();
      this.mesh = new THREE.Mesh(geometry, material);
      this.mesh.color = new THREE.Color(0xffff00);
      this.scene.add(this.mesh);
      this.mesh.castShadow = true;
      this.scene.background = new THREE.Color(0x1f1f1f);

      // 创建平面
      const planeGeometry = new THREE.PlaneGeometry(100, 100);
      const planeMaterial = new THREE.MeshStandardMaterial({
        color: 0x888888,
        side: THREE.DoubleSide,
      });
      const plane = new THREE.Mesh(planeGeometry, planeMaterial);
      plane.receiveShadow = true;
      plane.position.y = -1;
      plane.rotation.x = -Math.PI / 2;
      this.scene.add(plane);

      // 创建轨道控制器
      this.controls = new OrbitControls(this.camera, this.renderer.domElement);
      this.controls.enableDamping = true;
      this.controls.dampingFactor = 0.05;

      // 创建点光源及对应的球体
      const sphereGeometry = new THREE.SphereGeometry(0.1, 32, 32);
      const sphereMaterial = new THREE.MeshBasicMaterial({ color: 0xffffff });
      this.sphereLight = new THREE.Mesh(sphereGeometry, sphereMaterial);
      this.sphereLight.position.set(
        this.pointLightPosition.x,
        this.pointLightPosition.y,
        this.pointLightPosition.z
      );
      this.scene.add(this.sphereLight);

      const pointLight = new THREE.PointLight(0xffffff, 30, 100);
      pointLight.castShadow = true;
      this.sphereLight.add(pointLight); // 将点光源附着在球体上

      // 添加 PointLightHelper
      const pointLightHelper = new THREE.PointLightHelper(pointLight, 1);
      this.scene.add(pointLightHelper);

      // GUI 控制面板
      const lightFolder = this.gui.addFolder("Point Light");

      // 控制颜色
      lightFolder
        .addColor({ color: "#" + pointLight.color.getHexString() }, "color")
        .name("Color")
        .onChange((value) => {
          pointLight.color.set(value);
        });

      // 控制强度
      lightFolder.add(pointLight, "intensity", 0, 10).name("Intensity");

      // 控制距离
      lightFolder.add(pointLight, "distance", 0, 200).name("Distance");

      // 控制衰减
      lightFolder.add(pointLight, "decay", 0, 5).step(0.1).name("Decay");

      // 控制位置
      lightFolder
        .add(this.pointLightPosition, "x", -20, 20)
        .name("Position X")
        .onChange(() => {
          this.sphereLight.position.set(
            this.pointLightPosition.x,
            this.pointLightPosition.y,
            this.pointLightPosition.z
          );
          pointLightHelper.update(); // 更新helper显示
        });
      lightFolder
        .add(this.pointLightPosition, "y", -20, 20)
        .name("Position Y")
        .onChange(() => {
          this.sphereLight.position.set(
            this.pointLightPosition.x,
            this.pointLightPosition.y,
            this.pointLightPosition.z
          );
          pointLightHelper.update(); // 更新helper显示
        });
      lightFolder
        .add(this.pointLightPosition, "z", -20, 20)
        .name("Position Z")
        .onChange(() => {
          this.sphereLight.position.set(
            this.pointLightPosition.x,
            this.pointLightPosition.y,
            this.pointLightPosition.z
          );
          pointLightHelper.update();
        });

      // 动画循环
      this.animate();
    },
    animate() {
      requestAnimationFrame(this.animate);
      this.controls.update();
      this.renderer.render(this.scene, this.camera);
    },
  },
};
</script>
<style scoped></style>

聚光灯 (SpotLight)

属性

‌颜色(color)‌:聚光灯的颜色,可以通过设置颜色值来改变光的颜色。 ‌强度(intensity)‌:聚光灯的亮度,数值越大光线越亮。 ‌距离(distance)‌:聚光灯的有效照射距离,超过这个距离光线会逐渐减弱。 ‌角度(angle)‌:聚光灯的光锥角度,决定了光线的覆盖范围。 ‌模糊半径(penumbra)‌:聚光灯光锥的模糊程度,数值越大光线越模糊。 ‌衰减系数(decay)‌:控制光线随距离衰减的速度,数值越大衰减越快。 ‌位置(position)‌:聚光灯在场景中的位置。 ‌目标位置(target)‌:聚光灯照射的目标对象位置,通常用于确定聚光灯的方向。

描述

聚光灯是从一点出发并沿着特定方向发散出锥形光束,可以设置光束的角度大小及边缘模糊程度。

适用场景

非常适合模拟手电筒、汽车前灯等聚焦光源效果。

案例:通过GUI控制聚光灯参数

案例代码:

javascript 复制代码
<template>
  <div id="container"></div>
</template>

<script>
import * as THREE from "three";
import { GUI } from "three/examples/jsm/libs/lil-gui.module.min.js";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
export default {
  name: "three13Camera",
  components: {},
  mounted() {
    window.addEventListener("resize", () => {
      this.renderer.setSize(window.innerWidth, window.innerHeight);
      this.camera.aspect = window.innerWidth / window.innerHeight;
      this.camera.updateProjectionMatrix();
    });
    this.init();
  },
  data() {
    return {
      camera: null,
      scene: null,
      renderer: null,
      mesh: null,
      controls: null,
      gui: null,
      cameraHelper: null,
      cameraParams: {
        fov: 75,
        aspect: window.innerWidth / window.innerHeight,
        near: 0.1,
        far: 700,
        zoom: 1,
      },
      pointLightPosition: { x: -1, y: 2, z: -2 }, // 初始化点光源的位置
      sphereLight: null, // 球体光源对象
      spotLight: null,
      spotLightTarget: { x: 0, y: 0, z: 0 }, // 光源的目标点
    };
  },
  methods: {
    allView() {
      this.renderer.domElement.requestFullscreen();
    },
    backAllView() {
      this.renderer.domElement.exitFullscreen();
    },
    init() {
      this.gui = new GUI();
      const container = document.body;

      // 场景初始化
      this.scene = new THREE.Scene();

      // 相机初始化
      this.camera = new THREE.PerspectiveCamera(
        this.cameraParams.fov,
        this.cameraParams.aspect,
        this.cameraParams.near,
        this.cameraParams.far
      );
      this.camera.position.set(2, 2, 5);
      this.camera.lookAt(0, 0, 0);

      // 渲染器初始化
      this.renderer = new THREE.WebGLRenderer({ antialias: true });
      this.renderer.setSize(window.innerWidth, window.innerHeight);
      this.renderer.shadowMap.enabled = true;
      this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
      container.appendChild(this.renderer.domElement);

      // 创建立方体
      const geometry = new THREE.BoxGeometry(1, 1, 1);
      const material = new THREE.MeshLambertMaterial();
      this.mesh = new THREE.Mesh(geometry, material);
      this.mesh.color = new THREE.Color(0xffff00);
      this.scene.add(this.mesh);
      this.mesh.castShadow = true;
      this.scene.background = new THREE.Color(0x1f1f1f);

      // 创建平面
      const planeGeometry = new THREE.PlaneGeometry(100, 100);
      const planeMaterial = new THREE.MeshStandardMaterial({
        color: 0x888888,
        side: THREE.DoubleSide,
      });
      const plane = new THREE.Mesh(planeGeometry, planeMaterial);
      plane.receiveShadow = true;
      plane.position.y = -1;
      plane.rotation.x = -Math.PI / 2;
      this.scene.add(plane);

      // 创建轨道控制器
      this.controls = new OrbitControls(this.camera, this.renderer.domElement);
      this.controls.enableDamping = true;
      this.controls.dampingFactor = 0.05;

      // 创建点光源及对应的球体
      const sphereGeometry = new THREE.SphereGeometry(0.1, 32, 32);
      const sphereMaterial = new THREE.MeshBasicMaterial({ color: 0xffffff });
      this.sphereLight = new THREE.Mesh(sphereGeometry, sphereMaterial);
      this.sphereLight.position.set(
        this.pointLightPosition.x,
        this.pointLightPosition.y,
        this.pointLightPosition.z
      );
      this.scene.add(this.sphereLight);

      // 创建聚光灯
      const spotLight = new THREE.SpotLight(
        0xffffff,
        30,
        100,
        Math.PI / 6,
        0.1,
        1
      );
      spotLight.castShadow = true;
      spotLight.position.set(
        this.pointLightPosition.x,
        this.pointLightPosition.y,
        this.pointLightPosition.z
      );
      spotLight.position.set(0, 0, 0); // 关键!改为局部坐标
      this.spotLight = spotLight;

      // 设置光源目标(可以是任意物体或空对象)
      const targetObject = new THREE.Object3D();
      targetObject.position.set(0, 0, 0);
      this.scene.add(targetObject);
      spotLight.target = targetObject;

      this.sphereLight.add(spotLight); // 将聚光灯附着在球体上
      this.scene.add(this.sphereLight);

      // 添加 SpotLightHelper(显示光照范围)
      this.spotLightHelper = new THREE.SpotLightHelper(spotLight);
      this.scene.add(this.spotLightHelper);
      const lightFolder = this.gui.addFolder("Spot Light");

      // 颜色控制
      lightFolder
        .addColor({ color: "#" + spotLight.color.getHexString() }, "color")
        .name("Color")
        .onChange((value) => {
          spotLight.color.set(value);
          this.spotLightHelper.update(); // 更新辅助线
        });

      // 强度
      lightFolder.add(spotLight, "intensity", 0, 100).name("Intensity");

      // 距离
      lightFolder.add(spotLight, "distance", 0, 200).name("Distance");

      // 角度(转换成弧度)
      lightFolder
        .add(
          { angleDeg: THREE.MathUtils.radToDeg(spotLight.angle) },
          "angleDeg",
          0,
          180
        )
        .name("Angle (°)")
        .onChange((value) => {
          spotLight.angle = THREE.MathUtils.degToRad(value);
          this.spotLightHelper.update();
        });

      // 边缘模糊度
      lightFolder.add(spotLight, "penumbra", 0, 1).step(0.01).name("Penumbra");

      // 衰减
      lightFolder.add(spotLight, "decay", 0, 5).step(0.1).name("Decay");

      // 光源位置控制
      const positionFolder = lightFolder.addFolder("Position");
      positionFolder
        .add(this.pointLightPosition, "x", -20, 20)
        .name("X")
        .onChange(() => {
          this.sphereLight.position.set(
            this.pointLightPosition.x,
            this.pointLightPosition.y,
            this.pointLightPosition.z
          );
          this.spotLightHelper.update();
        });
      positionFolder
        .add(this.pointLightPosition, "y", -20, 20)
        .name("Y")
        .onChange(() => {
          this.sphereLight.position.set(
            this.pointLightPosition.x,
            this.pointLightPosition.y,
            this.pointLightPosition.z
          );
          this.spotLightHelper.update();
        });
      positionFolder
        .add(this.pointLightPosition, "z", -20, 20)
        .name("Z")
        .onChange(() => {
          this.sphereLight.position.set(
            this.pointLightPosition.x,
            this.pointLightPosition.y,
            this.pointLightPosition.z
          );
          this.spotLightHelper.update();
        });

      // 光源目标控制
      const targetFolder = lightFolder.addFolder("Target");
      targetFolder
        .add(this.spotLightTarget, "x", -20, 20)
        .name("X")
        .onChange(() => {
          targetObject.position.set(
            this.spotLightTarget.x,
            this.spotLightTarget.y,
            this.spotLightTarget.z
          );
          this.spotLightHelper.update();
        });
      targetFolder
        .add(this.spotLightTarget, "y", -20, 20)
        .name("Y")
        .onChange(() => {
          targetObject.position.set(
            this.spotLightTarget.x,
            this.spotLightTarget.y,
            this.spotLightTarget.z
          );
          this.spotLightHelper.update();
        });
      targetFolder
        .add(this.spotLightTarget, "z", -20, 20)
        .name("Z")
        .onChange(() => {
          targetObject.position.set(
            this.spotLightTarget.x,
            this.spotLightTarget.y,
            this.spotLightTarget.z
          );
          this.spotLightHelper.update();
        });

      lightFolder.open(); // 默认展开面板
      // 动画循环
      this.animate();
    },
    animate() {
      requestAnimationFrame(this.animate);
      this.controls.update();
      this.spotLightHelper.update(); // 更新 SpotLightHelper
      this.renderer.render(this.scene, this.camera);
    },
  },
};
</script>

<style scoped></style>

区域光 (AreaLight)

属性

color、intensity、width(宽度)、height(高度)、position、rotation

描述

区域光模拟的是来自某一平面的光源,比如窗户外透进来的自然光,主要用于模拟由一定面积发出的光。

适用场景

适用于需要柔和阴影和更真实的光照效果的室内或室外场景。每种光源都有其独特的用途和特点,在实际项目中,通常会结合多种光源以达到理想的视觉效果。例如,在一个室内场景中,你可能会使用环境光来提供基础照明,点光源来模拟灯泡,聚光灯来制造焦点或强调特定物体。而在户外场景中,可能主要依赖于平行光来模拟太阳光,并添加一些环境光来增强细节。

效果:区域光效果

javascript 复制代码
<template>
  <div id="container"></div>
</template>

<script>
import * as THREE from "three";
import { GUI } from "three/examples/jsm/libs/lil-gui.module.min.js";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import { RectAreaLight } from "three/examples/jsm/lights/RectAreaLightUniformsLib.js";

export default {
  name: "three13Camera",
  components: {},
  mounted() {
    window.addEventListener("resize", () => {
      this.renderer.setSize(window.innerWidth, window.innerHeight);
      this.camera.aspect = window.innerWidth / window.innerHeight;
      this.camera.updateProjectionMatrix();
    });
    this.init();
  },
  data() {
    return {
      camera: null,
      scene: null,
      renderer: null,
      mesh: null,
      controls: null,
      gui: null,
      cameraHelper: null,
      cameraParams: {
        fov: 75,
        aspect: window.innerWidth / window.innerHeight,
        near: 0.1,
        far: 700,
        zoom: 1,
      },
      pointLightPosition: { x: 2, y: 1, z: 2 }, // 初始化点光源的位置
      sphereLight: null, // 球体光源对象
    };
  },
  methods: {
    allView() {
      this.renderer.domElement.requestFullscreen();
    },
    backAllView() {
      this.renderer.domElement.exitFullscreen();
    },
    init() {
      this.gui = new GUI();
      const container = document.body;

      // 场景初始化
      this.scene = new THREE.Scene();

      // 相机初始化
      this.camera = new THREE.PerspectiveCamera(
        this.cameraParams.fov,
        this.cameraParams.aspect,
        this.cameraParams.near,
        this.cameraParams.far
      );
      this.camera.position.set(2, 2, 5);
      this.camera.lookAt(0, 0, 0);

      // 渲染器初始化
      this.renderer = new THREE.WebGLRenderer({
        width: window.innerWidth,
        height: window.innerHeight,
        scale: 1,
        antialias: true,
        tonemapping: THREE.FilmicOperator,
        brightness: 2.5,
      });
      this.renderer.setSize(window.innerWidth, window.innerHeight);
      this.renderer.shadowMap.enabled = true;
      this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
      container.appendChild(this.renderer.domElement);
      this.scene.background = new THREE.Color(0x1f1f1f);

      // 创建平面
      const planeGeometry = new THREE.PlaneGeometry(70, 70, 1, 1);
      const planeMaterial = new THREE.MeshStandardMaterial({
        color: 0xffffff,
        metalness: 0.1,
        roughness: 0.5,
      });
      const plane = new THREE.Mesh(planeGeometry, planeMaterial);
      plane.receiveShadow = true;
      plane.rotation.x = -0.5 * Math.PI;
      plane.position.x = 0;
      plane.position.y = 0;
      plane.position.z = 0;
      this.scene.add(plane);

      // 创建轨道控制器
      this.controls = new OrbitControls(this.camera, this.renderer.domElement);
      this.controls.enableDamping = true;
      this.controls.dampingFactor = 0.05;
      // 创建一个矩形区域光源1
      var areaLight1 = new THREE.RectAreaLight(0xff0000, 1.5, 2, 9.9);
      areaLight1.position.set(2, 5, 0);
      areaLight1.rotation.set(-Math.PI / 2, 0, 0);
      areaLight1.width = 4;
      areaLight1.height = 9.9;
      this.scene.add(areaLight1);

      var planeGeometry1 = new THREE.BoxGeometry(1, 2, 0);
      var planeGeometry1Mat = new THREE.MeshBasicMaterial({ color: 0xff0000 });
      var plane1 = new THREE.Mesh(planeGeometry1, planeGeometry1Mat);
      plane1.position.set(2, 0.5, 0);
      this.scene.add(plane1);

      // 创建一个矩形区域光源2
      var areaLight2 = new THREE.RectAreaLight(0x00ff00, 1.5, 2, 9.9);
      areaLight2.position.set(10, 5, 0);
      areaLight2.rotation.set(-Math.PI / 2, 0, 0);
      areaLight2.width = 4;
      areaLight2.height = 9.9;
      this.scene.add(areaLight2);

      var planeGeometry2 = new THREE.BoxGeometry(1, 2, 0);
      var planeGeometry2Mat = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
      var plane2 = new THREE.Mesh(planeGeometry2, planeGeometry2Mat);
      plane2.position.set(10, 0.5, 0);
      this.scene.add(plane2);
      // 动画循环
      this.animate();
    },
    animate() {
      requestAnimationFrame(this.animate);
      this.controls.update();
      this.renderer.render(this.scene, this.camera);
    },
  },
};
</script>

<style scoped></style>

threeJs灯光完结

在Three.js中,合理使用光源可以让场景更具有真实感和层次感,理解光源的使用特性和使用场景,是学习Three.js打造数字孪生的重要一步。

相关推荐
前端大卫11 小时前
Vue3 + Element-Plus 自定义虚拟表格滚动实现方案【附源码】
前端
却尘12 小时前
Next.js 请求最佳实践 - vercel 2026一月发布指南
前端·react.js·next.js
ccnocare12 小时前
浅浅看一下设计模式
前端
Lee川12 小时前
🎬 从标签到屏幕:揭秘现代网页构建与适配之道
前端·面试
Ticnix12 小时前
ECharts初始化、销毁、resize 适配组件封装(含完整封装代码)
前端·echarts
纯爱掌门人12 小时前
终焉轮回里,藏着 AI 与人类的答案
前端·人工智能·aigc
twl12 小时前
OpenClaw 深度技术解析
前端
崔庆才丨静觅12 小时前
比官方便宜一半以上!Grok API 申请及使用
前端
星光不问赶路人12 小时前
vue3使用jsx语法详解
前端·vue.js
天蓝色的鱼鱼13 小时前
shadcn/ui,给你一个真正可控的UI组件库
前端