mcpField
B
blender-web-pipeline

blender-web-pipeline

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

关于 blender-web-pipeline

blender-web-pipeline 是将 Blender 模型和动画导出为适合网页使用格式的技能指南,主要围绕 glTF 2.0。它面向资产制作与 Web 3D 流程,涵盖 Python 自动化、批量处理和模型优化。

主要功能

  1. 01导出并优化 glTF 2.0
  2. 02使用 Python(bpy)自动化
  3. 03批量处理 Blender 文件
  4. 04纹理烘焙与压缩
  5. 05生成 LOD 模型
  6. 06优化几何体和材质

适用场景

  1. 01将 Blender 资产导出为 GLB
  2. 02批量转换 3D 模型
  3. 03为网页交付优化模型与纹理
  4. 04搭建 Web 3D 资产生产流程

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/freshtechbro/claudedesignskills --skill blender-web-pipeline

安装后在 Claude Code 中输入/blender-web-pipeline确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

assets/
README.md
references/
bpy_api_reference.md
gltf_export_guide.md
optimization_strategies.md
scripts/
batch_export.py
generate_lods.py
optimize_model.py

详细介绍

Blender Web Pipeline

概述

Blender Web Pipeline 技能提供了将 3D 模型和动画从 Blender 导出为适合 Web 的格式(主要是 glTF 2.0)的工作流。内容涵盖用于批量处理的 Python 脚本、提升 Web 性能的优化技术,以及与 Three.js 和 Babylon.js 等 Web 3D 库的集成。

适用场景:

  • 为 Web 应用导出 Blender 模型
  • 批量处理多个 3D 资源
  • 优化文件大小以便通过 Web 交付
  • 自动执行重复的 Blender 任务
  • 为 3D Web 内容创建生产流水线
  • 将旧格式转换为 glTF

主要功能:

  • 支持优化的 glTF 2.0 导出
  • Python(bpy)自动化脚本
  • 纹理烘焙与压缩
  • LOD(细节层次)生成
  • 批量处理工作流
  • 面向 Web 的材质与光照优化

核心概念

glTF 2.0 格式

为什么选择 glTF 用于 Web:

  • Web 领域的行业标准 3D 格式
  • 高效的二进制编码(.glb)
  • 支持 PBR 材质
  • 支持动画和蒙皮
  • 可通过自定义数据扩展
  • 库支持广泛(Three.js、Babylon.js 等)

glTF 与 GLB 的区别:

.gltf = JSON + external .bin + external textures
.glb  = Single binary file (recommended for web)
Blender Python API(bpy)

通过 Python 访问 Blender 数据和操作:

import bpy

# Access scene data
scene = bpy.context.scene
objects = bpy.data.objects

# Modify objects
obj = bpy.data.objects['Cube']
obj.location = (0, 0, 1)
obj.scale = (2, 2, 2)

# Export glTF
bpy.ops.export_scene.gltf(
    filepath='/path/to/model.glb',
    export_format='GLB'
)
Web 优化目标

目标指标:

  • 文件大小:每个模型 <5 MB(理想值 <1 MB)
  • 多边形数量:实时使用时 <50k 个三角形
  • 纹理分辨率:最高 2048x2048(优先使用 1024x1024)
  • 绘制调用:通过纹理图集尽量减少
  • 加载时间:在平均网络连接下 <2 秒

常见模式

1. 基本 glTF 导出(手动)
# Blender Python Console or script

import bpy

# Select objects to export (optional - exports all if none selected)
bpy.ops.object.select_all(action='DESELECT')
bpy.data.objects['MyModel'].select_set(True)

# Export as GLB
bpy.ops.export_scene.gltf(
    filepath='/path/to/output.glb',
    export_format='GLB',                # Binary format
    use_selection=True,                 # Export selected only
    export_apply=True,                  # Apply modifiers
    export_texcoords=True,              # UV coordinates
    export_normals=True,                # Normals
    export_materials='EXPORT',          # Export materials
    export_colors=True,                 # Vertex colors
    export_cameras=False,               # Skip cameras
    export_lights=False,                # Skip lights
    export_animations=True,             # Include animations
    export_draco_mesh_compression_enable=True,  # Compress geometry
    export_draco_mesh_compression_level=6,      # 0-10 (6 recommended)
    export_draco_position_quantization=14,      # 8-14 bits
    export_draco_normal_quantization=10,        # 8-10 bits
    export_draco_texcoord_quantization=12       # 8-12 bits
)
2. 用于批量导出的 Python 脚本
#!/usr/bin/env blender --background --python
"""
Batch export all .blend files in a directory to glTF
Usage: blender --background --python batch_export.py -- /path/to/blend/files
"""

import bpy
import os
import sys

# Get command line arguments after --
argv = sys.argv
argv = argv[argv.index("--") + 1:] if "--" in argv else []

input_dir = argv[0] if argv else "/path/to/models"
output_dir = argv[1] if len(argv) > 1 else input_dir + "_gltf"

# Create output directory
os.makedirs(output_dir, exist_ok=True)

# Find all .blend files
blend_files = [f for f in os.listdir(input_dir) if f.endswith('.blend')]

print(f"Found {len(blend_files)} .blend files")

for blend_file in blend_files:
    input_path = os.path.join(input_dir, blend_file)
    output_name = blend_file.replace('.blend', '.glb')
    output_path = os.path.join(output_dir, output_name)

    print(f"Processing: {blend_file}")

    # Open blend file
    bpy.ops.wm.open_mainfile(filepath=input_path)

    # Export as GLB with optimizations
    bpy.ops.export_scene.gltf(
        filepath=output_path,
        export_format='GLB',
        export_apply=True,
        export_draco_mesh_compression_enable=True,
        export_draco_mesh_compression_level=6
    )

    print(f"  Exported: {output_name}")

print("Batch export complete!")

运行批处理脚本:

blender --background --python batch_export.py -- /models/source /models/output
3. 优化面向 Web 的模型(简化)
import bpy

def optimize_mesh(obj, target_ratio=0.5):
    """Reduce polygon count using decimation modifier."""

    if obj.type != 'MESH':
        return

    # Add Decimate modifier
    decimate = obj.modifiers.new(name='Decimate', type='DECIMATE')
    decimate.ratio = target_ratio  # 0.5 = 50% of original polygons
    decimate.use_collapse_triangulate = True

    # Apply modifier
    bpy.context.view_layer.objects.active = obj
    bpy.ops.object.modifier_apply(modifier='Decimate')

    print(f"Optimized {obj.name}: {len(obj.data.polygons)} polygons")

# Optimize all selected meshes
for obj in bpy.context.selected_objects:
    optimize_mesh(obj, target_ratio=0.3)
4. 面向 Web 的纹理烘焙
import bpy

def bake_textures(obj, resolution=1024):
    """Bake all materials to single texture."""

    # Setup bake settings
    bpy.context.scene.render.engine = 'CYCLES'
    bpy.context.scene.cycles.bake_type = 'COMBINED'

    # Create bake image
    bake_image = bpy.data.images.new(
        name=f"{obj.name}_bake",
        width=resolution,
        height=resolution
    )

    # Create bake material
    mat = bpy.data.materials.new(name=f"{obj.name}_baked")
    mat.use_nodes = True
    nodes = mat.node_tree.nodes

    # Add Image Texture node
    tex_node = nodes.new(type='ShaderNodeTexImage')
    tex_node.image = bake_image
    tex_node.select = True
    nodes.active = tex_node

    # Assign material
    if obj.data.materials:
        obj.data.materials[0] = mat
    else:
        obj.data.materials.append(mat)

    # Select object
    bpy.context.view_layer.objects.active = obj
    obj.select_set(True)

    # Bake
    bpy.ops.object.bake(type='COMBINED')

    # Save baked texture
    bake_image.filepath_raw = f"/tmp/{obj.name}_bake.png"
    bake_image.file_format = 'PNG'
    bake_image.save()

    print(f"Baked {obj.name} to {bake_image.filepath_raw}")

# Bake selected objects
for obj in bpy.context.selected_objects:
    if obj.type == 'MESH':
        bake_textures(obj, resolution=2048)
5. 生成 LOD(细节层次)
import bpy

def generate_lods(obj, lod_levels=[0.75, 0.5, 0.25]):
    """Generate LOD copies with decreasing polygon counts."""

    lod_objects = []

    for i, ratio in enumerate(lod_levels):
        # Duplicate object
        lod_obj = obj.copy()
        lod_obj.data = obj.data.copy()
        lod_obj.name = f"{obj.name}_LOD{i}"

        # Link to scene
        bpy.context.collection.objects.link(lod_obj)

        # Add Decimate modifier
        decimate = lod_obj.modifiers.new(name='Decimate', type='DECIMATE')
        decimate.ratio = ratio

        # Apply modifier
        bpy.context.view_layer.objects.active = lod_obj
        bpy.ops.object.modifier_apply(modifier='Decimate')

        lod_objects.append(lod_obj)

        print(f"Created {lod_obj.name}: {len(lod_obj.data.polygons)} polygons")

    return lod_objects

# Generate LODs for selected object
if bpy.context.active_object:
    generate_lods(bpy.context.active_object)
6. 使用纹理压缩导出
import bpy
import os

def export_optimized_gltf(filepath, texture_max_size=1024):
    """Export glTF with downscaled textures."""

    # Downscale all textures
    for img in bpy.data.images:
        if img.size[0] > texture_max_size or img.size[1] > texture_max_size:
            img.scale(texture_max_size, texture_max_size)
            print(f"Downscaled {img.name} to {texture_max_size}x{texture_max_size}")

    # Export with Draco compression
    bpy.ops.export_scene.gltf(
        filepath=filepath,
        export_format='GLB',
        export_apply=True,
        export_image_format='JPEG',  # JPEG for smaller size (or PNG for quality)
        export_jpeg_quality=85,       # 0-100
        export_draco_mesh_compression_enable=True,
        export_draco_mesh_compression_level=8,  # Max compression
        export_draco_position_quantization=12,
        export_draco_normal_quantization=8,
        export_draco_texcoord_quantization=10
    )

# Export optimized
export_optimized_gltf('/path/to/optimized.glb', texture_max_size=512)
7. 命令行自动化
#!/bin/bash
# Batch export Blender files to glTF without opening GUI

SCRIPT_DIR="$(dirname "$0")"

# Export all .blend files in current directory
for blend_file in *.blend; do
    echo "Exporting $blend_file..."

    blender --background "$blend_file" --python - <<EOF
import bpy
import os

# Get output filename
filename = os.path.splitext(bpy.data.filepath)[0]
output = filename + '.glb'

# Export
bpy.ops.export_scene.gltf(
    filepath=output,
    export_format='GLB',
    export_apply=True,
    export_draco_mesh_compression_enable=True,
    export_draco_mesh_compression_level=6
)

print(f'Exported to {output}')
EOF

done

echo "All files exported!"

集成模式

与 Three.js 集成
import * as THREE from 'three';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js';

const loader = new GLTFLoader();

// Setup Draco decoder for compressed models
const dracoLoader = new DRACOLoader();
dracoLoader.setDecoderPath('/draco/');
loader.setDRACOLoader(dracoLoader);

// Load Blender export
loader.load('/models/exported.glb', (gltf) => {
  scene.add(gltf.scene);

  // Play animations
  if (gltf.animations.length > 0) {
    const mixer = new THREE.AnimationMixer(gltf.scene);
    const action = mixer.clipAction(gltf.animations[0]);
    action.play();
  }
});
与 React Three Fiber 集成
import { useGLTF } from '@react-three/drei';

function Model() {
  const { scene } = useGLTF('/models/exported.glb');
  return <primitive object={scene} />;
}

// Preload for better performance
useGLTF.preload('/models/exported.glb');
与 Babylon.js 集成
import * as BABYLON from '@babylonjs/core';
import '@babylonjs/loaders/glTF';

BABYLON.SceneLoader.ImportMesh(
  '',
  '/models/',
  'exported.glb',
  scene,
  (meshes) => {
    console.log('Loaded meshes:', meshes);
  }
);

优化技术

1. 几何体优化

简化修改器:

# Reduce polygon count by 70%
obj.modifiers.new(name='Decimate', type='DECIMATE')
obj.modifiers['Decimate'].ratio = 0.3

按距离合并:

# Remove duplicate vertices
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.mesh.remove_doubles(threshold=0.0001)
bpy.ops.object.mode_set(mode='OBJECT')

三角化面:

# Ensure all faces are triangles (required for some engines)
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.mesh.quads_convert_to_tris()
bpy.ops.object.mode_set(mode='OBJECT')
2. 纹理优化

图像压缩:

# Save textures as JPEG (lossy but smaller)
for img in bpy.data.images:
    img.file_format = 'JPEG'
    img.filepath_raw = f"/output/{img.name}.jpg"
    img.save()

纹理图集:

# Combine multiple textures into one atlas
# Use Smart UV Project for automatic atlasing
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.uv.smart_project(angle_limit=66, island_margin=0.02)
bpy.ops.object.mode_set(mode='OBJECT')
3. 材质简化

转换为 PBR:

# Ensure materials use Principled BSDF (glTF standard)
for mat in bpy.data.materials:
    if not mat.use_nodes:
        mat.use_nodes = True

    nodes = mat.node_tree.nodes
    principled = nodes.get('Principled BSDF')

    if not principled:
        principled = nodes.new(type='ShaderNodeBsdfPrincipled')
        output = nodes.get('Material Output')
        mat.node_tree.links.new(principled.outputs[0], output.inputs[0])

常见问题

1. 文件过大

问题: 导出的 .glb 文件超过 20 MB

解决方案:

  • 启用 Draco 压缩(可减少 60-90%)
  • 降低纹理分辨率(2048 → 1024 或 512)
  • 纹理使用 JPEG 而不是 PNG
  • 简化几何体(目标为 <50k 个三角形)
  • 移除未使用的材质/纹理
2. 导出时缺少纹理

问题: 纹理未在 Web 查看器中显示

解决方案:

  • 确保所有图像都已保存(而非打包)
  • 纹理使用相对路径
  • 导出时启用“Export Images”
  • 检查图像格式是否兼容(PNG/JPEG)
3. 动画无法播放

问题: 动画未导出或播放异常

解决方案:

  • 确保动画位于时间轴上(而非 NLA 条带中)
  • 导出时启用“Export Animations”
  • 检查动画动作是否已分配给对象
  • 对复杂骨架使用“Bake Actions”
4. 材质外观不同

问题: 材质在 Web 中的渲染效果与 Blender 中不同

解决方案:

  • 使用 Principled BSDF(可映射到 glTF PBR)
  • 避免使用自定义着色器节点(无法导出)
  • 使用支持的纹理类型(Base Color、Metallic、Roughness、Normal、Emission)
  • 部署前在 glTF 查看器中测试
5. 导出耗时过长

问题: 导出耗时超过 10 分钟

解决方案:

  • 导出前应用修改器(不要以非破坏性方式导出)
  • 降低几何体复杂度
  • 移除未使用的数据(清理孤立数据)
  • 使用命令行导出(比图形界面更快)
6. 浏览器中的性能问题

问题: 模型在浏览器中运行卡顿

解决方案:

  • 生成 LOD(细节层次)
  • 对重复对象使用实例化
  • 限制绘制调用次数(合并对象、使用纹理图集)
  • 减少多边形数量(少于 50k 个三角形)
  • 优化着色器(避免透明效果和折射)

最佳实践

导出前检查清单
☐ Apply all modifiers
☐ Merge vertices (remove doubles)
☐ Triangulate faces (if required)
☐ Optimize polygon count (<50k triangles)
☐ UV unwrap all meshes
☐ Bake materials (if complex)
☐ Resize textures (max 2048x2048)
☐ Use Principled BSDF materials
☐ Remove unused data (orphan cleanup)
☐ Name objects descriptively
☐ Set origin points correctly
☐ Apply transformations (Ctrl+A)
导出设置
# Recommended glTF export settings
bpy.ops.export_scene.gltf(
    filepath='/output.glb',
    export_format='GLB',                # Binary format
    export_apply=True,                  # Apply modifiers
    export_image_format='JPEG',         # Smaller file size
    export_jpeg_quality=85,             # Quality vs size
    export_draco_mesh_compression_enable=True,  # Enable compression
    export_draco_mesh_compression_level=6,      # Balance speed/size
    export_animations=True,             # Include animations
    export_lights=False,                # Skip lights (recreate in code)
    export_cameras=False                # Skip cameras
)

资源

此技能包含:

scripts/
  • batch_export.py - 将 .blend 文件批量导出为 glTF
  • optimize_model.py - 针对 Web 优化几何体和纹理
  • generate_lods.py - 自动生成 LOD 副本
references/
  • gltf_export_guide.md - 完整的 glTF 导出参考
  • bpy_api_reference.md - Blender Python API 快速参考
  • optimization_strategies.md - 详细的优化技巧
assets/
  • export_template.blend - 预配置的导出模板
  • shader_library/ - 针对 Web 优化的 PBR 着色器

相关技能

  • threejs-webgl - 在 Three.js 中加载并渲染导出的 glTF 模型
  • react-three-fiber - 在 React 应用中使用 glTF 模型
  • babylonjs-engine - 可用于 Web 的替代 3D 引擎
  • playcanvas-engine - 支持导入 glTF 的游戏引擎

评论

支持 Markdown