第三部分-纹理与贴图——16. 高级纹理技术
16. 高级纹理技术1. 概述高级纹理技术包括压缩纹理、Mipmap、纹理数组、渲染到纹理等用于优化性能和实现复杂视觉效果。┌─────────────────────────────────────────────────────────────┐ │ 高级纹理技术体系 │ ├─────────────────────────────────────────────────────────────┤ │ │ │ 纹理压缩 │ │ ├── BasisTexture通用压缩格式 │ │ ├── KTX2Khronos 纹理格式 │ │ └── DDSDirectDraw Surface │ │ │ │ Mipmap │ │ ├── 自动生成 │ │ ├── 手动生成 │ │ └── 自定义 Mipmap │ │ │ │ 渲染到纹理 │ │ ├── WebGLRenderTarget │ │ ├── 实时反射 │ │ └── 后期效果 │ │ │ └─────────────────────────────────────────────────────────────┘2. 压缩纹理2.1 BasisTexturenpminstallthree/examples/jsm/libs/basisimport{BasisTextureLoader}fromthree/examples/jsm/loaders/BasisTextureLoader.js;constbasisLoadernewBasisTextureLoader();basisLoader.setTranscoderPath(three/examples/jsm/libs/basis/);basisLoader.load(texture.basis,(texture){constmaterialnewTHREE.MeshStandardMaterial({map:texture});});2.2 KTX2 纹理import{KTX2Loader}fromthree/examples/jsm/loaders/KTX2Loader.js;constktx2LoadernewKTX2Loader();ktx2Loader.setTranscoderPath(three/examples/jsm/libs/basis/);ktx2Loader.load(texture.ktx2,(texture){constmaterialnewTHREE.MeshStandardMaterial({map:texture});});2.3 DDS 纹理import{DDSLoader}fromthree/examples/jsm/loaders/DDSLoader.js;constddsLoadernewDDSLoader();ddsLoader.load(texture.dds,(texture){constmaterialnewTHREE.MeshStandardMaterial({map:texture});});3. Mipmap3.1 自动生成 MipmapconsttexturetextureLoader.load(texture.jpg);texture.generateMipmapstrue;texture.minFilterTHREE.LinearMipmapLinearFilter;3.2 手动生成 Mipmapconstcanvasdocument.createElement(canvas);canvas.width512;canvas.height512;constctxcanvas.getContext(2d);// 绘制各级 Mipmapconstmipmaps[];letsize512;while(size1){constmipCanvasdocument.createElement(canvas);mipCanvas.widthsize;mipCanvas.heightsize;constmipCtxmipCanvas.getContext(2d);mipCtx.drawImage(canvas,0,0,size,size);mipmaps.push({data:mipCtx.getImageData(0,0,size,size).data,width:size,height:size});size/2;}consttexturenewTHREE.DataTexture(mipmaps[0].data,512,512);texture.mipmapsmipmaps;texture.minFilterTHREE.LinearMipmapLinearFilter;4. 渲染到纹理Render Target4.1 WebGLRenderTarget// 创建渲染目标constrenderTargetnewTHREE.WebGLRenderTarget(512,512,{minFilter:THREE.LinearFilter,magFilter:THREE.LinearFilter,format:THREE.RGBAFormat});// 创建场景和相机用于渲染到纹理constrtScenenewTHREE.Scene();constrtCameranewTHREE.PerspectiveCamera(45,1,0.1,1000);// 渲染到纹理renderer.setRenderTarget(renderTarget);renderer.render(rtScene,rtCamera);renderer.setRenderTarget(null);// 使用渲染结果作为纹理constmaterialnewTHREE.MeshStandardMaterial({map:renderTarget.texture});4.2 实时反射纹理// 创建 CubeCamera 用于实时反射constcubeRenderTargetnewTHREE.WebGLCubeRenderTarget(256);constcubeCameranewTHREE.CubeCamera(0.1,1000,cubeRenderTarget);// 更新反射functionupdateReflection(){sphere.visiblefalse;cubeCamera.update(renderer,scene);sphere.visibletrue;constenvMapcubeRenderTarget.texture;reflectiveMaterial.envMapenvMap;}5. 纹理数组// 创建纹理数组consttextures[textureLoader.load(texture1.jpg),textureLoader.load(texture2.jpg),textureLoader.load(texture3.jpg)];// 纹理数组材质constmaterialnewTHREE.MeshStandardMaterial({map:textures[0]});// 切换纹理letcurrentIndex0;functionswitchTexture(){currentIndex(currentIndex1)%textures.length;material.maptextures[currentIndex];material.needsUpdatetrue;}6. 纹理动画// 纹理偏移动画consttexturetextureLoader.load(water.jpg);texture.wrapSTHREE.RepeatWrapping;texture.wrapTTHREE.RepeatWrapping;texture.repeat.set(4,4);letoffset0;functionanimateTexture(){offset0.01;texture.offset.set(offset,offset);requestAnimationFrame(animateTexture);}animateTexture();7. 完整示例import*asTHREEfromthree;import{OrbitControls}fromthree/examples/jsm/controls/OrbitControls.js;constscenenewTHREE.Scene();scene.backgroundnewTHREE.Color(0x111122);constcameranewTHREE.PerspectiveCamera(45,window.innerWidth/window.innerHeight,0.1,1000);camera.position.set(5,4,8);camera.lookAt(0,0,0);constrenderernewTHREE.WebGLRenderer({antialias:true});renderer.setSize(window.innerWidth,window.innerHeight);renderer.shadowMap.enabledtrue;document.body.appendChild(renderer.domElement);constcontrolsnewOrbitControls(camera,renderer.domElement);controls.enableDampingtrue;// 光源constambientLightnewTHREE.AmbientLight(0x404040,0.4);scene.add(ambientLight);constdirectionalLightnewTHREE.DirectionalLight(0xffffff,1);directionalLight.position.set(5,10,7);directionalLight.castShadowtrue;scene.add(directionalLight);// 辅助对象constaxesHelpernewTHREE.AxesHelper(5);scene.add(axesHelper);constgridHelpernewTHREE.GridHelper(10,20);scene.add(gridHelper);// 创建动态纹理CanvasTextureconstcanvasdocument.createElement(canvas);canvas.width512;canvas.height512;constctxcanvas.getContext(2d);functiondrawTexture(){consttimeDate.now()*0.001;ctx.fillStyle#112233;ctx.fillRect(0,0,canvas.width,canvas.height);for(leti0;i50;i){constxcanvas.width/2Math.sin(timei)*200;constycanvas.height/2Math.cos(time*1.3i)*200;consthue(time*50i*36)%360;ctx.fillStylehsl(${hue}, 100%, 60%);ctx.beginPath();ctx.arc(x,y,10,0,Math.PI*2);ctx.fill();}dynamicTexture.needsUpdatetrue;requestAnimationFrame(drawTexture);}constdynamicTexturenewTHREE.CanvasTexture(canvas);drawTexture();// 立方体constgeometrynewTHREE.BoxGeometry(2,2,2);constmaterialnewTHREE.MeshStandardMaterial({map:dynamicTexture,metalness:0.5,roughness:0.3});constcubenewTHREE.Mesh(geometry,material);cube.castShadowtrue;cube.receiveShadowtrue;scene.add(cube);// 创建渲染到纹理的目标constrenderTargetnewTHREE.WebGLRenderTarget(512,512,{minFilter:THREE.LinearFilter,magFilter:THREE.LinearFilter});// 辅助场景用于渲染到纹理constrtScenenewTHREE.Scene();rtScene.backgroundnewTHREE.Color(0xff6600);constrtGeometrynewTHREE.SphereGeometry(0.8,32,32);constrtMaterialnewTHREE.MeshStandardMaterial({color:0xff6600,metalness:0.5});constrtSpherenewTHREE.Mesh(rtGeometry,rtMaterial);rtScene.add(rtSphere);constrtCameranewTHREE.PerspectiveCamera(45,1,0.1,10);rtCamera.position.set(2,2,3);rtCamera.lookAt(0,0,0);constrtLightnewTHREE.DirectionalLight(0xffffff,1);rtLight.position.set(2,3,4);rtScene.add(rtLight);// 更新渲染到纹理functionupdateRenderTarget(){rtSphere.rotation.y0.02;renderer.setRenderTarget(renderTarget);renderer.render(rtScene,rtCamera);renderer.setRenderTarget(null);// 应用到另一个物体if(rtMaterial2)rtMaterial2.maprenderTarget.texture;requestAnimationFrame(updateRenderTarget);}// 第二个立方体使用渲染目标纹理constrtGeometry2newTHREE.BoxGeometry(1.5,1.5,1.5);constrtMaterial2newTHREE.MeshStandardMaterial({map:renderTarget.texture});constrtCubenewTHREE.Mesh(rtGeometry2,rtMaterial2);rtCube.position.set(2.5,0.5,1.5);rtCube.castShadowtrue;scene.add(rtCube);updateRenderTarget();// 平面constplaneGeometrynewTHREE.PlaneGeometry(8,8);constplaneMaterialnewTHREE.MeshStandardMaterial({color:0x336699,side:THREE.DoubleSide});constplanenewTHREE.Mesh(planeGeometry,planeMaterial);plane.rotation.x-Math.PI/2;plane.position.y-1.5;plane.receiveShadowtrue;scene.add(plane);// GUI 控制importGUIfromlil-gui;constguinewGUI();consttextureFoldergui.addFolder(纹理控制);textureFolder.add(material,metalness,0,1).name(金属度);textureFolder.add(material,roughness,0,1).name(粗糙度);textureFolder.add(dynamicTexture,wrapS,{ClampToEdgeWrapping:THREE.ClampToEdgeWrapping,RepeatWrapping:THREE.RepeatWrapping}).name(包裹模式).onChange(()dynamicTexture.needsUpdatetrue);textureFolder.add(dynamicTexture.repeat,x,0.1,4).name(重复X).onChange(()dynamicTexture.needsUpdatetrue);textureFolder.add(dynamicTexture.repeat,y,0.1,4).name(重复Y).onChange(()dynamicTexture.needsUpdatetrue);textureFolder.open();// 动画functionanimate(){requestAnimationFrame(animate);cube.rotation.x0.005;cube.rotation.y0.01;controls.update();renderer.render(scene,camera);}animate();window.addEventListener(resize,onWindowResize,false);functiononWindowResize(){camera.aspectwindow.innerWidth/window.innerHeight;camera.updateProjectionMatrix();renderer.setSize(window.innerWidth,window.innerHeight);}8. 总结技术类/方法用途压缩纹理BasisTextureLoader, KTX2Loader减少内存和带宽MipmapgenerateMipmaps提高远处纹理质量渲染到纹理WebGLRenderTarget动态纹理、后期效果CubeCameraCubeCamera实时环境贴图纹理数组多个 Texture纹理切换纹理动画offset, rotation动态效果纹理属性说明generateMipmaps是否生成 MipmapminFilter缩小过滤magFilter放大过滤needsUpdate需要更新mipmaps自定义 Mipmap 数组