纹理映射
此笔记记录于DISCOVER three.js,大多数为其中的摘要,少数为笔者自己的理解
基本知识
用最简单的术语来说,纹理映射意味着拿着图像并将其拉伸到 3D 对象的表面上。我们将以这种方式使用的图像称为纹理,我们可以使用纹理来表示颜色、粗糙度和不透明度等材料属性。例如,要更改几何区域的颜色,我们更改位于顶部的纹理区域的颜色,就像您在上图中看到的附加到面部模型的颜色纹理一样。
虽然获取 2D 纹理并将其拉伸到像立方体这样的规则形状上很容易,但对于像脸这样的不规则几何形状则要做到这一点要困难得多,而且多年来,已经开发了许多纹理映射技术。也许最简单的技术是 投影映射,它将纹理投影到一个对象(或场景)上,就好像它已经通过电影放映机照射了一样。想象一下,将您的手放在电影放映机前,并看到投影到您皮肤上的图像。
虽然投影映射和其他技术仍然广泛用于创建阴影(或模拟投影仪)等事情,但这不适用于将面部的颜色纹理附加到面部几何体。相反,我们使用一种称为 UV 映射的技术,它允许我们在几何体上的点和脸上的点之间创建连接。
表示 UV 映射的数据存储在几何体上。像BoxBufferGeometry
这样的 three.js 几何体已经设置了 UV 映射,并且在大多数情况下,当您加载在外部程序中创建的面部模型时,它也有已准备好的 UV 映射供使用。
纹理类型
uv-test-bw.png 是一个以 PNG 格式存储的普通 2D 图像文件,我们将使用TextureLoader
加载它,这将返回 Texture
类的一个实例。您可以以相同的方式使用浏览器支持的任何图像格式,例如 PNG、JPG、GIF、BMP。这是我们将遇到的最常见和最简单的纹理类型:存储在简单 2D 图像文件中的数据。
还有一些专用图像格式的加载器,如 HDR、EXR 和 TGA,它们具有相应的加载器,如 TGALoader
。同样,一旦加载,我们将获得一个Texture
实例,我们可以以与加载的 PNG 或 JPG 图像大致相同的方式使用它。
除此之外,three.js 还支持许多其他类型的非简单 2D 图像的纹理,例如 视频纹理、 3D 纹理、 画布纹理、 压缩纹理、 立方体纹理、 矩形纹理等等。
上图中,纹理的左上角已经映射到立方体角上的一个顶点坐标(−1,1,1):
(0,1)⟶(−1,1,1)
对立方体的其他五个面进行了类似的映射,从而在立方体的六个面上分别生成一个完整的纹理副本:
cube.js
import {
BoxBufferGeometry,
MathUtils,
Mesh,
MeshStandardMaterial,
TextureLoader,
} from 'three';
function createMaterial() {
// create a texture loader.
const textureLoader = new TextureLoader();
// load a texture
const texture = textureLoader.load(
'/assets/textures/uv-test-bw.png',
);
// create a "standard" material using
// the texture we just loaded as a color map
const material = new MeshStandardMaterial({
map: texture,
});
return material;
}
function createCube() {
const geometry = new BoxBufferGeometry(2, 2, 2);
const material = createMaterial();
const cube = new Mesh(geometry, material);
cube.rotation.set(-0.5, -0.1, 0.8);
const radiansPerSecond = MathUtils.degToRad(30);
cube.tick = (delta) => {
// increase the cube's rotation each frame
cube.rotation.z += delta * radiansPerSecond;
cube.rotation.x += delta * radiansPerSecond;
cube.rotation.y += delta * radiansPerSecond;
};
return cube;
}
export { createCube };