第三部分-纹理与贴图——14. 纹理基础
14. 纹理基础
1. 概述
纹理(Texture)是将图像映射到 3D 物体表面的技术,用于增加物体的细节和真实感。Three.js 支持多种纹理类型和加载方式。
┌─────────────────────────────────────────────────────────────┐ │ 纹理体系 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ 纹理类型 │ │ ├── Texture:基础纹理 │ │ ├── CanvasTexture:Canvas 纹理 │ │ ├── VideoTexture:视频纹理 │ │ ├── CubeTexture:立方纹理 │ │ ├── DataTexture:数据纹理 │ │ └── CompressedTexture:压缩纹理 │ │ │ │ 纹理属性 │ │ ├── wrapS / wrapT:包裹模式 │ │ ├── magFilter / minFilter:过滤模式 │ │ ├── anisotropy:各向异性 │ │ └── encoding:颜色编码 │ │ │ └─────────────────────────────────────────────────────────────┘2. 纹理加载
2.1 TextureLoader
import*asTHREEfrom'three';// 创建加载器consttextureLoader=newTHREE.TextureLoader();// 加载纹理consttexture=textureLoader.load('texture.jpg');// 带回调的加载textureLoader.load('texture.jpg',(texture)=>{console.log('纹理加载成功',texture);},(progress)=>{console.log('加载进度',(progress.loaded/progress.total)*100+'%');},(error)=>{console.error('加载失败',error);});// 应用到材质constmaterial=newTHREE.MeshStandardMaterial({map:texture});2.2 纹理属性配置
consttexture=textureLoader.load('texture.jpg');// 包裹模式texture.wrapS=THREE.RepeatWrapping;// 水平方向重复texture.wrapT=THREE.RepeatWrapping;// 垂直方向重复// 重复次数texture.repeat.set(2,2);// 水平和垂直各重复2次// 偏移texture.offset.set(0.5,0.5);// 偏移纹理坐标// 旋转texture.rotation=Math.PI/4;// 旋转45度texture.center.set(0.5,0.5);// 旋转中心// 过滤模式texture.magFilter=THREE.LinearFilter;// 放大过滤texture.minFilter=THREE.LinearMipmapLinearFilter;// 缩小过滤// 各向异性(提高倾斜视角的清晰度)texture.anisotropy=16;// 最大16// 颜色空间texture.encoding=THREE.sRGBEncoding;// sRGB 编码// 生成 mipmaptexture.generateMipmaps=true;3. 包裹模式(Wrapping)
3.1 包裹模式类型
| 模式 | 说明 |
|---|---|
ClampToEdgeWrapping | 边缘拉伸(默认) |
RepeatWrapping | 重复平铺 |
MirroredRepeatWrapping | 镜像重复 |
// 重复平铺constrepeatTexture=textureLoader.load('pattern.jpg');repeatTexture.wrapS=THREE.RepeatWrapping;repeatTexture.wrapT=THREE.RepeatWrapping;repeatTexture.repeat.set(4,4);// 镜像重复constmirrorTexture=textureLoader.load('pattern.jpg');mirrorTexture.wrapS=THREE.MirroredRepeatWrapping;mirrorTexture.wrapT=THREE.MirroredRepeatWrapping;mirrorTexture.repeat.set(4,4);// 边缘拉伸(默认)constclampTexture=textureLoader.load('pattern.jpg');clampTexture.wrapS=THREE.ClampToEdgeWrapping;clampTexture.wrapT=THREE.ClampToEdgeWrapping;4. 过滤模式(Filtering)
4.1 过滤模式类型
放大过滤(magFilter):
| 模式 | 说明 |
|---|---|
LinearFilter | 线性插值(平滑) |
NearestFilter | 最近邻(像素化) |
缩小过滤(minFilter):
| 模式 | 说明 |
|---|---|
NearestFilter | 最近邻 |
LinearFilter | 线性插值 |
NearestMipmapNearestFilter | 最近邻 mipmap |
LinearMipmapNearestFilter | 线性 mipmap,最近邻 |
NearestMipmapLinearFilter | 最近邻 mipmap,线性 |
LinearMipmapLinearFilter | 线性 mipmap,线性插值(默认,质量最高) |
// 像素风纹理constpixelTexture=textureLoader.load('pixel.png');pixelTexture.magFilter=THREE.NearestFilter;pixelTexture.minFilter=THREE.NearestFilter;// 高质量纹理consthighQualityTexture=textureLoader.load('highres.jpg');highQualityTexture.magFilter=THREE.LinearFilter;highQualityTexture.minFilter=THREE.LinearMipmapLinearFilter;5. CanvasTexture
将 HTML Canvas 作为纹理。
// 创建 Canvasconstcanvas=document.createElement('canvas');canvas.width=512;canvas.height=512;constctx=canvas.getContext('2d');// 绘制内容ctx.fillStyle='#ff6600';ctx.fillRect(0,0,canvas.width,canvas.height);ctx.fillStyle='#ffffff';ctx.font='Bold 40px Arial';ctx.fillText('Three.js',canvas.width/2-100,canvas.height/2);// 创建纹理constcanvasTexture=newTHREE.CanvasTexture(canvas);// 动态更新纹理functionupdateCanvasTexture(){ctx.fillStyle=`hsl(${Date.now()%360}, 100%, 50%)`;ctx.fillRect(0,0,canvas.width,canvas.height);canvasTexture.needsUpdate=true;}constmaterial=newTHREE.MeshStandardMaterial({map:canvasTexture});6. VideoTexture
将视频作为纹理。
// 创建 video 元素constvideo=document.createElement('video');video.src='video.mp4';video.loop=true;video.muted=true;video.autoplay=true;video.play();// 创建视频纹理constvideoTexture=newTHREE.VideoTexture(video);videoTexture.minFilter=THREE.LinearFilter;videoTexture.magFilter=THREE.LinearFilter;constmaterial=newTHREE.MeshStandardMaterial({map:videoTexture});7. DataTexture
从原始数据创建纹理。
// 创建数据constwidth=512;constheight=512;constsize=width*height;constdata=newUint8Array(size*4);// RGBAfor(leti=0;i<size;i++){conststride=i*4;constvalue=Math.floor(Math.random()*256);data[stride]=value;// Rdata[stride+1]=value;// Gdata[stride+2]=value;// Bdata[stride+3]=255;// A}constdataTexture=newTHREE.DataTexture(data,width,height,THREE.RGBAFormat);dataTexture.needsUpdate=true;8. 纹理数组
consttextureLoader=newTHREE.TextureLoader();consttextures=[textureLoader.load('texture1.jpg'),textureLoader.load('texture2.jpg'),textureLoader.load('texture3.jpg')];// 切换纹理letcurrentTextureIndex=0;material.map=textures[currentTextureIndex];material.needsUpdate=true;9. 完整示例
import*asTHREEfrom'three';import{OrbitControls}from'three/examples/jsm/controls/OrbitControls.js';constscene=newTHREE.Scene();scene.background=newTHREE.Color(0x111122);constcamera=newTHREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,0.1,1000);camera.position.set(5,5,8);camera.lookAt(0,0,0);constrenderer=newTHREE.WebGLRenderer({antialias:true});renderer.setSize(window.innerWidth,window.innerHeight);document.body.appendChild(renderer.domElement);constcontrols=newOrbitControls(camera,renderer.domElement);controls.enableDamping=true;// 辅助对象constaxesHelper=newTHREE.AxesHelper(5);scene.add(axesHelper);constgridHelper=newTHREE.GridHelper(10,20);scene.add(gridHelper);// 光源constambientLight=newTHREE.AmbientLight(0x404040,0.5);scene.add(ambientLight);constdirectionalLight=newTHREE.DirectionalLight(0xffffff,1);directionalLight.position.set(5,10,7);scene.add(directionalLight);// 纹理加载器consttextureLoader=newTHREE.TextureLoader();// 创建棋盘格纹理(CanvasTexture)constcanvas=document.createElement('canvas');canvas.width=512;canvas.height=512;constctx=canvas.getContext('2d');constsize=64;for(leti=0;i<canvas.width;i+=size){for(letj=0;j<canvas.height;j+=size){ctx.fillStyle=((i+j)/size)%2===0?'#ff6600':'#ffffff';ctx.fillRect(i,j,size,size);}}constcheckerTexture=newTHREE.CanvasTexture(canvas);// 立方体constgeometry=newTHREE.BoxGeometry(2,2,2);constmaterial=newTHREE.MeshStandardMaterial({map:checkerTexture});constcube=newTHREE.Mesh(geometry,material);cube.castShadow=true;cube.receiveShadow=true;scene.add(cube);// 平面constplaneGeometry=newTHREE.PlaneGeometry(6,6);constplaneMaterial=newTHREE.MeshStandardMaterial({color:0x336699,side:THREE.DoubleSide});constplane=newTHREE.Mesh(planeGeometry,planeMaterial);plane.rotation.x=-Math.PI/2;plane.position.y=-1.5;plane.receiveShadow=true;scene.add(plane);// GUI 控制importGUIfrom'lil-gui';constgui=newGUI();// 纹理属性控制consttextureFolder=gui.addFolder('纹理属性');textureFolder.add(checkerTexture,'wrapS',{ClampToEdgeWrapping:THREE.ClampToEdgeWrapping,RepeatWrapping:THREE.RepeatWrapping,MirroredRepeatWrapping:THREE.MirroredRepeatWrapping}).name('水平包裹').onChange(()=>checkerTexture.needsUpdate=true);textureFolder.add(checkerTexture,'wrapT',{ClampToEdgeWrapping:THREE.ClampToEdgeWrapping,RepeatWrapping:THREE.RepeatWrapping,MirroredRepeatWrapping:THREE.MirroredRepeatWrapping}).name('垂直包裹').onChange(()=>checkerTexture.needsUpdate=true);textureFolder.add(checkerTexture.repeat,'x',0.1,4).name('水平重复').onChange(()=>checkerTexture.needsUpdate=true);textureFolder.add(checkerTexture.repeat,'y',0.1,4).name('垂直重复').onChange(()=>checkerTexture.needsUpdate=true);textureFolder.add(checkerTexture.offset,'x',-2,2).name('水平偏移').onChange(()=>checkerTexture.needsUpdate=true);textureFolder.add(checkerTexture.offset,'y',-2,2).name('垂直偏移').onChange(()=>checkerTexture.needsUpdate=true);textureFolder.add(checkerTexture,'rotation',0,Math.PI*2).name('旋转').onChange(()=>checkerTexture.needsUpdate=true);textureFolder.open();// 动画functionanimate(){requestAnimationFrame(animate);cube.rotation.x+=0.005;cube.rotation.y+=0.01;controls.update();renderer.render(scene,camera);}animate();window.addEventListener('resize',onWindowResize,false);functiononWindowResize(){camera.aspect=window.innerWidth/window.innerHeight;camera.updateProjectionMatrix();renderer.setSize(window.innerWidth,window.innerHeight);}10. 总结
| 纹理类型 | 创建方式 | 适用场景 |
|---|---|---|
| Texture | TextureLoader | 图片纹理 |
| CanvasTexture | Canvas 元素 | 动态纹理 |
| VideoTexture | Video 元素 | 视频纹理 |
| CubeTexture | 6张图片 | 环境贴图 |
| DataTexture | 原始数据 | 程序化纹理 |
| 纹理属性 | 说明 |
|---|---|
wrapS/wrapT | 包裹模式 |
repeat | 重复次数 |
offset | 偏移量 |
rotation | 旋转角度 |
magFilter/minFilter | 过滤模式 |
anisotropy | 各向异性 |
needsUpdate | 需要更新 |
