Three.js 中的光源对象详解
Three.js 中的光源对象详解
引言 (Foreword/Motivation)
在现实世界中,没有光,我们就无法看到物体的形状、颜色和纹理。在计算机 3D 图形学中,光照同样至关重要。光源是照亮场景、使物体可见、赋予物体体积感和真实感的关键。合适的光源设置能够突出物体的细节,营造特定的氛围,极大地影响最终的视觉效果。没有光源或者光源设置不当,你的 3D 场景可能会显得黑暗、平坦、缺乏生机。
Three.js 作为一个强大的 WebGL 库,提供了多种类型的光源,每种类型都模拟了现实世界中不同性质的光照来源(如太阳光、灯泡、环境光、聚光灯等)。理解这些光源的特性、它们如何与不同材质交互以及如何在场景中合理使用它们,是创建高质量 3D 场景的基础。
技术背景 (Technical Background)
- 3D 渲染基础: 3D 图形渲染是将三维场景呈现在二维屏幕上的过程。它涉及定义几何体(描述物体的形状)、材质(描述物体的表面属性)以及设置相机(决定观察视角)和光源。
- 光照与材质交互: 光源本身不可见,但它们发出的光线与物体表面的材质进行交互,计算出每个像素最终呈现的颜色。材质的属性(如基础颜色、光的概念、金属度、粗糙度、透明度等)决定了它如何反射、吸收或透射光线。
- 光照模型: 描述了光线与材质交互的数学模型。
- 环境光 (Ambient): 不考虑方向,均匀地照亮场景中的所有物体,使物体的阴影区域也能略微可见。
- 光的概念 (Diffuse): 模拟光线在物体表面各个方向均匀散射的效果,使得物体表面颜色均匀,其亮度取决于光线入射角。
- 光的概念 (Specular): 模拟光线在物体表面像镜子一样反射的效果,产生高光,其亮度和形状取决于光线方向、观察方向和材质的光泽度。
- 物理基础渲染 (PBR): 更先进的模型,基于光的物理属性,模拟能量守恒、菲涅尔效应等,提供更真实的渲染效果。Three.js 的
MeshStandardMaterial
和MeshPhysicalMaterial
使用 PBR 模型。
- WebGL: Three.js 通常使用 WebGL API 与浏览器中的 GPU 进行通信,利用 GPU 强大的并行计算能力进行高效的图形渲染。光照计算是渲染管线中的重要环节。
应用使用场景 (Application Scenarios)
光源在 Three.js 应用中的应用场景多种多样:
- 产品在线展示: 精确模拟摄影棚灯光,全方位展示产品细节和材质。
- 虚拟现实 (VR) / 增强现实 (AR): 在虚拟或现实叠加的场景中提供符合环境的光照。
- 游戏和模拟: 模拟游戏世界的光照环境,如太阳、手电筒、火焰等。
- 数据可视化: 照亮复杂的 3D 数据模型,使其结构和细节清晰可见。
- 艺术和设计: 利用独特的光影效果创造视觉风格。
- 建筑可视化: 模拟自然光(阳光)和人造光(灯泡、筒灯),展示建筑内部和外部效果。
原理解释 (Principle Explanation)
在 Three.js 场景中添加光源,并在渲染时生效的过程可以概括如下:
- 创建光源对象: 您根据需求选择合适的光源类型(如
AmbientLight
,DirectionalLight
,PointLight
等),创建其对象并设置颜色(color
)、强度(intensity
)等属性。 - 将光源添加到场景: 光源也是场景图中的一个节点,您需要使用
scene.add(light)
方法将其添加到场景中。 - 渲染器处理: 当
renderer.render(scene, camera)
被调用时,WebGLRenderer
会遍历场景图中的所有对象,包括几何体、材质、光源等。 - 计算光照: 对于每个需要光照计算的物体表面点(通常是在顶点着色器或片段着色器中),渲染器会:
- 获取该点的法线向量(垂直于表面的向量)。
- 获取相机到该点的向量(观察方向)。
- 遍历场景中的所有光源。
- 对于每个光源,根据其类型、位置、方向、强度以及当前表面点的法线、位置、观察方向等信息,计算该光源对该表面点贡献的光照强度和颜色。
- 这个计算过程会考虑材质的属性(如
光的概念
、光的概念
、粗糙度
、金属度
等)。 - 将所有光源的贡献累加起来,作为该表面点的最终光照结果。
- 颜色输出: 最终计算出的光照结果(颜色)与物体表面的基础颜色(材质的
color
或map
纹理)结合,得到该表面点在屏幕上显示的最终颜色。
不同光源类型对光照计算的影响:
AmbientLight
: 光照颜色和强度直接加到物体表面颜色上,与表面法线、位置无关。DirectionalLight
: 光线方向固定(light.position
减去light.target.position
得到方向向量),亮度均匀,像无限远处的平行光。光照强度取决于表面法线与光线方向的夹角(点积)。PointLight
: 光线从光源位置向所有方向辐射,亮度随距离衰减(light.distance
,light.decay
)。光照强度取决于表面法线与光源到表面点向量的夹角以及表面点到光源的距离。SpotLight
: 在 PointLight 基础上增加方向和锥形范围限制(light.angle
,light.penumbra
)。光照强度取决于表面法线与光线方向的夹角、距离以及表面点是否在光锥范围内。HemisphereLight
: 模拟天空和地面发出的半球形环境光,有两个颜色(天空颜色和地面颜色)。光照强度取决于表面法线的朝向(向上或向下)。
核心特性 (Core Features - of Three.js Lights)
- 多种光源类型: 支持模拟不同物理特性的光源。
- 可定制属性: 可以设置颜色、强度、位置、方向、范围、衰减等。
- 阴影支持: 部分光源类型(
DirectionalLight
,PointLight
,SpotLight
)可以配置为投射阴影(需要额外设置)。 - 场景图集成: 光源是场景中的对象,可以通过
scene.add()
添加和管理。 - 影响多种材质: 不同光源类型和材质类型(Lambertian, Phong, PBR 等)之间会进行不同的光照计算。
原理流程图以及原理解释 (Principle Flowchart)
(此处无法直接生成图形,用文字描述 Three.js 场景设置和渲染流程中与光照相关的部分)
图示:Three.js 光照设置与渲染流程
+---------------------+ +---------------------+ +---------------------+
| 创建 Three.js 场景 | ----> | 创建渲染器 | ----> | 创建相机 |
| (THREE.Scene) | | (THREE.WebGLRenderer)| | (THREE.PerspectiveCamera)|
+---------------------+ +---------------------+ +---------------------+
^ ^
| 添加 | 观察
| |
+---------------------+ +---------------------+ +---------------------+
| 创建物体 | ----> | 创建材质 | ----> | 创建光源 |
| (Geometry+Material) | | (THREE.Material) | | (THREE.Light 类型) |
+---------------------+ +---------------------+ +---------------------+
| 添加到场景图 | 添加到场景图
+--------------------------------------------+
| 包含在 Scene 中
v
+---------------------+
| 设置渲染循环 |
| (requestAnimationFrame)|
+---------------------+
| 在循环中调用
v
+---------------------+
| renderer.render |
| (scene, camera) |
+---------------------+
| 渲染器执行
v
+---------------------------+
| 计算光照交互并绘制 |
| (Renderer 计算光线与材质, |
| 考虑所有光源,绘制到 Canvas) |
+---------------------------+
|
v
+---------------------------+
| Canvas 显示在浏览器 |
+---------------------------+
原理解释:
- 首先创建基础的 3D 场景元素:场景 (
Scene
)、渲染器 (WebGLRenderer
) 和相机 (Camera
)。 - 然后创建构成场景内容的物体 (
Mesh
=Geometry
+Material
) 和光源 (Light
的派生类),并设置它们的属性(位置、颜色、强度等)。 - 将创建好的物体和光源都使用
scene.add()
方法添加到场景图中。 - 通过
requestAnimationFrame
设置一个渲染循环,在每一帧中调用renderer.render(scene, camera)
方法。 - 当
renderer.render()
被调用时,渲染器会遍历整个场景图。对于每个物体,它会根据物体表面的法线、位置、材质属性,以及场景中所有光源的类型、位置、方向、强度等信息,计算光线与物体的交互效果(包括漫反射、光的概念、光的概念、光的概念、光的概念等等,取决于材质类型)。 - 最终计算出的颜色信息会被绘制到浏览器中的 Canvas 元素上,呈现出带有光照效果的 3D 场景。
环境准备 (Environment Setup)
- 现代 Web 浏览器: 确保使用支持 WebGL 的现代浏览器(如 Chrome, Firefox, Edge, Safari)。
- 文本编辑器: 用于编写 HTML, CSS 和 JavaScript 代码。
- 本地 Web 服务器: 强烈推荐使用一个简单的本地 Web 服务器来托管您的文件进行测试。直接在浏览器中打开本地 HTML 文件 (
file:///...
) 可能会因为浏览器安全限制(如 CORS)导致无法正确加载 Three.js 库或纹理等外部资源。- Node.js 用户可以使用
http-server
(npm install -g http-server
后在项目目录运行http-server
)。 - Python 用户可以使用
python -m http.server
。 - VS Code 用户可以安装 Live Server 扩展。
- Node.js 用户可以使用
- Three.js 库: 在 HTML 文件中通过 CDN 引入 Three.js 库文件。
完整代码实现 (Full Code Implementation)
以下是使用 JavaScript 编写的 Three.js 示例代码,演示如何在场景中添加不同类型的光源并观察其效果。
1. HTML 文件 (index.html
)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Three.js 光源示例</title>
<style>
body { margin: 0; }
canvas { display: block; } /* 确保 Canvas 不会有额外的空白 */
</style>
</head>
<body>
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three@0.163.0/build/three.module.js",
"three/addons/": "https://unpkg.com/three@0.163.0/examples/jsm/"
}
}
</script>
<script type="module" src="./script.js"></script>
</body>
</html>
2. JavaScript 文件 (script.js
)
import * as THREE from 'three'; // 使用 ES Modules 方式导入 Three.js
let scene, camera, renderer;
let cube;
// 初始化场景、相机、渲染器和物体
function init() {
// --- 场景 ---
scene = new THREE.Scene();
scene.background = new THREE.Color(0xaaaaaa); // 设置场景背景色
// --- 相机 ---
// 透视相机 (视角, 宽高比, 近裁剪面, 远裁剪面)
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 1, 5); // 设置相机位置
camera.lookAt(scene.position); // 相机看向场景中心
// --- 渲染器 ---
renderer = new THREE.WebGLRenderer({ antialias: true }); // 开启抗锯齿
renderer.setSize(window.innerWidth, window.innerHeight); // 设置渲染器尺寸
renderer.setPixelRatio(window.devicePixelRatio); // 设置设备像素比,提高清晰度
document.body.appendChild(renderer.domElement); // 将渲染器的 Canvas 添加到 HTML body
// --- 创建一个用于演示光照效果的物体 ---
const geometry = new THREE.BoxGeometry(1, 1, 1); // 创建一个立方体几何体
// 使用 MeshStandardMaterial,它受各种光源影响,支持物理基础渲染
const material = new THREE.MeshStandardMaterial({ color: 0x00ff00 }); // 设置材质颜色 (绿色)
cube = new THREE.Mesh(geometry, material); // 创建网格对象 (物体)
scene.add(cube); // 将物体添加到场景
// --- 添加不同类型的光源 ---
// 一开始可以注释掉一些光源,逐个观察效果
// 1. 环境光 (AmbientLight): 均匀地照亮整个场景,没有方向,不会产生阴影
// 参数: 颜色, 强度 (0.0 - 1.0)
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5); // 柔和的白光
scene.add(ambientLight);
console.log('添加了环境光');
// 2. 定向光 (DirectionalLight): 模拟远处的光源,光线平行,有方向
// 参数: 颜色, 强度 (0.0 - 1.0)
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
directionalLight.position.set(5, 10, 7.5); // 设置光源位置 (决定光线方向)
// directionalLight.target = cube; // 可以让定向光指向特定物体,决定光线方向是 position -> target
// 如果不设置 target,默认指向场景原点 (0,0,0)
scene.add(directionalLight);
console.log('添加了定向光');
// 3. 点光源 (PointLight): 从一个点向所有方向发射光线,亮度随距离衰减
// 参数: 颜色, 强度 (亮度), 距离 (光线作用范围,0为无限远), 衰减 (光的衰减速度)
const pointLight = new THREE.PointLight(0xff0000, 1, 10, 2); // 红色光源,强度1,作用范围10,衰减速度2
pointLight.position.set(-5, 5, 5); // 设置光源位置
scene.add(pointLight);
// 可以添加一个表示点光源位置的小球体,方便观察
// const sphereGeometry = new THREE.SphereGeometry(0.2, 16, 8);
// const sphereMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 });
// const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
// sphere.position.copy(pointLight.position); // 将小球体放在点光源位置
// scene.add(sphere);
console.log('添加了点光源');
// 4. 聚光灯 (SpotLight): 从一个点向一个方向发射锥形光线,亮度随距离衰减,有范围和夹角
// 参数: 颜色, 强度, 距离, 角度 (弧度), 半影 (0-1,边缘模糊度), 衰减
const spotLight = new THREE.SpotLight(0x00ff00, 1, 0, Math.PI / 4, 0.5, 2); // 绿色光源,45度夹角,50%模糊边缘
spotLight.position.set(0, 10, 0); // 设置光源位置
spotLight.target = cube; // 让聚光灯指向立方体
scene.add(spotLight);
// 可以添加一个聚光灯辅助线,方便观察方向和角度
// const spotLightHelper = new THREE.SpotLightHelper(spotLight);
// scene.add(spotLightHelper);
console.log('添加了聚光灯');
// 5. 半球光 (HemisphereLight): 模拟天空光和地面光的混合,没有位置,不会产生阴影
// 参数: 天空颜色, 地面颜色, 强度
const hemisphereLight = new THREE.HemisphereLight(0xffffbb, 0x080820, 0.6); // 暖色天空,冷色地面
// scene.add(hemisphereLight); // 示例中与其他环境光一起可能过亮,可以注释掉 AmbientLight 观察
console.log('添加了半球光');
// 处理窗口尺寸变化,保持渲染器的正确宽高比
window.addEventListener('resize', onWindowResize, false);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio); // 确保在高分辨率屏幕上清晰
}
// 动画循环,每一帧都会调用
function animate() {
// requestAnimationFrame 告诉浏览器您希望执行动画,并请求浏览器在下一次重绘之前调用指定的函数来更新动画
requestAnimationFrame(animate);
// 可以在这里更新场景中的物体或光源位置等,创建动画效果
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
// 渲染场景
renderer.render(scene, camera);
}
// 启动应用
init();
animate();
运行结果 (Execution Results)
- 使用本地 Web 服务器托管您的
index.html
和script.js
文件。 - 在浏览器中访问
index.html
。 - 您将看到一个绿色的立方体显示在灰色背景中。
- 随着您在
script.js
中解除不同光源的注释并刷新页面,立方体的光照效果会发生变化:- AmbientLight: 整个立方体被柔和地照亮,即使是朝向远离定向光或点光源的部分也能看到。
- DirectionalLight: 立方体朝向光源的一侧更亮,远离光源的一侧较暗,显示出明显的明暗交界线,体现了方向性。
- PointLight: 立方体靠近点光源的部分更亮,远离的部分逐渐变暗,体现了距离衰减。如果点光源靠近立方体,光照会非常强烈。
- SpotLight: 立方体只有在聚光灯锥形范围内的部分被照亮,光照强度和衰减与点光源类似,但光照范围是有限的。
- HemisphereLight: 立方体朝天(Y 轴正方向)的部分呈现天空颜色,朝地(Y 轴负方向)的部分呈现地面颜色,模拟自然光。
- 立方体将围绕 X 轴和 Y 轴旋转,展示不同角度下的光照效果。
测试步骤以及详细代码 (Testing Steps and Detailed Code)
测试 Three.js 光源主要通过修改代码中的光源参数,并在浏览器中观察渲染效果。
- 环境设置: 确保您已按照“环境准备”部分设置好本地 Web 服务器,并将
index.html
和script.js
文件放入托管目录下。 - 启动应用: 在终端中启动本地 Web 服务器,并在浏览器中访问
index.html
。 - 逐个测试光源类型:
- 步骤: 在
script.js
的init()
函数中,注释掉除AmbientLight
外的所有光源。保存文件,刷新浏览器。观察立方体被均匀照亮的效果。 - 步骤: 注释掉所有光源,只解除
directionalLight
的注释。保存,刷新。观察立方体的定向光照效果。尝试修改directionalLight.position
的值,保存,刷新,观察光线方向的变化。 - 步骤: 类似地,逐个解除
pointLight
和spotLight
的注释,观察它们的独特光照效果(距离衰减、范围、夹角)。尝试修改它们的位置、颜色、强度、距离、角度等参数。 - 步骤: 结合不同光源,例如同时启用
AmbientLight
和DirectionalLight
,观察环境光如何照亮阴影区域,使定向光的效果更柔和真实。 - 代码: 参考“完整代码实现”中的
script.js
文件,通过注释/解除注释和修改属性值来进行测试。
- 步骤: 在
- 测试光源与材质的交互:
- 步骤: 修改
cube
的材质为THREE.MeshBasicMaterial
(new THREE.MeshBasicMaterial({ color: 0x00ff00 });
)。保存,刷新。 - 验证: 即使添加了各种光源,立方体可能只显示基础颜色(除非设置
光的概念
)。这演示了MeshBasicMaterial
不受标准光源影响的特性。 - 步骤: 换回
THREE.MeshStandardMaterial
或THREE.MeshPhongMaterial
,再次观察光源效果,验证这些材质能够正确响应光照。 - 代码: 修改
script.js
中创建material
的代码行。
- 步骤: 修改
- 使用浏览器开发者工具:
- 步骤: 打开开发者工具 (F12),查看 Console 标签页,检查是否有 Three.js 或您代码中的错误或警告信息。
- 步骤: 在 Elements 标签页中,找到 Three.js 生成的
canvas
元素。 - 步骤: (如果浏览器和显卡支持) 某些浏览器扩展(如 Spector.js)可以帮助您检查 WebGL 渲染过程,查看绘制调用和光照相关的 Shader 信息。
- 代码: 在您的
script.js
中添加console.log()
语句,打印光源对象的属性值,辅助调试。
部署场景 (Deployment Scenarios)
Three.js 应用的部署是标准的 Web 应用部署:
- 静态文件托管: 将
index.html
和script.js
文件(以及 Three.js 库文件,如果不是从 CDN 加载)上传到任何支持静态文件托管的服务(如 Nginx, Apache, Netlify, Vercel, GitHub Pages, AWS S3 + CloudFront)。 - 与后端应用集成: 如果您的应用有后端服务(如 Node.js, Python Flask/Django, Java Spring Boot),可以将这些前端文件放在后端应用的静态文件目录下,由后端提供服务。
- CDN 部署: 将 Three.js 库文件和您应用自身的静态资源部署到 CDN,以提高加载速度。
- 容器化部署: 将您的 Web 文件打包到 Docker 镜像中,通常与一个轻量级 Web 服务器一起,部署到 Docker 或 Kubernetes 环境。
疑难解答 (Troubleshooting)
- 场景一片漆黑:
- 问题: 场景中没有光源,或者光源强度为零,或者光源距离物体太远,或者物体材质不受光源影响。
- 排查: 确认您已创建了光源对象并使用
scene.add(light)
添加到场景中。检查光源的intensity
属性是否大于 0。检查光源的position
,确保它靠近或能够照亮物体。检查物体使用的是否是会受光照影响的材质(如MeshLambertMaterial
,MeshPhongMaterial
,MeshStandardMaterial
)。
- 光照效果不自然或太弱/太强:
- 问题: 光源颜色、强度、位置设置不当。
- 排查: 调整光源的
color
和intensity
。对于 PointLight 和 SpotLight,调整distance
和decay
。尝试不同的光源组合。
- 阴影不工作:
- 问题: 设置了投射阴影的光源,但场景中没有看到阴影。
- 排查: 阴影需要多处配置:
- Renderer:
renderer.shadowMap.enabled = true;
- Light:
light.castShadow = true;
(仅 DirectionalLight, PointLight, SpotLight 支持) - Objects (Caster): 需要投射阴影的物体材质上设置
mesh.castShadow = true;
- Objects (Receiver): 需要接收阴影的物体材质上设置
mesh.receiveShadow = true;
- Shadow Camera: 需要为光源配置阴影相机(
light.shadow.camera
),确保相机范围包含投射阴影的区域。 - Shadow Map Resolution:
light.shadow.mapSize.width
和light.shadow.mapSize.height
设置阴影贴图分辨率(影响阴影质量和性能)。 - 确保光源和物体在同一个场景中。
- Renderer:
- 性能问题:
- 问题: 添加大量光源(特别是投射阴影的点光源和聚光灯)导致帧率下降。
- 排查: 减少光源数量。避免让过多的光源投射阴影。降低阴影贴图分辨率。优化几何体复杂度。使用更简单的材质。考虑使用烘焙光照(Light Baking)或预计算照明技术来替代实时复杂光照。
- 使用
MeshBasicMaterial
或MeshNormalMaterial
看不到光照效果:- 问题: 这是预期行为。
- 排查:
MeshBasicMaterial
只受光的概念(颜色和透明度)影响,不受标准光源影响。MeshNormalMaterial
只根据法线显示颜色,也与光源无关。如果需要受光照影响,请使用MeshLambertMaterial
,MeshPhongMaterial
,MeshStandardMaterial
,MeshPhysicalMaterial
等。
未来展望 (Future Outlook)
Three.js 中的光照功能将持续发展和增强,紧随实时图形学的趋势:
- PBR 更加成熟: 物理基础渲染将成为主流,提供更真实的光照效果。
- 实时全局光照 (GI): 探索和实现更高效的实时全局光照技术,模拟光线在场景中的多次反射和散射,提高真实感。
- 更高级的阴影技术: 软阴影、接触硬化阴影 (Contact Hardening Shadows) 等技术将进一步完善。
- WebGPU 支持: 随着 WebGPU 成为新的 Web 图形标准,Three.js 将迁移到 WebGPU,可能带来更强大的底层光照控制能力和性能提升。
技术趋势与挑战 (Technology Trends and Challenges)
技术趋势:
- PBR 的广泛应用: 行业标准,要求美术和开发者具备 PBR 相关的知识。
- 实时光线追踪/路径追踪: 虽然在 WebGL/实时环境中仍有挑战,但未来随着硬件发展可能逐步应用。
- 基于图像的光照 (IBL): 使用全景图等图像来模拟环境光和反射。
- 声明式和节点式光照编辑工具: 简化复杂光照场景的设置。
挑战:
- 实现真实感与性能的平衡: 复杂的光照计算(如实时阴影、全局光照)对实时渲染性能有很大影响。
- 管理复杂的光照场景: 在大型或细节丰富的场景中,设置和调整众多光源以达到预期效果非常具有挑战性。
- 跨设备兼容性: 不同设备的 GPU 能力差异巨大,保证在低端设备上也能流畅运行。
- 烘焙光照与实时光照的结合: 如何有效结合预计算的烘焙光照和动态的实时光照。
- 调试复杂的光照问题: 定位光照计算、阴影或材质设置中的错误。
总结 (Conclusion)
光源是 Three.js 场景中不可或缺的元素,它们使物体可见并赋予场景生命力。Three.js 提供了 AmbientLight, DirectionalLight, PointLight, SpotLight, HemisphereLight 等多种光源类型,每种都有其独特的属性和适用场景。理解这些光源的原理、如何设置它们以及它们如何与不同材质交互,是创建有效且美观的 3D 场景的关键。
通过本指南提供的 JavaScript 代码示例,您可以实践如何在 Three.js 场景中添加和配置这些光源,并观察它们对物体光照效果的影响。虽然您提到希望使用 C#, C, Java 进行代码实现,但 Three.js 本身是 JavaScript 库,只能在支持 JavaScript 和 WebGL 的客户端环境(主要是浏览器)中运行。C#, C, Java 通常用于后端服务,与 Three.js 前端进行数据交互。掌握 Three.js 的光照特性并进行实践,将为您的 Web 3D 开发能力带来显著提升。
- 点赞
- 收藏
- 关注作者
评论(0)