Assets
Web Engine Dev provides a multi-layered asset system: a runtime loader for glTF models, a build-time pipeline for asset processing, and texture management utilities for GPU upload.
glTF Loading
The primary 3D asset format is glTF 2.0 (GL Transmission Format). The @web-engine-dev/gltf package loads .gltf and .glb files and converts them into engine-ready meshes, materials, and animations.
Basic Loading
import { GLTFLoader } from '@web-engine-dev/gltf';
import { createDevice } from '@web-engine-dev/renderer';
const { device } = await createDevice({
canvas,
preferredBackend: 'auto',
});
const loader = new GLTFLoader(device);
const result = await loader.load('/models/character.glb');Load Result
The loader returns a structured result containing all parsed data:
// Meshes -- geometry data ready for GPU rendering
const mesh = result.meshes.get('CharacterMesh');
// Materials -- PBR materials with textures
const material = result.materials.get('Skin');
// Animations -- keyframe animation clips
const walkAnim = result.animations.get('Walk');
// Skeletons -- joint hierarchies for skeletal animation
const skeleton = result.skeletons.get('Armature');
// Scenes -- scene definitions with root nodes
const mainScene = result.scenes[0];
// Nodes -- all nodes with transforms and hierarchy
const nodes = result.nodes;ECS Integration
Spawn loaded glTF scenes directly into the ECS world:
import { spawnGLTFScene } from '@web-engine-dev/gltf';
const spawnResult = spawnGLTFScene(world, result);
// Access spawned entities
for (const entity of spawnResult.entities) {
// Each node becomes an entity with Transform3D,
// MeshHandle, and material components
}Vertex Layouts
Loaded meshes use standard engine vertex layouts:
| Layout | Size | Contents |
|---|---|---|
Position | 12 bytes | Position only |
PositionNormal | 24 bytes | Position + normals |
PositionNormalUV | 32 bytes | Position + normals + UVs |
PositionNormalTangentUV | 48 bytes | Full PBR (tangents for normal mapping) |
Additional vertex data (not in the main vertex buffer) is stored on the GLTFPrimitive:
- Vertex colors (
COLOR_0) -- Normalized to RGBA float - Joint indices and weights (
JOINTS_0,WEIGHTS_0) -- For skeletal animation - Second UV set (
TEXCOORD_1) -- For lightmaps or detail textures - Morph target deltas -- Position, normal, and tangent deltas per blend shape
Extension Support
The loader supports common glTF compression extensions:
| Extension | Description |
|---|---|
KHR_draco_mesh_compression | Draco mesh compression |
EXT_meshopt_compression | Meshopt compression |
KHR_texture_basisu | KTX2/Basis Universal textures |
Extensions are enabled by default. Disable specific extensions for strict core-only loading:
const loader = new GLTFLoader(device, {
extensions: ['KHR_draco_mesh_compression'], // Only enable Draco
});Cleanup
Dispose loaded resources when no longer needed:
loader.dispose(result); // Disposes all meshes, materials, and texturesTexture Loading
The renderer handles texture creation and GPU upload. Textures loaded from glTF use the industry-standard direct GPU upload path:
createImageBitmap()withpremultiplyAlpha: 'none'andcolorSpaceConversion: 'none'(glTF 2.0 spec requires ignoring ICC profiles)- Direct
copyExternalImageToTexture()for zero-copy GPU upload - Automatic mipmap generation
Straight Alpha
The engine always preserves straight (non-premultiplied) alpha during texture loading. Never use Canvas 2D drawImage + getImageData to extract pixel data from images that need alpha preservation, as Canvas 2D unconditionally premultiplies alpha, destroying RGB values where alpha is zero.
Asset Pipeline
The build-time asset pipeline (@web-engine-dev/asset-pipeline) transforms raw assets into optimized, game-ready formats.
Pipeline Stages
Raw Asset → Import → Process → Output- Import -- Parse raw files into an intermediate format (e.g., read PNG as pixel data)
- Process -- Transform, optimize, and compress (e.g., resize textures, generate mipmaps, compress audio)
- Output -- Write processed files to the distribution directory with metadata
Importers
Importers handle specific file types:
interface Importer {
extensions: string[];
import(path: string): Promise<AssetData>;
}Built-in importers cover common asset types: textures (PNG, JPG, WebP), audio files, 3D models (glTF/GLB), and more.
Processors
Processors transform imported data:
interface Processor {
type: string;
process(asset: AssetData, options: ProcessorOptions): Promise<ProcessedAsset>;
}Example processing operations:
- Resize textures to maximum dimensions
- Generate texture mipmaps
- Compress textures to GPU-native formats (ASTC, ETC2, S3TC, BC)
- Convert audio to compressed formats (OGG, WebM)
- Optimize mesh data
Configuration
Configure the pipeline in your project:
// asset-pipeline.config.js
export default {
inputDir: './assets',
outputDir: './dist/assets',
processors: {
texture: { maxSize: 2048, compress: true },
audio: { format: 'ogg', quality: 0.7 },
},
};Incremental Builds
The pipeline supports incremental builds through:
- Hash-based change detection -- Only reprocess assets whose content has changed
- Dependency tracking -- When a texture changes, materials referencing it are reprocessed
- Cache invalidation -- Configuration changes trigger full rebuilds of affected assets
Texture Formats
The renderer supports multiple texture formats on WebGPU, constrained by adapter capabilities:
| Format | WebGPU | Notes |
|---|---|---|
| RGBA8 | Yes | Standard 8-bit per channel |
| RGBA16F | Yes | HDR half-float |
| RGBA32F | Adapter-dependent | Full-float workflows depend on device support |
| Depth24Stencil8 | Yes | Depth + stencil |
| Depth32F | Yes | High-precision depth |
| BC (S3TC) | Adapter-dependent | supportsTextureCompressionBC |
| ETC2 | Adapter-dependent | supportsTextureCompressionETC2 |
| ASTC | Adapter-dependent | supportsTextureCompressionASTC |