目录
Three.js入门
Three.js光源
Three.js阴影
Three.js纹理贴图
纹理是一种图像或图像数据,用于为物体的材质提供颜色、纹理、法线、位移等信息,从而实现更加逼真的渲染结果。
纹理可以应用于Three.js
中的材质类型,如MeshBasicMaterial
、MeshLambertMaterial
、MeshPhongMaterial
、MeshStandardMaterial
等。
UV映射
UV映射是2D图像投影到3D模型的表面以进行纹理映射的3D建模过程(也即把位图贴到3D几何形状的过程或者方法)。在这个过程中,3D模型上的每个顶点都会被赋予一个二维坐标(U, V)。
由于X,Y,Z已经表示模型空间中的3D图形的轴了。所以用U和V分别表示纹理坐标的水平和垂直方向。
顶点UV坐标可以在0~1.0之间任意取值,纹理贴图左下角对应的UV坐标是(0,0)
,右上角对应的坐标(1,1)
。
UV映射公式如下:
(u,v) -> (x,y,z)
(u,v)
代表纹理上的坐标,(x,y,z)
代表几何图形上的点(向量)。
以立方缓冲几何体的一个面为例:
贴图的左下角
(0,0)
映射到几何体的(-1,-1,1)
;贴图的左下角
(1,0)
映射到几何体的(1,-1,1)
;贴图的左下角
(0,1)
映射到几何体的(-1,1,1)
;贴图的左下角
(1,1)
映射到几何体的(1,1,1)
;
three.js的所有内置的几何体都内置了UV映射,所以开发者不需要担心这个问题。
纹理的使用方法
加载纹理
// 1.const textureLoader = new THREE.TextureLoader();// 2.const texture = textureLoader.load(uv);const boxGeometry = new THREE.BoxGeometry(2, 2, 2);const boxMaterial = new THREE.MeshStandardMaterial({color: 0xffffff,map: texture, // 2.重点位置});const boxMesh = new THREE.Mesh(boxGeometry, boxMaterial);scene.add(boxMesh);
使用TextureLoader
进行加载纹理;加载图像并在纹理准备就绪后更新纹理,然后设置给MeshStandardMaterial的map
。
纹理变换
repeat
我们可以使用repeat
属性对纹理进行重复显示,repeat
是一个Vector2
实例,所以可以指定x
和y
属性。
texture.repeat.x = 2;texture.repeat.y = 2;
默认情况下纹理不会重复(
THREE.ClampToEdgeWrapping
),最后一个像素被拉伸了,我们需要设置 wrapS 和 wrapT可重复。
texture.wrapS = THREE.RepeatWrappingtexture.wrapT = THREE.RepeatWrapping
wrapS
和wrapT
上面重复的纹理方向是相同的,可以设置为镜像方向。
texture.wrapS = THREE.MirroredRepeatWrappingtexture.wrapT = THREE.MirroredRepeatWrapping`
offset
我们可以使用offset
属性对纹理进行重复偏移,repeat
是一个Vector2
实例,所以可以指定x
和y
属性。
texture.offset.x = 0.1;texture.offset.y = 0.1;texture.wrapS = THREE.RepeatWrapping;texture.wrapT = THREE.RepeatWrapping;
如果不设置
THREE.RepeatWrapping
重复,则会出现纹理空白区域。
rotation
texture.rotation = Math.PI / 4;
旋转是弧度,逆时针方向旋转。旋转的点默认是(0,0)这个点
center
如果要按照纹理的中心进行旋转,需要修改center
。
texture.center = new THREE.Vector2(0.5, 0.5);
minFilter
和magFilter
可以使用minFilter
属性来设置纹理图的minification
缩小过滤器,使用magFilter
属性来设置纹理图的minification
放大过滤器。
当纹理的像素小于渲染像素时,我们需要将纹理放大;当纹理的像素大于渲染像素时,我们需要将纹理缩小
以放大过滤器为例:
Nearest
就是找最近的一个像素点的颜色;Linear
就是根据附近的四个像素点的平均颜色值️;
纹理类型
纹理有很多种类型,接下来我们就来介绍这些不同的纹理。
如果只是测试效果,可以在一些免费的纹理图片网站上去下载。譬如 www.3dtextures.me 等。
本文使用的纹理图片如下:
颜色纹理
颜色纹理只会将纹理的像素应用在几何体上。它等同于直接在material
上设置color
属性,但是color
属性只能设置一种颜色,而颜色纹理可以为每一个位置设置颜色。
const textureLoader = new THREE.TextureLoader();const colorTexture = textureLoader.load('path/to/color_texture.jpg');const material = new THREE.MeshBasicMaterial({map: colorTexture // 增加颜色纹理});
法线纹理
法线纹理它不会移动顶点,但是它会让光线认为面的朝向不同。所以看起来会有凹凸立体感。
const normalTexture = textureLoader.load('./images/door/normal.jpg');const planeMaterial = new THREE.MeshStandardMaterial({map: texture,normalMap: normalTexture, // 增加法线纹理});
立体视觉效果还是比较明显的
位移纹理
位移纹理是灰度图像,它将移动顶点以创造一些高度。使用高度纹理,你要添加更多的细分网格才能看到效果。
const displacementTexture = textureLoader.load("./images/door/height.jpg");const planeGeometry = new THREE.PlaneGeometry(3, 3, 16, 16); // 增加网格const planeMaterial = new THREE.MeshStandardMaterial({map: texture,normalMap: normalTexture,displacementMap: displacementTexture,// 增加高度纹理});
可以通过
displacementScale
控制位移的距离。
金属纹理
金属纹理(metalness texture)是灰度图像,将指定哪个部分是金属(白色)和非金属(黑色)。此信息将有助于创造反射,给 material 增加金属质感。
const metalTexture = textureLoader.load("./images/door/metalness.jpg");const planeMaterial = new THREE.MeshStandardMaterial({map: texture,normalMap: normalTexture,metalnessMap: metalTexture, // 增加金属纹理});
增加金属感,是否有感觉?我没看出来。
粗糙度纹理
粗糙度(rougness texture)经常和金属度纹理一起使用,它也是灰度图,它将指定哪个部分是粗糙的(白色),哪一部分是光滑的(黑色)。
const roughTexture = textureLoader.load("./images/door/roughness.jpg");const planeMaterial = new THREE.MeshStandardMaterial({map: texture,normalMap: normalTexture,metalnessMap: metalTexture, roughnessMap: roughTexture, // 增加粗糙度纹理});
这个例子看不出效果,就不截图了。
环境光遮蔽纹理
环境遮挡纹理(ambient occlusion texture)是灰度图像,它将在表面缝隙中添加假的阴影。虽然它在物理上不准确,但它有助于创建对比度。
const aoTexture = textureLoader.load("./images/door/ambientOcclusion.jpg");const planeMaterial = new THREE.MeshStandardMaterial({map: texture,normalMap: normalTexture,metalnessMap: metalTexture, roughnessMap: roughTexture, aoMap: aoTexture, // 增加环境光遮蔽纹理});
环境纹理
环境纹理来模拟物体周围的环境光照和反射。环境纹理通常用于创建反射镜面效果或提供全局光照。
const sphere = new THREE.Mesh(new THREE.SphereGeometry(2, 50, 50),new THREE.MeshPhysicalMaterial({roughness: 0,metalness: 0,color: 0xffea00,envMap: texture, // 设置环境纹理transmission: 1,ior: 2.3,}));
看看这个玻璃球上的效果
重要参考资料:
three.js - Textures & Texture Mapping
Three.js Texture Mapping Tutorial
Texture