关于 substance-3d-texturing
substance-3d-texturing 是面向实时渲染与 Web 3D 制作者的 Substance 3D Painter 纹理工作流技能,涵盖 PBR 材质制作、导出与优化。它还介绍 Python 批量自动化,以及面向 glTF、Three.js 和 Babylon.js 的纹理准备。
主要功能
- 01金属度/粗糙度 PBR 材质制作
- 02面向 Web 与实时引擎的纹理导出
- 03Python API 批量导出
- 04纹理压缩与分辨率优化
- 05通道打包与自定义导出预设
适用场景
- 01为 glTF 资产导出 PBR 纹理
- 02批量处理多个纹理集
- 03为移动端 WebGL 压缩纹理
- 04将纹理接入 Three.js 或 Babylon.js
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ freshtechbro/ claudedesignskills --skill substance-3d-texturing安装后在 Claude Code 中输入/substance-3d-texturing确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
assets/README.mdassets/export_templates/babylonjs_pbr.jsongltf_standard.jsonmobile_webgl.jsonthreejs_optimized.jsonweb_orm_packed.jsonreferences/export_presets.mdpbr_channel_guide.mdpython_api_reference.mdscripts/batch_export.pygenerate_export_preset.pyweb_optimizer.py详细介绍
Substance 3D Texturing
概述
掌握面向 Web 和实时引擎的 PBR(基于物理的渲染)纹理创建与导出工作流。本技能涵盖 Substance 3D Painter 工作流,从材质创建到面向 Web 优化的纹理导出,并通过 Python 自动化实现批处理和与 WebGL/WebGPU 引擎的集成。
主要功能:
- PBR 材质制作(金属度/粗糙度工作流)
- 面向 Web 优化的纹理导出(glTF、Three.js、Babylon.js)
- 用于批量导出的 Python API 自动化
- 面向实时渲染的纹理压缩与优化
核心概念
PBR 工作流
Substance 3D Painter 使用金属度/粗糙度 PBR 工作流,包含以下核心通道:
基础纹理贴图:
baseColor(反照率)- RGB 漫反射颜色,不含光照信息normal- RGB 法线贴图(切线空间)metallic- 灰度金属度(0 = 电介质,1 = 金属)roughness- 灰度表面粗糙度(0 = 光滑/有光泽,1 = 粗糙/无光泽)
其他贴图:
ambientOcclusion(AO)- 灰度凹陷/遮蔽height- 灰度位移/高度emissive- RGB 自发光opacity- 灰度透明度
导出预设
Substance 3D Painter 内置了适用于常见引擎的导出预设:
- PBR Metallic Roughness - 标准 glTF/WebGL 格式
- Unity HDRP/URP - Unity 渲染管线
- Unreal Engine - UE4/UE5 格式
- Arnold (AiStandard) - 特定渲染器格式
对于 Web 引擎,PBR Metallic Roughness 是通用标准。
纹理分辨率
适用于 Web 的常见分辨率(2 的幂次):
- 512×512 - 低细节道具、移动设备
- 1024×1024 - 标准道具、角色
- 2048×2048 - 主体资产、特写
- 4096×4096 - 展示级画质(谨慎使用)
Web 优化规则: 从 1024×1024 开始,仅在纹理细节清晰可见时才提高分辨率。
常见模式
1. 基础 Web 导出(Three.js/Babylon.js)
单个纹理集的手动导出工作流:
步骤:
- 文件 → 导出纹理
- 选择预设:“PBR Metallic Roughness”
- 配置导出:
- 输出目录:选择目标文件夹
- 文件格式:PNG(8 位),用于 Web
- 填充: “Infinite”(防止接缝)
- 分辨率:1024×1024(根据资产调整)
- 导出
结果文件:
MyAsset_baseColor.png
MyAsset_normal.png
MyAsset_metallicRoughness.png // Packed: R=nothing, G=roughness, B=metallic
MyAsset_emissive.png // Optional
Three.js 用法:
import * as THREE from 'three';
const textureLoader = new THREE.TextureLoader();
const material = new THREE.MeshStandardMaterial({
map: textureLoader.load('MyAsset_baseColor.png'),
normalMap: textureLoader.load('MyAsset_normal.png'),
metalnessMap: textureLoader.load('MyAsset_metallicRoughness.png'),
roughnessMap: textureLoader.load('MyAsset_metallicRoughness.png'),
aoMap: textureLoader.load('MyAsset_ambientOcclusion.png'),
});
2. 使用 Python API 批量导出
自动导出多个纹理集:
import substance_painter.export
import substance_painter.resource
import substance_painter.textureset
# Define export preset
export_preset = substance_painter.resource.ResourceID(
context="starter_assets",
name="PBR Metallic Roughness"
)
# Configure export for all texture sets
config = {
"exportShaderParams": False,
"exportPath": "C:/export/web_textures",
"defaultExportPreset": export_preset.url(),
"exportList": [],
"exportParameters": [{
"parameters": {
"fileFormat": "png",
"bitDepth": "8",
"dithering": True,
"paddingAlgorithm": "infinite",
"sizeLog2": 10 // 1024×1024
}
}]
}
# Add all texture sets to export list
for texture_set in substance_painter.textureset.all_texture_sets():
config["exportList"].append({
"rootPath": texture_set.name()
})
# Execute export
result = substance_painter.export.export_project_textures(config)
if result.status == substance_painter.export.ExportStatus.Success:
for stack, files in result.textures.items():
print(f"Exported {stack}: {len(files)} textures")
else:
print(f"Export failed: {result.message}")
3. 按资产覆盖分辨率
为不同资产导出不同分辨率(例如,主体与背景):
config = {
"exportPath": "C:/export",
"defaultExportPreset": export_preset.url(),
"exportList": [
{"rootPath": "HeroCharacter"}, # Will use 2048 (override below)
{"rootPath": "BackgroundProp"} # Will use 512 (override below)
],
"exportParameters": [
{
"filter": {"dataPaths": ["HeroCharacter"]},
"parameters": {"sizeLog2": 11} # 2048×2048
},
{
"filter": {"dataPaths": ["BackgroundProp"]},
"parameters": {"sizeLog2": 9} # 512×512
}
]
}
4. 自定义导出预设(分离通道)
创建自定义预设,将金属度和粗糙度导出为单独文件:
custom_preset = {
"exportPresets": [{
"name": "WebGL_Separated",
"maps": [
{
"fileName": "$textureSet_baseColor",
"channels": [
{"destChannel": "R", "srcChannel": "R", "srcMapType": "documentMap", "srcMapName": "baseColor"},
{"destChannel": "G", "srcChannel": "G", "srcMapType": "documentMap", "srcMapName": "baseColor"},
{"destChannel": "B", "srcChannel": "B", "srcMapType": "documentMap", "srcMapName": "baseColor"}
]
},
{
"fileName": "$textureSet_normal",
"channels": [
{"destChannel": "R", "srcChannel": "R", "srcMapType": "documentMap", "srcMapName": "normal"},
{"destChannel": "G", "srcChannel": "G", "srcMapType": "documentMap", "srcMapName": "normal"},
{"destChannel": "B", "srcChannel": "B", "srcMapType": "documentMap", "srcMapName": "normal"}
]
},
{
"fileName": "$textureSet_metallic",
"channels": [
{"destChannel": "R", "srcChannel": "R", "srcMapType": "documentMap", "srcMapName": "metallic"}
],
"parameters": {"fileFormat": "png", "bitDepth": "8"}
},
{
"fileName": "$textureSet_roughness",
"channels": [
{"destChannel": "R", "srcChannel": "R", "srcMapType": "documentMap", "srcMapName": "roughness"}
],
"parameters": {"fileFormat": "png", "bitDepth": "8"}
}
]
}]
}
config = {
"exportPath": "C:/export",
"exportPresets": custom_preset["exportPresets"],
"exportList": [{"rootPath": "MyAsset", "exportPreset": "WebGL_Separated"}]
}
5. 面向移动设备优化的导出
针对移动端 WebGL 进行高强度压缩:
mobile_config = {
"exportPath": "C:/export/mobile",
"defaultExportPreset": export_preset.url(),
"exportList": [{"rootPath": texture_set.name()}],
"exportParameters": [{
"parameters": {
"fileFormat": "jpeg", # JPEG for baseColor (lossy but smaller)
"bitDepth": "8",
"sizeLog2": 9, # 512×512 maximum
"paddingAlgorithm": "infinite"
}
}, {
"filter": {"outputMaps": ["$textureSet_normal", "$textureSet_metallicRoughness"]},
"parameters": {
"fileFormat": "png" # PNG for data maps (need lossless)
}
}]
}
导出后: 使用 pngquant 或 tinypng 等工具进一步压缩。
6. glTF/GLB 集成
为 glTF 2.0 格式导出纹理:
gltf_config = {
"exportPath": "C:/export/gltf",
"defaultExportPreset": substance_painter.resource.ResourceID(
context="starter_assets",
name="PBR Metallic Roughness"
).url(),
"exportList": [{"rootPath": texture_set.name()}],
"exportParameters": [{
"parameters": {
"fileFormat": "png",
"bitDepth": "8",
"sizeLog2": 10, # 1024×1024
"paddingAlgorithm": "infinite"
}
}]
}
# After export, reference in glTF:
# {
# "materials": [{
# "name": "Material",
# "pbrMetallicRoughness": {
# "baseColorTexture": {"index": 0},
# "metallicRoughnessTexture": {"index": 1}
# },
# "normalTexture": {"index": 2}
# }]
# }
7. 事件驱动的导出插件
使用 Python 插件在保存时自动导出:
import substance_painter.event
import substance_painter.export
import substance_painter.project
def auto_export(e):
if not substance_painter.project.is_open():
return
config = {
"exportPath": substance_painter.project.file_path().replace('.spp', '_textures'),
"defaultExportPreset": substance_painter.resource.ResourceID(
context="starter_assets", name="PBR Metallic Roughness"
).url(),
"exportList": [{"rootPath": ts.name()} for ts in substance_painter.textureset.all_texture_sets()],
"exportParameters": [{
"parameters": {"fileFormat": "png", "bitDepth": "8", "sizeLog2": 10}
}]
}
substance_painter.export.export_project_textures(config)
print("Auto-export completed")
# Register event
substance_painter.event.DISPATCHER.connect(
substance_painter.event.ProjectSaved,
auto_export
)
集成模式
Three.js + React Three Fiber
在 R3F 中使用导出的纹理:
import { useTexture } from '@react-three/drei';
function TexturedMesh() {
const [baseColor, normal, metallicRoughness, ao] = useTexture([
'/textures/Asset_baseColor.png',
'/textures/Asset_normal.png',
'/textures/Asset_metallicRoughness.png',
'/textures/Asset_ambientOcclusion.png',
]);
return (
<mesh>
<boxGeometry />
<meshStandardMaterial
map={baseColor}
normalMap={normal}
metalnessMap={metallicRoughness}
roughnessMap={metallicRoughness}
aoMap={ao}
/>
</mesh>
);
}
有关高级 R3F 材质工作流,请参阅 react-three-fiber 技能。
Babylon.js PBR 材质
import { PBRMaterial, Texture } from '@babylonjs/core';
const pbr = new PBRMaterial("pbr", scene);
pbr.albedoTexture = new Texture("/textures/Asset_baseColor.png", scene);
pbr.bumpTexture = new Texture("/textures/Asset_normal.png", scene);
pbr.metallicTexture = new Texture("/textures/Asset_metallicRoughness.png", scene);
pbr.useRoughnessFromMetallicTextureAlpha = false;
pbr.useRoughnessFromMetallicTextureGreen = true;
pbr.useMetallnessFromMetallicTextureBlue = true;
有关高级 PBR 工作流,请参阅 babylonjs-engine 技能。
GLTF 导出管线
- 从 Substance 导出纹理(如上所述)
- 使用 Blender 的 glTF 导出器导出模型
- 在
.gltfJSON 中引用 Substance 纹理 - 使用
gltf-pipeline进行 Draco 压缩:
gltf-pipeline -i model.gltf -o model.glb -d
有关完整的 3D 资产管线,请参阅 blender-web-pipeline 技能。
性能优化
纹理大小预算
桌面 WebGL: 总纹理内存约 100–150MB
移动端 WebGL: 总纹理内存约 30–50MB
每个资产的预算:
- 背景/道具:512×512(每张纹理 1MB × 4 张贴图 = 4MB)
- 标准资产:1024×1024(每张纹理 4MB × 4 张贴图 = 16MB)
- 主体资产:2048×2048(每张纹理 16MB × 4 张贴图 = 64MB)
压缩策略
- baseColor 使用 JPEG(70-80% 质量)——比 PNG 小 10×
- 数据贴图使用 PNG-8(法线、金属度、粗糙度)——需要无损压缩
- Basis Universal(
.basis)——GPU 纹理压缩(缩小 90%) - 纹理图集——将多个资源合并到一张纹理中
通道打包
将灰度贴图打包到 RGB 通道中,以减少纹理数量:
打包 ORM(环境光遮蔽-粗糙度-金属度):
- 红色:环境光遮蔽
- 绿色:粗糙度
- 蓝色:金属度
在 Substance 中导出:
orm_map = {
"fileName": "$textureSet_ORM",
"channels": [
{"destChannel": "R", "srcChannel": "R", "srcMapType": "documentMap", "srcMapName": "ambientOcclusion"},
{"destChannel": "G", "srcChannel": "R", "srcMapType": "documentMap", "srcMapName": "roughness"},
{"destChannel": "B", "srcChannel": "R", "srcMapType": "documentMap", "srcMapName": "metallic"}
]
}
Mipmap
对于远距离查看的纹理,务必在引擎中启用 mipmap:
// Three.js (automatic)
texture.generateMipmaps = true;
// Babylon.js
texture.updateSamplingMode(Texture.TRILINEAR_SAMPLINGMODE);
常见问题
1. BaseColor 的颜色空间错误
**问题:**以线性空间导出的 BaseColor 看起来褪色。
**解决方案:**Substance 默认以 sRGB 导出 baseColor(正确)。确保引擎使用 sRGB:
// Three.js
baseColorTexture.colorSpace = THREE.SRGBColorSpace;
// Babylon.js (automatic for albedoTexture)
2. 法线贴图烘焙问题
**问题:**法线贴图显示反转或不正确的着色。
解决方案:
- 确认切线空间法线格式(DirectX 与 OpenGL 的 Y 轴翻转)
- Substance 使用 OpenGL(Y+),与 glTF 标准相同
- 如果使用 DirectX 引擎,请在导出时翻转绿色通道
3. 金属度/粗糙度通道顺序
**问题:**金属度/粗糙度纹理的通道顺序错误。
**解决方案:**Substance 默认导出设置:
- 蓝色通道 = 金属度
- 绿色通道 = 粗糙度
- 符合 glTF 2.0 规范
4. UV 接缝处的填充伪影
**问题:**UV 接缝处出现黑线或彩色线条。
**解决方案:**在导出设置中将填充算法设为 “无限”:
"paddingAlgorithm": "infinite"
5. Web 纹理过大
**问题:**4K 纹理会导致 Web 加载时间过长和内存问题。
解决方案:
- Web 默认使用 1024×1024
- 仅对近距离查看的主视觉资源使用 2048×2048
- 使用多个分辨率集实现 LOD 系统
6. 引擎中缺少 AO 贴图
**问题:**AO 贴图已导出,但在引擎中不可见。
解决方案:
- Three.js:需要第二个 UV 通道(
geometry.attributes.uv2) - Babylon.js:设置
material.useAmbientOcclusionFromMetallicTextureRed = true - 替代方案:在 Substance 中将 AO 烘焙到 baseColor 中
资源
完整工作流请参阅随附资源:
- references/python_api_reference.md - 完整的 Substance Painter Python API
- references/export_presets.md - 内置和自定义导出预设目录
- references/pbr_channel_guide.md - 深入了解 PBR 纹理通道
- scripts/batch_export.py - 批量导出所有纹理集
- scripts/web_optimizer.py - 针对 Web 对纹理进行后处理(调整大小、压缩)
- scripts/generate_export_preset.py - 创建自定义导出预设 JSON
- assets/export_templates/ - 为 Three.js、Babylon.js、Unity 预配置的导出预设
相关技能
- blender-web-pipeline - 完整的 3D 模型 → 纹理 → Web 工作流
- threejs-webgl - 在 Three.js 中加载和使用 PBR 纹理
- react-three-fiber - 使用 Substance 纹理的 R3F 材质工作流
- babylonjs-engine - Babylon.js PBR 材质系统集成