






javascript
class MaterialSelector {
static selectMaterial(requirements) {
const {
needsLighting = true,
needsReflections = false,
performanceCritical = false,
style = 'realistic',
hasTextures = false,
textureTypes = [],
platform = 'desktop'
} = requirements;
// 决策逻辑
if (!needsLighting) {
return 'MeshBasicMaterial'; // 无光照需求
}
if (performanceCritical) {
if (needsLighting && !needsReflections) {
return 'MeshLambertMaterial'; // 性能优先
}
return 'MeshPhongMaterial'; // 平衡选择
}
if (style === 'cartoon') {
return 'MeshToonMaterial'; // 卡通风格
}
if (style === 'matcap') {
return 'MeshMatcapMaterial'; // 风格化
}
if (style === 'realistic') {
if (platform === 'mobile' || performanceCritical) {
return 'MeshStandardMaterial'; // 移动端或性能敏感
}
// 检查是否需要Physical的高级特性
if (textureTypes.includes('clearcoat') ||
textureTypes.includes('sheen') ||
requirements.needsIridescence) {
return 'MeshPhysicalMaterial'; // 需要高级PBR特性
}
return 'MeshStandardMaterial'; // 默认PBR
}
// 默认选择
return 'MeshStandardMaterial';
}
// 示例使用
static exampleSelections() {
const scenarios = [
{
name: '移动端游戏',
requirements: {
needsLighting: true,
performanceCritical: true,
style: 'realistic',
platform: 'mobile'
},
result: 'MeshStandardMaterial'
},
{
name: '产品展示',
requirements: {
needsLighting: true,
needsReflections: true,
style: 'realistic',
textureTypes: ['clearcoat', 'roughness'],
platform: 'desktop'
},
result: 'MeshPhysicalMaterial'
},
{
name: 'UI元素',
requirements: {
needsLighting: false,
performanceCritical: true
},
result: 'MeshBasicMaterial'
},
{
name: '卡通风格游戏',
requirements: {
needsLighting: true,
style: 'cartoon',
performanceCritical: false
},
result: 'MeshToonMaterial'
}
];
return scenarios;
}
}

javascript
class MaterialOptimizer {
// 根据平台优化材质
static optimizeForPlatform(material, platform) {
const optimizedMaterial = material.clone();
switch(platform) {
case 'mobile':
// 移动端优化
optimizedMaterial.precision = 'mediump';
optimizedMaterial.vertexColors = false;
if (optimizedMaterial instanceof THREE.MeshStandardMaterial) {
optimizedMaterial.envMapIntensity = 0.5;
optimizedMaterial.roughness = 0.8; // 降低计算
}
break;
case 'desktop':
// 桌面端可以启用更多特性
if (optimizedMaterial instanceof THREE.MeshPhysicalMaterial) {
optimizedMaterial.clearcoat = 1.0;
optimizedMaterial.clearcoatRoughness = 0.1;
}
break;
case 'vr':
// VR需要保持高帧率
optimizedMaterial.precision = 'highp';
optimizedMaterial.dithering = true; // 减少色带
break;
}
return optimizedMaterial;
}
// 性能分级配置
static getPerformanceProfile(level) {
const profiles = {
low: {
material: 'MeshLambertMaterial',
textures: {
maxSize: 512,
mipmaps: false,
anisotropic: 1
},
shadows: false,
antialias: false
},
medium: {
material: 'MeshPhongMaterial',
textures: {
maxSize: 1024,
mipmaps: true,
anisotropic: 2
},
shadows: true,
antialias: false
},
high: {
material: 'MeshStandardMaterial',
textures: {
maxSize: 2048,
mipmaps: true,
anisotropic: 4
},
shadows: true,
antialias: true
},
ultra: {
material: 'MeshPhysicalMaterial',
textures: {
maxSize: 4096,
mipmaps: true,
anisotropic: 16
},
shadows: true,
antialias: true,
postprocessing: true
}
};
return profiles[level] || profiles.medium;
}
}
javascript
const MaterialTemplates = {
// 基础材质 - UI元素
basicUI: new THREE.MeshBasicMaterial({
color: 0xffffff,
transparent: true,
opacity: 0.9,
side: THREE.DoubleSide
}),
// Lambert - 性能优先的3D物体
lambertPerformance: new THREE.MeshLambertMaterial({
color: 0x808080,
emissive: 0x000000,
emissiveIntensity: 0.5,
flatShading: false // 设为true可提升性能但质量降低
}),
// Phong - 塑料/光滑表面
phongPlastic: new THREE.MeshPhongMaterial({
color: 0xffffff,
specular: 0x111111,
shininess: 30,
reflectivity: 0.5,
combine: THREE.MixOperation
}),
// Standard - 通用PBR
standardGeneric: new THREE.MeshStandardMaterial({
color: 0xffffff,
metalness: 0.0, // 0=非金属, 1=金属
roughness: 0.5, // 0=光滑, 1=粗糙
envMapIntensity: 1.0,
aoMapIntensity: 1.0
}),
// Standard - 金属材质
standardMetal: new THREE.MeshStandardMaterial({
color: 0xcccccc,
metalness: 0.9,
roughness: 0.1,
envMapIntensity: 2.0
}),
// Physical - 汽车漆
physicalCarPaint: new THREE.MeshPhysicalMaterial({
color: 0xff0000,
metalness: 0.0,
roughness: 0.1,
clearcoat: 1.0,
clearcoatRoughness: 0.0,
sheen: 0.5,
sheenColor: 0xff0000,
sheenRoughness: 0.1
}),
// Physical - 清漆木材
physicalVarnishedWood: new THREE.MeshPhysicalMaterial({
color: 0x8b4513,
metalness: 0.0,
roughness: 0.7,
clearcoat: 0.3,
clearcoatRoughness: 0.2,
anisotropy: 0.8,
anisotropyRotation: Math.PI / 4
}),
// Toon - 卡通风格
toonCartoon: new THREE.MeshToonMaterial({
color: 0x00aaff,
gradientMap: this.createGradientTexture(),
shininess: 100,
specular: 0x444444
}),
// Matcap - 风格化
matcapStylized: new THREE.MeshMatcapMaterial({
matcap: this.loadMatcapTexture('metal'),
color: 0xffffff
}),
// 透明玻璃
transparentGlass: new THREE.MeshPhysicalMaterial({
color: 0xffffff,
metalness: 0.0,
roughness: 0.0,
transmission: 0.9, // 透光率
thickness: 0.5, // 玻璃厚度
ior: 1.5, // 折射率
specularIntensity: 1.0,
specularColor: 0xffffff
})
};
javascript
class TextureConfiguration {
// 根据材质类型配置纹理
static configureTextures(material, textureConfig) {
const {
colorMap,
normalMap,
roughnessMap,
metalnessMap,
aoMap,
emissiveMap,
displacementMap
} = textureConfig;
// 公共纹理设置
const applyTextureSettings = (texture) => {
if (!texture) return;
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
texture.anisotropy = 4; // 各向异性过滤
texture.minFilter = THREE.LinearMipmapLinearFilter;
texture.magFilter = THREE.LinearFilter;
texture.needsUpdate = true;
};
// 应用纹理到材质
if (colorMap) {
material.map = colorMap;
applyTextureSettings(colorMap);
}
if (normalMap && material.normalMap !== undefined) {
material.normalMap = normalMap;
material.normalScale = new THREE.Vector2(1, 1);
applyTextureSettings(normalMap);
}
if (roughnessMap && material.roughnessMap !== undefined) {
material.roughnessMap = roughnessMap;
applyTextureSettings(roughnessMap);
}
if (metalnessMap && material.metalnessMap !== undefined) {
material.metalnessMap = metalnessMap;
applyTextureSettings(metalnessMap);
}
if (aoMap && material.aoMap !== undefined) {
material.aoMap = aoMap;
applyTextureSettings(aoMap);
}
if (emissiveMap && material.emissiveMap !== undefined) {
material.emissiveMap = emissiveMap;
material.emissiveIntensity = 1.0;
applyTextureSettings(emissiveMap);
}
if (displacementMap && material.displacementMap !== undefined) {
material.displacementMap = displacementMap;
material.displacementScale = 0.1;
applyTextureSettings(displacementMap);
}
return material;
}
// 纹理压缩建议
static getTextureCompressionSettings(platform) {
const settings = {
desktop: {
format: THREE.RGBAFormat,
type: THREE.UnsignedByteType,
compression: THREE.NoCompression,
maxSize: 4096
},
mobile: {
format: THREE.RGBAFormat,
type: THREE.HalfFloatType,
compression: THREE.CompressedTexture,
maxSize: 2048
},
webgl1: {
format: THREE.RGBFormat, // 减少内存
type: THREE.UnsignedByteType,
compression: THREE.NoCompression,
maxSize: 1024
}
};
return settings[platform] || settings.desktop;
}
}

javascript
class MaterialPool {
constructor() {
this.pool = new Map();
this.stats = {
created: 0,
reused: 0,
active: 0
};
}
// 获取或创建材质
getMaterial(config) {
const key = this.generateKey(config);
if (this.pool.has(key)) {
this.stats.reused++;
return this.pool.get(key);
}
// 创建新材质
const material = this.createMaterial(config);
this.pool.set(key, material);
this.stats.created++;
this.stats.active++;
return material;
}
// 生成材质配置的唯一键
generateKey(config) {
return JSON.stringify({
type: config.type,
color: config.color?.getHex(),
map: config.map?.uuid,
metalness: config.metalness,
roughness: config.roughness,
transparent: config.transparent
});
}
// 创建材质实例
createMaterial(config) {
switch(config.type) {
case 'basic':
return new THREE.MeshBasicMaterial(config);
case 'lambert':
return new THREE.MeshLambertMaterial(config);
case 'phong':
return new THREE.MeshPhongMaterial(config);
case 'standard':
return new THREE.MeshStandardMaterial(config);
case 'physical':
return new THREE.MeshPhysicalMaterial(config);
default:
return new THREE.MeshStandardMaterial(config);
}
}
// 清理未使用的材质
cleanup(unusedTimeout = 60000) { // 60秒
const now = Date.now();
for (const [key, material] of this.pool.entries()) {
if (material.userData.lastUsed &&
now - material.userData.lastUsed > unusedTimeout) {
material.dispose();
this.pool.delete(key);
this.stats.active--;
}
}
}
// 获取性能统计
getStats() {
return {
...this.stats,
poolSize: this.pool.size,
memoryEstimate: this.estimateMemoryUsage()
};
}
estimateMemoryUsage() {
let total = 0;
for (const material of this.pool.values()) {
// 粗略估算,实际会更复杂
total += 1024; // 每个材质约1KB基础开销
if (material.map) total += 1024 * 10; // 纹理额外开销
if (material.normalMap) total += 1024 * 10;
// 其他纹理...
}
return `${(total / 1024).toFixed(1)} KB`;
}
}

javascript
class MaterialDebugger {
constructor(mesh) {
this.mesh = mesh;
this.originalMaterial = mesh.material;
this.debugModes = new Map();
this.initDebugModes();
}
initDebugModes() {
// 法线可视化
this.debugModes.set('normal', new THREE.MeshNormalMaterial());
// 线框模式
this.debugModes.set('wireframe', new THREE.MeshBasicMaterial({
wireframe: true,
color: 0x00ff00
}));
// UV可视化
this.debugModes.set('uv', new THREE.MeshBasicMaterial({
map: this.createUVTexture(),
side: THREE.DoubleSide
}));
// 深度可视化
this.debugModes.set('depth', new THREE.MeshDepthMaterial());
// 面索引可视化
this.debugModes.set('face', this.createFaceIndexMaterial());
}
setDebugMode(mode) {
if (mode === 'off') {
this.mesh.material = this.originalMaterial;
} else if (this.debugModes.has(mode)) {
this.mesh.material = this.debugModes.get(mode);
}
}
createUVTexture() {
const canvas = document.createElement('canvas');
canvas.width = 256;
canvas.height = 256;
const ctx = canvas.getContext('2d');
// 绘制UV网格
ctx.strokeStyle = '#ff0000';
ctx.lineWidth = 2;
for (let i = 0; i <= 10; i++) {
const pos = i * 25.6;
ctx.beginPath();
ctx.moveTo(pos, 0);
ctx.lineTo(pos, 256);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(0, pos);
ctx.lineTo(256, pos);
ctx.stroke();
}
const texture = new THREE.CanvasTexture(canvas);
return texture;
}
// 分析材质性能
analyzePerformance() {
const material = this.mesh.material;
const analysis = {
type: material.type,
textureCount: 0,
shaderComplexity: 'low',
memoryEstimate: 'unknown'
};
// 计算纹理数量
const textureProperties = [
'map', 'normalMap', 'roughnessMap', 'metalnessMap',
'aoMap', 'emissiveMap', 'displacementMap', 'envMap'
];
analysis.textureCount = textureProperties.filter(
prop => material[prop]
).length;
// 评估着色器复杂度
if (material instanceof THREE.MeshBasicMaterial) {
analysis.shaderComplexity = 'very low';
} else if (material instanceof THREE.MeshLambertMaterial) {
analysis.shaderComplexity = 'low';
} else if (material instanceof THREE.MeshPhongMaterial) {
analysis.shaderComplexity = 'medium';
} else if (material instanceof THREE.MeshStandardMaterial) {
analysis.shaderComplexity = 'high';
} else if (material instanceof THREE.MeshPhysicalMaterial) {
analysis.shaderComplexity = 'very high';
}
return analysis;
}
}

早期开发:
使用Basic/Lambert快速原型
关注功能而非视觉效果
中期优化:
根据性能测试选择材质
建立材质库和配置系统
后期完善:
使用Standard/Physical提升质量
实施材质LOD系统
优化内存和加载时间
维护阶段:
定期清理未使用材质
监控性能变化
更新到新版本API
初学者:
掌握Basic、Lambert、Phong
理解光照基本原理
中级开发者:
熟练使用Standard Material
掌握PBR工作流
学习纹理优化
高级开发者:
深入Physical Material
掌握自定义ShaderMaterial
实现材质管理系统
这个综合指南应该能帮助你在不同场景下做出合适的材质选择。记住最重要的原则是:根据实际需求平衡视觉效果和性能开销。