Three.js 纹理贴图

embedded/2024/11/19 0:18:05/

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中,我们可以通过设置纹理的minFiltermagFilter属性来控制纹理过滤。

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.NearestFiltermagFilter属性为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.GeometryTHREE.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);
});

在这个例子中,我们首先加载了纹理,然后设置了wrapSwrapT属性为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方向上移动,产生动态效果。


http://www.ppmy.cn/embedded/138655.html

相关文章

贪心算法入门(三)

相关文章 贪心算法入门(一)-CSDN博客 贪心算法入门(二)-CSDN博客 1.什么是贪心算法? 贪心算法是一种解决问题的策略,它将复杂的问题分解为若干个步骤,并在每一步都选择当前最优的解决方案&am…

操作系统启动实验

简单的操作系统 汇编代码 ; hello-os ; TAB4ORG 0x7c00 ; 指明程序装载地址; 标准FAT12格式软盘专用的代码 Stand FAT12 format floppy codeJMP entryDB 0x90DB "HELLOIPL" ; 启动扇区名称(8字节)DW 512 ; 每个扇区(s…

机器学习基础02

目录 1.特征工程 1.1特征工程概念 1.2特征工程的步骤 1.3特征工程-特征提取 1.3.1字典列表(json)特征提取 1.3.2文本特征提取 英文文本提取 中文文本提取 1.3.3TF-IDF文本特征词的稀有程度特征提取 2.无量纲化 2.1归一化 2.2标准化 2.3fit、fit_transform、transfo…

@ComponentScan:Spring Boot中的自动装配大师

文章目录 1. 什么是ComponentScan注解?2. 为什么需要ComponentScan注解?3. 如何使用ComponentScan注解?4. ComponentScan注解的高级用法5. 注意事项6. 结语推荐阅读文章 在Spring Boot的世界里,自动装配(Auto-wiring&a…

git分支合并到远程后如何回滚合并

在GitLab中删除远程仓库的某个特定commit并不是一个直接的操作,因为Git版本控制系统的设计是为了保持历史记录的完整性和不可变性。然而,你可以通过以下步骤来实现删除某个特定的commit: 回退到目标commit之前的状态: 首先&#x…

探秘Spring Boot中的@Conditional注解

文章目录 1. 什么是Conditional注解?2. 为什么需要Conditional注解?3. 如何使用Conditional注解?4. Conditional注解的高级用法5. 注意事项6. 结语推荐阅读文章 在Spring Boot的世界里,配置的灵活性和多样性是至关重要的。有时候&…

【SQL】mysql常用命令

为方便查询,特整理MySQL常用命令。 约定:$后为Shell环境命令,>后为MySQL命令。 1 常用命令 第一步,连接数据库。 $ mysql -u root -p # 进入MySQL bin目录后执行,回车后输入密码连接。# 常用参数&…

前端无感刷新token

摘要: Axios 无感知刷新令牌是一种在前端应用中实现自动刷新访问令牌(access token)的技术,确保用户在进行 API 请求时不会因为令牌过期而中断操作 目录概览 XMLHttpRequestAxiosFetch APIJQuni.request注意事项: 访问…