各种light详解

各种灯光示意图

在这里插入图片描述

1. AmbientLight(环境光)

不是作为单独使用,整体提亮,比如有一个物体,对着光的面,亮的,背对着的,暗,有环境光的存在,背面不会一片漆黑,环境光不产生阴影

const aLight = new THREE.AmbientLight(0xffffff, 0.2);
// scene.add(aLight);

参数详解:

  • 0xffffff - 光的颜色(白色)
  • 0.2 - 光的强度(0-1之间)
    特点验证:
  • ✅ 不是单独使用:通常配合其他光源使用
  • ✅ 整体提亮:均匀照亮所有物体表面
  • ✅ 背面不会漆黑:给阴影区域提供基础照明
  • ❌ 不产生阴影:环境光无法产生投影
  • 使用场景:
  • 基础照明,避免完全黑暗的区域
  • 模拟间接光照(光线反弹)

2. PointLight(点光源)

灯泡:最常见的类比对象,如台灯或灯泡,从固定位置向四周发射光线。 或者蜡烛:似蜡烛的火焰,光线从中心点向四周扩散,(可以产生阴影) 点光源方向是四面八方的

const pointLight = new THREE.PointLight(0xffffff);
pointLight.position.y = 2;
pointLight.intensity = 1;
pointLight.distance = 5;

参数详解:

0xffffff - 光的颜色

  • position - 光源在3D空间中的位置

  • intensity - 光的强度(0-1)

  • distance - 光的照射距离,超过此距离光线衰减为0

特点验证:

  • ✅ 像灯泡:从一点向所有方向发射光线

  • ✅ 四面八方:没有明确的方向性

  • ✅ 可以产生阴影:点光源可以投射阴影

  • 类比: 灯泡、蜡烛、发光球体

3. SpotLight(聚光灯)

台订光---像台灯,圆锥的光源,在锥形范围内是亮的(可以产生阴影)

const spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(1, 1, 1);
spotLight.angle = (60 / 180) * Math.PI;
spotLight.distance = 0.1;  // GUI中可调 0.1-10

参数详解:

  • position - 光源位置

  • angle - 光锥的角度(弧度制),60度转换为弧度

  • distance - 光的最大照射距离

  • penumbra - 光锥边缘的模糊程度(0-1)

  • decay - 光的衰减率

特点验证:

  • ✅ 像台灯:圆锥形的光照区域

  • ✅ 锥形范围内亮:有明显的照射范围

  • ✅ 可以产生阴影:聚光灯可以投射阴影

  • 类比: 台灯、手电筒、舞台追光灯

4. DirectionalLight(平行光)

方向光,太阳光,真实界的平行光是不存在的,太阳光最接近 迎着光的一面,发亮,背对着的是阴影(可以产生阴影)

const dLight = new THREE.DirectionalLight(0xffffff);
dLight.intensity = 1;
dLight.position.set(1, 1, 1);

参数详解:

  • position - 不表示光源位置,而是表示光线方向

  • intensity - 光的强度

  • target - 光线指向的目标点(默认指向原点)

特点验证:

  • ✅ 像太阳光:所有光线平行传播

  • ✅ 迎着光亮,背对阴影:产生明确的亮面和暗面

  • ✅ 可以产生阴影:平行光可以投射清晰的阴影

重要概念:

  • 平行光在现实中不存在,是计算机图形学的近似

  • 太阳光严格来说不是平行光,但在图形学中这样处理

5. HemisphereLight(半球光)

两束光,上边照,下边照(户外可能用到)

const hLight = new THREE.HemisphereLight(0xff0000, 0x0000ff, 1);
scene.add(hLight);

参数详解:

  • 0xff0000 - 天空颜色(红色)

  • 0x0000ff - 地面颜色(蓝色)

  • 1 - 光的强度

特点验证:

  • ✅ 两束光:上半球天空光 + 下半球地面反射光

  • ✅ 户外使用:模拟自然室外光照环境

  • ❌ 不常用在室内:室内通常没有这么明显的颜色区分

6. RectAreaLight(矩形区域光)–仅影响 MeshStandardMaterial 和 MeshPhysicalMaterial

const rectAreaLight = new THREE.RectAreaLight(0xffffff, 1, 2, 2);
rectAreaLight.position.set(0, 1, 0);
rectAreaLight.rotation.x = -0.5 * Math.PI;

参数详解:

  • 0xffffff - 光的颜色

  • 1 - 光的强度

  • 2 - 光的宽度

  • 2 - 光的高度

重要限制:

❗ 只对特定材质有效:仅影响 MeshStandardMaterial 和 MeshPhysicalMaterial

  • 其他材质无法正确显示区域光效果

  • 类比: 灯箱、LED屏幕、窗户透光

以下是完整代码:

<template>
  <div class="container" ref="containerRef"></div>
</template>

<script setup>
import * as THREE from "three";
import { onMounted, ref } from "vue";
// Controls鼠标交互
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import Stats from "three/examples/jsm/libs/stats.module";
import * as dat from "dat.gui";
// RectAreaLight用这个需要导入
import { RectAreaLightHelper } from 'three/examples/jsm/helpers/RectAreaLightHelper';

const gui = new dat.GUI();
const containerRef = ref(null);
const stat = new Stats();

// 场景、相机、渲染器
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
  75,
  window.innerWidth / window.innerHeight,
  0.1,
  1000
);
camera.position.set(4, 2, 5);
camera.lookAt(0, 0, 0);

const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);

// 坐标轴
const axes = new THREE.AxesHelper(50);
scene.add(axes);

// 场景物体
const planeM = new THREE.MeshStandardMaterial({ color: 0xcccccc });
const PlaneG = new THREE.PlaneGeometry(4, 4);
const plane = new THREE.Mesh(PlaneG, planeM);
plane.rotation.x = -0.5 * Math.PI;
scene.add(plane);

const material = new THREE.MeshStandardMaterial({ color: 0xff00ff });

// 球体
const shaereG = new THREE.SphereGeometry(0.25);
const sphere = new THREE.Mesh(shaereG, material);
sphere.position.y = 0.25;
scene.add(sphere);

// 立方体
const cubeG = new THREE.BoxGeometry(0.5, 0.5, 0.5);
const cube = new THREE.Mesh(cubeG, material);
cube.position.set(1, 0.8, 0);
scene.add(cube);

// 圆环
const torusG = new THREE.TorusGeometry(0.3, 0.1, 10, 20);
const torus = new THREE.Mesh(torusG, material);
torus.position.set(-1, 0.8, 0);
torus.rotation.x = -0.5 * Math.PI;
scene.add(torus);

// 灯光配置
const colors = {
  dLight: 0xffffff,
  sLight: 0xffffff,
  pLight: 0xffffff,
};

// 环境光
const aLight = new THREE.AmbientLight(0xffffff, 0.2);
// scene.add(aLight);

// 平行光
const dLight = new THREE.DirectionalLight(0xffffff);
dLight.intensity = 1;
dLight.position.set(1, 1, 1);
// scene.add(dLight);

const dFol = gui.addFolder("DirectionalLight");
dFol.addColor(colors, "dLight").onChange(() => {
  dLight.color.set(colors.dLight);
});
dFol.add(dLight, "intensity", 0, 1, 0.01);
dFol.add(dLight.position, "x", -5, 5);
dFol.add(dLight.position, "y", -5, 5);
dFol.add(dLight.position, "z", -5, 5);

const dLightHelper = new THREE.DirectionalLightHelper(dLight);
// scene.add(dLightHelper);

// 聚光灯
const spotLight = new THREE.SpotLight(0xffffff);
spotLight.position.set(1, 1, 1);
spotLight.angle = (60 / 180) * Math.PI;
// scene.add(spotLight);

const sFol = gui.addFolder("SpotLight");
sFol.addColor(colors, "sLight").onChange(() => {
  spotLight.color.set(colors.sLight);
});
sFol.add(spotLight, "intensity", 0, 1, 0.01);
sFol.add(spotLight.position, "x", -5, 5);
sFol.add(spotLight.position, "y", -5, 5);
sFol.add(spotLight.position, "z", -5, 5);
sFol.add(spotLight, "distance", 0.1, 10);
sFol.add(spotLight, "angle", 0.01, 3.14);

const spotLightHelper = new THREE.SpotLightHelper(spotLight);
// scene.add(spotLightHelper);

// 点光源
const pointLight = new THREE.PointLight(0xffffff);
pointLight.position.y = 2;
pointLight.intensity = 1;
pointLight.distance = 5;
// scene.add(pointLight);

const PFol = gui.addFolder("PointLight");
PFol.addColor(colors, "pLight").onChange(() => {
  pointLight.color.set(colors.pLight);
});
PFol.add(pointLight, "intensity", 0, 1, 0.01);
PFol.add(pointLight.position, "x", -5, 5);
PFol.add(pointLight.position, "y", -5, 5);
PFol.add(pointLight.position, "z", -5, 5);
PFol.add(pointLight, "distance", 0.1, 10);

const pointLightHelper = new THREE.PointLightHelper(pointLight);
// scene.add(pointLightHelper);

// 矩形区域光
const rectAreaLight = new THREE.RectAreaLight(0xffffff, 1, 2, 2);
rectAreaLight.position.set(0, 1, 0);
rectAreaLight.rotation.x = -0.5 * Math.PI;
// scene.add(rectAreaLight);

const rectAreaLightHelper = new RectAreaLightHelper(rectAreaLight);
// scene.add(rectAreaLightHelper);

// 半球光
const hLight = new THREE.HemisphereLight(0xff0000, 0x0000ff, 1);
scene.add(hLight);

// 控制器和动画
let orbitControls; // 在外部声明,确保在animate中可访问
const clock = new THREE.Clock();

function animate() {
  const time = clock.getElapsedTime();
  
  // 物体动画
  cube.rotation.x = time * 0.4;
  cube.rotation.y = time * 0.4;
  torus.rotation.y = time * 0.4;
  torus.rotation.x = time * 0.4;

  // 更新控制器
  if (orbitControls) {
    orbitControls.update();
  }

  // 更新辅助线
  if (spotLightHelper.parent) {
    spotLightHelper.update();
  }

  // 渲染
  renderer.render(scene, camera);
  stat.update();

  requestAnimationFrame(animate);
}

// 挂载
onMounted(() => {
  // 初始化轨道控制器
  orbitControls = new OrbitControls(camera, containerRef.value);
  orbitControls.enableDamping = true;

  // 添加到DOM
  containerRef.value.appendChild(renderer.domElement);
  containerRef.value.appendChild(stat.domElement);

  // 开始动画
  animate();
});

// 窗口大小调整
window.addEventListener('resize', () => {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
});
</script>

<style>
.container {
  width: 100%;
  height: 100vh;
  overflow: hidden;
}
</style>

代码中的GUI控制

// 每种灯光都有对应的控制面板
const dFol = gui.addFolder("DirectionalLight");
dFol.addColor(colors, "dLight").onChange(() => {
  dLight.color.set(colors.dLight);
});
dFol.add(dLight, "intensity", 0, 1, 0.01);
// ... 位置控制

可调整参数:

*颜色:实时改变光的颜色

*强度:0-1范围的光照强度

*位置:X/Y/Z坐标调整

*特殊参数:聚光灯角度、点光源距离等

灯光辅助线

const dLightHelper = new THREE.DirectionalLightHelper(dLight);
const spotLightHelper = new THREE.SpotLightHelper(spotLight);
const pointLightHelper = new THREE.PointLightHelper(pointLight);
const rectAreaLightHelper = new RectAreaLightHelper(rectAreaLight);

其中// RectAreaLight用这个需要导入
import { RectAreaLightHelper } from ‘three/examples/jsm/helpers/RectAreaLightHelper’;
这个需要引入
const rectAreaLightHelper = new RectAreaLightHelper(rectAreaLight); 这里不需要THREE.

辅助线帮助可视化:

平行光:显示光线方向
聚光灯:显示光锥范围
点光源:显示光源位置
区域光:显示光面大小和方向

我本来想把每种光辅助线截图的,可是我太累了,有时间再弄吧

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值