or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

abstractions.mdcameras.mdcontrols.mdgizmos.mdhooks.mdindex.mdloaders.mdmaterials.mdperformance.mdstaging.mdweb-integration.md

loaders.mddocs/

0

# Loaders

1

2

Asset loading utilities for textures, models, and media with automatic caching, disposal, and format support. These components provide efficient loading strategies for various 3D assets.

3

4

## Capabilities

5

6

### useGLTF

7

8

GLTF model loading hook with automatic disposal, Draco compression, and type safety.

9

10

```typescript { .api }

11

/**

12

* GLTF model loading hook with automatic disposal

13

* @param path - Path to GLTF/GLB file

14

* @param useDraco - Enable Draco compression support, true

15

* @param useMeshOpt - Enable MeshOpt compression support, true

16

* @returns GLTF object with nodes, materials, and animations

17

*/

18

function useGLTF(path: string, useDraco?: boolean, useMeshOpt?: boolean): GLTF & ObjectMap;

19

20

interface GLTF {

21

/** Animation clips from the model */

22

animations: AnimationClip[];

23

/** Root scene group */

24

scene: Group;

25

/** All scenes in the file */

26

scenes: Group[];

27

/** Cameras from the model */

28

cameras: Camera[];

29

/** Asset metadata */

30

asset: object;

31

/** Parser used */

32

parser: GLTFParser;

33

/** User data */

34

userData: any;

35

}

36

37

interface ObjectMap {

38

/** Named nodes from the model */

39

nodes: { [name: string]: Object3D };

40

/** Named materials from the model */

41

materials: { [name: string]: Material };

42

}

43

44

// Static methods

45

function useGLTF.preload(path: string): void;

46

function useGLTF.clear(input: string | string[]): void;

47

```

48

49

**Usage Examples:**

50

51

```typescript

52

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

53

54

// Basic GLTF loading

55

function Model({ path }) {

56

const { nodes, materials, scene } = useGLTF(path);

57

58

return <primitive object={scene} />;

59

}

60

61

// Accessing specific nodes and materials

62

function DetailedModel() {

63

const { nodes, materials } = useGLTF('/models/character.glb');

64

65

return (

66

<group>

67

<mesh

68

geometry={nodes.Head.geometry}

69

material={materials.SkinMaterial}

70

/>

71

<mesh

72

geometry={nodes.Body.geometry}

73

material={materials.ClothMaterial}

74

/>

75

<skinnedMesh

76

geometry={nodes.Character.geometry}

77

material={materials.CharacterMaterial}

78

skeleton={nodes.Character.skeleton}

79

/>

80

</group>

81

);

82

}

83

84

// With animations

85

function AnimatedModel() {

86

const group = useRef();

87

const { nodes, materials, animations } = useGLTF('/models/animated.glb');

88

const { actions } = useAnimations(animations, group);

89

90

useEffect(() => {

91

actions['Walk']?.play();

92

}, [actions]);

93

94

return (

95

<group ref={group}>

96

<primitive object={nodes.Scene} />

97

</group>

98

);

99

}

100

101

// Preload models for better performance

102

useGLTF.preload('/models/important.glb');

103

104

// Clear cache when needed

105

useGLTF.clear('/models/old.glb');

106

```

107

108

### useTexture

109

110

Texture loading hook with multiple format support, automatic disposal, and batch loading.

111

112

```typescript { .api }

113

/**

114

* Texture loading hook with format support

115

* @param input - Texture path or array of paths

116

* @param onLoad - Load callback function

117

* @returns Texture or array of textures

118

*/

119

function useTexture(

120

input: string | string[],

121

onLoad?: (texture: Texture | Texture[]) => void

122

): Texture | Texture[];

123

124

// Static methods

125

function useTexture.preload(input: string | string[]): void;

126

function useTexture.clear(input: string | string[]): void;

127

```

128

129

**Usage Examples:**

130

131

```typescript

132

import { useTexture } from '@react-three/drei';

133

134

// Single texture

135

function TexturedMesh() {

136

const texture = useTexture('/textures/diffuse.jpg');

137

138

return (

139

<mesh>

140

<planeGeometry />

141

<meshStandardMaterial map={texture} />

142

</mesh>

143

);

144

}

145

146

// Multiple textures

147

function PBRMaterial() {

148

const [colorMap, normalMap, roughnessMap, metalnessMap] = useTexture([

149

'/textures/color.jpg',

150

'/textures/normal.jpg',

151

'/textures/roughness.jpg',

152

'/textures/metalness.jpg'

153

]);

154

155

return (

156

<meshStandardMaterial

157

map={colorMap}

158

normalMap={normalMap}

159

roughnessMap={roughnessMap}

160

metalnessMap={metalnessMap}

161

/>

162

);

163

}

164

165

// Object syntax for named textures

166

function NamedTextures() {

167

const textures = useTexture({

168

diffuse: '/textures/diffuse.jpg',

169

normal: '/textures/normal.jpg',

170

roughness: '/textures/roughness.jpg'

171

});

172

173

return (

174

<meshStandardMaterial

175

map={textures.diffuse}

176

normalMap={textures.normal}

177

roughnessMap={textures.roughness}

178

/>

179

);

180

}

181

182

// Texture configuration callback

183

function ConfiguredTexture() {

184

const texture = useTexture('/textures/tile.jpg', (texture) => {

185

texture.wrapS = texture.wrapT = RepeatWrapping;

186

texture.repeat.set(4, 4);

187

texture.minFilter = NearestFilter;

188

texture.magFilter = NearestFilter;

189

});

190

191

return (

192

<mesh>

193

<planeGeometry args={[10, 10]} />

194

<meshBasicMaterial map={texture} />

195

</mesh>

196

);

197

}

198

199

// Preload critical textures

200

useTexture.preload([

201

'/textures/hero-diffuse.jpg',

202

'/textures/hero-normal.jpg'

203

]);

204

```

205

206

### useFont

207

208

Font loading hook for text rendering with caching and format support.

209

210

```typescript { .api }

211

/**

212

* Font loading hook for text rendering

213

* @param path - Path to font JSON file

214

* @returns Font data object with glyphs

215

*/

216

function useFont(path: string): FontData;

217

218

interface FontData {

219

/** Font data object */

220

data: any;

221

/** Character glyph definitions */

222

glyphs: { [key: string]: Glyph };

223

}

224

225

interface Glyph {

226

/** Glyph X position in font atlas */

227

x: number;

228

/** Glyph Y position in font atlas */

229

y: number;

230

/** Glyph width */

231

width: number;

232

/** Glyph height */

233

height: number;

234

/** X advance for character spacing */

235

xAdvance?: number;

236

/** X rendering offset */

237

xOffset?: number;

238

/** Y rendering offset */

239

yOffset?: number;

240

}

241

242

// Static methods

243

function useFont.preload(path: string): void;

244

function useFont.clear(path: string): void;

245

```

246

247

**Usage Examples:**

248

249

```typescript

250

import { useFont, Text3D } from '@react-three/drei';

251

252

// Basic font usage

253

function StyledText() {

254

const font = useFont('/fonts/helvetiker_regular.json');

255

256

return (

257

<Text3D font={font} size={1} height={0.2}>

258

Hello World

259

<meshNormalMaterial />

260

</Text3D>

261

);

262

}

263

264

// Multiple fonts

265

function MultiFontText() {

266

const regularFont = useFont('/fonts/helvetiker_regular.json');

267

const boldFont = useFont('/fonts/helvetiker_bold.json');

268

269

return (

270

<group>

271

<Text3D font={regularFont} position={[0, 1, 0]}>

272

Regular Text

273

<meshStandardMaterial color="blue" />

274

</Text3D>

275

<Text3D font={boldFont} position={[0, -1, 0]}>

276

Bold Text

277

<meshStandardMaterial color="red" />

278

</Text3D>

279

</group>

280

);

281

}

282

283

// Preload fonts

284

useFont.preload('/fonts/main.json');

285

```

286

287

### useEnvironment

288

289

Environment texture loading hook with presets, HDRI support, and configuration options.

290

291

```typescript { .api }

292

/**

293

* Environment texture loading hook with presets

294

* @param props - Environment loader configuration

295

* @returns Environment cube texture

296

*/

297

function useEnvironment(props?: EnvironmentLoaderProps): Texture;

298

299

interface EnvironmentLoaderProps {

300

/** Environment preset name */

301

preset?: PresetsType;

302

/** Custom environment files (single HDR or 6 cube faces) */

303

files?: string | string[];

304

/** Base path for environment files */

305

path?: string;

306

/** Texture encoding, sRGBEncoding */

307

encoding?: TextureEncoding;

308

}

309

310

type PresetsType =

311

| 'apartment' | 'city' | 'dawn' | 'forest' | 'lobby'

312

| 'night' | 'park' | 'studio' | 'sunset' | 'warehouse';

313

```

314

315

**Usage Examples:**

316

317

```typescript

318

import { useEnvironment } from '@react-three/drei';

319

320

// Environment preset

321

function ReflectiveSphere() {

322

const envMap = useEnvironment({ preset: 'sunset' });

323

324

return (

325

<mesh>

326

<sphereGeometry />

327

<meshStandardMaterial

328

envMap={envMap}

329

metalness={1}

330

roughness={0}

331

/>

332

</mesh>

333

);

334

}

335

336

// Custom HDRI environment

337

function CustomEnvironment() {

338

const envMap = useEnvironment({

339

files: '/hdri/studio_small_03_1k.hdr',

340

encoding: RGBEEncoding

341

});

342

343

return (

344

<mesh>

345

<torusGeometry />

346

<meshStandardMaterial envMap={envMap} />

347

</mesh>

348

);

349

}

350

351

// Cube map environment (6 faces)

352

function CubeEnvironment() {

353

const envMap = useEnvironment({

354

files: [

355

'/cubemap/px.jpg', '/cubemap/nx.jpg',

356

'/cubemap/py.jpg', '/cubemap/ny.jpg',

357

'/cubemap/pz.jpg', '/cubemap/nz.jpg'

358

],

359

path: '/environments/'

360

});

361

362

return (

363

<mesh>

364

<boxGeometry />

365

<meshStandardMaterial envMap={envMap} />

366

</mesh>

367

);

368

}

369

```

370

371

### useFBX

372

373

FBX model loading hook with animation support and material handling.

374

375

```typescript { .api }

376

/**

377

* FBX model loading hook

378

* @param path - Path to FBX file

379

* @returns FBX group with animations

380

*/

381

function useFBX(path: string): Group & { animations: AnimationClip[] };

382

383

// Static methods

384

function useFBX.preload(path: string): void;

385

function useFBX.clear(path: string): void;

386

```

387

388

**Usage Examples:**

389

390

```typescript

391

import { useFBX } from '@react-three/drei';

392

393

function FBXModel() {

394

const fbx = useFBX('/models/character.fbx');

395

396

return <primitive object={fbx} />;

397

}

398

399

// With animations

400

function AnimatedFBX() {

401

const group = useRef();

402

const fbx = useFBX('/models/animated.fbx');

403

const { actions } = useAnimations(fbx.animations, group);

404

405

useEffect(() => {

406

actions['Take 001']?.play();

407

}, [actions]);

408

409

return (

410

<group ref={group}>

411

<primitive object={fbx} />

412

</group>

413

);

414

}

415

```

416

417

### useKTX2

418

419

KTX2 texture loading hook for GPU-compressed textures.

420

421

```typescript { .api }

422

/**

423

* KTX2 texture loading hook for GPU compression

424

* @param path - Path to KTX2 file

425

* @returns KTX2 texture

426

*/

427

function useKTX2(path: string): CompressedTexture;

428

429

// Static methods

430

function useKTX2.preload(path: string): void;

431

function useKTX2.clear(path: string): void;

432

```

433

434

### useVideoTexture

435

436

Video texture loading hook with playback control and format support.

437

438

```typescript { .api }

439

/**

440

* Video texture loading hook with playback control

441

* @param src - Video source URL or HTMLVideoElement

442

* @param props - Video texture configuration

443

* @returns Video texture

444

*/

445

function useVideoTexture(

446

src: string | HTMLVideoElement,

447

props?: Partial<VideoTextureProps>

448

): VideoTexture;

449

450

interface VideoTextureProps extends Omit<ThreeElements['videoTexture'], 'ref' | 'args'> {

451

/** Auto-play video, true */

452

autoplay?: boolean;

453

/** Loop video, true */

454

loop?: boolean;

455

/** Video crossOrigin, 'anonymous' */

456

crossOrigin?: string;

457

/** Muted playback, true */

458

muted?: boolean;

459

/** Video playback rate, 1 */

460

playbackRate?: number;

461

/** Video volume, 1 */

462

volume?: number;

463

/** Load start callback */

464

onLoadStart?: () => void;

465

/** Load callback */

466

onLoad?: (video: HTMLVideoElement) => void;

467

/** Progress callback */

468

onProgress?: (event: ProgressEvent) => void;

469

/** Error callback */

470

onError?: (error: ErrorEvent) => void;

471

}

472

```

473

474

**Usage Examples:**

475

476

```typescript

477

import { useVideoTexture } from '@react-three/drei';

478

479

// Basic video texture

480

function VideoScreen() {

481

const texture = useVideoTexture('/videos/demo.mp4');

482

483

return (

484

<mesh>

485

<planeGeometry args={[16, 9]} />

486

<meshBasicMaterial map={texture} />

487

</mesh>

488

);

489

}

490

491

// Video with controls

492

function InteractiveVideo() {

493

const texture = useVideoTexture('/videos/interactive.mp4', {

494

autoplay: false,

495

loop: false,

496

muted: false,

497

onLoad: (video) => {

498

console.log('Video loaded:', video.duration);

499

}

500

});

501

502

const playPause = () => {

503

const video = texture.image;

504

video.paused ? video.play() : video.pause();

505

};

506

507

return (

508

<group>

509

<mesh onClick={playPause}>

510

<planeGeometry args={[4, 3]} />

511

<meshBasicMaterial map={texture} />

512

</mesh>

513

</group>

514

);

515

}

516

```

517

518

### useCubeTexture

519

520

Cube texture loading hook for skyboxes and environment mapping.

521

522

```typescript { .api }

523

/**

524

* Cube texture loading hook for skyboxes

525

* @param files - Array of 6 image paths [px, nx, py, ny, pz, nz]

526

* @param options - Cube texture options

527

* @returns Cube texture

528

*/

529

function useCubeTexture(

530

files: [string, string, string, string, string, string],

531

options?: CubeTextureOptions

532

): CubeTexture;

533

534

interface CubeTextureOptions {

535

/** Base path for files */

536

path?: string;

537

/** Texture encoding */

538

encoding?: TextureEncoding;

539

}

540

541

// Static methods

542

function useCubeTexture.preload(files: string[], path?: string): void;

543

```

544

545

**Usage Examples:**

546

547

```typescript

548

import { useCubeTexture } from '@react-three/drei';

549

550

function Skybox() {

551

const texture = useCubeTexture([

552

'px.jpg', 'nx.jpg',

553

'py.jpg', 'ny.jpg',

554

'pz.jpg', 'nz.jpg'

555

], { path: '/skybox/' });

556

557

const { scene } = useThree();

558

scene.background = texture;

559

560

return null;

561

}

562

```

563

564

## Integration Patterns

565

566

### Progressive Loading

567

568

```typescript

569

function ProgressiveAssets() {

570

const [loadHigh, setLoadHigh] = useState(false);

571

572

// Load low-res first

573

const lowTexture = useTexture('/textures/low-res.jpg');

574

575

// Load high-res after delay

576

const highTexture = useTexture(

577

loadHigh ? '/textures/high-res.jpg' : null

578

);

579

580

useEffect(() => {

581

const timer = setTimeout(() => setLoadHigh(true), 1000);

582

return () => clearTimeout(timer);

583

}, []);

584

585

return (

586

<mesh>

587

<planeGeometry />

588

<meshStandardMaterial map={highTexture || lowTexture} />

589

</mesh>

590

);

591

}

592

```

593

594

### Asset Preloading Strategy

595

596

```typescript

597

// Preload critical assets during app initialization

598

const preloadCriticalAssets = () => {

599

// Models

600

useGLTF.preload('/models/hero.glb');

601

useGLTF.preload('/models/environment.glb');

602

603

// Textures

604

useTexture.preload([

605

'/textures/hero-diffuse.jpg',

606

'/textures/hero-normal.jpg',

607

'/textures/environment.jpg'

608

]);

609

610

// Fonts

611

useFont.preload('/fonts/main.json');

612

613

// Environment

614

useEnvironment.preload({ preset: 'studio' });

615

};

616

617

// Call during app startup

618

useEffect(preloadCriticalAssets, []);

619

```

620

621

### Memory Management

622

623

```typescript

624

function MemoryEfficientLoader() {

625

const [currentModel, setCurrentModel] = useState('model1');

626

627

// Clear previous model from cache when switching

628

useEffect(() => {

629

return () => {

630

// Clean up unused assets

631

if (currentModel !== 'model1') {

632

useGLTF.clear('/models/model1.glb');

633

}

634

if (currentModel !== 'model2') {

635

useGLTF.clear('/models/model2.glb');

636

}

637

};

638

}, [currentModel]);

639

640

const model = useGLTF(`/models/${currentModel}.glb`);

641

642

return <primitive object={model.scene} />;

643

}

644

```

645

646

### Error Handling

647

648

```typescript

649

function RobustAssetLoader() {

650

const [error, setError] = useState(null);

651

const [loading, setLoading] = useState(true);

652

653

try {

654

const model = useGLTF('/models/complex.glb');

655

const texture = useTexture('/textures/diffuse.jpg', () => {

656

setLoading(false);

657

});

658

659

if (error) return <ErrorFallback error={error} />;

660

if (loading) return <LoadingSpinner />;

661

662

return (

663

<mesh>

664

<primitive object={model.scene} />

665

<meshStandardMaterial map={texture} />

666

</mesh>

667

);

668

} catch (err) {

669

setError(err);

670

return <ErrorFallback error={err} />;

671

}

672

}

673

674

function ErrorFallback({ error }) {

675

return (

676

<mesh>

677

<boxGeometry />

678

<meshBasicMaterial color="red" />

679

<Html center>

680

<div>Failed to load: {error.message}</div>

681

</Html>

682

</mesh>

683

);

684

}

685

```

686

687

### Conditional Loading

688

689

```typescript

690

function ConditionalAssets() {

691

const { viewport } = useThree();

692

const isMobile = viewport.width < 768;

693

const [quality, setQuality] = useState('medium');

694

695

// Load appropriate quality assets

696

const modelPath = `/models/character-${isMobile ? 'low' : quality}.glb`;

697

const texturePath = `/textures/diffuse-${isMobile ? '512' : '2048'}.jpg`;

698

699

const model = useGLTF(modelPath);

700

const texture = useTexture(texturePath);

701

702

return (

703

<group>

704

<primitive object={model.scene} />

705

<meshStandardMaterial map={texture} />

706

</group>

707

);

708

}

709

```

710

711

### Batch Loading with Progress

712

713

```typescript

714

function BatchLoader({ onProgress }) {

715

const [loaded, setLoaded] = useState(0);

716

const totalAssets = 10;

717

718

const handleLoad = useCallback(() => {

719

setLoaded(prev => {

720

const newLoaded = prev + 1;

721

onProgress?.(newLoaded / totalAssets);

722

return newLoaded;

723

});

724

}, [onProgress, totalAssets]);

725

726

// Load multiple assets with progress tracking

727

const textures = useTexture([

728

'/tex1.jpg', '/tex2.jpg', '/tex3.jpg',

729

'/tex4.jpg', '/tex5.jpg'

730

], handleLoad);

731

732

const models = [

733

useGLTF('/model1.glb'),

734

useGLTF('/model2.glb'),

735

useGLTF('/model3.glb'),

736

useGLTF('/model4.glb'),

737

useGLTF('/model5.glb')

738

];

739

740

return (

741

<group>

742

{models.map((model, i) => (

743

<primitive key={i} object={model.scene} />

744

))}

745

</group>

746

);

747

}

748

```