Three.js 官方文档学习笔记

Address:Three.js中文网 (webgl3d.cn)

Author:方越 50041588

Date:2024-07-19

img

第一个3D案例—创建3D场景

创建3D场景对象Scene:

const scene = new THREE.Scene();

创建一个长方体几何对象Geometry:

const geometry = new THREE.BoxGeometry(100, 100, 100); 

常见几何体对象如下:

创建一个材质对象Material:

const material = new THREE.MeshBasicMaterial({color: 0xff0000,//0xff0000设置材质颜色为红色
}); 

常见材质对象如下:

创建一个网格模型对象Mesh,两个参数分别为几何体geometry、材质material:

const mesh = new THREE.Mesh(geometry, material);

设置网格模型在三维空间中的位置坐标,默认是坐标原点:

mesh.position.set(0,10,0);

把网格模型mesh添加到三维场景scene中:

scene.add(mesh); 

第一个3D案例—透视投影相机

实例化一个透视投影相机对象:

const camera = new THREE.PerspectiveCamera();

相机在Three.js三维坐标系中的位置,根据需要设置相机位置具体值:

camera.position.set(200, 200, 200); 

相机观察目标指向Threejs 3D空间中某个位置:

camera.lookAt(0, 0, 0); //坐标原点
camera.lookAt(0, 10, 0);  //y轴上位置10
camera.lookAt(mesh.position);//指向mesh对应的位置

img

透视投影相机的四个参数fov, aspect, near, far构成一个四棱台3D空间,被称为视锥体,只有视锥体之内的物体,才会渲染出来,视锥体范围之外的物体不会显示在Canvas画布上:

// 30:视场角度(fov)
// width / height:Canvas画布宽高比(aspect)
// 1:近裁截面(near)
// 3000:远裁截面(far)
camera = new THREE.PerspectiveCamera(30, width / height, 1, 3000);

视锥体

第一个3D案例—渲染器

创建渲染器对象:

const renderer = new THREE.WebGLRenderer();

定义threejs输出画布的尺寸(单位:像素px):

const width = 800; //宽度
const height = 500; //高度
renderer.setSize(width, height); //设置three.js渲染区域的尺寸

执行渲染操作:

renderer.render(scene, camera);

Canvas画布插入到任意HTML元素中:

<div id="webgl" style="margin-top: 200px;margin-left: 100px;"></div>
document.getElementById('webgl').appendChild(renderer.domElement);

三维坐标系-加强三维空间认识

辅助观察的坐标系AxesHelper:

const axesHelper = new THREE.AxesHelper(150);
scene.add(axesHelper);

设置材质半透明,这样可以看到坐标系的坐标原点:

const material = new THREE.MeshBasicMaterial({color: 0x0000ff, //设置材质颜色transparent:true,//开启透明opacity:0.5,//设置透明度
});

光源对物体表面影响

MeshBasicMaterial不受光照影响:

const material = new THREE.MeshBasicMaterial(); 

MeshLambertMaterial受光照影响:

const material = new THREE.MeshLambertMaterial(); 

光源对物体表面影响关系如下:

常见光源分类如下:

点光源:两个参数分别表示光源颜色和光照强度:

// 参数1:0xffffff是纯白光,表示光源颜色
// 参数2:1.0,表示光照强度,可以根据需要调整
const pointLight = new THREE.PointLight(0xffffff, 1.0);

光源衰减属性decay默认值是2.0,如果不希望衰减可以设置为0.0:

pointLight.decay = 0.0;//设置光源不随距离衰减

设置点光源位置:

pointLight.position.set(400, 0, 0);//点光源放在x轴上

点光源添加到场景中:

scene.add(pointLight); 

相机控件OrbitControls

引入轨道控制器扩展库OrbitControls.js:

import { OrbitControls } from 'three/addons/controls/OrbitControls.js';

设置相机控件轨道控制器OrbitControls:

const controls = new OrbitControls(camera, renderer.domElement);
// 如果OrbitControls改变了相机参数,重新调用渲染器渲染三维场景
controls.addEventListener('change', function () {renderer.render(scene, camera); //执行渲染操作
});//监听鼠标、键盘事件

平行光与环境光

点光源辅助观察:

const pointLightHelper = new THREE.PointLightHelper(pointLight, 10);
scene.add(pointLightHelper);

环境光:没有特定方向,整体改变场景的光照明暗:

const ambient = new THREE.AmbientLight(0xffffff, 0.4);
scene.add(ambient);

平行光:沿着特定方向发射:

const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
// 设置光源的方向:通过光源position属性和目标指向对象的position属性计算
directionalLight.position.set(80, 100, 50);
// 方向光指向对象网格模型mesh,可以不设置,默认的位置是0,0,0
directionalLight.target = mesh;
scene.add(directionalLight);

可视化平行光DirectionalLightHelper:

const dirLightHelper = new THREE.DirectionalLightHelper(directionalLight, 5, 0xff0000);
scene.add(dirLightHelper);

动作渲染循环

requestAnimationFrame实现周期性循环执行,用其实现threejs旋转动画:

const renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height);
document.body.appendChild(renderer.domElement);function render() {renderer.render(scene, camera); //执行渲染操作mesh.rotateY(0.01);//每次绕y轴旋转0.01弧度requestAnimationFrame(render);//请求再次执行渲染函数render,渲染下一帧
}
render();

Canvas画布布局和全屏

全屏渲染canvas:

// width和height用来设置Three.js输出的Canvas画布尺寸(像素px)
const width = window.innerWidth; //窗口文档显示区的宽度作为画布宽度
const height = window.innerHeight; //窗口文档显示区的高度作为画布高度
const renderer = new THREE.WebGLRenderer();
document.body.appendChild(renderer.domElement);

onresize 事件会在窗口被调整大小时发生,实现宽高度动态变化:

window.onresize = function () {// 重置渲染器输出画布canvas尺寸renderer.setSize(window.innerWidth, window.innerHeight);// 全屏情况下:设置观察范围长宽比aspect为窗口宽高比camera.aspect = window.innerWidth / window.innerHeight;// 渲染器执行render方法的时候会读取相机对象的投影矩阵属性projectionMatrix// 但是不会每渲染一帧,就通过相机的属性计算投影矩阵(节约计算资源)// 如果相机的一些属性发生了变化,需要执行updateProjectionMatrix ()方法更新相机的投影矩阵camera.updateProjectionMatrix();
};

stats查看threejs渲染帧率

引入性能监视器stats.js:

import Stats from 'three/addons/libs/stats.module.js';

创建stats对象:

const stats = new Stats();
//stats.domElement:web页面上输出计算结果,一个div元素,
document.body.appendChild(stats.domElement);
function render() {
//requestAnimationFrame循环调用的函数中调用方法update(),来刷新时间
stats.update();
renderer.render(scene, camera); //执行渲染操作
requestAnimationFrame(render); //请求再次执行渲染函数render,渲染下一帧
}
render();

通过setMode()方法的参数mode的数值设置首次打开页面,测试结果的显示模式:

//stats.domElement显示:渲染帧率 刷新频率,一秒渲染次数 
stats.setMode(0);//默认模式
//stats.domElement显示:渲染周期 渲染一帧多长时间(单位:毫秒ms)
stats.setMode(1);

阵列立方体和相机适配体验

相机控件OrbitControls会影响lookAt设置,注意手动设置OrbitControls的目标参数:

const controls = new OrbitControls(camera, renderer.domElement);
// 相机控件.target属性在OrbitControls.js内部表示相机目标观察点,默认0,0,0
// console.log('controls.target', controls.target);
controls.target.set(1000, 0, 1000);
controls.update();//update()函数内会执行camera.lookAt(controls.target)

Threejs常见几何体简介

常见几何体对象:

//BoxGeometry:长方体
const geometry = new THREE.BoxGeometry(100, 100, 100);
// SphereGeometry:球体
const geometry = new THREE.SphereGeometry(50);
// CylinderGeometry:圆柱
const geometry = new THREE.CylinderGeometry(50,50,100);
// PlaneGeometry:矩形平面
const geometry = new THREE.PlaneGeometry(100,50);
// CircleGeometry:圆形平面
const geometry = new THREE.CircleGeometry(50);

Three.js的材质默认正面可见,反面不可见,对于矩形平面、圆形平面如果你想看到两面,可以设置side:

new THREE.MeshBasicMaterial({side: THREE.FrontSide, //默认只有正面可见
});
new THREE.MeshBasicMaterial({side: THREE.DoubleSide, //两面可见
});

高光网格材质Phong

MeshPhongMaterial 可以提供一个镜面反射效果,可以类比你生活中拿一面镜子,放在太阳光下,调整角度,可以把太阳光反射到其它地方,如果反射光对着眼睛,也就是反射光线和视线平行的时候,会非常刺眼。

MeshLambertMaterial 对应的Mesh受到光线照射,没有镜面反射的效果,只是一个漫反射,也就是光线向四周反射。

// 模拟镜面反射,产生一个高光效果
const material = new THREE.MeshPhongMaterial({color: 0xff0000,shininess: 20, //高光部分的亮度,默认30specular: 0x444444, //高光部分的颜色
});

WebGL渲染器设置(锯齿模糊)

设置锯齿属性:

renderer.antialias = true; 

获取你屏幕对应的设备像素比devicePixelRatio,告诉threejs,以免渲染模糊问题:

renderer.setPixelRatio(window.devicePixelRatio);

设置背景颜色:

renderer.setClearColor(0x444444, 1); 

gui.js库(可视化改变三维场景)

引入dat.gui.js的一个类GUI:

import { GUI } from 'three/addons/libs/lil-gui.module.min.js';

实例化一个gui对象:

const gui = new GUI();

改变交互界面style属性:

gui.domElement.style.right = '0px';
gui.domElement.style.width = '300px';

执行gui的add()方法可以快速创建一个UI交互界面:

//创建一个对象,对象属性的值可以被GUI库创建的交互界面改变
const obj = {x: 30,
};
// gui增加交互界面,用来改变obj对应属性
gui.add(obj, 'x', 0, 100);

gui调试界面2-颜色命名等

通过name()方法改变gui生成交互界面显示的内容:

gui.add(ambient, 'intensity', 0, 2.0).name('环境光强度');
gui.add(directionalLight, 'intensity', 0, 2.0).name('平行光强度');

通过step()方法设置步长:

gui.add(ambient, 'intensity', 0, 2.0).name('环境光强度').step(0.1);

当gui界面某个值的时候,onChange()方法就会执行,可以根据需要通过onChange()执行某些代码:

const obj = {
x: 30,
};
// 当obj的x属性变化的时候,就把此时obj.x的值value赋值给mesh的x坐标
gui.add(obj, 'x', 0, 180).onChange(function(value){
mesh.position.x = value;
// 你可以写任何你想跟着obj.x同步变化的代码
// 比如mesh.position.y = value;
});

通过addColor()方法生成颜色值改变的交互界面:

const obj = {color:0x00ffff,
};
// .addColor()生成颜色值改变的交互界面
gui.addColor(obj, 'color').onChange(function(value){mesh.material.color.set(value);
});

gui调试3-下拉菜单、单选框

参数3和参数4,分别是一个数字,交互界面是一个鼠标可以拖动的拖动条,可以在一个区间改变属性的值:

// 参数3、参数4数据类型:数字(拖动条)
gui.add(obj, 'x', 0, 180).onChange(function (value) {mesh.position.x = value;
});

参数3是一个数组,生成交互界面是下拉菜单:

const obj = {scale: 0,
};
// 参数3数据类型:数组(下拉菜单)
gui.add(obj, 'scale', [-100, 0, 100]).name('y坐标').onChange(function (value) {mesh.position.y = value;
});

参数3是一个对象,生成交互界面是下拉菜单:

const obj = {scale: 0,
};
// 参数3数据类型:对象(下拉菜单)
gui.add(obj, 'scale', {left: -100,center: 0,right: 100
}).name('位置选择').onChange(function (value) {mesh.position.x = value;
});

参数3是布尔值,生成交互界面是单选框

const obj3 = {bool: false,
};
// 改变的obj属性数据类型是布尔值,交互界面是单选框
gui.add(obj3, 'bool').name('是否旋转').onChange(function (value) {// 点击单选框,控制台打印obj.bool变化console.log('obj.bool',value);
});

gui.js库(分组)

new GUI() 实例化一个gui对象,默认创建一个总的菜单,通过gui对象的addFolder()方法可以创建一个子菜单,当你通过GUI控制的属性比较多的时候,可以使用addFolder()进行分组。addFolder()返回的子文件夹对象,同样具有gui对象的add()、onChange()、addColor()等等属性。

// 创建材质子菜单
const matFolder = gui.addFolder('材质');
matFolder.close();
// 材质颜色color
matFolder.addColor(obj, 'color').onChange(function(value){material.color.set(value);
});

gui对象创建的总菜单或gui.addFolder()创建的子菜单都可以用代码控制交互界面关闭或开展状态:

gui.open(); // 展开菜单
gui.close(); // 关闭菜单

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

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

相关文章

FTP、NFS、SAMBA系统服务

⼀、rsync托管xinetd 1 、为什么要进⾏服务托管 独⽴服务&#xff1a;独⽴启动脚本 ssh ftp nfs dns ... 依赖服务 : 没有独⽴的启动脚本 rsync telnet 依赖 xinetd 服务&#xff08;独⽴服务&#xff09; 2 、如何将 rsync 托管给 xinetd 服务去管理&#xff1f; 第⼀步&am…

VMware中Ubuntu磁盘空间的清理

最近发现Ubuntu占用空间过大&#xff0c;在网上找了一些方法&#xff0c;在这里总结一下。 1.删除快照 把不需要的快照删除&#xff0c;但要注意删除快照可能会影响到后续的快照链。每个快照依赖于前面的快照。如果删除一个中间快照&#xff0c;虚拟机可能无法找到完整的差异…

leetcode 513.找树左下角的值

1.题目要求: 代码块: 给定一个二叉树的 根节点 root&#xff0c;请找出该二叉树的 最底层 最左边 节点的值。假设二叉树中至少有一个节点。2.此题思路: 1.创建队列&#xff0c;出队函数和入队函数: //创建队列 typedef struct queuet{struct TreeNode* value;struct queue* n…

IB user verbs介绍

本文来自对内核源代码文档/Documentation/infiniband/user_verbs.rst的翻译和理解。 在Infiniband设备帮助下&#xff0c;跨计算机的两个进程可以相互访问对方的虚地址空间。在Linux操作系统上&#xff0c;支持进程能直接访问本地Infiniband设备的资源&#xff0c;从而实现跨机…

TeamViewer手机端APP提示:请先验证账户

当你在手机端下载安装了TeamViewerAPP后&#xff0c;需要你先登录个人账号&#xff0c;然后还会要求你验证账户&#xff0c;同时跳转到一个网址中&#xff0c;但是这个网址并没有自动跳转到验证账户的位置。 解决办法&#xff1a; 在手机浏览器中进入下面这个网址&#xff1a;…

鸿蒙语言基础类库:【@system.vibrator (振动)】

振动 说明&#xff1a; 本模块首批接口从API version 4开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。从API Version 8开始&#xff0c;该接口不再维护&#xff0c;推荐使用新接口[ohos.vibrator]。该功能使用需要对应硬件支持&#xff0c;仅支持…

VMware虚拟机无法访问互联网

一、什么情况下需要访问互联网 在某些情况下&#xff0c;VMware虚拟机需要通过访问互联网去获取外部资源&#xff0c;例如进行yum安装或者wget拉取操作等等。 二、处理方法 2.1.检查虚拟机网络模式和服务状态 虚拟机的网络模式需要使用 NAT 模式。 VMware NAT Service服务…

Delphi 11.2 配置Android SDK 环境

打开 Delphi 11 点击 Tools–Options… 然后点击 Deployment–SDK Manager–Add… 这里如果配置64位就选 Android 64-bit&#xff0c;如果配置32位就选 Android 32-bit 点击 Select an SDK version–Add New… 有警告图标的就是有问题的项&#xff0c;需要手动更新一下&#xf…

微信小程序开发:项目程序代码构成

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

PostgreSQL创建表和自增序列

一、创建表&#xff1a; 注意&#xff1a; 1、在mysql没有序列的概念&#xff0c;id自增通过auto_increment实现&#xff1b; 2、pgsql没有auto_increment的概念&#xff0c;如何实现id自增&#xff1f;有两种方式&#xff1a; 方式一&#xff1a;创建序列&#xff0c;绑定…

Android lmkd机制详解

目录 一、lmkd介绍 二、lmkd实现原理 2.1 工作原理图 2.2 初始化 2.3 oom_adj获取 2.4 监听psi事件及处理 2.5 进程选取与查杀 2.5.1 进程选取 2.5.2 进程查杀 三、关键系统属性 四、核心数据结构 五、代码时序 一、lmkd介绍 Android lmkd采用epoll方式监听linux内…

SpringBoot连接PostgreSQL+MybatisPlus入门案例

项目结构 一、Java代码 pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://mave…

客户案例 | 识货基于向量检索服务 Milvus 版搭建电商领域的向量数据检索平台

阿里云的Milvus服务以其性能稳定和功能多样化的向量检索能力&#xff0c;为识货团队在电商领域的向量检索场景中搭建业务系统提供了强有力的支持。该服务的分布式扩展能力不仅可靠&#xff0c;而且能够适应日益增长的数据规模。 一、客户介绍 识货&#xff0c;成立于2012年6月…

Selenium之execute_script()方法执行js脚本

目录 场景应用和使用 页面滚动 获取返回值 返回JavaScript定位的元素对象 修改元素属性 弹出提示框 场景应用和使用 在自动化测试中&#xff0c;部分场景无法使用自动化Selenium原生方法来进行测试&#xff1a; 滚动到某个元素&#xff08;位置&#xff09; 修改…

水利行业的智慧转型之路:分析智慧水利的核心要素与优势,展望其在提升水资源利用效率、保障水安全方面的广阔前景

目录 引言 一、智慧水利的核心要素 1. 物联网技术 2. 大数据与云计算 3. 人工智能与机器学习 4. 移动互联网与GIS技术 5. 标准化与信息安全 二、智慧水利的优势 1. 提高水资源利用效率 2. 增强水灾害防御能力 3. 提升水环境治理水平 4. 促进水利服务智能化 三、展望…

响应式商标知识产权企业网站源码系统 带模版以及搭建部署教程

系统概述 响应式商标知识产权企业网站源码系统是一款专门为商标知识产权企业打造的综合性网站平台。它融合了先进的技术和设计理念&#xff0c;旨在为企业提供一个全面展示自身形象、业务能力和专业服务的数字化窗口。 该系统采用了现代化的架构和开发方式&#xff0c;具备高度…

Mem0 - 个人 AI 的内存层

文章目录 一、关于 Mem0核心功能&#x1f511;路线图 &#x1f5fa;️常见用例Mem0与RAG有何不同&#xff1f; 二、快速入门 &#x1f680;1、安装2、基本用法&#xff08;开源&#xff09;3、高级用法&#x1f527;4、大模型支持 三、MultiOn1、概览2、设置和配置4、将记忆添加…

电脑基础知识 | 电脑的基本组成

电脑作为我们日常工作和娱乐的重要工具&#xff0c;扮演着举足轻重的角色。当我们谈论电脑的基本组成时&#xff0c;其实是在探讨电脑硬件和软件两个核心部分。硬件是电脑看得见、摸得着的物理设备&#xff0c;而软件则是运行在这些硬件之上的程序和指令。两者相辅相成&#xf…

数据结构(二叉树-1)

文章目录 一、树 1.1 树的概念与结构 1.2 树的相关术语 1.3 树的表示 二、二叉树 2.1 二叉树的概念与结构 2.2特殊的二叉树 满二叉树 完全二叉树 2.3 二叉树的存储结构 三、实现顺序结构二叉树 3.1 堆的概念与结构 3.2 堆的实现 Heap.h Heap.c 默认初始化堆 堆的销毁 堆的插入 …

【web】-flask-简单的计算题(不简单)

打开页面是这样的 初步思路&#xff0c;打开F12&#xff0c;查看头&#xff0c;都发现了这个表达式的base64加密字符串。编写脚本提交答案&#xff0c;发现不对&#xff1b; 无奈点开source发现源代码&#xff0c;是flask,初始化表达式&#xff0c;获取提交的表达式&#xff0…