材质和纹理
相关API实践
材质
材质,又称为材料,是人类可以利用制作有用构件、器件或物品的物质。
纹理
是物质界面的性质,由地形(lay)、表面粗糙度(surface roughness)、起伏度(waviness)三个特征定义。
材质贴图,又称纹理贴图,在计算机图形学中是把存储在内存里的位图包裹到3D渲染物体的表面
。纹理贴图给物体提供了丰富的细节
,用简单的方式模拟出了复杂的外观。
加载
通过TextureLoader加载纹理图片
import img from './img.png';
const textureLoader = new TextureLoader();
const texture = textureLoader.load(img as string);
随后为材质指定纹理
const basicMaterial = new MeshBasicMaterial({
map: texture,
});
偏移
可以通过设置offset属性来改变纹理偏移,改变初始点位置即左下角
纹理图如下:
x轴方向偏移0.1,y轴方向偏移0.5
texture.offset.set(0.1, 0.5);
旋转
通过设置rotation属性来改变纹理的旋转角度,旋转中心点是左下角
texture.rotation = Math.PI / 4;
也可以通过center属性设置旋转中心点
texture.center.set(0.5, 0.5);
texture.rotation = Math.PI / 4;
重复
纹理改成如logo图
,重复时更明显。可以通过设置repeat属性改变水平、垂直方向上的重复次数
texture.repeat.set(3, 2);
但是并没有得到我们想要的效果,即水平方向重复3次、垂直方向重复2次
文档中提到
INFO
如果重复次数在任何方向上设置了超过1的数值, 对应的Wrap需要设置为THREE.RepeatWrapping
或者THREE.MirroredRepeatWrapping
来 达到想要的平铺效果。
包裹模式:
- RepeatWrapping,即简单重复到无穷大
- MirroredRepeatWrapping,镜像重复到无穷大
texture.wrapS = RepeatWrapping;
texture.wrapT = MirroredRepeatWrapping;
贴图采样
当展示区域的像素大小与纹理像素不匹配时,可以通过设置magFilter、minFilter来改变,
- magFilter:设置放大时的采样模式,默认值为LinearFilter,获取最接近的4个纹素并进行双线性插值
- minFilter:设置缩小时的采样模式,默认值为LinearMipmapLinearFilter,使用mipmapping和三次线性过滤
texture.magFilter = NearestFilter;
texture.minFilter = NearestFilter;
INFO
为了加快渲染速度和减少图像锯齿,将贴图处理处理成由一系列被预先计算和优化过的图片组成的文件,这样的贴图被称为 MIP map 或者 mipmap。
渲染面
设置side属性控制webgl渲染哪一面, 默认为THREE.FrontSide:
- THREE.FrontSide:只渲染前面
- THREE.BackSide:只渲染后面
- THREE.DoubleSide:渲染前面、后面
透明贴图
可以通过设置alphaMap属性来控制物体的透明度,主要要同时设置transparent
属性为true
alphaMap对应的图如下

在alphaMap图中对应的黑色为透明
,白色为不透明
import alphaMap from './alpha-map.png';
// 加载alpha map
const alphaTexture = textureLoader.load(alphaMap as string);
const basicMaterial = new MeshBasicMaterial({
map: texture,
alphaMap: alphaTexture,
transparent: true,
});
环境遮挡贴图
通过设置aoMap属性添加环境遮挡贴图,是物体看起来更像三维的。设置aoMap时,需要同时对物体设置第二组UV

// 设置aoMap
const basicMaterial = new MeshBasicMaterial({
map: map, // 加载纹理贴图
alphaMap: textureLoader.load(alpha as string), // 加载alpha map
aoMap: textureLoader.load(ambientOcclusion as string),
transparent: true,
// opacity: 0.3,
side: DoubleSide,
});
// 为物体添加第二组uv
geometry.setAttribute('uav2', new BufferAttribute(geometry.attributes.uv.array, 2));
渲染结果如下
可以看到渲染结果与color纹理
相比,颜色上有很大差异。texture和renderer的颜色空间不一致,则会导致严重的色差。

在之前的three版本中,加载后的texture的颜色空间模默认值为THREE.LinearEncoding
,renderer的颜色空间模默认值也为THREE.LinearEncoding
,因此在加载texture时无需显示指定即可正常渲染。
但是在最新的版本(0.160.0
)中,加载后的texture的颜色空间模默认值为THREE.NoColorSpace
,renderer的颜色空间为THREE.SRGBColorSpace
,两者不同则导致了严重的色差。
因此需要显式指定texture的colorSpace与renderer保持一致
texture.colorSpace = SRGBColorSpace;
参考: