材质属性详解
深入解析 Three.js 各类材质的属性配置,帮助开发者精确控制渲染效果。
概述
每种材质都有其特定的属性集合,正确配置这些属性可以实现各种视觉效果。本章节将详细说明常用属性的含义和使用方法,并提供完整的属性参考表。
通用属性
所有材质共有的基础属性。
基础属性总览
| 属性名 | 类型 | 默认值 | 说明 | 使用场景 |
|---|---|---|---|---|
id | number | 自动生成 | 材质唯一标识 | 内部使用 |
uuid | string | 自动生成 | 材质 UUID | 序列化/反序列化 |
name | string | '' | 材质名称 | 调试、资源管理 |
type | string | 类名 | 材质类型字符串 | 类型判断 |
version | number | 0 | 版本号 | 内部追踪变更 |
visible | boolean | true | 是否可见 | 显示/隐藏物体 |
transparent | boolean | false | 是否开启透明 | 半透明物体 |
opacity | number | 1.0 | 透明度 (0-1) | 控制不透明度 |
renderOrder | number | 0 | 渲染顺序 | 解决透明物体渲染问题 |
userData | object | {} | 自定义数据 | 存储应用数据 |
javascript
const material = new THREE.MeshStandardMaterial();
// 基础属性
material.id // 材质唯一标识
material.uuid // UUID
material.name // 名称
material.type // 类型
material.version // 版本号
// 可见性
material.visible = true; // 是否可见
// 透明度
material.transparent = false; // 是否开启透明
material.opacity = 1.0; // 透明度(0-1)
// 颜色
material.color = new THREE.Color(0xff0000);
material.color.setHex(0x00ff00);
material.color.setRGB(1, 0, 0);
material.color.setHSL(0.5, 1, 0.5);
// 渲染顺序
material.renderOrder = 0; // 渲染顺序(越小越先渲染)
// 自定义属性
material.userData = {}; // 存储自定义数据渲染面(Side)
| 属性值 | 说明 | 性能影响 | 适用场景 |
|---|---|---|---|
THREE.FrontSide | 仅渲染正面(默认) | 低 | 封闭物体 |
THREE.BackSide | 仅渲染背面 | 低 | 内部视角 |
THREE.DoubleSide | 渲染双面 | 高(约2倍) | 平面、开放物体 |
javascript
// 正面(默认)
material.side = THREE.FrontSide;
// 背面
material.side = THREE.BackSide;
// 双面
material.side = THREE.DoubleSide;
// 注意:双面渲染会增加约100%性能消耗深度测试(Depth)
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
depthTest | boolean | true | 是否启用深度测试 |
depthWrite | boolean | true | 是否写入深度缓冲 |
depthFunc | DepthModes | LessEqualDepth | 深度比较函数 |
深度函数说明:
| 深度函数值 | 比较逻辑 | 使用场景 |
|---|---|---|
THREE.NeverDepth | 永不通过 | 特殊效果 |
THREE.AlwaysDepth | 总是通过 | 禁用深度测试 |
THREE.LessDepth | 新像素 < 已有像素 | 特殊需求 |
THREE.LessEqualDepth | 新像素 ≤ 已有像素 | 默认值 |
THREE.EqualDepth | 新像素 = 已有像素 | 模板效果 |
THREE.GreaterEqualDepth | 新像素 ≥ 已有像素 | 特殊需求 |
THREE.GreaterDepth | 新像素 > 已有像素 | 特殊需求 |
THREE.NotEqualDepth | 新像素 ≠ 已有像素 | 特殊效果 |
javascript
// 深度测试
material.depthTest = true; // 是否测试深度
material.depthWrite = true; // 是否写入深度缓冲
// 深度函数
material.depthFunc = THREE.LessEqualDepth; // 默认值
// 常见配置
// 透明物体:禁用深度写入
transparentMaterial.depthWrite = false;
transparentMaterial.depthTest = true;
// UI 元素:禁用深度测试
uiMaterial.depthTest = false;混合模式(Blending)
混合模式说明:
| 混合模式 | 效果描述 | 性能影响 | 典型应用 |
|---|---|---|---|
NoBlending | 不混合 | 无 | 不透明物体 |
NormalBlending | 标准透明混合 | 低 | 默认,半透明物体 |
AdditiveBlending | 加法混合(变亮) | 低 | 发光效果、火焰 |
SubtractiveBlending | 减法混合(变暗) | 低 | 阴影、暗化效果 |
MultiplyBlending | 乘法混合 | 低 | 叠加效果 |
CustomBlending | 自定义混合 | 中 | 特殊效果 |
混合因子说明:
| 混合因子 | 说明 |
|---|---|
THREE.ZeroFactor | 0 |
THREE.OneFactor | 1 |
THREE.SrcColorFactor | 源颜色 |
THREE.OneMinusSrcColorFactor | 1 - 源颜色 |
THREE.SrcAlphaFactor | 源透明度 |
THREE.OneMinusSrcAlphaFactor | 1 - 源透明度 |
THREE.DstAlphaFactor | 目标透明度 |
THREE.OneMinusDstAlphaFactor | 1 - 目标透明度 |
THREE.DstColorFactor | 目标颜色 |
THREE.OneMinusDstColorFactor | 1 - 目标颜色 |
javascript
// 混合模式
material.blending = THREE.NormalBlending;
// 可选值
THREE.NoBlending // 不混合
THREE.NormalBlending // 正常混合(默认)
THREE.AdditiveBlending // 加法混合
THREE.SubtractiveBlending // 减法混合
THREE.MultiplyBlending // 乘法混合
THREE.CustomBlending // 自定义混合
// 自定义混合参数
material.blendSrc = THREE.SrcAlphaFactor;
material.blendDst = THREE.OneMinusSrcAlphaFactor;
material.blendEquation = THREE.AddEquation;
// 常见混合配置示例
// 1. 发光效果
glowMaterial.blending = THREE.AdditiveBlending;
glowMaterial.depthWrite = false;
// 2. 半透明叠加
overlayMaterial.blending = THREE.NormalBlending;
overlayMaterial.transparent = true;
overlayMaterial.opacity = 0.5;
// 3. 自定义混合(如叠加模式)
customMaterial.blending = THREE.CustomBlending;
customMaterial.blendSrc = THREE.SrcAlphaFactor;
customMaterial.blendDst = THREE.OneMinusSrcAlphaFactor;多边形偏移
javascript
// 解决 z-fighting 问题
material.polygonOffset = false;
material.polygonOffsetFactor = 0;
material.polygonOffsetUnits = 0;
// 示例
material.polygonOffset = true;
material.polygonOffsetFactor = 1;
material.polygonOffsetUnits = 1;MeshBasicMaterial 属性
属性列表
| 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
color | Color | 0xffffff | 材质颜色 |
wireframe | boolean | false | 是否显示线框 |
wireframeLinewidth | number | 1 | 线框宽度(WebGL 限制通常为 1) |
map | Texture | null | 漫反射贴图 |
alphaMap | Texture | null | 透明度贴图 |
envMap | Texture | null | 环境贴图 |
reflectivity | number | 1 | 反射率(配合 envMap) |
refractionRatio | number | 0.98 | 折射率 |
javascript
const material = new THREE.MeshBasicMaterial({
// 颜色
color: 0xffffff,
// 线框
wireframe: false, // 是否显示线框
wireframeLinewidth: 1, // 线框宽度(WebGL 通常只能为 1)
// 纹理
map: null, // 漫反射贴图
alphaMap: null, // 透明度贴图
envMap: null, // 环境贴图
// 透明度
transparent: false,
opacity: 1.0,
// 渲染面
side: THREE.FrontSide,
// 其他
reflectivity: 1, // 反射率(与 envMap 配合)
refractionRatio: 0.98 // 折射率
});使用场景
- UI 元素:不受光照影响的 2D 元素
- 调试渲染:快速预览几何体
- 背景元素:天空盒、全景图
- 性能优化:大量远距离物体的简化渲染
MeshLambertMaterial 属性
javascript
const material = new THREE.MeshLambertMaterial({
// 基础颜色
color: 0xffffff,
// 自发光
emissive: 0x000000, // 自发光颜色
emissiveIntensity: 1.0, // 自发光强度
emissiveMap: null, // 自发光贴图
// 纹理
map: null,
alphaMap: null,
specularMap: null, // 高光贴图
// 光照
reflectivity: 1,
refractionRatio: 0.98,
// 其他
wireframe: false,
wireframeLinewidth: 1,
flatShading: false // 平面着色
});MeshPhongMaterial 属性
javascript
const material = new THREE.MeshPhongMaterial({
// 基础颜色
color: 0xffffff,
// 高光
specular: 0x111111, // 高光颜色
shininess: 30, // 高光强度(0-100)
specularMap: null, // 高光贴图
// 自发光
emissive: 0x000000,
emissiveIntensity: 1.0,
emissiveMap: null,
// 纹理
map: null,
alphaMap: null,
bumpMap: null, // 凹凸贴图
bumpScale: 1, // 凹凸强度
// 法线
normalMap: null,
normalScale: new THREE.Vector2(1, 1),
// 位移
displacementMap: null,
displacementScale: 1,
displacementBias: 0,
// 光照
reflectivity: 1,
refractionRatio: 0.98,
// 其他
flatShading: false,
wireframe: false,
wireframeLinewidth: 1
});MeshStandardMaterial 属性
核心属性
| 属性名 | 类型 | 默认值 | 范围 | 说明 |
|---|---|---|---|---|
color | Color | 0xffffff | - | 漫反射颜色 |
metalness | number | 0.0 | 0-1 | 金属度 |
roughness | number | 0.5 | 0-1 | 粗糙度 |
emissive | Color | 0x000000 | - | 自发光颜色 |
emissiveIntensity | number | 1.0 | ≥0 | 自发光强度 |
flatShading | boolean | false | - | 平面着色 |
贴图属性
| 属性名 | 类型 | 默认值 | 说明 | 通道需求 |
|---|---|---|---|---|
map | Texture | null | 漫反射贴图 | RGB |
normalMap | Texture | null | 法线贴图 | RGB |
normalScale | Vector2 | (1, 1) | 法线强度 | - |
bumpMap | Texture | null | 凹凸贴图 | R |
bumpScale | number | 1 | 凹凸强度 | - |
displacementMap | Texture | null | 位移贴图 | R |
displacementScale | number | 1 | 位移强度 | - |
displacementBias | number | 0 | 位移偏移 | - |
aoMap | Texture | null | 环境光遮蔽贴图 | R,需要 UV2 |
aoMapIntensity | number | 1 | AO 强度 | - |
metalnessMap | Texture | null | 金属度贴图 | R |
roughnessMap | Texture | null | 粗糙度贴图 | R |
alphaMap | Texture | null | 透明度贴图 | R |
envMap | Texture | null | 环境贴图 | RGB |
envMapIntensity | number | 1 | 环境贴图强度 | - |
lightMap | Texture | null | 光照贴图 | RGB,需要 UV2 |
lightMapIntensity | number | 1 | 光照贴图强度 | - |
emissiveMap | Texture | null | 自发光贴图 | RGB |
贴图通道配置
javascript
// 设置贴图使用的通道
material.aoMapChannel = 'r';
material.roughnessMapChannel = 'g';
material.metalnessMapChannel = 'b';
// ORM 贴图(Ambient Occlusion + Roughness + Metalness)
// 将 AO、粗糙度、金属度合并到一张贴图的 RGB 通道
const ormTexture = textureLoader.load('orm.jpg');
material.aoMap = ormTexture;
material.roughnessMap = ormTexture;
material.metalnessMap = ormTexture;
material.aoMapChannel = 'r'; // AO 使用 R 通道
material.roughnessMapChannel = 'g'; // 粗糙度使用 G 通道
material.metalnessMapChannel = 'b'; // 金属度使用 B 通道
// 注意:AO 贴图需要第二组 UV 坐标
geometry.setAttribute('uv2', geometry.attributes.uv);完整示例
javascript
const material = new THREE.MeshStandardMaterial({
// 基础颜色
color: 0xffffff,
// PBR 核心
metalness: 0.0, // 金属度(0-1)
roughness: 0.5, // 粗糙度(0-1)
// 自发光
emissive: 0x000000,
emissiveIntensity: 1.0,
emissiveMap: null
});
// 动态加载贴图
const textureLoader = new THREE.TextureLoader();
material.map = textureLoader.load('diffuse.jpg');
material.normalMap = textureLoader.load('normal.jpg');
material.roughnessMap = textureLoader.load('roughness.jpg');
material.metalnessMap = textureLoader.load('metalness.jpg');
material.aoMap = textureLoader.load('ao.jpg');MeshPhysicalMaterial 属性
MeshPhysicalMaterial 继承了 MeshStandardMaterial 的所有属性,并添加了更多物理特性。
物理属性总览
| 属性分类 | 属性名 | 类型 | 默认值 | 说明 |
|---|---|---|---|---|
| 清漆层 | clearcoat | number | 0 | 清漆强度(0-1) |
clearcoatRoughness | number | 0 | 清漆粗糙度(0-1) | |
clearcoatMap | Texture | null | 清漆贴图 | |
clearcoatNormalMap | Texture | null | 清漆法线贴图 | |
| 透射 | transmission | number | 0 | 透光度(0-1) |
thickness | number | 0 | 厚度 | |
attenuationDistance | number | 0 | 衰减距离 | |
attenuationColor | Color | 0xffffff | 衰减颜色 | |
| 折射 | ior | number | 1.5 | 折射率 |
| 光泽 | sheen | number | 0 | 光泽强度(0-1) |
sheenColor | Color | 0xffffff | 光泽颜色 | |
sheenRoughness | number | 1 | 光泽粗糙度 | |
| 镜面 | specularIntensity | number | 1.0 | 镜面强度 |
specularColor | Color | 0xffffff | 镜面颜色 | |
| 各向异性 | anisotropy | number | 0 | 各向异性强度(0-1) |
anisotropyRotation | number | 0 | 各向异性旋转 |
清漆层(Clearcoat)
用于模拟车漆、钢琴漆等双涂层效果。
javascript
material.clearcoat = 0; // 清漆强度(0-1)
material.clearcoatRoughness = 0; // 清漆粗糙度(0-1)
material.clearcoatMap = null; // 清漆贴图
material.clearcoatRoughnessMap = null; // 清漆粗糙度贴图
material.clearcoatNormalMap = null; // 清漆法线贴图
material.clearcoatNormalScale = new THREE.Vector2(1, 1);
// 车漆材质示例
const carPaintMaterial = new THREE.MeshPhysicalMaterial({
color: 0xff0000,
metalness: 0.9,
roughness: 0.1,
clearcoat: 1.0,
clearcoatRoughness: 0.05
});透射(Transmission)
用于模拟玻璃、水等透明材质。
javascript
material.transmission = 0; // 透光度(0-1)
material.thickness = 0; // 厚度
material.attenuationDistance = 0; // 衰减距离
material.attenuationColor = new THREE.Color(0xffffff); // 衰减颜色
material.transmissionMap = null; // 透射贴图
material.thicknessMap = null; // 厚度贴图
// 玻璃材质示例
const glassMaterial = new THREE.MeshPhysicalMaterial({
color: 0xffffff,
metalness: 0,
roughness: 0,
transmission: 0.95,
transparent: true,
ior: 1.5,
thickness: 0.5
});折射率(IOR)参考表
| 材质 | 折射率 (IOR) | 材质 | 折射率 (IOR) |
|---|---|---|---|
| 真空/空气 | 1.0 | 塑料 | 1.46 |
| 水 | 1.33 | 玻璃 | 1.5 |
| 冰 | 1.31 | 琥珀 | 1.55 |
| 酒精 | 1.36 | 蓝宝石 | 1.77 |
| 石英 | 1.55 | 钻石 | 2.42 |
javascript
// 常见材质折射率
const iorValues = {
air: 1.0,
water: 1.33,
ice: 1.31,
glass: 1.5,
diamond: 2.42,
sapphire: 1.77,
amber: 1.55,
plastic: 1.46
};
// 使用示例
material.ior = iorValues.glass;光泽(Sheen)
用于模拟织物、天鹅绒等材质。
javascript
material.sheen = 0; // 光泽强度(0-1)
material.sheenColor = new THREE.Color(0xffffff); // 光泽颜色
material.sheenRoughness = 1; // 光泽粗糙度
material.sheenColorMap = null; // 光泽颜色贴图
material.sheenRoughnessMap = null; // 光泽粗糙度贴图
// 天鹅绒材质示例
const velvetMaterial = new THREE.MeshPhysicalMaterial({
color: 0x800020,
metalness: 0,
roughness: 0.8,
sheen: 1.0,
sheenColor: new THREE.Color(0xff80ff),
sheenRoughness: 0.3
});镜面反射(Specular)
javascript
material.specularIntensity = 1.0; // 镜面强度
material.specularColor = new THREE.Color(0xffffff); // 镜面颜色
material.specularColorMap = null; // 镜面颜色贴图
material.specularIntensityMap = null; // 镜面强度贴图各向异性(Anisotropy)
用于模拟拉丝金属、头发等材质。
javascript
material.anisotropy = 0; // 各向异性强度(0-1)
material.anisotropyRotation = 0; // 各向异性旋转
material.anisotropyMap = null; // 各向异性贴图点材质属性
javascript
const material = new THREE.PointsMaterial({
// 颜色
color: 0xffffff,
// 大小
size: 1, // 点大小(像素)
sizeAttenuation: true, // 是否随距离衰减
// 纹理
map: null, // 纹理贴图
alphaMap: null, // 透明度贴图
alphaTest: 0, // Alpha 测试阈值
// 顶点颜色
vertexColors: false, // 是否使用顶点颜色
// 其他
transparent: false,
opacity: 1.0,
sizeAttenuation: true
});线条材质属性
LineBasicMaterial
javascript
const material = new THREE.LineBasicMaterial({
color: 0xffffff,
linewidth: 1, // 线宽(WebGL 通常只能为 1)
linecap: 'round', // 线端样式
linejoin: 'round', // 线连接样式
// 纹理
map: null,
alphaMap: null,
// 顶点颜色
vertexColors: false,
// 其他
transparent: false,
opacity: 1.0
});LineDashedMaterial
javascript
const material = new THREE.LineDashedMaterial({
// 基础属性
color: 0xffffff,
linewidth: 1,
// 虚线属性
dashSize: 3, // 虚线长度
gapSize: 1, // 间隔长度
scale: 1 // 缩放
// 注意:使用时必须调用 line.computeLineDistances()
});精灵材质属性
javascript
const material = new THREE.SpriteMaterial({
color: 0xffffff,
map: null, // 纹理贴图
alphaMap: null,
alphaTest: 0,
// 旋转
rotation: 0, // 旋转角度(弧度)
// 大小
sizeAttenuation: true, // 是否随距离衰减
// 其他
transparent: false,
opacity: 1.0
});着色器材质属性
javascript
const material = new THREE.ShaderMaterial({
// 着色器代码
vertexShader: '...',
fragmentShader: '...',
// Uniform 变量
uniforms: {
time: { value: 0 },
color: { value: new THREE.Color(0xff0000) }
},
// 属性
attributes: {}, // 自定义属性(已废弃,使用 BufferGeometry.setAttribute)
// 定义
defines: {
USE_MAP: true
},
// 渲染设置
side: THREE.FrontSide,
transparent: false,
depthTest: true,
depthWrite: true,
// 混合
blending: THREE.NormalBlending,
blendSrc: THREE.SrcAlphaFactor,
blendDst: THREE.OneMinusSrcAlphaFactor,
blendEquation: THREE.AddEquation,
// 扩展
extensions: {
derivatives: false, // 导数扩展
fragDepth: false, // 片元深度扩展
drawBuffers: false, // 绘制缓冲扩展
shaderTextureLOD: false // 纹理 LOD 扩展
},
// 其他
lights: false, // 是否接收光照
clipping: false, // 是否接收裁剪
fog: true // 是否接收雾效
});材质方法
更新方法
javascript
// 标记材质需要更新
material.needsUpdate = true;
// 设置值
material.setValues({
color: 0xff0000,
transparent: true,
opacity: 0.5
});
// 转换为 JSON
const json = material.toJSON();
// 从 JSON 恢复
const material2 = loader.parse(json);
// 克隆
const clonedMaterial = material.clone();
// 复制
material.copy(otherMaterial);
// 释放
material.dispose();颜色方法
javascript
// 设置颜色
material.color.set(0xff0000); // 十六进制
material.color.set('red'); // 颜色名称
material.color.set('rgb(255,0,0)'); // RGB 字符串
material.color.set('hsl(0,100%,50%)'); // HSL 字符串
// 获取颜色值
const hex = material.color.getHex();
const hexString = material.color.getHexString();
const hsl = {};
material.color.getHSL(hsl);
// 颜色转换
material.color.convertSRGBToLinear();
material.color.convertLinearToSRGB();使用示例
创建自定义材质配置
javascript
// 金属材质配置
function createMetalMaterial(color) {
return new THREE.MeshStandardMaterial({
color: color,
metalness: 1.0,
roughness: 0.2,
envMapIntensity: 1.0
});
}
// 玻璃材质配置
function createGlassMaterial() {
return new THREE.MeshPhysicalMaterial({
color: 0xffffff,
metalness: 0,
roughness: 0,
transmission: 0.95,
transparent: true,
ior: 1.5,
thickness: 0.5
});
}
// 织物材质配置
function createFabricMaterial(color) {
return new THREE.MeshPhysicalMaterial({
color: color,
metalness: 0,
roughness: 0.8,
sheen: 1.0,
sheenColor: new THREE.Color(0xffffff),
sheenRoughness: 0.5
});
}动态修改材质属性
javascript
const material = new THREE.MeshStandardMaterial({
color: 0xff0000,
metalness: 0.5,
roughness: 0.5
});
function updateMaterial(time) {
// 动态金属度
material.metalness = (Math.sin(time) + 1) / 2;
// 动态粗糙度
material.roughness = (Math.cos(time) + 1) / 2;
// 动态颜色
material.color.setHSL((time * 0.1) % 1, 1, 0.5);
// 如果修改了 uniforms 或着色器相关属性
material.needsUpdate = true;
}材质属性关系图
PBR 材质属性影响关系
plaintext
基础外观
├── color (漫反射颜色)
├── map (漫反射贴图)
├── opacity (透明度)
└── transparent (透明开关)
光照响应
├── metalness (金属度)
│ ├── 0: 非金属 → 有漫反射
│ └── 1: 金属 → 无漫反射,有金属反射
├── roughness (粗糙度)
│ ├── 0: 光滑 → 镜面反射
│ └── 1: 粗糙 → 漫反射
└── normalMap (法线贴图)
└── 影响表面法线,改变光照计算
环境交互
├── envMap (环境贴图)
│ └── 提供反射和间接光照
├── aoMap (环境光遮蔽)
│ └── 模拟角落和裂缝的遮蔽
└── lightMap (光照贴图)
└── 预计算的间接光照
高级效果 (MeshPhysicalMaterial)
├── clearcoat (清漆层)
│ └── 在基础层上添加第二层反射
├── transmission (透射)
│ └── 玻璃、水等透明材质
├── sheen (光泽)
│ └── 织物、天鹅绒等材质
└── ior (折射率)
└── 影响折射效果常见问题
1. 贴图不显示
问题:设置了贴图但材质上没有显示。
检查清单:
javascript
// 1. 检查几何体是否有 UV 坐标
console.log(geometry.attributes.uv); // 应该存在
// 2. 检查贴图是否加载成功
textureLoader.load('texture.jpg', (texture) => {
console.log('Texture loaded:', texture);
material.map = texture;
material.needsUpdate = true; // 触发更新
}, undefined, (error) => {
console.error('Texture load error:', error);
});
// 3. AO 贴图需要第二组 UV
if (material.aoMap) {
geometry.setAttribute('uv2', geometry.attributes.uv);
}
// 4. 检查材质是否正确应用
console.log('Material map:', material.map);2. 材质颜色与预期不符
问题:设置了颜色但显示不正确。
解决方案:
javascript
// 检查颜色空间
// Three.js 默认使用线性颜色空间
material.color = new THREE.Color(0xff0000);
// 如果贴图颜色不对,可能需要设置颜色空间
texture.colorSpace = THREE.SRGBColorSpace;
// 检查是否被其他贴图影响
// emissive 可能会影响最终颜色
material.emissive = new THREE.Color(0x000000);3. 透明物体渲染问题
问题:透明物体显示不正确。
解决方案:
javascript
// 正确的透明材质配置
material.transparent = true;
material.opacity = 0.5;
material.depthWrite = false; // 关键:禁用深度写入
material.side = THREE.DoubleSide; // 双面渲染
// 设置渲染顺序
mesh.renderOrder = 1; // 后渲染透明物体4. 法线贴图方向错误
问题:法线贴图让表面看起来是凹陷的而不是凸起的。
解决方案:
javascript
// 方法1:反转法线贴图的 Y 通道
material.normalScale.set(1, -1);
// 方法2:在图像编辑软件中翻转法线贴图的绿色通道5. 贴图重复或偏移
问题:贴图显示不正确,需要调整。
解决方案:
javascript
const texture = textureLoader.load('texture.jpg');
// 重复贴图
texture.wrapS = THREE.RepeatWrapping;
texture.wrapT = THREE.RepeatWrapping;
texture.repeat.set(2, 2); // 重复 2x2
// 偏移贴图
texture.offset.set(0.5, 0);
// 旋转贴图
texture.rotation = Math.PI / 4; // 旋转 45 度
texture.center.set(0.5, 0.5); // 旋转中心最佳实践
1. 属性设置建议
javascript
// ✅ 推荐:一次性设置所有属性
const material = new THREE.MeshStandardMaterial({
color: 0xff0000,
metalness: 0.5,
roughness: 0.5,
transparent: true,
opacity: 0.8
});
// ❌ 避免:多次单独设置(可能触发多次更新)
const material = new THREE.MeshStandardMaterial();
material.color = new THREE.Color(0xff0000);
material.metalness = 0.5;
// ... 多次设置2. 贴图优化
javascript
// ✅ 推荐:使用合并贴图(ORM)
const ormTexture = textureLoader.load('orm.jpg');
material.aoMap = ormTexture;
material.roughnessMap = ormTexture;
material.metalnessMap = ormTexture;
// ✅ 推荐:合理设置贴图尺寸
// 贴图尺寸应为 2 的幂次方:256, 512, 1024, 2048
// 根据物体重要性选择合适尺寸3. 性能优化
javascript
// ✅ 推荐:共享材质
const sharedMaterial = new THREE.MeshStandardMaterial({ color: 0x00ff00 });
meshes.forEach(mesh => mesh.material = sharedMaterial);
// ✅ 推荐:及时释放
material.dispose();
if (material.map) material.map.dispose();
// ✅ 推荐:合理选择材质类型
// 简单场景使用 MeshBasicMaterial
// 需要光照使用 MeshLambertMaterial
// 真实渲染使用 MeshStandardMaterial4. 调试技巧
javascript
// 使用 MeshNormalMaterial 调试法线
mesh.material = new THREE.MeshNormalMaterial();
// 使用线框模式查看几何体
material.wireframe = true;
// 打印材质信息
console.log('Material properties:', {
type: material.type,
color: material.color.getHex(),
metalness: material.metalness,
roughness: material.roughness,
transparent: material.transparent,
opacity: material.opacity
});