mcpField
S
substance-3d-texturing

substance-3d-texturing

github.com/freshtechbro创意与媒体1.2k2.4k 次安装49 周前更新
代码仓库

关于 substance-3d-texturing

substance-3d-texturing 是面向实时渲染与 Web 3D 制作者的 Substance 3D Painter 纹理工作流技能,涵盖 PBR 材质制作、导出与优化。它还介绍 Python 批量自动化,以及面向 glTF、Three.js 和 Babylon.js 的纹理准备。

主要功能

  1. 01金属度/粗糙度 PBR 材质制作
  2. 02面向 Web 与实时引擎的纹理导出
  3. 03Python API 批量导出
  4. 04纹理压缩与分辨率优化
  5. 05通道打包与自定义导出预设

适用场景

  1. 01为 glTF 资产导出 PBR 纹理
  2. 02批量处理多个纹理集
  3. 03为移动端 WebGL 压缩纹理
  4. 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.md
assets/export_templates/
babylonjs_pbr.json
gltf_standard.json
mobile_webgl.json
threejs_optimized.json
web_orm_packed.json
references/
export_presets.md
pbr_channel_guide.md
python_api_reference.md
scripts/
batch_export.py
generate_export_preset.py
web_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)

单个纹理集的手动导出工作流:

步骤:

  1. 文件 → 导出纹理
  2. 选择预设:“PBR Metallic Roughness”
  3. 配置导出:
    • 输出目录:选择目标文件夹
    • 文件格式:PNG(8 位),用于 Web
    • 填充: “Infinite”(防止接缝)
    • 分辨率:1024×1024(根据资产调整)
  4. 导出

结果文件:

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 导出管线
  1. 从 Substance 导出纹理(如上所述)
  2. 使用 Blender 的 glTF 导出器导出模型
  3. 在 .gltf JSON 中引用 Substance 纹理
  4. 使用 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)
压缩策略
  1. baseColor 使用 JPEG(70-80% 质量)——比 PNG 小 10×
  2. 数据贴图使用 PNG-8(法线、金属度、粗糙度)——需要无损压缩
  3. Basis Universal(.basis)——GPU 纹理压缩(缩小 90%)
  4. 纹理图集——将多个资源合并到一张纹理中
通道打包

将灰度贴图打包到 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 材质系统集成

评论

支持 Markdown