在 Three.js 搭建的 3D 虚拟世界里,有一位默默奉献的 “光影魔法师”—— 平行光(DirectionalLight)。它不像聚光灯那样锋芒毕露,也不像点光源那样 “以自我为中心”,却以自己独特的方式,为虚拟场景注入灵魂,让那些冰冷的几何模型瞬间 “活” 过来。接下来,就让我们一起揭开这位 “魔法师” 的神秘面纱,看看它究竟有何神通!
一、平行光的 “庐山真面目”:底层原理大揭秘
从底层原理来看,平行光就像是来自宇宙深处的光线军团,所有的光线都朝着同一个方向,整齐划一地前进,互不干扰。想象一下,无数支小光箭,保持着绝对的平行,齐刷刷地射向你的 3D 场景,这就是平行光的工作方式。
在现实世界中,最接近平行光的例子就是太阳。因为太阳距离地球实在太遥远了,当阳光照射到地球上时,这些光线之间的夹角几乎可以忽略不计,我们就近似地把太阳光看作平行光。在 Three.js 的虚拟世界里,平行光同样具有这样 “一视同仁” 的特性,它不会因为某个物体离得近就多照一些,也不会因为某个物体在角落就少照一点,所有物体都会受到同等强度、同一方向的光照。
这种特性的实现,依赖于 Three.js 底层的数学运算和渲染机制。它通过精确计算光线的方向向量,让每一束光都沿着这个固定的方向 “冲锋陷阵”,为场景中的物体带来均匀的照明。就好像有一位严格的教官,指挥着光线士兵们,时刻保持着整齐的队列,绝不 “掉链子”。
二、平行光的神奇作用:点亮虚拟世界
(一)营造真实氛围
平行光最基本也是最重要的作用,就是为场景营造出真实的光照氛围。当你创建一个户外场景,比如一片广袤的草原、一座巍峨的高山,或者是繁华的都市街景时,添加一盏平行光,就相当于为这个世界 “安装” 了一个太阳。瞬间,原本黯淡无光的几何模型变得生动起来,物体的明暗对比清晰可见,阴影也随之产生,整个场景仿佛从二维平面跃入了三维真实世界。
比如我们创建一个简单的场景,有一个正方体和一个球体:
// 创建场景
const scene = new THREE.Scene();
// 创建正方体
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshStandardMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
// 创建球体
const sphereGeometry = new THREE.SphereGeometry(1, 32, 32);
const sphereMaterial = new THREE.MeshStandardMaterial({ color: 0x0000ff });
const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
sphere.position.x = 2;
scene.add(sphere);
// 创建平行光
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(1, 1, 1).normalize();
scene.add(directionalLight);
在这段代码中,我们创建了一个绿色的正方体和一个蓝色的球体,然后添加了一盏平行光。通过调整平行光的位置(position),我们可以改变光线照射的方向。此时,你会看到正方体和球体的不同面呈现出不同的亮度,这就是平行光带来的明暗效果,让场景有了立体感。
(二)塑造物体形态
平行光就像是一位技艺高超的雕刻大师手中的刻刀,通过光影的变化,勾勒出物体的形态和细节。物体表面的凸起、凹陷、纹理,在平行光的照射下,都会以明暗交替的方式展现出来。原本平淡无奇的模型,在平行光的 “雕琢” 下,变得栩栩如生。
比如我们创建一个带有纹理的地形模型:
// 创建地形几何
const terrainGeometry = new THREE.PlaneGeometry(10, 10, 100, 100);
// 假设这里通过某种算法生成地形高度数据,改变顶点位置,模拟地形起伏
// (实际应用中可能需要更复杂的算法,这里简化说明)
const vertices = terrainGeometry.attributes.position.array;
for (let i = 0; i < vertices.length; i += 3) {
vertices[i + 1] = Math.sin(vertices[i] * 0.5) * 0.5; // 简单的正弦函数模拟起伏
}
terrainGeometry.attributes.position.needsUpdate = true;
const terrainMaterial = new THREE.MeshStandardMaterial({ map: texture }); // texture为加载的地形纹理贴图
const terrain = new THREE.Mesh(terrainGeometry, terrainMaterial);
scene.add(terrain);
// 添加平行光
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(0, 2, 0).normalize();
scene.add(directionalLight);
在这个例子中,平行光照射在起伏的地形上,山丘的阳面明亮耀眼,山谷的阴面则显得深邃神秘,通过光影的变化,我们能清晰地感受到地形的高低起伏,仿佛置身于真实的山川之间。
(三)引导视觉焦点
平行光还能充当 “舞台导演”,巧妙地引导观众的视线。通过调整平行光的方向和强度,我们可以让特定的物体更加突出,吸引用户的注意力。比如在一个展示艺术品的虚拟展厅中,我们可以用平行光重点照亮某一件珍贵的展品,让它在整个展厅中脱颖而出,而其他部分则相对暗淡,这样观众的目光就会自然而然地聚焦在这件展品上。
// 创建展厅场景,包含多个展品模型
const artPiece1 = new THREE.Mesh(/* 艺术品1的几何和材质 */);
const artPiece2 = new THREE.Mesh(/* 艺术品2的几何和材质 */);
const artPiece3 = new THREE.Mesh(/* 艺术品3的几何和材质 */);
scene.add(artPiece1);
scene.add(artPiece2);
scene.add(artPiece3);
// 创建主平行光,照亮整个展厅
const mainLight = new THREE.DirectionalLight(0xffffff, 0.5);
mainLight.position.set(1, 1, 1).normalize();
scene.add(mainLight);
// 创建聚焦平行光,重点照亮艺术品1
const focusLight = new THREE.DirectionalLight(0xffffff, 1);
focusLight.position.set(0, 2, 0).normalize();
focusLight.target = artPiece1;
scene.add(focusLight);
在这段代码中,我们先创建了一个主平行光,给展厅提供基础照明,然后又创建了一盏聚焦平行光,专门照亮艺术品 1。这样,艺术品 1 就会比其他展品更加明亮,成功吸引观众的注意力。
三、平行光的使用技巧:玩转光影魔法
(一)调整方向:给光线 “指路”
平行光的方向决定了光线照射的角度,直接影响着场景的光影效果。通过修改position属性,我们可以轻松改变平行光的方向。就好像我们在调整太阳在天空中的位置一样,不同的方向会带来截然不同的氛围。比如,让平行光从头顶垂直照射下来,场景会显得明亮而直接;让它从侧面斜射过来,物体的阴影会拉长,营造出一种黄昏或清晨的氛围。
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
// 从正上方垂直照射
directionalLight.position.set(0, 10, 0).normalize();
// 改为从侧面斜射
directionalLight.position.set(-5, 5, 0).normalize();
(二)控制强度:调节光线 “亮度”
平行光的强度可以通过intensity属性来控制。intensity的值越大,光线越亮;值越小,光线越暗。你可以把它想象成调节太阳的 “亮度旋钮”,根据场景的需要,打造出或明亮或昏暗的效果。比如在一个恐怖游戏场景中,降低平行光的强度,让整个场景笼罩在昏暗的光线中,能大大增强紧张恐怖的氛围;而在一个欢快的儿童游戏场景里,调高平行光的强度,让阳光明媚,会让场景充满活力。
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
// 降低强度,营造昏暗氛围
directionalLight.intensity = 0.3;
// 调高强度,让场景更明亮
directionalLight.intensity = 1.5;
(三)搭配其他光源:打造光影交响乐
虽然平行光很强大,但在复杂的场景中,仅仅依靠平行光可能无法达到理想的效果。这时,我们可以搭配聚光灯、点光源等其他类型的光源,就像一场交响乐,不同的乐器相互配合,才能演奏出美妙的乐章。比如,用平行光作为主光源提供基础照明,用聚光灯照亮特定的细节区域,用点光源模拟灯泡、烛光等局部光源,多种光源协同工作,能让场景的光影效果更加丰富、真实。
// 创建平行光作为主光源
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
directionalLight.position.set(1, 1, 1).normalize();
scene.add(directionalLight);
// 创建聚光灯照亮特定区域
const spotLight = new THREE.SpotLight(0xffffff, 1);
spotLight.position.set(0, 5, 0);
spotLight.target = someObject; // someObject为需要照亮的物体
scene.add(spotLight);
// 创建点光源模拟局部光源
const pointLight = new THREE.PointLight(0xffff00, 1);
pointLight.position.set(2, 2, 2);
scene.add(pointLight);
四、总结:平行光,让虚拟世界 “光芒万丈”
Three.js 中的平行光,就像是虚拟世界的 “太阳引擎”,以其独特的平行光照特性,为场景带来真实的氛围、丰富的形态和明确的视觉引导。通过调整它的方向、强度,以及与其他光源的搭配使用,我们能够创造出千变万化的光影效果,让每一个 Three.js 构建的虚拟世界都 “光芒万丈”。下次当你在 Three.js 的世界里遨游时,不妨好好利用这位 “光影魔法师”,打造出令人惊艳的 3D 场景吧!
上述文章从多方面介绍了 Three.js 平行光。若你还想了解其在特定场景的应用,或对其他 Three.js 知识感兴趣,欢迎随时和我说。