Three.js 第三天进阶:几何体组合、高级材质与灯光布局

在 Three.js 的学习旅程中,第三天我们将解锁更高级的技能,深入探索几何体组合、高级材质特性以及灯光布局技巧,让 3D 场景变得更加丰富立体。

一、复杂几何体构建

1.1 几何体组合

实际项目中,单个基础几何体很难满足需求,这时就需要将多个基础几何体组合成复杂形状。比如创建一个带轮子的小车,我们可以使用Group对象将多个几何体组合在一起。

js 复制代码
// 创建车身
const bodyGeometry = new THREE.BoxGeometry(2, 1, 1);
const bodyMaterial = new THREE.MeshStandardMaterial({ color: 0x007bff });
const body = new THREE.Mesh(bodyGeometry, bodyMaterial);
// 创建轮子
const wheelGeometry = new THREE.CylinderGeometry(0.3, 0.3, 0.2, 32);
const wheelMaterial = new THREE.MeshStandardMaterial({ color: 0x343a40 });
const wheel1 = new THREE.Mesh(wheelGeometry, wheelMaterial);
const wheel2 = new THREE.Mesh(wheelGeometry, wheelMaterial);
wheel1.position.set(-0.8, -0.5, 0);
wheel2.position.set(0.8, -0.5, 0);
// 创建小车组
const car = new THREE.Group();
car.add(body);
car.add(wheel1);
car.add(wheel2);
scene.add(car);

上述代码中,我们分别创建了车身和轮子的几何体,然后通过Group对象将它们组合成一个完整的小车模型,最后添加到场景中。

1.2 变形几何体

Three.js 还支持对几何体进行变形操作,以实现独特的视觉效果。例如使用ExtrudeGeometry创建一个拉伸的文本。

js 复制代码
const fontLoader = new THREE.FontLoader();
fontLoader.load(
    'fonts/helvetiker_regular.typeface.json',
    function (font) {
        const textGeometry = new THREE.TextGeometry('THREE', {
            font: font,
            size: 0.8,
            height: 0.1,
            curveSegments: 12
        });
        const textMaterial = new THREE.MeshStandardMaterial({ color: 0xffc107 });
        const textMesh = new THREE.Mesh(textGeometry, textMaterial);
        scene.add(textMesh);
    }
);

这里通过加载字体文件,利用TextGeometry创建文本形状,再进行拉伸处理,赋予材质后添加到场景,实现了立体文本效果。

二、高级材质应用

2.1 物理材质

MeshStandardMaterial是基于物理的材质,它能更真实地模拟现实世界中物体的反射、折射和阴影效果。我们来设置一个金属材质的球体:

js 复制代码
const metalSphereGeometry = new THREE.SphereGeometry(1, 32, 32);
const metalMaterial = new THREE.MeshStandardMaterial({
    color: 0x009688,
    metalness: 1,
    roughness: 0.1
});
const metalSphere = new THREE.Mesh(metalSphereGeometry, metalMaterial);
scene.add(metalSphere);

metalness属性控制材质的金属程度,roughness属性控制粗糙度,通过调整这两个参数,可以表现出不同质感的金属表面。

2.2 透明材质与混合模式

想要创建透明物体,可以使用MeshStandardMaterial的opacity和transparent属性。同时,还能设置混合模式,如正常混合、相加混合等。

js 复制代码
const glassGeometry = new THREE.BoxGeometry(1, 1, 1);
const glassMaterial = new THREE.MeshStandardMaterial({
    color: 0x00ffff,
    opacity: 0.5,
    transparent: true,
    blending: THREE.AdditiveBlending
});
const glassBox = new THREE.Mesh(glassGeometry, glassMaterial);
scene.add(glassBox);

上述代码创建了一个透明的玻璃盒子,blending: THREE.AdditiveBlending设置为相加混合模式,让透明物体在光照下呈现出更绚丽的效果。

三、灯光布局与氛围营造

3.1 多光源组合

在一个场景中,通常需要多种灯光配合使用,才能营造出理想的氛围。下面我们同时使用环境光、平行光和点光源来照亮场景。

js 复制代码
// 环境光
const ambientLight = new THREE.AmbientLight(0x333333);
scene.add(ambientLight);
// 平行光
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
directionalLight.position.set(1, 2, 3);
directionalLight.castShadow = true;
scene.add(directionalLight);
// 点光源
const pointLight = new THREE.PointLight(0xff0000, 1, 10);
pointLight.position.set(0, 3, 0);
scene.add(pointLight);

通过组合不同类型的灯光,并设置各自的属性,如强度、位置、阴影投射等,让场景中的物体呈现出丰富的光影效果。

3.2 阴影设置

在 Three.js 中开启阴影效果,能让场景更加真实。首先需要在渲染器上开启阴影计算:

js 复制代码
renderer.shadowMap.enabled = true;

然后为相应的灯光和物体设置阴影投射与接收属性,比如让平行光投射阴影,物体接收阴影:

js 复制代码
directionalLight.castShadow = true;
directionalLight.shadow.mapSize.width = 1024;
directionalLight.shadow.mapSize.height = 1024;
const groundGeometry = new THREE.PlaneGeometry(10, 10);
const groundMaterial = new THREE.MeshStandardMaterial({ color: 0x999999 });
const ground = new THREE.Mesh(groundGeometry, groundMaterial);
ground.receiveShadow = true;
ground.rotation.x = -Math.PI / 2;
scene.add(ground);

以上设置使场景中的物体在光照下产生真实的阴影,增强了场景的立体感和真实感。

通过今天的学习,我们在 Three.js 的世界里又前进了一大步。掌握了复杂几何体的构建、高级材质的运用以及灯光阴影的布局,这些知识将为后续创建更精彩的 3D 应用打下坚实基础。

相关推荐
我是伪码农2 小时前
Vue 1.23
前端·javascript·vue.js
wqwqweee2 小时前
Flutter for OpenHarmony 看书管理记录App实战:搜索功能实现
开发语言·javascript·python·flutter·harmonyos
HIT_Weston3 小时前
107、【Ubuntu】【Hugo】搭建私人博客:模糊搜索 Fuse.js(三)
linux·javascript·ubuntu
henujolly7 小时前
ethers.js读取合约信息
开发语言·javascript·区块链
毕设源码-郭学长7 小时前
【开题答辩全过程】以 基于Web的高校课程目标达成度系统设计与实现为例,包含答辩的问题和答案
前端
wuhen_n7 小时前
高阶函数与泛型函数的类型体操
前端·javascript·typescript
POLITE38 小时前
Leetcode 437. 路径总和 III (Day 16)JavaScript
javascript·算法·leetcode
難釋懷8 小时前
解决状态登录刷新问题
java·开发语言·javascript
ヤ鬧鬧o.8 小时前
多彩背景切换演示
前端·css·html·html5
一起养小猫8 小时前
Flutter实战:从零实现俄罗斯方块(三)交互控制与事件处理
javascript·flutter·交互