Three.js 纹理贴图
1. 纹理贴图
在Three.js中,纹理贴图是一种将二维图像贴到三维物体表面的技术,以增强物体的视觉表现。纹理贴图可以使物体表面更加真实、细腻,为场景增色不少。
在Three.js中,纹理贴图的加载主要通过THREE.TextureLoader
类实现。下面是一个简单的加载纹理的示例:
const loader = new THREE.TextureLoader();
loader.load('path/to/your/texture.png', function(texture) {// 创建一个材质对象并设置纹理贴图const material = new THREE.MeshBasicMaterial({map: texture});// 创建一个物体并为其添加纹理贴图const geometry = new THREE.BoxGeometry(1, 1, 1);const cube = new THREE.Mesh(geometry, material);scene.add(cube);
});
2. 纹理过滤
纹理过滤是一种处理技术,用于决定当纹理图像被映射到比其原始分辨率大或小的像素时,如何从纹理中采样颜色。主要有三种类型的纹理过滤:线性过滤、最近邻过滤和mipmap过滤。
- 线性过滤(Linear Filtering) :这种过滤方法使用了纹理中最近的四个像素的加权平均值,以得到一个新的颜色值。这种方法产生的效果通常比较平滑,但在处理高对比度纹理时,可能会产生模糊的效果。
- 最近邻过滤(Nearest Filtering) :这种过滤方法简单地选择纹理中最近的一个像素的颜色。这种方法在处理像素艺术和其他需要保持锐利边缘的纹理时非常有用,但可能会导致锯齿状边缘。
- Mipmap过滤:这种过滤方法在加载纹理时,会创建纹理的多个缩小版本(称为mipmap),然后根据纹理在屏幕上的大小,选择合适大小的mipmap进行采样。这种方法可以在不同距离都保持纹理的良好表现,但会增加内存使用量。
在Three.js中,我们可以通过设置纹理的minFilter
和magFilter
属性来控制纹理过滤。
minFilter
属性控制当纹理被缩小时使用的过滤方法,magFilter
属性控制当纹理被放大时使用的过滤方法。这两个属性的默认值都是THREE.LinearMipmapLinearFilter
,即使用mipmap过滤。
以下是一个简单的示例,展示了如何在Three.js中设置纹理过滤:
var loader = new THREE.TextureLoader();
// 加载纹理
loader.load('textures/yourTexture.png', function(texture) {// 设置纹理过滤texture.minFilter = THREE.NearestFilter;texture.magFilter = THREE.LinearFilter;
// 创建材质var material = new THREE.MeshBasicMaterial({map: texture});
// 创建网格var mesh = new THREE.Mesh(geometry, material);
// 将网格添加到场景scene.add(mesh);
});
在这个例子中,我们首先加载了纹理,然后设置minFilter
属性为THREE.NearestFilter
,magFilter
属性为THREE.LinearFilter
。这表示当纹理被缩小时,我们使用最近邻过滤,当纹理被放大时,我们使用线性过滤。
3. UV映射原理
在三维图形中,UV坐标是用于将二维纹理映射到三维模型上的。这个名字中的"U"和"V"代表的是纹理坐标的两个维度,它们与三维空间的"X"、"Y"和"Z"坐标是独立的。
在UV映射中,"U"对应于纹理的水平(宽度)方向,"V"对应于纹理的垂直(高度)方向。UV坐标的范围通常是从0到1,其中(0,0)表示纹理的左下角,(1,1)表示纹理的右上角。
几何体有两组UV坐标,第一组组用于.map
、.normalMap
、.specularMap
等贴图的映射,第二组用于阴影贴图.lightMap
的映射
3.1 纹理UV坐标
在Three.js中,UV坐标是通过THREE.Geometry
或THREE.BufferGeometry
对象的.uv
属性来定义的。每个面(或者是三角形)都有自己的UV坐标集合,这些集合是一个包含两个元素(U和V)的THREE.Vector2
对象的数组。
以下是一个简单的示例,展示了如何在Three.js中定义UV坐标:
var geometry = new THREE.Geometry();
// 创建顶点
var v1 = new THREE.Vector3(0,0,0);
var v2 = new THREE.Vector3(1,0,0);
var v3 = new THREE.Vector3(0,1,0);
var v4 = new THREE.Vector3(1,1,0);
geometry.vertices.push(v1);
geometry.vertices.push(v2);
geometry.vertices.push(v3);
geometry.vertices.push(v4);
// 创建面
var face1 = new THREE.Face3(0, 1, 2);
var face2 = new THREE.Face3(1, 2, 3);
// 创建UV坐标
var uv1 = new THREE.Vector2(0, 0);
var uv2 = new THREE.Vector2(1, 0);
var uv3 = new THREE.Vector2(0, 1);
var uv4 = new THREE.Vector2(1, 1);
// 将UV坐标添加到每个面
geometry.faces.push(face1);
geometry.faceVertexUvs[0].push([uv1, uv2, uv3]);
geometry.faces.push(face2);
geometry.faceVertexUvs[0].push([uv2, uv3, uv4]);
在这个例子中,我们首先创建了一个新的THREE.Geometry
对象,然后添加了四个顶点和两个面。然后,我们定义了每个面的UV坐标,并将它们添加到geometry.faceVertexUvs[0]
数组。
3.2 纹理映射
现在我们有了几何体和UV坐标,下一步就是创建和加载纹理。在Three.js中,我们可以使用THREE.TextureLoader
来加载纹理图片。以下是一个简单的例子:
var loader = new THREE.TextureLoader();
// 加载纹理
loader.load('textures/yourTexture.png', function(texture) {// 创建材质var material = new THREE.MeshBasicMaterial({map: texture});
// 创建网格var mesh = new THREE.Mesh(geometry, material);
// 将网格添加到场景scene.add(mesh);
});
在上述代码中,我们首先创建一个新的THREE.TextureLoader
实例,然后调用它的.load()
方法来加载纹理。加载完成后,我们创建了一个新的THREE.MeshBasicMaterial
对象,并将加载的纹理作为地图属性传递给它。然后,我们使用几何体和材质创建了一个新的THREE.Mesh
对象,并将它添加到场景中。
为了更好地控制纹理贴图的映射,可以通过以下方法:
- 改变纹理的偏移量:
texture.offset = new THREE.Vector2(x, y);
- 改变纹理的缩放比例:
texture.repeat = new THREE.Vector2(x, y);
4. 纹理阵列,偏移和旋转
4.1 纹理阵列
在某些情况下,你可能希望在物体表面上重复使用一张纹理。比如,当你创建一片草地或墙壁时,你可能需要在模型上多次平铺相同的纹理。这就是纹理阵列的作用。
在Three.js中,我们可以通过设置纹理的repeat
属性来实现纹理阵列。repeat
属性是一个THREE.Vector2
对象,表示纹理在U和V方向上的重复次数。默认情况下,这个值是(1, 1),表示纹理只在每个方向上显示一次。
以下是一个简单的示例,展示了如何在Three.js中创建纹理阵列:
var loader = new THREE.TextureLoader();
// 加载纹理
loader.load('textures/yourTexture.png', function(texture) {// 设置纹理阵列texture.wrapS = texture.wrapT = THREE.RepeatWrapping;texture.repeat.set(4, 4);
// 创建材质var material = new THREE.MeshBasicMaterial({map: texture});
// 创建网格var mesh = new THREE.Mesh(geometry, material);
// 将网格添加到场景scene.add(mesh);
});
在这个例子中,我们首先加载了纹理,然后设置了wrapS
和wrapT
属性为THREE.RepeatWrapping
,表示我们希望纹理在两个方向上都能重复。接着,我们使用texture.repeat.set(4, 4)
来设置纹理在U和V方向上重复4次
4.2 纹理偏移
如前所述,纹理偏移可以通过调整纹理的offset
属性来实现。offset
属性是一个THREE.Vector2
对象,表示纹理在U和V方向上的偏移量。默认情况下,这个值是(0, 0),表示没有偏移。
以下是一个简单的示例,展示了如何在Three.js中设置纹理偏移:
texture.offset.set(0.5, 0.5);
在这个例子中,我们将纹理的偏移设置为(0.5, 0.5),表示纹理在U和V方向上都向正方向偏移了一半的距离。
4.3 纹理旋转
Three.js中的纹理旋转可以通过修改纹理的rotation
属性来实现。
rotation
属性是一个以弧度为单位的角度值,用于指定纹理的旋转角度。默认情况下,这个值是0,表示没有旋转。
以下是一个简单的示例,展示了如何在Three.js中设置纹理旋转:
// 旋转纹理90度
texture.rotation = Math.PI / 2;
在这个例子中,我们将纹理的旋转角度设置为Math.PI / 2
,即90度。需要注意的是,纹理旋转是以纹理的中心点为轴进行的。
5. UV动画
在Three.js中,我们可以通过修改纹理的offset
属性来改变纹理的UV坐标。offset
属性是一个THREE.Vector2
对象,代表了纹理在U和V方向上的偏移量。我们可以在每一帧中稍微改变这个值,来实现纹理的移动效果。
下面是一个简单的示例,展示了如何在Three.js中创建一个UV动画:
// 加载纹理
var loader = new THREE.TextureLoader();
var texture = loader.load('textures/yourTexture.png');
// 创建材质
var material = new THREE.MeshBasicMaterial({map: texture});
// 创建网格
var mesh = new THREE.Mesh(geometry, material);
// 将网格添加到场景
scene.add(mesh);
// 在渲染循环中更新纹理偏移
function animate() {requestAnimationFrame(animate);
// 每一帧稍微移动纹理material.map.offset.y -= 0.01;
// 渲染场景renderer.render(scene, camera);
}
animate();
在这个例子中,我们首先加载了纹理,然后创建了一个包含该纹理的材质和一个使用该材质的网格。然后,在我们的渲染循环中,我们每一帧都稍微改变纹理的offset.y
值,从而使纹理在V方向上移动,产生动态效果。
相关文章:

Three.js 纹理贴图
1. 纹理贴图 在Three.js中,纹理贴图是一种将二维图像贴到三维物体表面的技术,以增强物体的视觉表现。纹理贴图可以使物体表面更加真实、细腻,为场景增色不少。 在Three.js中,纹理贴图的加载主要通过THREE.TextureLoader类实现。…...

2024年软件设计师中级(软考中级)详细笔记【12】软件系统分析与设计
目录 前言第12章 软件系统分析与设计12.2 数据库分析与设计12.2.1 数据库设计的策略与步骤12.2.2 需求分析12.2.3 概念结构设计12.2.4 逻辑结构设计12.2.5 数据库的物理设计 结语 前言 在备考软件设计师中级考试的过程中,我遇到了些许挑战,也收获了宝贵…...

【Windows】CMD命令学习——系统命令
CMD(命令提示符)是Windows操作系统中的一个命令行解释器,允许用户通过输入命令来执行各种系统操作。 系统命令 systeminfo - 显示计算机的详细配置信息。 tasklist - 显示当前正在运行的进程列表。 taskkill - 终止正在运行的进程。例如&am…...

React第一个项目
运行效果: 知识讲解: 组件:先定义后使用,用户界面的构成要素(标签、css和JavaScript) 定义组件: 导出组件:export default 前缀是JavaScript标准语法 定义函数:function …...

计算机网络基本概念总结
IP地址 概念 使网络中的设备都有唯一的地址标识,用于表示其在网络中的位置。 格式 IP地址是一个32位的二进制数,通常被分割为4个8位二进制数(也就是4个字节),如:01100100.00001000.00001010.00000110。通常…...

考研要求掌握C语言(归并排序)
归并排序考啥? 在考研中归并排序只出在选择题,理解原理很重要 且在考研中考两两归并,还是比较简单的 归并排序原理 就是每次分一半,直到每一半只含有一个或不能再分时,一半一半的进行排序,最终合并两个…...

Spring Authorization Server:实现OAuth2认证服务
Spring Authorization Server为构建安全的SpringBoot应用提供了一系列解决方案,本节课程我们将结合OAuth2来实现认证服务,该认证服务将支持常用的OAuth2授权模式和刷新Token。 Spring Authorization Server简介 Spring Authorization Server是一个安全框架,它提供了OAuth 2.…...

Rocky、Almalinux、CentOS、Ubuntu和Debian系统初始化脚本v9版
Rocky、Almalinux、CentOS、Ubuntu和Debian系统初始化脚本 Shell脚本源码地址: Gitee:https://gitee.com/raymond9/shell Github:https://github.com/raymond999999/shell脚本可以去上面的Gitee或Github代码仓库拉取。 支持的功能和系统&am…...

ScrumMaster认证机构及CSM、PSM、RSM价值解析
近十年Scrum在国内备受关注,成为一种最流行的现代敏捷工作方式。ScrumMaster这一独特的角色,在企业内部推动Scrum落地的过程中越来越重要。各种ScrumMaster认证课程也蜂拥而至,甚至鱼目混珠。 我们为大家梳理了目前市面上出现的ScrumMaster认…...

借助 Pause 容器调试 Pod
借助 Pause 容器调试 Pod 在 K8S 中,Pod 是最核心、最基础的资源对象,也是 Kubernetes 中调度最小单元。在介绍 Pause 容器之前需要先说明下 Pod 与容器的关系来理解为什么需要 Pause 容器来帮助调试 1. Pod 与 容器的关系 Pod 是一个抽象的逻辑概念&…...
PostgreSQL 开启密码验证插件
我们知道在数据安全和等保要求中,用户的密码复杂度需要满足一定的条件,那么在 PostgreSQL 数据库中如何保证创建的用户的密码满足这些要求呢。 [rootlocalhost ~]# su - postgres [postgreslocalhost ~]$ cd /usr/local/pgsql-12.8/data/ [postgresloca…...

Go 语言已立足主流,编程语言排行榜24 年 11 月
Go语言概述 Go语言,简称Golang,是由Google的Robert Griesemer、Rob Pike和Ken Thompson在2007年设计,并于2009年11月正式宣布推出的静态类型、编译型开源编程语言。Go语言以其提高编程效率、软件构建速度和运行时性能的设计目标,…...
flutter下拉刷新上拉加载的简单实现方式三
使用 CustomScrollView 结合 SliverList 实现了一个支持下拉刷新和上拉加载更多功能的滚动列表,对下面代码进行解析学习。 import dart:math;import package:flutter/material.dart;import custom_pull/gsy_refresh_sliver.dart; import package:flutter/cupertino…...
【C++ 20进阶(2):属性 Attribute】
【C 20进阶(2):属性 Attribute】 原文:https://blog.csdn.net/weixin_44259356/article/details/143663492 引言 本篇文章为系列文章将着重介绍C20新特性,一是希望可以和大家交流分享,二是也便于自己巩固…...

【系统面试篇】其他相关题目——虚拟内存、局部性原理、分页、分块、页面置换算法
目录 一、相关问题 1. 什么是虚拟内存?为什么需要虚拟内存? (1)内存扩展 (2)内存隔离 (3)物理内存管理 (4)页面交换 (5)内存映…...

力扣617:合并二叉树
给你两棵二叉树: root1 和 root2 。 想象一下,当你将其中一棵覆盖到另一棵之上时,两棵树上的一些节点将会重叠(而另一些不会)。你需要将这两棵树合并成一棵新二叉树。合并的规则是:如果两个节点重叠&#…...
软件设计师 - 第1章 计算机网络概论
计算机系统硬件基本组成 输入设备:键盘,鼠标输出设备:显示器,打印机...存储器:主存储器,如内存;辅助存储器,如外存运算器:与控制器一同集成在CPU中控制器:与…...

方案丨车险保单OCR:3秒钟完成保单审核
在涉及车辆交易的各种情况下,记录和管理车险保单信息是一项必不可少的任务。然而,面对数量庞大的电子保单,传统的手工录入方式显得尤为低效——它不仅消耗大量时间,而且容易出现错误,这不仅影响了用户的满意度…...

Jmeter中的监听器(一)
监听器 1--查看结果树 用途 调试测试计划:查看每个请求的详细信息,帮助调试和修正测试计划。分析响应数据:查看服务器返回的响应数据,验证请求是否成功。检查错误:识别和分析请求失败的原因。 配置步骤 添加查看结果…...
C++ 标准库 std::vector 的介绍
std::vector 是 C 标准库中的一个动态数组容器,它提供了多种成员函数来管理其内部存储的元素。以下是一些常用的 std::vector 成员函数的介绍: 构造函数和析构函数 vector(): 默认构造函数。vector(size_type n): 构造一个包含 n 个元素的向量…...
关于近期中国移动民用家庭网络,新增的UDP网络限制。
在近期中国移动在全国一定范围普及新的打击 “PCDN、P2P、HY/HY2” 等流氓网络应用的技术方案,并接入在 “省/州” 的边界网关路由上。 根据遥测数据的具体研究分析,且本人曾非常生气的详细质询过,移动城域网管理人员,可以确认该技…...

C++数据结构 : 哈希表的实现
C数据结构 : 哈希表的实现 目录 C数据结构 : 哈希表的实现引言1. 哈希概念1.1 直接定址法1.2 哈希冲突1.3 负载因子 2. 哈希函数2.1 除法散列法/除留余数法2.2 乘法散列法(了解)2.3 全域散列法(了解) 3. 处…...

Cypress + React + TypeScript
🧪 Cypress + React + TypeScript 组件测试全流程实战:从入门到自动化集成 在现代前端开发中,组件测试 是保障 UI 行为可靠性的重要手段。本文将通过一个 React 项目示例,实战演示如何结合 Cypress + React + TypeScript 实现从零配置到自动化集成的完整测试链路。 一、项…...
LeetCode - 203. 移除链表元素
目录 题目 解题思路 读者可能出现的错误写法 正确的写法 题目 203. 移除链表元素 - 力扣(LeetCode) 解题思路 使用哨兵节点: 创建一个哨兵节点(dummy),将其next指向原链表头节点 哨兵节点的作用是统一处理所有情况&#x…...
汽车高速通信的EMC挑战
随着“软件定义汽车”的理念全面渗透,中国汽车行业正加速向集中式电子电气架构(E/E架构)转型。SOA(面向服务的架构)理念推动下,整车开始围绕中央计算平台(OIB)与分布式域控制器(VIU)构建,硬件平台具备前所未有的数据处理能力,能掌控整车控制与实时感知决策。 一、…...

CPO-BP+MOPSO,冠豪猪优化BP神经网络+多目标粒子群算法!(Matlab源码)
目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.CPO-BPNSGA,冠豪猪优化BP神经网络粒子群算法!(Matlab完整源码和数据),冠豪猪算法优化BP神经网络的权值和阈值,运行环境Matlab2020b及以上。 多…...
Java集合操作常见错误与最佳实践
错误69:搜索无关类型的对象 泛型方法的类型安全漏洞 在Java引入参数化类型前,集合元素只能声明为Object类型,导致可以随意将字符串添加到数值列表中。虽然泛型机制对添加元素的方法进行了类型约束,但搜索和删除相关方法仍保留了Object类型的参数设计。这包括以下关键方法…...

day023-网络基础与OSI七层模型
文章目录 1. 网络基础知识点1.1 网络中的单位1.2 查看实时网速:iftop1.3 交换机、路由器 2. 路由表2.1 查看路由表的命令2.2 路由追踪命令 3. 通用网站网络架构4. 局域网上网原理-NAT5. 虚拟机上网原理6. 虚拟机的网络模式6.1 NAT模式6.2 桥接模式6.3 仅主机模式 7.…...

大数据-273 Spark MLib - 基础介绍 机器学习算法 决策树 分类原则 分类原理 基尼系数 熵
点一下关注吧!!!非常感谢!!持续更新!!! 大模型篇章已经开始! 目前已经更新到了第 22 篇:大语言模型 22 - MCP 自动操作 FigmaCursor 自动设计原型 Java篇开…...
关于Web安全:7. WebShell 管理与持久化后门
一、菜刀马 菜刀马(ChinaZ WebShell) 是一种与“中国菜刀(ChinaZ)”客户端配合使用的 WebShell 木马,广泛应用于 Web 渗透测试中,主要使用 PHP/ASP/JSP 等语言编写。 它的本质是一个一句话木马࿰…...