返回 Skill 列表
extension
分类: 内容与媒体无需 API Key

asset-pipeline-3d

优化并准备3D资源以供网页传输。在处理GLTF/GLB文件、压缩3D模型、优化纹理、设置Blender导出或为Three.js/R3F准备资源时使用此技能。涵盖GLTF工作流程、Draco/meshopt压缩、纹理优化、LOD生成和性能分析。

person作者: jakexiaohubgithub

3D Asset Pipeline

Prepare and optimize 3D assets for performant web delivery.

Tool Versions (2026)

  • gltf-transform: v4+
  • Meshoptimizer: v0.21+
  • Basis Universal: v1.16+
  • Blender: 4.2+

Decision Frameworks

When to Use Which Compression

Geometry Compression:
├─ Need fastest decode time? → Meshopt (recommended)
├─ Need smallest file size? → Draco (10-20% smaller)
├─ Animated models (skinned/morphs)? → Meshopt (better animation support)
├─ Static meshes only? → Either works
└─ Maximum compatibility? → No compression (larger files)

Texture Compression:
├─ GPU-compressed (fastest rendering)? → KTX2/Basis Universal
├─ Good balance (size vs quality)? → WebP
├─ Best quality at cost of size? → PNG (lossless) or AVIF
├─ Need alpha channel? → WebP, PNG, KTX2, or AVIF
└─ Photo textures, no alpha? → JPEG or WebP

When to Use Which Pipeline

Single hero model (product viewer)?
  → gltf-transform optimize with high quality settings

Many similar models (e-commerce)?
  → Batch processing script with consistent settings

Game assets (performance critical)?
  → Aggressive compression + LODs + texture atlases

Architectural visualization?
  → High poly + baked lighting + KTX2 textures

Real-time application?
  → Meshopt + KTX2 + LODs + strict budgets

Compression Decision Matrix

| Scenario | Geometry | Textures | LODs | |----------|----------|----------|------| | Product viewer | Meshopt | WebP/KTX2 | Optional | | Game assets | Meshopt | KTX2 | Required | | Archviz | Meshopt | KTX2 2048px | Per-room | | Mobile | Meshopt | KTX2 512-1024px | Required | | E-commerce batch | Draco (smaller) | WebP | Optional |

GLTF/GLB Overview

GLTF (GL Transmission Format) is the standard for web 3D. GLB is the binary version (single file).

GLTF supports:

  • Meshes, materials (PBR), textures
  • Skeletal animations, morph targets
  • Scene hierarchy, cameras, lights
  • Extensions for advanced features

File structure:

  • .gltf - JSON with external binary/textures
  • .glb - Single binary file (preferred for web)

Compression Tools

gltf-transform (Recommended)

Node.js CLI for GLTF optimization. Install: npm install -g @gltf-transform/cli

# Meshopt compression (recommended - faster decode)
gltf-transform meshopt input.glb output.glb

# Draco compression (smaller files, slower decode)
gltf-transform draco input.glb output.glb

# Texture compression to KTX2/Basis (GPU-compressed)
gltf-transform ktx input.glb output.glb --compress uastc

# Full optimization pipeline (2026 recommended)
gltf-transform optimize input.glb output.glb \
  --compress meshopt \
  --texture-compress ktx2

# WebP textures (good balance, wider support)
gltf-transform optimize input.glb output.glb \
  --compress meshopt \
  --texture-compress webp

# Resize textures (power of 2)
gltf-transform resize input.glb output.glb --width 1024 --height 1024

# Flatten scene hierarchy (reduces draw calls)
gltf-transform flatten input.glb output.glb

# Merge meshes sharing materials
gltf-transform join input.glb output.glb

# Remove unused data
gltf-transform prune input.glb output.glb

# Deduplicate accessors
gltf-transform dedup input.glb output.glb

# Generate simplified LOD
gltf-transform simplify input.glb output.glb --ratio 0.5 --error 0.001

# Full production pipeline
gltf-transform optimize input.glb output.glb \
  --compress meshopt \
  --texture-compress ktx2 \
  --texture-size 1024

gltfpack

Alternative CLI (part of meshoptimizer). Faster, less flexible.

# Basic optimization
gltfpack -i input.glb -o output.glb

# With Meshopt compression
gltfpack -i input.glb -o output.glb -cc

# With KTX2 texture compression
gltfpack -i input.glb -o output.glb -tc

# Simplify (50% triangle reduction)
gltfpack -i input.glb -o output.glb -si 0.5

# All optimizations (production ready)
gltfpack -i input.glb -o output.glb -cc -tc -si 0.5

Texture Optimization

Format Selection

| Format | Use Case | Alpha | Compression | GPU Decode | |--------|----------|-------|-------------|------------| | KTX2/Basis | GPU-compressed (best) | Yes | UASTC/ETC1S | Native | | WebP | General textures | Yes | Lossy/Lossless | CPU | | AVIF | Best file compression | Yes | Lossy | CPU | | JPEG | Photos, no alpha | No | Lossy | CPU | | PNG | UI, sharp edges | Yes | Lossless | CPU |

KTX2/Basis Universal is preferred for 2026 - textures stay compressed in GPU memory.

Size Guidelines

| Texture Type | Mobile | Desktop | Notes | |--------------|--------|---------|-------| | Diffuse/Albedo | 512-1024 | 1024-2048 | sRGB color space | | Normal | 512-1024 | 1024-2048 | Linear, tangent space | | Roughness/Metal | 256-512 | 512-1024 | Linear, can pack | | AO | 256-512 | 512-1024 | Linear, can pack | | Environment | 256-512 | 512-1024 | HDR for reflections |

Power of 2: Always use power-of-2 dimensions (256, 512, 1024, 2048) for mipmapping.

Compression Commands

# ImageMagick - resize and convert
magick input.png -resize 1024x1024 -quality 85 output.webp

# cwebp (WebP)
cwebp -q 80 input.png -o output.webp

# Basis Universal (KTX2) - high quality UASTC
basisu -uastc -uastc_level 2 input.png -output_file output.ktx2

# Basis Universal - smaller ETC1S (lower quality)
basisu input.png -output_file output.ktx2

# toktx (Khronos tool)
toktx --t2 --uastc 2 output.ktx2 input.png

# Squoosh CLI (WebP/AVIF)
squoosh-cli --webp '{quality:80}' input.png
squoosh-cli --avif '{quality:60}' input.png

Channel Packing (ORM)

Combine grayscale maps into RGBA channels to reduce texture count:

R: Ambient Occlusion
G: Roughness
B: Metalness
A: (unused or height)
// Three.js with packed ORM texture
const ormTexture = textureLoader.load('/orm.png')
ormTexture.colorSpace = THREE.LinearSRGBColorSpace

const material = new THREE.MeshStandardNodeMaterial({
  aoMap: ormTexture,
  roughnessMap: ormTexture,
  metalnessMap: ormTexture,
  // Channel selection happens automatically in ORM workflow
})

Blender Export Settings

GLTF Export Checklist

  1. Apply transforms: Ctrl+A → All Transforms
  2. Apply modifiers: Check "Apply Modifiers" in export
  3. Check scale: Blender default 1 unit = 1 meter
  4. Clean up: Remove unused materials, objects, shape keys

Export Settings (Blender 4.2+)

Format: GLB (single file)

Include:
  [x] Selected Objects (if exporting subset)
  [x] Custom Properties
  [x] Cameras (if needed)
  [x] Punctual Lights (if needed)

Transform:
  +Y Up (standard for web)

Data:
  Mesh:
    [x] Apply Modifiers
    [x] UVs
    [x] Normals
    [ ] Tangents (let Three.js compute)
    [ ] Vertex Colors (unless needed)

  Material:
    [x] Materials → Export
    [x] Images → Automatic (embeds in GLB)

  Shape Keys: [x] (if using morph targets)
  Skinning: [x] (if using armatures)
  Armature:
    [x] Export Deformation Bones Only

Animation:
  [x] Animations
  Sampling Rate: 24 or match source

Compression:
  [ ] Draco (prefer post-processing with gltf-transform)

Common Export Issues

| Problem | Solution | |---------|----------| | Model too big/small | Apply scale (Ctrl+A) before export | | Missing textures | Pack textures (File → External Data → Pack) | | Broken normals | Recalculate normals (Shift+N in Edit mode) | | Flipped faces | Check normals direction, flip if needed | | Animation jitter | Increase keyframe sampling rate | | Materials wrong | Use Principled BSDF, check texture paths | | Bones missing | Check "Export Deformation Bones Only" |

Loading in Three.js

WebGPU Setup (2026)

import * as THREE from 'three/webgpu'
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'
import { MeshoptDecoder } from 'three/addons/libs/meshopt_decoder.module.js'
import { KTX2Loader } from 'three/addons/loaders/KTX2Loader.js'

const loader = new GLTFLoader()

// Meshopt decoder (recommended)
loader.setMeshoptDecoder(MeshoptDecoder)

// KTX2 textures (requires renderer for format detection)
const ktx2Loader = new KTX2Loader()
ktx2Loader.setTranscoderPath('https://cdn.jsdelivr.net/npm/three@0.171.0/examples/jsm/libs/basis/')
ktx2Loader.detectSupport(renderer) // Required!
loader.setKTX2Loader(ktx2Loader)

// Load
const gltf = await loader.loadAsync('/model.glb')
scene.add(gltf.scene)

Draco Fallback (if needed)

import { DRACOLoader } from 'three/addons/loaders/DRACOLoader.js'

const dracoLoader = new DRACOLoader()
dracoLoader.setDecoderPath('https://www.gstatic.com/draco/versioned/decoders/1.5.7/')
loader.setDRACOLoader(dracoLoader)

React Three Fiber

import { useGLTF } from '@react-three/drei'

// Drei handles Meshopt and Draco automatically
const { scene, nodes, materials, animations } = useGLTF('/model.glb')

// Preload for instant display
useGLTF.preload('/model.glb')

Performance Budgets

Target Metrics

| Platform | Triangles | Draw Calls | Texture Memory | File Size | |----------|-----------|------------|----------------|-----------| | Mobile | <100K | <50 | <50MB | <5MB | | Desktop | <500K | <100 | <200MB | <20MB | | High-end | <2M | <200 | <500MB | <50MB |

Profiling

// Three.js render info (call after render)
console.log(renderer.info.render)
// { calls, triangles, points, lines, frame }

console.log(renderer.info.memory)
// { geometries, textures }

// Performance monitor
import Stats from 'stats.js'
const stats = new Stats()
stats.showPanel(0) // 0: fps, 1: ms, 2: mb
document.body.appendChild(stats.dom)

function animate() {
  stats.begin()
  renderer.render(scene, camera)
  stats.end()
}
renderer.setAnimationLoop(animate)

Asset Validation

# Validate GLTF structure
npx gltf-validator model.glb

# Online validation
# https://gltf.report

# Check file size breakdown
gltf-transform inspect model.glb

Related Skills

| When you need... | Use skill | |------------------|-----------| | Build 3D scenes with Three.js | → threejs | | Build 3D scenes with React | → react-three-fiber | | Debug rendering/performance issues | → graphics-troubleshooting |

Reference Files