当前位置: 首页 > news >正文

第三部分-纹理与贴图——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. 总结

纹理类型创建方式适用场景
TextureTextureLoader图片纹理
CanvasTextureCanvas 元素动态纹理
VideoTextureVideo 元素视频纹理
CubeTexture6张图片环境贴图
DataTexture原始数据程序化纹理
纹理属性说明
wrapS/wrapT包裹模式
repeat重复次数
offset偏移量
rotation旋转角度
magFilter/minFilter过滤模式
anisotropy各向异性
needsUpdate需要更新

http://www.jsqmd.com/news/730801/

相关文章:

  • ts-prune vs knip:哪个更适合你的TypeScript项目?
  • 技术变革:Sunshine如何重新定义自托管游戏串流体验
  • Llama-3.2V-11B-cot实操手册:推理过程JSON日志结构与字段说明
  • Linux线程栈内存优化详解 机制风险调优与排障实践
  • CPPM和CPSM同时备考可行吗 - 众智商学院官方
  • 革命性视线交互解决方案:eyetracker如何实现无鼠标电脑控制?
  • 3步掌握OBS多平台直播:obs-multi-rtmp插件完全指南
  • 苹果新款iPhone或推“液态玻璃”全曲面屏,是旧方案轮回还是创新突破?
  • Seraphine:英雄联盟玩家的终极自动化助手使用指南
  • 3种快速解决TranslucentTB启动失败的终极指南:让Windows任务栏透明化工具完美运行
  • Linux服务器安全加固终极指南:10个关键步骤全面保护你的系统
  • 第二部分-光照与阴影——09. 光源类型
  • 存储字长是一个存储单元的位数还是一次读写从主存中提取的位数 刚学计组, 我看王道书和我问ai的答案不太一样,有些疑惑
  • TI LMR14030电源芯片选型避坑:开关频率设到2MHz,为什么我的板子一上36V就炸?
  • 从预测到干预:基于因果推断的决策引擎架构与实战
  • BBDown深度解析:高效下载B站视频的完整实战指南
  • 3分钟快速查询:如何通过手机号找到对应的QQ号码
  • LinkSwift网盘直链下载助手:八大主流网盘一站式解决方案终极指南
  • AMD Ryzen处理器深度调校终极指南:免费开源工具SMUDebugTool完整教程
  • 适合新人财经记者采访准备用的,市场营销会议干货指南
  • AudioSeal Pixel Studio部署案例:在线教育平台录播课防录屏盗用系统
  • 2026年3月食品输送带工厂推荐,食品输送带/输送带/pvc输送带/工业皮带,食品输送带公司有哪些 - 品牌推荐师
  • Go-Ethereum虚拟机性能优化终极指南:10个关键操作码深度解析
  • Redisson 分布式锁实现:可重入与看门狗
  • LangChain 开源了 Open SWE:Stripe、Ramp、Coinbase 内部都在造的编程 Agent
  • 三步轻松玩转《Degrees of Lewdity》中文汉化版:完整安装指南与技巧分享
  • ok-ww:鸣潮游戏自动化助手的技术实现与实战应用
  • Flux2-Klein-9B-True-V2文生图教程:摄影级提示词撰写与参数调优技巧
  • TwelveMonkeys ImageIO插件架构深度解析:Java图像处理的终极扩展方案
  • MouseTester终极指南:快速掌握鼠标性能测试的专业方法