当前位置: 首页 > news >正文

three.js 入门三:buffergeometry贴图属性(position、index和uvs)

环境:

  • three.js 0.159.0

一、基础知识

  • geometry:决定物体的几何形状、轮廓;
  • material:决定物体呈现的色彩、光影特性、贴图皮肤;
  • mesh:场景中的物体,由geometrymateria组成;
  • texture:贴图,用于将一个jpg等格式的图片贴到material上面(当然,material也可以不贴texture);

另外,如果material上是定义的color,那么说明,物体是自发光的,不需要灯光就能看到,
materia如果整个是靠texture贴上去的,则需要光照才能看到它,最简单的是用环境光。

另外,对于一张图片,无论它有多大或多小,左下角是(0,0),右上角是(1,1),这就是uv,宽用u表示,高用v表示。

另外,无论一个物体形状有多复杂,其表面也可以分割成很多三角面。

下面使用的示例图片如下:

在这里插入图片描述

二、简单实例

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>* {margin: 0;padding: 0;box-sizing: border-box;}</style><script type="importmap">{"imports": {"three": "https://unpkg.com/three@0.159.0/build/three.module.js","three/addons/": "https://unpkg.com/three@0.159.0/examples/jsm/"}}</script>
</head><body><script type="module">import * as THREE from 'three';import { OrbitControls } from 'three/addons/controls/OrbitControls.js';let camera, scene, renderer;//基础对象camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 10000);camera.position.set(50, 50, 50);camera.updateProjectionMatrix();renderer = new THREE.WebGLRenderer();renderer.setPixelRatio(window.devicePixelRatio);renderer.setSize(window.innerWidth, window.innerHeight);document.body.appendChild(renderer.domElement);const controls = new OrbitControls(camera, renderer.domElement);controls.minDistance = 5;controls.maxDistance = 300;controls.update()scene = new THREE.Scene();// 环境光const light = new THREE.AmbientLight(0x404040); // soft white lightscene.add(light);//坐标轴const axesHelper = new THREE.AxesHelper(5);scene.add(axesHelper);//准备geometry//点位var position = [10, 10, 0,10, 0, 0,0, 0, 0]//贴图var uvs = [1, 1,1, 0,0, 0,]        //构造geometrylet geometry = new THREE.BufferGeometry();geometry.setAttribute('position', new THREE.Float32BufferAttribute(position, 3));geometry.setAttribute('uv', new THREE.Float32BufferAttribute(uvs, 2));//加载贴图const texture = new THREE.TextureLoader().load('number.png');texture.wrapS = texture.wrapT = THREE.RepeatWrapping;texture.repeat.set(1, 1);//准备materialconst material = new THREE.MeshBasicMaterial({side: THREE.DoubleSide,map: texture,transparent: true,opacity: 0.7,});//组成meshconst mesh = new THREE.Mesh(geometry, material);scene.add(mesh);function animate() {requestAnimationFrame(animate);renderer.render(scene, camera);}animate();</script>
</body></html>

效果如下:
在这里插入图片描述

三、探索贴图原理

先说上面示例:

  • position 表达了三个点位的坐标和顺序(看向-z轴,逆时针),此时面的法方向是 (0,0,-1);
  • uv 表达了position每个点位在贴图上的点;
  • 又因为,将material设为了透明和双面渲染,所以我们看向-z轴也是可以看到效果的(我们默认看到的效果其实是背面,可以将上面的 side: THREE.DoubleSide, 注释掉试试);

这里是否有一个疑问:怎么知道贴图的正面是朝向哪的呢?为什么这里是朝向+z轴,而不是-z轴呢?

其实,因为position和uv,webgl的插值计算只能将贴图的正面朝向+z轴,如下图示意:
在这里插入图片描述

四、考虑index作用

上面只是3个点位,所以仅用position和uv即可表达,但如果有很多点位,再这么写的话position会很多,而且很多都是重复的,
比如:立方体有8个点位,如果每个面分成两个三角面,那么总共需要24 = 6*2*3个点位坐标(每个3角面要3个点)。

此时使用index的写法:
position:8个点位
index: 列出每个三角面的点位序号, 共计 24 个元素
uv:和position一一对应

将上面示例中geometry部分改造如下:

//准备geometry
//点位
var position = [10, 10, 0,10, 0, 0,0, 0, 0,0, 10, 0,
]
//贴图
var uvs = [1, 1,1, 0,0, 0,0, 1,
]
//点位序号
var index = [0, 1, 2,0, 2, 3,
]        
//构造geometry
let geometry = new THREE.BufferGeometry();
geometry.setIndex(index);
geometry.setAttribute('position', new THREE.Float32BufferAttribute(position, 3));
geometry.setAttribute('uv', new THREE.Float32BufferAttribute(uvs, 2));

此时,我们看到的效果:
在这里插入图片描述

可以看到,我们仅用了4个点位,便描述了两个3角面。

五、看一个特殊的示例

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>* {margin: 0;padding: 0;box-sizing: border-box;}</style><script type="importmap">{"imports": {"three": "https://unpkg.com/three@0.159.0/build/three.module.js","three/addons/": "https://unpkg.com/three@0.159.0/examples/jsm/"}}</script>
</head><body><script type="module">import * as THREE from 'three';import { OrbitControls } from 'three/addons/controls/OrbitControls.js';let camera, scene, renderer;//基础对象camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 10000);camera.position.set(50, 50, 50);camera.updateProjectionMatrix();renderer = new THREE.WebGLRenderer();renderer.setPixelRatio(window.devicePixelRatio);renderer.setSize(window.innerWidth, window.innerHeight);document.body.appendChild(renderer.domElement);const controls = new OrbitControls(camera, renderer.domElement);controls.minDistance = 5;controls.maxDistance = 300;controls.update()scene = new THREE.Scene();// 环境光const light = new THREE.AmbientLight(0x404040); // soft white lightscene.add(light);//坐标轴const axesHelper = new THREE.AxesHelper(5);scene.add(axesHelper);//准备geometry//点位var position = [10, 10, 0,10, 0, 0,0, 0, 0,]//贴图var uvs = [0, 1,1, 1,0, 0,]//点位序号var index = [0, 1, 2]//构造geometrylet geometry = new THREE.BufferGeometry();geometry.setIndex(index);geometry.setAttribute('position', new THREE.Float32BufferAttribute(position, 3));geometry.setAttribute('uv', new THREE.Float32BufferAttribute(uvs, 2));//加载贴图const texture = new THREE.TextureLoader().load('number.png');texture.wrapS = texture.wrapT = THREE.RepeatWrapping;texture.repeat.set(1, 1);//准备materialconst material = new THREE.MeshBasicMaterial({side: THREE.DoubleSide,map: texture,transparent: true,opacity: 0.7,});//组成meshconst mesh = new THREE.Mesh(geometry, material);scene.add(mesh);function animate() {requestAnimationFrame(animate);renderer.render(scene, camera);}animate();</script>
</body></html>

效果如下:
在这里插入图片描述

六、最后看一个用立方体实现全景图预览的效果

效果图如下:
在这里插入图片描述

代码下载请看博文顶部。。。

相关文章:

three.js 入门三:buffergeometry贴图属性(position、index和uvs)

环境&#xff1a; three.js 0.159.0 一、基础知识 geometry&#xff1a;决定物体的几何形状、轮廓&#xff1b;material&#xff1a;决定物体呈现的色彩、光影特性、贴图皮肤&#xff1b;mesh&#xff1a;场景中的物体&#xff0c;由geometry和materia组成&#xff1b;textu…...

Initial用法-FPGA入门3

Initial是什么 FPGA Initial是一种在FPGA中进行初始化的方法。在FPGA设备上&#xff0c;初始值决定了逻辑门的状态和寄存器的初始值。FPGA Initial可以通过设置初始值来控制电路在上电后的初始状态。 Initial的作用 2.1&#xff0c;控制电路启动时的初始状态 通过设置FPGA Ini…...

perl脚本中使用eval函数执行可能有异常的操作

perl脚本中有时候执行的操作可能会引发异常&#xff0c;为了直观的说明&#xff0c;这里举一个json反序列化的例子&#xff0c;脚本如下&#xff1a; #! /usr/bin/perl use v5.14; use JSON; use Data::Dumper;# 读取json字符串数据 my $json_str join(, <DATA>); # 反…...

『Redis』在Docker中快速部署Redis并进行数据持久化挂载

&#x1f4e3;读完这篇文章里你能收获到 在Docke中快速部署Redis如何将Redis的数据进行持久化 文章目录 一、拉取镜像二、创建挂载目录1 宿主机与容器挂载映射2 挂载命令执行 三、创建容器—运行Redis四、查看运行情况 一、拉取镜像 版本号根据需要自己选择&#xff0c;这里以…...

ubuntu创建apt-mirror本地仓库

首先创建apt-mirror的服务端&#xff0c;也就是存储所有apt-get下载的文件和依赖。大约需要300G&#xff0c;预留400G左右空间就可以开始了。 安装ubuntu省略&#xff0c;用的是ubuntu202204 ubuntu挂载硬盘&#xff08;不需要的可以跳过&#xff09;: #下载挂载工具 sudo apt…...

计算机网络 internet应用 (水

ARPA net ---Internet 前身 发展史: ARPA net 第一个主干网..美国军方NSFnet 美国国家科学基金会NSFANSnet 美国全国 (internet 叫法开始出现) 第二代互联网(现在() IP地址 IP地址 最高管理机构 - InterNIC IPV4 32位 IPV6 128位 域名 起名 解析 domain name sys…...

【ChatGLM3】第三代大语言模型多GPU部署指南

关于ChatGLM3 ChatGLM3是智谱AI与清华大学KEG实验室联合发布的新一代对话预训练模型。在第二代ChatGLM的基础之上&#xff0c; 更强大的基础模型&#xff1a; ChatGLM3-6B 的基础模型 ChatGLM3-6B-Base 采用了更多样的训练数据、更充分的训练步数和更合理的训练策略。在语义、…...

云原生Kubernetes系列 | Docker/Kubernetes的卷管理

云原生Kubernetes系列 | Docker/Kubernetes的卷管理 1. Docker卷管理2. Kubernetes卷管理2.1. 本地存储2.1.1. emptyDir2.1.2. hostPath2.2. 网络存储2.2.1. 使用NFS2.2.2. 使用ISCSI2.3. 持久化存储2.3.1. PV和PVC2.3.2. 访问模式2.3.3. 回收策略1. Docker卷管理...

Java实现快速排序算法

快速排序算法 &#xff08;1&#xff09;概念&#xff1a;快速排序是指通过一趟排序将要排序的数据分割成独立的两部分&#xff0c;其中一部分的所有数据都比另外一部分的所有数据都要小&#xff0c;然后再按此方法对这两部分数据分别进行快速排序。整个排序过程可以递归进行&…...

MAC配置环境变量

1、配置 JAVA JDK 1.1、查看 JDK 安装目录 &#xff08;1&#xff09;可以在Android Studio中查看&#xff0c;复制该路径 &#xff08;2&#xff09;也可以在官网下载 Java JDK下载地址 mac中的安装地址是"资源库->Java->JavaVirtualMachines"中 1.2、…...

系列五、DQL

一、DQL 1.1、概述 DQL的英文全称为&#xff1a;Data Query Language&#xff0c;中文意思为&#xff1a;数据查询语言&#xff0c;用大白话讲就是查询数据。对于大多数系统来说&#xff0c;查询操作的频次是要远高于增删改的&#xff0c;当我们去访问企业官网、电商网站&…...

【智能家居】七、人脸识别 翔云平台编程使用(编译openSSL支持libcurl的https访问、安装SSL依赖库openSSL)

一、翔云 人工智能开放平台 API文档开发示例下载 二、编译openSSL支持libcurl的https访问 安装SSL依赖库openSSL(使用工具wget)libcurl库重新配置&#xff0c;编译&#xff0c;安装运行&#xff08;运行需添加动态库为环境变量&#xff09; 三、编程实现人脸识别 四、Base6…...

基于node 安装express后端脚手架

1.首先创建文件件 2.在文件夹内打开终端 npm init 3.安装express: npm install -g express-generator注意的地方&#xff1a;这个时候安装特别慢,最后导致不成功 解决方法&#xff1a;npm config set registry http://registry.npm.taobao.org/ 4.依次执行 npm install -g ex…...

Mrdoc知识文档

MrDoc知识文档平台是一款基于Python开发的在线文档系统&#xff0c;适合作为个人和中小型团队的私有云文档、云笔记和知识管理工具&#xff0c;致力于成为优秀的私有化在线文档部署方案。我现在主要把markdown笔记放在上面&#xff0c;因为平时老是需要查询一些知识点&#xff…...

C语言中getchar函数

在 C 语言中&#xff0c;getchar() 是一个标准库函数&#xff0c;用于从标准输入&#xff08;通常是键盘&#xff09;读取单个字符。它的函数原型如下&#xff1a; int getchar(void);getchar() 函数的工作原理如下&#xff1a; 当调用 getchar() 函数时&#xff0c;它会等待…...

全栈开发组合

SpringBoot是什么&#xff1f; SpringBoot是一个基于Spring框架的开源框架&#xff0c;由Pivotal团队开发。它的设计目的是用来简化Spring应用的初始搭建以及开发过程。SpringBoot提供了丰富的Spring模块化支持&#xff0c;可以帮助开发者更轻松快捷地构建出企业级应用 Sprin…...

wpf TelerikUI使用DragDropManager

首先&#xff0c;我先创建事务对象ApplicationInfo&#xff0c;当暴露出一对属性当例子集合对于构成ListBoxes。这个类在例子中显示如下代码&#xff1a; public class ApplicationInfo { public Double Price { get; set; } public String IconPath { get; set; } public …...

Python+Appium自动化测试之元素等待方法与重新封装元素定位方法

在appium自动化测试脚本运行的过程中&#xff0c;因为网络不稳定、测试机或模拟器卡顿等原因&#xff0c;有时候会出现页面元素加载超时元素定位失败的情况&#xff0c;但实际这又不是bug&#xff0c;只是元素加载较慢&#xff0c;这个时候我们就会使用元素等待的方法来避免这种…...

详解Maven如何打包SpringBoot工程

目录 一、spring-boot-maven-plugin详解 1、添加spring-boot-maven-plugin插件到pom.xml 2、配置主类&#xff08;Main Class&#xff09; 3、配置打包的JAR文件名 4、包含或排除特定的资源文件 5、指定额外的依赖项 6、配置运行参数 7、自定义插件执行阶段 二、Maven打…...

PyQt6 QFrame分割线控件

锋哥原创的PyQt6视频教程&#xff1a; 2024版 PyQt6 Python桌面开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili2024版 PyQt6 Python桌面开发 视频教程(无废话版) 玩命更新中~共计46条视频&#xff0c;包括&#xff1a;2024版 PyQt6 Python桌面开发 视频教程(无废话版…...

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…...

国防科技大学计算机基础课程笔记02信息编码

1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制&#xff0c;因此这个了16进制的数据既可以翻译成为这个机器码&#xff0c;也可以翻译成为这个国标码&#xff0c;所以这个时候很容易会出现这个歧义的情况&#xff1b; 因此&#xff0c;我们的这个国…...

K8S认证|CKS题库+答案| 11. AppArmor

目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作&#xff1a; 1&#xff09;、切换集群 2&#xff09;、切换节点 3&#xff09;、切换到 apparmor 的目录 4&#xff09;、执行 apparmor 策略模块 5&#xff09;、修改 pod 文件 6&#xff09;、…...

Cesium1.95中高性能加载1500个点

一、基本方式&#xff1a; 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

SCAU期末笔记 - 数据分析与数据挖掘题库解析

这门怎么题库答案不全啊日 来简单学一下子来 一、选择题&#xff08;可多选&#xff09; 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘&#xff1a;专注于发现数据中…...

CMake基础:构建流程详解

目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...

Golang dig框架与GraphQL的完美结合

将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用&#xff0c;可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器&#xff0c;能够帮助开发者更好地管理复杂的依赖关系&#xff0c;而 GraphQL 则是一种用于 API 的查询语言&#xff0c;能够提…...

MODBUS TCP转CANopen 技术赋能高效协同作业

在现代工业自动化领域&#xff0c;MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步&#xff0c;这两种通讯协议也正在被逐步融合&#xff0c;形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...

ETLCloud可能遇到的问题有哪些?常见坑位解析

数据集成平台ETLCloud&#xff0c;主要用于支持数据的抽取&#xff08;Extract&#xff09;、转换&#xff08;Transform&#xff09;和加载&#xff08;Load&#xff09;过程。提供了一个简洁直观的界面&#xff0c;以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

多种风格导航菜单 HTML 实现(附源码)

下面我将为您展示 6 种不同风格的导航菜单实现&#xff0c;每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...