第二篇:Three.js核心三要素:场景、相机、渲染器

第二篇:Three.js核心三要素:场景、相机、渲染器

引言

在Three.js的世界里,场景(Scene)、相机(Camera)和渲染器(Renderer)构成了最基础的"铁三角"。它们如同导演、摄像机和放映机,共同决定了3D内容的呈现方式。本篇将深入解析这三个核心组件,并通过Vue3实战案例展示它们的协同工作。


在这里插入图片描述

1. 场景(Scene):3D世界的容器
1.1 场景的本质

场景是Three.js的顶级容器,所有3D对象(网格、灯光、相机)都需要加入场景才能被渲染。可以将其理解为:

  • 3D对象的舞台
  • 空间坐标系的管理者
  • 场景图(Scene Graph)的根节点
// 创建场景
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x87CEEB); // 设置天空蓝背景
1.2 场景层级管理

Three.js使用树状结构管理对象:

Scene
Camera
Mesh1
Group
Mesh2
Mesh3

实战:使用Group组织对象

<script setup>
import { ref, onMounted } from 'vue';
import * as THREE from 'three';const scene = new THREE.Scene();// 创建汽车组
const carGroup = new THREE.Group();
scene.add(carGroup);// 车身
const bodyGeo = new THREE.BoxGeometry(2, 0.5, 1);
const bodyMat = new THREE.MeshBasicMaterial({ color: 0xff0000 });
const body = new THREE.Mesh(bodyGeo, bodyMat);
carGroup.add(body);// 车轮
const wheelGeo = new THREE.CylinderGeometry(0.3, 0.3, 0.2, 16);
wheelGeo.rotateZ(Math.PI/2); // 旋转90度使其立起
const wheelMat = new THREE.MeshBasicMaterial({ color: 0x333333 });const wheel1 = new THREE.Mesh(wheelGeo, wheelMat);
wheel1.position.set(0.7, -0.3, 0.5);
carGroup.add(wheel1);const wheel2 = wheel1.clone();
wheel2.position.z = -0.5;
carGroup.add(wheel2);// 移动整个汽车组
carGroup.position.x = -3;
</script>

关键点Group允许将多个对象作为单一实体操作,大幅简化复杂对象的变换控制。


2. 相机(Camera):观察世界的眼睛
2.1 透视相机(PerspectiveCamera)

模拟人眼视角,近大远小效果:

const camera = new THREE.PerspectiveCamera(75, // 视野角度(FOV)window.innerWidth / window.innerHeight, // 宽高比0.1, // 近裁剪面(near)1000 // 远裁剪面(far)
);
camera.position.set(0, 2, 5); // 设置相机位置
2.2 正交相机(OrthographicCamera)

平行投影,无透视变形:

const aspect = window.innerWidth / window.innerHeight;
const camera = new THREE.OrthographicCamera(-5 * aspect, // left5 * aspect,  // right5,           // top-5,          // bottom0.1,         // near100          // far
);
2.3 相机类型对比
特性透视相机正交相机
投影方式锥形投影平行投影
适用场景真实感场景技术图纸/2.5D游戏
尺寸感知近大远小保持物体原尺寸
参数复杂度简单(4参数)复杂(6参数)
典型应用第一人称游戏CAD查看器

3. 渲染器(Renderer):将3D转为2D
3.1 渲染器核心配置
<script setup>
import { ref, onMounted, onUnmounted } from 'vue';const canvasRef = ref(null);onMounted(() => {const renderer = new THREE.WebGLRenderer({canvas: canvasRef.value,antialias: true, // 开启抗锯齿alpha: true,     // 允许透明背景powerPreference: "high-performance" // 高性能模式});// 设置像素比和尺寸renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));renderer.setSize(window.innerWidth, window.innerHeight);// 开启阴影renderer.shadowMap.enabled = true;renderer.shadowMap.type = THREE.PCFSoftShadowMap; // 柔和阴影
});
</script>
3.2 响应式窗口处理
// Vue3中使用@vueuse/core监听窗口变化
import { useWindowSize } from '@vueuse/core';const { width, height } = useWindowSize();watch([width, height], () => {camera.aspect = width.value / height.value;camera.updateProjectionMatrix(); // 必须更新相机renderer.setSize(width.value, height.value);
});

4. 综合实战:多相机切换系统
4.1 项目结构
src/├── components/│    ├── CameraSystem.vue   // 相机系统组件│    └── SceneObjects.vue   // 场景对象组件└── App.vue
4.2 相机切换核心代码
<!-- CameraSystem.vue -->
<script setup>
import { ref } from 'vue';// 相机枚举类型
const CameraType = {PERSPECTIVE: 0,ORTHOGRAPHIC: 1
};const currentCamera = ref(CameraType.PERSPECTIVE);
const cameras = {[CameraType.PERSPECTIVE]: createPerspectiveCamera(),[CameraType.ORTHOGRAPHIC]: createOrthographicCamera()
};function createPerspectiveCamera() {const camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);camera.position.set(0, 2, 5);return camera;
}function createOrthographicCamera() {const aspect = window.innerWidth / window.innerHeight;const camera = new THREE.OrthographicCamera(-5*aspect, 5*aspect, 5, -5, 0.1, 100);camera.position.set(0, 2, 5);camera.lookAt(0, 0, 0);return camera;
}function toggleCamera() {currentCamera.value = currentCamera.value === CameraType.PERSPECTIVE ? CameraType.ORTHOGRAPHIC : CameraType.PERSPECTIVE;
}
</script><template><button @click="toggleCamera" class="camera-toggle">{{ currentCamera === CameraType.PERSPECTIVE ? '正交视图' : '透视视图' }}</button>
</template>
4.3 渲染循环适配多相机
// 在渲染循环中使用当前相机
function animate() {requestAnimationFrame(animate);// 获取当前激活的相机const activeCamera = cameras[currentCamera.value];// 旋转场景物体scene.traverse(obj => {if (obj.isMesh) obj.rotation.y += 0.01;});renderer.render(scene, activeCamera);
}
4.4 相机切换效果对比

5. 高级技巧:相机控制器
5.1 引入OrbitControls
npm install three-orbitcontrols
<script setup>
import { OrbitControls } from 'three-orbitcontrols';onMounted(() => {const controls = new OrbitControls(camera, renderer.domElement);// 配置控制器参数controls.enableDamping = true; // 启用阻尼效果controls.dampingFactor = 0.05; // 阻尼系数controls.autoRotate = true;    // 自动旋转controls.autoRotateSpeed = 1.0;// 在渲染循环中更新控制器function animate() {requestAnimationFrame(animate);controls.update(); // 必须每帧更新renderer.render(scene, camera);}
});
</script>
5.2 控制器限制设置
// 限制垂直旋转角度
controls.minPolarAngle = Math.PI / 6; // 30度
controls.maxPolarAngle = Math.PI / 2; // 90度// 禁用平移
controls.enablePan = false;// 缩放限制
controls.minDistance = 3;
controls.maxDistance = 15;

6. 常见问题解答

Q1:物体在场景中不可见怎么办?

  1. 检查物体是否添加到场景 scene.add(mesh)
  2. 确认相机位置是否在物体前方
  3. 验证物体是否在相机裁剪范围内

Q2:如何实现画布透明背景?

const renderer = new THREE.WebGLRenderer({alpha: true, // 开启透明度premultipliedAlpha: false // 避免颜色预乘
});
scene.background = null; // 清除场景背景

Q3:为什么正交相机看到的物体是扁平的?

  • 调整正交相机参数范围:
// 正确设置左右上下参数的比例关系
const aspect = window.innerWidth / window.innerHeight;
const height = 10;
const width = height * aspect;const camera = new THREE.OrthographicCamera(-width/2, width/2, // left, rightheight/2, -height/2, // top, bottom1, 1000
);

7. 总结

通过本篇学习,你已掌握:

  1. 场景的层级管理技巧(使用Group组织对象)
  2. 透视相机与正交相机的核心区别及适用场景
  3. 渲染器的关键配置项(抗锯齿/阴影/响应式)
  4. Vue3中实现多相机切换系统
  5. 使用OrbitControls实现交互控制

核心原理:Three.js的渲染流程本质上是将场景中的3D对象,通过相机的视角转换,最终由渲染器投影到2D画布上的过程。


下一篇预告

第三篇:几何体入门:内置几何体全解析
你将学习:

  • 12种基础几何体的创建与参数调整
  • 几何体顶点(Vertex)与面(Face)的底层原理
  • 动态生成参数化几何体(如可调节分段数的球体)
  • 几何体性能优化技巧(BufferGeometry详解)
  • Vue3实现几何体参数实时调节面板

准备好探索Three.js的几何世界了吗?让我们从最简单的立方体开始,逐步揭开3D建模的神秘面纱!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/91467.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/91467.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RagFlow本地源码部署(非Docker)

参考官方文档做个总结 1. 提前安装好uv pipx install uv pre-commit2. 下载源码&#xff1a; git clone https://github.com/infiniflow/ragflow.git cd ragflow/ uv sync --python 3.10 --all-extras # install RAGFlow dependent python modules uv run download_deps.py …

[免费]基于Python的招聘职位信息推荐系统(猎聘网数据分析与可视化)(Django+requests库)【论文+源码+SQL脚本】

大家好&#xff0c;我是python222_小锋老师&#xff0c;看到一个不错的基于Python的招聘职位信息推荐系统(猎聘网数据分析与可视化)(Djangorequests库)&#xff0c;分享下哈。 项目视频演示 【免费】基于Python的招聘职位信息推荐系统(猎聘网数据分析与可视化)(Django爬虫) P…

国产化PDF处理控件Spire.PDF教程:Java 提取 PDF 图片,高质量提取与图片过滤技巧

在处理包含图片的 PDF 文件时&#xff0c;例如扫描文档、产品手册或宣传资料&#xff0c;我们经常需要将其中的图像提取出来&#xff0c;用于保存、识别或再加工。E-iceblue旗下Spire系列产品&#xff0c;是文档处理领域的佼佼者&#xff0c;支持国产化信创。本文将介绍如何使用…

Cesium 快速入门(七)材质详解

Cesium 快速入门&#xff08;七&#xff09;材质详解 看过的知识不等于学会。唯有用心总结、系统记录&#xff0c;并通过温故知新反复实践&#xff0c;才能真正掌握一二 作为一名摸爬滚打三年的前端开发&#xff0c;开源社区给了我饭碗&#xff0c;我也将所学的知识体系回馈给大…

C++:结构体(Structure)

目录 第一性原理出发&#xff1a;我们要解决什么问题&#xff1f; 定义结构体&#xff08;Defining Structures&#xff09; 问题&#xff1a;名字太长怎么办&#xff1f; 如何定义结构体变量&#xff1f; 结构体的大小&#xff08;Size of Structures&#xff09; 初始化…

化学结构式解读指南:从基础认知到InDraw智能识别

中文名称&#xff1a;3-[2-(二甲基氨基)乙基]-1H-吲哚英文名称&#xff1a;3-[2-(dimethylamino)ethyl]-1H-indole分子式: C12H16N2分子量: 188.2740这是什么结构式&#xff1f;怎么绘制呢&#xff1f;可以用InDraw里的AI图像识别这个结构式&#xff0c;也可以手动绘图&#xf…

如何使用一台电脑adb调试多个Android设备

目录 一、临时断开其中一个设备连接 二、指定调试设备 总结 当我们使用Android调试工具调试多个设备&#xff0c;例如一开始使用adb连接了一台Android真机进行调试&#xff0c;此时又在Android studio中打开了一个模拟机&#xff0c;此时我们在adb命令窗口中使用adb命令的…

ChatGPT的下一站:从“答案引擎”到“思维教练”

摘要&#xff1a;我们正处在一个“万物皆可ChatGPT”的时代&#xff0c;但当它沦为最高效的“代码搬运工”和“作业速成器”时&#xff0c;我们得到的究竟是效率的提升还是思维的退化&#xff1f;本文深入探讨一个引人深思的概念——“导师模式”的AI。它不再直接提供答案&…

SpringBoot集成Flyway

SpringBoot集成Flyway_springboot flyway-CSDN博客 Flyway 本质上是一个开源的数据库迁移工具&#xff0c;它能够以自动化、可重复且可靠的方式管理数据库的变更。无论是小型项目还是大型企业级应用&#xff0c;Flyway 都能助力开发者轻松应对数据库架构的演进。它支持多种数据…

【实时Linux实战系列】实时图像处理应用开发

在当今快速发展的技术领域&#xff0c;实时图像处理应用在众多领域发挥着至关重要的作用。从自动驾驶汽车、工业自动化检测到医疗影像诊断&#xff0c;实时图像处理技术的应用场景无处不在。通过在实时Linux系统中开发图像处理应用&#xff0c;开发者能够充分利用Linux的稳定性…

Caterpillar Fungus Optimizer, CFO

核心算法解析1. 算法框架与初始化class EnhancedCFO: def __init__(self, objective_func, dim10, pop_size30, max_iter200, lb-10, ub10):​​改进点​​&#xff1a;针对传统优化算法后期易停滞的问题&#xff0c;结合了精英策略、多样性控制和自适应参数​​关键特性​​&a…

c++设计模式编程练习

一、运用观察者模式原理编写鸟类模型运行结果&#xff1a;二、运用简单工厂模式编写打怪掉装备模型运行结果

FastMCP本地构建Server和Clinet交互

1. MCP Server介绍 MCP Server 是实现模型上下文协议&#xff08;MCP&#xff09;的服务器&#xff0c;旨在为 AI 模型提供一个标准化接口&#xff0c;连接外部数据源和工具&#xff0c;例如文件系统、数据库或 API。 相比之下&#xff0c;在MCP出现前&#xff0c;AI调用工具…

工业企业与清洁生产匹配数据库(1998-2015年)

1484工业企业与清洁生产匹配数据库&#xff08;1998-2015年&#xff09;“清洁生产”近年发文趋势及主题分布数据来源中华人民共和国生态环境部以及中国工业企业数据库&#xff0c;由数据皮皮侠团队整理时间跨度1998-2015年数据范围各工业企业数据指标参考文献孙博文,郑世林.环…

第13届蓝桥杯C++青少组中/高级组选拔赛2022年1月22日真题

第13届蓝桥杯C青少组中/高级组选拔赛2022年1月22日真题 更多内容请查看网站&#xff1a;【试卷中心 -----> 蓝桥杯----> C ----> 选拔赛】 网站链接 青少年软件编程历年真题模拟题实时更新 编程题 第 1 题 比大小 题目描述&#xff1a; 给出两个不同的整数&#…

从0到1学PHP(七):PHP 与 HTML 表单:实现数据交互

目录一、表单的创建与提交方式1.1 HTML 表单的基本结构1.2 GET 和 POST 提交方式的区别及适用场景二、表单数据的接收与处理2.1 使用\$_GET、\$_POST 超全局变量获取表单数据2.2 对接收的数据进行验证三、表单安全处理3.1 防止 XSS 攻击的方法3.2 防止 CSRF 攻击的措施一、表单…

Docker compose和Docker-compose的区别

Docker Compose 的两个命令形式 docker compose&#xff08;空格连接&#xff09;与 docker-compose&#xff08;短横线连接&#xff09;核心区别如下&#xff1a;一、技术本质docker-compose&#xff08;短横线&#xff09;独立可执行文件&#xff1a;早期实现方式&#xff0c…

自定心深凹槽参数检测装置及检测方法 - 激光频率梳 3D 轮廓检测

一、引言在机械零件深凹槽检测中&#xff0c;传统方法常因定心不准导致检测误差。如平台推表检测时零件基准面与测量平台难以精准对齐&#xff0c;三坐标测量需人工找正&#xff0c;效率低且误差大。激光频率梳 3D 轮廓检测虽精度高&#xff0c;但缺乏自定心机制会影响深凹槽轴…

C语言---结构体(格式、用法、嵌套、初始化)、共用体、枚举类型、typedef类型

目录 结构体与共用体 1、结构体(struct) (1) 格式与用法 (2) 结构体允许嵌套 (3) 结构体成员初始化 (4) 指针替换变量 (5) 求结构体在内存空间所占字节 2、共用体(union) (1) 格式与概念 (2) 应用 3、枚举类型(enum) (1) 格式与概念 (2) 应用 4、typedef 类型 结构体与共用…

辐射源定位方法简述

文章目录 前言 一、按照信息建模分类 1.1.时间参数 1.1.1.到达时间&#xff08;TOA, Time of Arrival&#xff09;定位 1.1.2.到达时间差&#xff08;TDOA, Time Difference of Arrival&#xff09;定位 1.2.角度参数 1.2.1.到达角度&#xff08;AOA, Angle of Arrival&a…