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 light
        scene.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,
        ]        
        //构造geometry
        let 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);
        //准备material
        const material = new THREE.MeshBasicMaterial({
            side: THREE.DoubleSide,
            map: texture,
            transparent: true,
            opacity: 0.7,
        });
        //组成mesh
        const 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 light
        scene.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
        ]
        //构造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));

        //加载贴图
        const texture = new THREE.TextureLoader().load('number.png');
        texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
        texture.repeat.set(1, 1);
        //准备material
        const material = new THREE.MeshBasicMaterial({
            side: THREE.DoubleSide,
            map: texture,
            transparent: true,
            opacity: 0.7,
        });
        //组成mesh
        const mesh = new THREE.Mesh(geometry, material);
        scene.add(mesh);

        function animate() {
            requestAnimationFrame(animate);
            renderer.render(scene, camera);
        }
        animate();
    </script>
</body>

</html>

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

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

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【MySQL系列】Centos安装MySQL

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

电镀污水处理设备有哪些

电镀污水处理设备是用来处理电镀过程中产生的废水&#xff0c;并将废水中的有害物质去除&#xff0c;使其达到排放标准的设备。通常&#xff0c;电镀污水处理设备包括以下几种类型&#xff1a; 1. 预处理设备&#xff1a;预处理设备通常包括过滤器、物理方法和化学方法等。过滤…

智能优化算法应用:基于混合蛙跳算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于混合蛙跳算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于混合蛙跳算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.混合蛙跳算法4.实验参数设定5.算法结果6.…

Android集成科大讯飞语音识别与语音唤醒简易封装

目录 一、语音唤醒部分 1、首先在科大讯飞官网注册开发者账号 2、配置唤醒词然后下载sdk 3、选择对应功能下载 4、语音唤醒lib包全部复制到工程目录下 5、把语音唤醒词文件复制到工程的assets目录 6、复制对应权限到AndroidManifest.xml中 7、唤醒工具类封装 二、语音识…

Java第二十一章

网络程序设计基础 局域网与互联网 为了实现两台计算机的通信&#xff0c;必须用一个网络线路连接两台计算机。如下图所示 网络协议 1.IP协议 IP是Internet Protocol的简称&#xff0c;是一种网络协议。Internet 网络采用的协议是TCP/IP协议&#xff0c;其全称是Transmissio…

node.js express cors解决跨域

目录 什么是跨域 示例 postman请求 前端请求 cors中间件解决跨域 流程 配置cors参数 什么是跨域 跨域&#xff08;Cross-Origin&#xff09;是指在 Web 开发中&#xff0c;当一个网页的源&#xff08;Origin&#xff09;与另一个网页的源不同时&#xff0c;就发生了跨域…

【USRP】LFTX / LFRX

LFTX/LFRX 设备概述 LFTX 子板利用两个高速运算放大器来允许 0-30 MHz 的传输。该板仅接受实模式信号。LFTX 非常适合 HF 频段的应用&#xff0c;或使用外部前端来上变频和放大中间信号的应用。LFTX 的输出可以独立处理&#xff0c;也可以作为单个 I/Q 对进行处理。 主要特征…

Mac 如何删除文件及文件夹?可以尝试使用终端进行删除

MacOS 是 Mac 电脑采用的操作系统&#xff0c;你知道 Mac 如何删除文件吗&#xff1f;除了直接将文件或者文件夹拖入废纸篓之外&#xff0c;我们还可以采用终端命令的办法去删除文件&#xff0c;本文为大家总结了 Mac 删除文件方法。 为何使用命令行删除文件 在使用 Mac 电脑…

无人零售柜:快捷舒适购物体验

无人零售柜&#xff1a;快捷舒适购物体验 通过无人零售柜和人工智能技术&#xff0c;消费者在购物过程中可以自由选择商品&#xff0c;根据个人需求和喜好查询商品清单。这种自主选择的购物环境能够为消费者提供更加舒适和满意的体验。此外&#xff0c;无人零售柜还具有节约时间…

字符统计[c]

#include<stdio.h> #include<string.h> int main() {int a,b,c;abc0;char s[100];int i0;while(1){i;scanf("%c",&s[i]);if(s[i]?)break;}for(int k1;k<i;k){if(s[k]>48&&s[k]<57){a;//数字}else if((s[k]>65&&s[k]<…

我的 CSDN 三周年创作纪念日:2020-12-12

本人大叔一枚&#xff0c;自1992年接触电脑&#xff0c;持续了30年的业余电脑发烧爱好者&#xff0c;2022年CSDN博客之星Top58&#xff0c;阿里云社区“乘风者计划”专家博主。自某不知名财校毕业后进入国有大行工作至今&#xff0c;先后任职于某分行信息科技部、电子银行部、金…

12月11日作业

完善对话框&#xff0c;点击登录对话框&#xff0c;如果账号和密码匹配&#xff0c;则弹出信息对话框&#xff0c;给出提示”登录成功“&#xff0c;提供一个Ok按钮&#xff0c;用户点击Ok后&#xff0c;关闭登录界面&#xff0c;跳转到其他界面 如果账号和密码不匹配&#xf…

Vue 创建一个 Vue 应用

下载安装Node.js Node.Js中文网Node.jsNode.Js中文网 按步骤安装到你想安装的目录即可 安装完毕在控制台输入node 或者node -v测试 将Node.js下载路径改为国内镜像站 npm config set registryhttps://registry.npm.taobao.org/ 查看镜像 npm config get registry 创建项目 …

【C语言】【数据结构】自定义类型:结构体

引言 这是一篇对结构体的详细介绍&#xff0c;这篇文章对结构体声明、结构体的自引用、结构体的初始化、结构体的内存分布和对齐规则、库函数offsetof、以及进行内存对齐的原因、如何修改默认对齐数、结构体传参进行介绍和说明。 ✨ 猪巴戒&#xff1a;个人主页✨ 所属专栏&am…

雨云服务器快速搭建Cloudreve网盘网站并挂载雨云对象存储的教程

雨云服务器快速搭建Cloudreve网盘网站并挂载雨云对象存储的教程。本教程的Cloudreve安装就直接用雨云云服务器的预安装APP功能了&#xff0c;然后安装宝塔面板用于反代&#xff0c;如果不需要域名访问功能也可以直接IP端口来访问。 其他建站教程&#xff1a;https://blog.zeru…

C++——继承

目录&#xff1a; 继承的概念及定义 面向对象的三个基本特征&#xff1a;封装、继承、多态。在前面的讲解中封装已经用的很多了&#xff0c;那么接下来的两篇文章就来介绍一下继承和多态。 继承的概念 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段&am…

记录 | xftp远程连接两台windows

1、打开openssh 设置 -> 应用 -> 可选功能 -> 添加功能 -> OpenSSH 客户端&#xff0c;将 ssh 客户端安装将两台电脑的 ssh 开启&#xff0c;cmd 中输入 net start sshd2、配置 win10 账号密码 3、进行 xftp 连接

SSD在AI发展中的关键作用:从高速缓存到数据湖-1

随着人工智能技术的飞速发展&#xff0c;存储在其中发挥着至关重要的作用。特别是在AI训练过程中&#xff0c;存储SSD&#xff08;固态硬盘&#xff09;的高性能和可靠性对于提升训练效率和保证数据安全具有不可替代的作用。 存储SSD在AI发展中的作用和趋势&#xff0c;存储将…

自动化测试之读取配置文件

前言&#xff1a; 在日常自动化测试开发工作中&#xff0c;经常要使用配置文件&#xff0c;进行环境配置&#xff0c;或进行数据驱动等。我们常常把这些文件放置在 resources 目录下&#xff0c;然后通过 getResource、ClassLoader.getResource 和 getResourceAsStream() 等方法…

Spring框架学习:Bean生命周期

目录 SpringBean的生命周期 Bean实例属性填充 三级缓存 常用的Aware接口 Spring IoC容器实例化Bean总结 SpringBean的生命周期 Spring Bean的生命周期是从 Bean 实例化之后&#xff0c;即通过反射创建出对象之后&#xff0c;到Bean成为一个完整对象&#xff0c;最终存储到…