javascript
// 使用合适尺寸的纹理
const textureLoader = new THREE.TextureLoader();
// 避免超大纹理 (4096x4096以上需谨慎)
const texture = textureLoader.load('texture.jpg', (tex) => {
tex.needsUpdate = true;
// 自动生成mipmaps
tex.generateMipmaps = true;
// 设置合适的过滤方式
tex.minFilter = THREE.LinearMipmapLinearFilter;
tex.magFilter = THREE.LinearFilter;
});
javascript
// 根据需求选择格式
// WebP/AVIF - 现代浏览器,高压缩比
// JPEG - 照片类纹理
// PNG - 需要透明度
// Basis Universal - 跨平台压缩纹理
// 使用压缩纹理
const ktxLoader = new THREE.KTX2Loader();
ktxLoader.load('texture.ktx2', (texture) => {
material.map = texture;
});
// 或使用Basis纹理
const basisLoader = new THREE.BasisTextureLoader();
basisLoader.load('texture.basis', (texture) => {
material.map = texture;
});
javascript
// 合并多个小纹理为一个大纹理
const atlasTexture = new THREE.TextureLoader().load('atlas.png');
// 在shader或UV坐标中定位子纹理
const material = new THREE.ShaderMaterial({
uniforms: {
atlas: { value: atlasTexture },
uvOffset: { value: new THREE.Vector2(0, 0) },
uvScale: { value: new THREE.Vector2(0.25, 0.25) }
},
vertexShader: `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
uniform sampler2D atlas;
uniform vec2 uvOffset;
uniform vec2 uvScale;
varying vec2 vUv;
void main() {
vec2 atlasUv = uvOffset + vUv * uvScale;
gl_FragColor = texture2D(atlas, atlasUv);
}
`
});
javascript
// 启用各向异性过滤(提升斜角纹理质量)
texture.anisotropy = renderer.capabilities.getMaxAnisotropy();
// Mipmapping设置
texture.minFilter = THREE.LinearMipmapLinearFilter; // 质量最好
texture.magFilter = THREE.LinearFilter;
javascript
// 使用BufferGeometry代替Geometry
const geometry = new THREE.BufferGeometry();
// 合并几何体减少draw calls
const geometries = [geom1, geom2, geom3];
const mergedGeometry = THREE.BufferGeometryUtils.mergeBufferGeometries(geometries);
// 使用LOD(细节层次)
const lod = new THREE.LOD();
const highDetail = new THREE.Mesh(highDetailGeometry, material);
const lowDetail = new THREE.Mesh(lowDetailGeometry, material);
lod.addLevel(highDetail, 0);
lod.addLevel(lowDetail, 50); // 50单位距离切换
scene.add(lod);
javascript
// 使用索引减少重复顶点
const geometry = new THREE.BufferGeometry();
const vertices = new Float32Array([...]);
const indices = new Uint16Array([...]); // 或Uint32Array
geometry.setAttribute('position', new THREE.BufferAttribute(vertices, 3));
geometry.setIndex(new THREE.BufferAttribute(indices, 1));
// 计算法线(如果需要)
geometry.computeVertexNormals();
javascript
// 大量相同几何体使用实例化
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const instanceCount = 1000;
const mesh = new THREE.InstancedMesh(geometry, material, instanceCount);
// 设置每个实例的变换矩阵
const matrix = new THREE.Matrix4();
for (let i = 0; i < instanceCount; i++) {
matrix.setPosition(
Math.random() * 100 - 50,
Math.random() * 100 - 50,
Math.random() * 100 - 50
);
mesh.setMatrixAt(i, matrix);
}
mesh.instanceMatrix.needsUpdate = true;
javascript
// 使用简化算法减少面数
import { SimplifyModifier } from 'three/examples/jsm/modifiers/SimplifyModifier';
const modifier = new SimplifyModifier();
const simplifiedGeometry = modifier.modify(originalGeometry, count); // 目标面数
javascript
// 纹理回收
function disposeTexture(texture) {
texture.dispose();
texture.image = null;
}
// 按需加载/卸载纹理
class TextureManager {
constructor() {
this.cache = new Map();
this.maxCacheSize = 10;
}
loadTexture(url) {
if (this.cache.has(url)) {
return this.cache.get(url);
}
const texture = new THREE.TextureLoader().load(url);
this.cache.set(url, texture);
// LRU缓存清理
if (this.cache.size > this.maxCacheSize) {
const firstKey = this.cache.keys().next().value;
this.cache.get(firstKey).dispose();
this.cache.delete(firstKey);
}
return texture;
}
}
javascript
// 清理几何体
function disposeGeometry(geometry) {
geometry.dispose();
geometry.attributes = null;
geometry.index = null;
}
// 使用BufferGeometry池
class GeometryPool {
constructor() {
this.pool = new Map();
}
getGeometry(type, params) {
const key = `${type}_${JSON.stringify(params)}`;
if (!this.pool.has(key)) {
this.pool.set(key, this.createGeometry(type, params));
}
return this.pool.get(key).clone();
}
}
javascript
// 使用压缩纹理格式
renderer.textureFormat = THREE.RGBFormat; // 或RGBAFormat
renderer.textureEncoding = THREE.sRGBEncoding;
// 调整纹理精度
renderer.precision = 'mediump'; // 或 'highp'
// 使用顶点压缩
const packedGeometry = new THREE.BufferGeometry();
// 使用半浮点数存储位置
const positions = new Uint16Array(vertexCount * 3);
// 使用8位无符号整数存储颜色/法线
const colors = new Uint8Array(vertexCount * 3);
javascript
import Stats from 'three/examples/jsm/libs/stats.module';
const stats = new Stats();
document.body.appendChild(stats.dom);
function animate() {
stats.begin();
// 渲染场景
stats.end();
requestAnimationFrame(animate);
}
javascript
// 纹理大小检查
function checkTextureSize(texture, maxSize = 2048) {
if (texture.image) {
const width = texture.image.width || texture.image.videoWidth;
const height = texture.image.height || texture.image.videoHeight;
if (width > maxSize || height > maxSize) {
console.warn(`Texture too large: ${width}x${height}`);
return false;
}
}
return true;
}
// 纹理自动降级
function loadAdaptiveTexture(url, quality = 'high') {
const suffixes = {
high: '',
medium: '_medium',
low: '_low'
};
const suffix = suffixes[quality] || '';
const adaptedUrl = url.replace(/(\.\w+)$/, `${suffix}$1`);
return new Promise((resolve, reject) => {
new THREE.TextureLoader().load(adaptedUrl, resolve, undefined, reject);
});
}
纹理方面:
使用合适的尺寸(通常不超过2048x2048)
采用压缩纹理格式(KTX2/Basis)
实现纹理流式加载
使用纹理图集减少draw calls
几何体方面:
使用BufferGeometry而非Geometry
实现LOD系统
大量重复物体使用实例化
合并静态几何体
内存管理:
及时释放不再使用的资源
实现资源缓存和复用
监控GPU内存使用
性能调优:
使用性能分析工具
分批处理渲染
合理使用Web Workers进行数据处理
通过实施这些优化策略,可以显著提升Three.js应用的性能,特别是在处理复杂场景和大量对象时。