当前位置: 首页 > 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桌面开发 视频教程(无废话版…...

dedecms 织梦自定义表单留言增加ajax验证码功能

增加ajax功能模块&#xff0c;用户不点击提交按钮&#xff0c;只要输入框失去焦点&#xff0c;就会提前提示验证码是否正确。 一&#xff0c;模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

基础测试工具使用经验

背景 vtune&#xff0c;perf, nsight system等基础测试工具&#xff0c;都是用过的&#xff0c;但是没有记录&#xff0c;都逐渐忘了。所以写这篇博客总结记录一下&#xff0c;只要以后发现新的用法&#xff0c;就记得来编辑补充一下 perf 比较基础的用法&#xff1a; 先改这…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)

笔记整理&#xff1a;刘治强&#xff0c;浙江大学硕士生&#xff0c;研究方向为知识图谱表示学习&#xff0c;大语言模型 论文链接&#xff1a;http://arxiv.org/abs/2407.16127 发表会议&#xff1a;ISWC 2024 1. 动机 传统的知识图谱补全&#xff08;KGC&#xff09;模型通过…...

unix/linux,sudo,其发展历程详细时间线、由来、历史背景

sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...

爬虫基础学习day2

# 爬虫设计领域 工商&#xff1a;企查查、天眼查短视频&#xff1a;抖音、快手、西瓜 ---> 飞瓜电商&#xff1a;京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空&#xff1a;抓取所有航空公司价格 ---> 去哪儿自媒体&#xff1a;采集自媒体数据进…...

自然语言处理——循环神经网络

自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元&#xff08;GRU&#xff09;长短期记忆神经网络&#xff08;LSTM&#xff09…...

C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...

FFmpeg:Windows系统小白安装及其使用

一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】&#xff0c;注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录&#xff08;即exe所在文件夹&#xff09;加入系统变量…...

PHP 8.5 即将发布:管道操作符、强力调试

前不久&#xff0c;PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5&#xff01;作为 PHP 语言的又一次重要迭代&#xff0c;PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是&#xff0c;借助强大的本地开发环境 ServBay&am…...

探索Selenium:自动化测试的神奇钥匙

目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...