Three.js 入门——核心概念和坐标系理解

Three.js 是什么?

一个封装了 WebGL 的库,简化 WebGL 的使用

WebGL vs OpenGL

OpenGL 主要被认为是一种 API(应用程序编程接口),它为我们提供了大量可用于操作图形和图像的函数,主要用 C语言编写的。

然而,OpenGL 本身并不是一个 API,而是一个规范,规定了每个函数如何执行和输出,至于具体实现,是由各个厂商的开发者根据自己的硬件特性开发出相应的 API。市场上,OpenGL 大都是显卡、GPU 、浏览器厂商来实现的,例如 Google。

WebGL 是一种用于在Web浏览器中展示 3D 图形的技术,是基于 OpenGL ES 2.0 的 Javascript API。也就是,通过浏览器提供的接口,我们可以使用底层的 OpenGL 库。

OpenGL ES 是 OpenGL 为了满足嵌入式设备需求而开发的一个特殊版本,是它的子集。但和 OpenGL 还是有差别,并不是只取其中一部分。

基础的 Three.js 应用结构

要写一个 Three.js 应用常用用到的四个核心概念,包括渲染器(Renderer)、场景(Scene)、相机(Camera)、网格(Mesh)。
在这里插入图片描述

渲染器 Renderer

将在指定相机角度下看到的 scene 画面绘制到浏览器上,也就是将摄像机的三维场景渲染成一个二维场景。

如果涉及到动态的场景,例如旋转,需要创建循环渲染 requestAnimationFrame,它会以每秒 60 次的频率来绘制场景

var renderer = new THREE.WebGLRenderer({ antialias: true });
// 将渲染器的像素比设置为设备像素比
renderer.setPixelRatio(window.devicePixelRatio);
// 将渲染器的大小设置为窗口的内部宽度(window.innerWidth)和高度(window.innerHeight)
//  如果为 1/2 ,视图将缩小一半
renderer.setSize(window.innerWidth, window.innerHeight);
// 设置动画循环
document.body.appendChild(renderer.domElement);function renderFunc() {requestAnimationFrame(renderFunc); // 循环渲染renderer.render(scene, camera);
}renderFunc()

场景 Scene

场景是一个容器,可以将所有我们想渲染的物体都装在里面

 var scene = new THREE.Scene();scene.add(cube) // 把cube装入场景里,初始位置为 (0,0,0)

相机 Camera

在浏览器里渲染的景象就是从相机视角拍出来的。
相机的位置、视角不同,拍到的风景也不同,只能拍到相机投影范围内的景物
相机的类型有两种,透视摄像机(PerspectiveCamera)、正投影相机(OrthographicCamera)

透视摄像机 PerspectiveCamera

近大远小,距离相机近的地方大,距离相机远的地方小
在这里插入图片描述

var camera = new THREE.PerspectiveCamera(fov, aspect, near, far);

PerspectiveCamera 的参数说明,如下图所示:

  • fov:视场。可以理解为睁眼时,下眼皮到上眼皮睁开的角度。假如是 90 度,那么两个眼皮距离中间的角度分别是 45 度。假如是 180 度,那么物体会变小,因为在整个可视区的占比变小了。
  • aspect:长宽比。整个窗口的长宽比,一般是 window.innerWidth / window.innerHeight
  • near:近面。距离相机多近的距离开始渲染场景。
  • far:远面。定义相机可以看多远。

近面到远面的范围,为相机可以看到的范围,出了这个范围,则不可见。

在这里插入图片描述

正投影相机 OrthographicCamera

正投影相机的所有对象渲染的尺寸都一样。因此它不关心使用什么样的长宽比和视角。
在这里插入图片描述

var camera = new THREE.OrthographicCamera(left, right, top, bottom, near, far)

OrthographicCamera 的参数说明,如下图所示:

  • left:左边界。可视范围的左平面,超出这个范围的不会被渲染。
  • right:右边界。可被渲染的最右面。
  • top:上边界。可被渲染的最上面。
  • bottom:下边界。可被渲染的最下面。
  • near:近面。距离相机的位置,从该位置开始渲染
  • far:远面。基于相机的位置,一直渲染到场景中的这一点

只有在范围 left、right、top、bottom、near、far 范围内的可见。超出该范围不可见。

在这里插入图片描述

网格 Mesh

可以理解为用一种特定的材质(Material)来绘制的一个特定的几何体(Geometry)

var cubeGeometry = new THREE.BoxGeometry(4, 4, 4); // 绘制立方体
var cubeMaterial = new THREE.MeshBasicMaterial({color: 0xff0000, wireframe: true}); // 绘制材质
var cube = new THREE.Mesh(cubeGeometry, cubeMaterial); // 用该材质绘制后的立方体
scene.add(cube); // 添加到场景中

坐标系转换

坐标如下所示
在这里插入图片描述
可通过创建坐标系辅助对象,来展示坐标系。红色代表 X 轴. 绿色代表 Y 轴. 蓝色代表 Z 轴.

var coneAxesHelper = new THREE.AxesHelper(size); // size 为轴的线段长度

右手坐标系

Three.js 使用的是右手坐标系,x 轴朝右,y 轴朝上,z 轴朝向自己。

在这里插入图片描述

围绕轴旋转

拇指指向轴正方向,四指弯曲的方向为旋转正方向。
在这里插入图片描述

如下图所示,将 rotation 的 y 值,从 0 度改为 50 度,物体沿着 y 轴逆时针旋转

在这里插入图片描述
物体旋转 50 度:
在这里插入图片描述

editor 编辑器

使用 Three.js 源码 的 editor编辑器,可以让我们更直观的理解 Three.js 中的物体的坐标系位置。

将项目跑起来,点击到对应的目录即可。

由此可看出,相机被添加到场景中时的初始位置是 (0,0,0)
在这里插入图片描述
相机朝向 Z 轴的负方向
在这里插入图片描述

一个简单的 Three.js 应用

HTML 代码:

<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8"><title>My first three.js app</title><style>body { margin: 0; }</style></head><body><script type="module" src="/main.js"></script></body>
</html>

Javascript 代码:

import * as THREE from 'three';const scene = new THREE.Scene(); // 场景
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 ); // 透视摄像机const renderer = new THREE.WebGLRenderer(); // 渲染器
renderer.setSize( window.innerWidth, window.innerHeight ); // 设置渲染器的大小
document.body.appendChild( renderer.domElement ); // 将渲染器元素添加到 HTML 文档中const geometry = new THREE.BoxGeometry( 1, 1, 1 ); // 创建一个立方体几何
const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } ); // 创建材质
const cube = new THREE.Mesh( geometry, material ); // 用材质绘制后的立方体
scene.add( cube ); // 添加到场景中camera.position.z = 5; // 设置相机的位置,因为相机朝向 Z 轴负方向。往后推,这样才能看得到全局function animate() {requestAnimationFrame( animate ); // 循环渲染cube.rotation.x += 0.01; // 立方体沿 x 轴旋转cube.rotation.y += 0.01; // 立方体沿 y 轴旋转renderer.render( scene, camera ); // 渲染
}animate(); 

换成优雅的类封装

把所有的代码放在同一个页面里,会越堆越多,阅读体验不好。因此可按照功能拆分成函数。进一步可放到类里调用。

以下代码仅提供思路。

// 调用game = new Game("canvas.webgl");game.start();// 封装
export class Game {width!: number; // 视图宽度height!: number; // 视图高度aspect!: number; // 视图宽高比...constructor(selector: string) {if (Game.instance) {return Game.instance;}Game.instance = this;this.selector = selector;this.initConfig();this.initTime();this.initResource();this.initContainer();this.initScene();this.initCamera();this.initRenderer();...}initConfig() {this.width = window.innerWidth;this.height = window.innerHeight;this.aspect = this.width / this.height;}initScene() {this.gameScene = new GameScene();}initCamera() {this.gameCamera = new GameCamera();}...
}

参考资料,也为不错的学习资料。

《Three.js 开发指南》
Three.js 专栏
Three.js-docs
Three.js-manual

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

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

相关文章

python辅助QQ登入

python辅助QQ登入 import pyautogui import time import random from pyautogui import ImageNotFoundException# 生成随机等待时间&#xff0c;范围在1到3秒之间 random_time random.uniform(1, 3)def find_and_click(image_path, moveFalse, execute_nextTrue):try:image_l…

【QT学习】7.事件,把文本显示在页面中(文本可变),鼠标指针切换,鼠标左键右键按下,qt设置背景样式

0.创建项目&#xff0c;事件的创建 1.事件的位置 2.这就是多态&#xff0c;子类重写父类函数&#xff0c;子类调用子类函数&#xff0c;也可以调用父类函数。但同函数名 1.要求&#xff1a;文本显示在页面中&#xff08;文本可变&#xff09; 1.文本显示在页面的核心代码 主要步…

DRF requets源码分析

【四】requets源码分析 【1】查看request传递的数据 &#xff08;1&#xff09;视图层 编写传输数据的接口查看request方法的参数 class BookAPIView(APIView):def get(self, request, *args, **kwargs):return Response({body: request.body, data: request.data, post: r…

【Web】DASCTF X GFCTF 2022十月挑战赛题解

目录 EasyPOP hade_waibo EasyLove BlogSystem EasyPOP 先读hint.php sorry.__destruct -> secret_code::secret() exp: $anew sorry(); $bnew secret_code(); $a->password"suibian"; $a->name"jay"; echo serialize($a); 真暗号啊&…

web项目中jsp页面不识别el表达式

如果使用el表达式出现下图问题 ** 解决办法 ** 这是因为maven创建项目时&#xff0c;web.xml头部声明默认是2.3&#xff0c;这个默认jsp关闭el表达式 修改web.xml文件开头的web-app的版本 <?xml version"1.0" encoding"UTF-8"?> <web-app x…

Python爬取猫眼电影票房 + 数据可视化

目录 主角查看与分析 爬取可视化分析猫眼电影上座率前10分析猫眼电影票房场均人次前10分析猫眼电影票票房占比分析 主角查看与分析 爬取 对猫眼电影票房进行爬取&#xff0c;首先我们打开猫眼 接着我们想要进行数据抓包&#xff0c;就要看网站的具体内容&#xff0c;通过按F12…

Postman之安装

Postman工具之介绍与安装 Postman是什么&#xff1f;Postman有几种安装方式&#xff1f; Postman是什么&#xff1f; postman是一款http客户端的模拟器&#xff0c;它可以模拟发出各种各样的网络请求&#xff0c;用于接口测试。 Postman有几种安装方式&#xff1f; 两种&…

4.17 网络编程

思维导图 select实现TCP并发服务器 #include <myhead.h> #define SER_IP "192.168.125.26" #define SER_PORT 8888int main(int argc, const char *argv[]) {int sfd socket(AF_INET,SOCK_STREAM,0);if(sfd -1){perror("socket error");return -1…

基于Java+SpringBoot+Mybaties-plus+Vue+elememt 小区物业管理系统 的设计与实现

一.项目介绍 系统分为管理员 和 业主 两块&#xff1a; 管理员点击进入到系统操作界面&#xff0c;可以对首页、业主信息管理、管理员信息管理、 楼栋和房屋信息管理、物业费管理、地下停车位管理、公告信息管理、报修信息管理、 投诉管理以及个人信息等功能模块 …

libftdi1学习笔记 5 - SPI Nor Flash

目录 1. 初始化 2. CS控制例子 3. 读ID 3.1 制造商 3.2 容量大小 3.3 设置IO类型 3.3.1 setQSPIWinbond 3.3.2 setQSPIMxic 3.3.3 setQSPIMicrochip 3.3.4 setQSPIMicron 4. 写保护 5. 等待空闲 6. 擦除扇区 7. 页编程 8. 页读 9. 写 10. 读 11. 验证 基于M…

cesium加载高层级离线影像地图瓦片(天地图、19级Arcgis)

实际加载效果如图&#xff1a; 1、下载离线地图瓦片方式&#xff08;多种任选其一&#xff0c;个人倾向于Qgis工具&#xff09;&#xff1a; 方式1、采用第三方下载工具如&#xff1a;91卫图、水经注、全能电子地图下载器、bigemap等等。&#xff08;这些有的下载层级不够&…

Spring Boot:Web应用开发之登录与退出的实现

Spring Boot 前言实现登录功能配置拦截器 实现退出功能 前言 登录与退出功能作为 Web 应用中的基础且重要的组成部分&#xff0c;直接关系到用户的安全和隐私保护。通过实现登录与退出功能&#xff0c;可以对用户的身份进行验证和授权&#xff0c;确保只有合法的用户才能访问特…

Qwen1.5大语言模型微调实践

在人工智能领域&#xff0c;大语言模型&#xff08;Large Language Model&#xff0c;LLM&#xff09;的兴起和广泛应用&#xff0c;为自然语言处理&#xff08;NLP&#xff09;带来了前所未有的变革。Qwen1.5大语言模型作为其中的佼佼者&#xff0c;不仅拥有强大的语言生成和理…

vue3【详解】选项式 API 实现逻辑复用

抽离逻辑代码到一个函数函数命名约定为 useXxxx格式 ( React Hooks 也是 )在 setup 中引用 useXxx 函数 演示代码&#xff1a;实时获取鼠标的坐标 逻辑封装 useMousePosition.js // 导入 ref, onMounted, onUnmounted import { ref, onMounted, onUnmounted } from "vue…

锐捷云桌面的安装

按下 <DEL> 键进入 BIOS setup 界面&#xff08;初始密码为 admin &#xff09;。 输入密码之后就进入 BIOS 的 Main 界面 设置服务器 BMC IP 地址。 a 云服务器启动后&#xff0c;在 BIOS 的主页面&#xff0c;把光标移到 [Server Mgmt] 项。 b 选择 [BMC Network C…

游戏前摇后摇Q闪E闪QE闪QA等操作

备注&#xff1a;未经博主允许禁止转载 个人笔记&#xff08;整理不易&#xff0c;有帮助&#xff0c;收藏点赞评论&#xff0c;爱你们&#xff01;&#xff01;&#xff01;你的支持是我写作的动力&#xff09; 笔记目录&#xff1a;学习笔记目录_pytest和unittest、airtest_w…

基于Springboot的社区防疫物资申报系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的社区防疫物资申报系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系…

Quartz + SpringBoot 实现分布式定时任务

文章目录 前言一、分布式定时任务解决方案二、Quartz是什么&#xff1f;1.quartz简介2.quartz的优缺点 二、Quartz分布式部署总结 前言 因为应用升级&#xff0c;由之前的单节点微服务应用升级为集群微服务应用&#xff0c;所以之前的定时任务Spring Scheduled不再适用了&…

SV-704LW 无线WIFI网络音柱

SV-704LW 无线WIFI网络音柱(工业级) 一、描述 SV-704LW是深圳锐科达电子有限公司的一款壁挂式WIFI无线网络音柱&#xff0c;通过WIFI无线接入到WIFI覆盖的网络中&#xff0c;可将网络音源通过自带的功放和喇叭输出播放&#xff0c;其采用防水设计&#xff0c;功率可以从30W到6…

如何利用FLUENT计算流体力学方法解决大气与环境领域流动问题

ANSYS FLUENT是目前全球领先的商用CFD 软件&#xff0c;市场占有率达70%左右&#xff0c;是工程师和研究者不可多得的有力工具。由于采用了多种求解方法和多重网格加速收敛技术&#xff0c;因而FLUENT能达到最佳的收敛速度和求解精度。灵活的非结构化网格和基于解的自适应网格技…