🚗 Three.js 实战全解析:打造 SU7 展示 + 人物控制 + HDR 场景 + 碰撞检测

用 Three.js 做一个能开车、能走人、能撞墙,还能跳跃的酷炫 3D 展示场景。本文基于 项目源码 和真实模型资源,进行逐行讲解,适合学习 Three.js 实践开发。

📦 模型 & 贴图资源
-
SU7 3D 模型下载:
- Sketchfab:sketchfab.com/3d-models/s...
-
建筑贴图 / 地面纹理资源:
- Free3D 建筑贴图合集:free3d.com/3d-models/a...
贴图目录结构如下:
arduino
public/textures/
├── brick_pavement_02_diff_1k.jpg
├── brick_pavement_02_disp_1k.png
├── concrete_pavement_diff_1k.jpg
├── concrete_pavement_disp_1k.png
├── sky.hdr
🧱 项目结构
arduino
car/
├── public/
│ ├── models/
│ │ ├── su7-xiaomini.glb
│ │ └── person/Character.glb
│ └── textures/
├── src/
│ ├── main.js // 主场景逻辑
│ └── person.js // 人物模块
├── index.html
├── vite.config.js
🚀 快速启动
bash
git clone https://github.com/yunshengya/car
cd car
npm install
npm run dev
浏览器打开 http://localhost:5173 即可进入场景。
🎮 操作说明
汽车控制
键位 | 说明 |
---|---|
W / S | 前进 / 后退 |
A / D | 左转 / 右转 |
Q / E | 车体倾斜 |
Shift | 加速 |
Space | 跳跃 |
R | 重置位置 |
人物控制
键位 | 说明 |
---|---|
↑ / ↓ | 前进/后退 |
← / → | 左右旋转 |
0(键盘) | 跳跃 |
✨ 主逻辑详解(main.js)
✅ 初始化场景、相机、渲染器
dart
const scene = new THREE.Scene(); // 创建场景对象
scene.background = new THREE.Color(0x111111); // 设置背景颜色为深灰
const camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000); // 设置相机参数:视角、宽高比、近远裁剪面
camera.position.set(0, 5, 8); // 相机位置设置在空中,稍微偏后
const renderer = new THREE.WebGLRenderer({ antialias: true }); // 创建 WebGL 渲染器并开启抗锯齿
renderer.setSize(window.innerWidth, window.innerHeight); // 设置渲染器尺寸
javascript
document.body.appendChild(renderer.domElement); // 将渲染画布挂载到页面中
🌅 加载 HDR 贴图用于环境光照和背景

arduino
const rgbeLoader = new RGBELoader(); // 创建 HDR 加载器
const pmremGenerator = new THREE.PMREMGenerator(renderer); // 用于从 HDR 创建环境贴图
ini
rgbeLoader.load(`${baseUrl}textures/sky.hdr`, (hdrTexture) => {
const envMap = pmremGenerator.fromEquirectangular(hdrTexture).texture; // 生成环境贴图
scene.environment = envMap; // 用作物体反射
scene.background = envMap; // 设置背景图为 HDR 图
});
🧱 加载地面贴图

ini
const asphaltDiffuse = textureLoader.load('/textures/brick_pavement_02_disp_1k.png');
const asphaltNormal = textureLoader.load('/textures/brick_pavement_02_diff_1k.jpg');
设置贴图重复效果:
ini
asphaltDiffuse.wrapS = asphaltDiffuse.wrapT = THREE.RepeatWrapping;
asphaltNormal.wrapS = asphaltNormal.wrapT = THREE.RepeatWrapping;
asphaltDiffuse.repeat.set(20, 20);
asphaltNormal.repeat.set(20, 20);
创建地面:
php
const plane = new THREE.Mesh(
new THREE.PlaneGeometry(50, 50),
new THREE.MeshStandardMaterial({
map: asphaltDiffuse,
normalMap: asphaltNormal,
metalness: 0.2,
roughness: 0.8
})
);
plane.rotation.x = -Math.PI / 2; // 平面朝上
scene.add(plane);
💡 添加环境光与方向光
csharp
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5); // 环境光,提供整体亮度
const directionalLight = new THREE.DirectionalLight(0xffffff, 1); // 平行光,类似太阳
scene.add(ambientLight);
scene.add(directionalLight);
🚧 创建场景边界墙体 + 贴图 + 碰撞
ini
const wallDiffuse = textureLoader.load(`${baseUrl}textures/concrete_pavement_diff_1k.jpg`);
const wallDisplace = textureLoader.load(`${baseUrl}textures/concrete_pavement_disp_1k.png`);
php
const wallMaterial = new THREE.MeshStandardMaterial({
map: wallDiffuse,
displacementMap: wallDisplace,
displacementScale: 0.15,
metalness: 0.2,
roughness: 0.8
});
创建四面墙:
ini
function createWall (x, y, z, w, h, d) {
const geometry = new THREE.BoxGeometry(w, h, d, 64, 64, 1);
const wall = new THREE.Mesh(geometry, wallMaterial);
wall.position.set(x, y, z);
scene.add(wall);
obstacles.push(new THREE.Box3().setFromObject(wall));
}
👦 人物控制模块(person.js)讲解重点
kotlin
export class People {
constructor(scene, baseUrl) {
this.scene = scene;
this.baseUrl = baseUrl;
this.model = null; // 人物模型引用
控制状态与按键监听:
kotlin
this.keys = {
ArrowUp: false,
ArrowDown: false,
ArrowLeft: false,
ArrowRight: false,
Digit0: false, // 跳跃
};
this.initListeners();
模型加载:
kotlin
const loader = new GLTFLoader();
loader.load(`${this.baseUrl}models/person/Character.glb`, gltf => {
this.model = gltf.scene;
this.model.position.set(5, 0, 0);
this.model.scale.set(0.5, 0.5, 0.5);
this.scene.add(this.model);
});
跳跃逻辑: 用正弦模拟自然跳跃

arduino
this.model.position.y = Math.sin(p * Math.PI) * this.jumpHeight;
旋转移动:
kotlin
if (this.keys.ArrowLeft) {
this.model.rotation.y += this.rotationSpeed;
}
if (this.keys.ArrowRight) {
this.model.rotation.y -= this.rotationSpeed;
}
✅ GitHub 项目地址
下一步你可以:
- 添加第一人称视角相机跟随人物
- 给人物增加动画融合(走路、跳跃)
- 加载更多模型进行场景装饰
愿你在 Three.js 的路上越玩越溜!🚀