@lijuhong1981/three.instancedsprite 1.1.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/API.md CHANGED
@@ -8,26 +8,40 @@
8
8
  <li>但它可以作为属性Module使用,修改InstancedSprite的属性会自动更新至GPU中</li>
9
9
  </ul>
10
10
  </dd>
11
+ <dt><a href="#Billboard">Billboard</a></dt>
12
+ <dd></dd>
11
13
  <dt><a href="#InstancedSpriteCollection">InstancedSpriteCollection</a> ⇐ <code>Object3D</code></dt>
12
14
  <dd><p>InstancedSpriteCollection类,批量管理InstancedSprite实例</p>
13
15
  <ul>
14
16
  <li>继承自Object3D</li>
15
- <li>根据InstancedSprite的图像属性生成InstancedSpriteMaterial和InstancedSpriteMesh,</li>
16
- <li>管理InstancedSprite与InstancedSpriteMesh实例</li>
17
+ <li>使用纹理图集将不同图片打包,一张图集对应一个 InstancedSpriteMesh(一次 draw call)</li>
18
+ <li>图集扩容到上限后会新建图集与 Mesh</li>
17
19
  </ul>
18
20
  </dd>
21
+ <dt><a href="#BillboardCollection">BillboardCollection</a></dt>
22
+ <dd></dd>
19
23
  <dt><a href="#InstancedSpriteMaterial">InstancedSpriteMaterial</a> ⇐ <code>ShaderMaterial</code></dt>
20
24
  <dd><p>InstancedSprite 材质类,以attribute形式传入InstancedSprite对象实例属性</p>
21
25
  </dd>
26
+ <dt><a href="#BillboardMaterial">BillboardMaterial</a></dt>
27
+ <dd></dd>
22
28
  <dt><a href="#InstancedSpriteMesh">InstancedSpriteMesh</a> ⇐ <code>Mesh</code></dt>
23
29
  <dd><p>InstancedSpriteMesh类,基于InstancedBufferGeometry实现的高性能InstancedSprite渲染组件</p>
30
+ <p>一张图集纹理对应一个 InstancedSpriteMesh,所有使用该图集的 Sprite 由其统一绘制</p>
24
31
  </dd>
32
+ <dt><a href="#BillboardMesh">BillboardMesh</a></dt>
33
+ <dd></dd>
25
34
  <dt><a href="#InstancedSpriteNodeMaterial">InstancedSpriteNodeMaterial</a> ⇐ <code>NodeMaterial</code></dt>
26
35
  <dd><p>InstancedSpriteNodeMaterial 材质类,基于 Three.js TSL (Three Shading Language) 语法实现</p>
27
36
  <p>功能与 InstancedSpriteMaterial (ShaderMaterial) 完全相同,但使用 TSL 节点系统构建,
28
37
  可更好地与 Three.js 的 NodeMaterial 管线集成(自动处理色调映射、色彩空间转换等)。</p>
29
38
  <p><strong>注意</strong>:使用此类需要 Three.js 的 WebGPU/TSL 构建(<code>three/webgpu</code>),非标准 <code>three</code> 构建。</p>
30
39
  </dd>
40
+ <dt><a href="#BillboardNodeMaterial">BillboardNodeMaterial</a></dt>
41
+ <dd></dd>
42
+ <dt><a href="#TextureAtlas">TextureAtlas</a></dt>
43
+ <dd><p>纹理图集,将多张图片按行(shelf)打包进一张 Canvas 纹理,用于合并 draw call</p>
44
+ </dd>
31
45
  </dl>
32
46
 
33
47
  ## Constants
@@ -257,42 +271,58 @@ Computes intersection points between a casted ray and this sprite.
257
271
  | intersects | <code>Array.&lt;Object&gt;</code> | The target array that holds the intersection points. |
258
272
  | modelViewMatrix | <code>Matrix4</code> | |
259
273
 
274
+ <a name="Billboard"></a>
275
+
276
+ ## Billboard
277
+ **Kind**: global class
278
+ <a name="new_Billboard_new"></a>
279
+
280
+ ### new Billboard()
281
+ InstancedSprite 的别名(广告牌语义)。
282
+
260
283
  <a name="InstancedSpriteCollection"></a>
261
284
 
262
285
  ## InstancedSpriteCollection ⇐ <code>Object3D</code>
263
286
  InstancedSpriteCollection类,批量管理InstancedSprite实例
264
287
 
265
288
  * 继承自Object3D
266
- * 根据InstancedSprite的图像属性生成InstancedSpriteMaterial和InstancedSpriteMesh,
267
- * 管理InstancedSprite与InstancedSpriteMesh实例
289
+ * 使用纹理图集将不同图片打包,一张图集对应一个 InstancedSpriteMesh(一次 draw call)
290
+ * 图集扩容到上限后会新建图集与 Mesh
268
291
 
269
292
  **Kind**: global class
270
293
  **Extends**: <code>Object3D</code>
271
294
 
272
295
  * [InstancedSpriteCollection](#InstancedSpriteCollection) ⇐ <code>Object3D</code>
273
- * [new InstancedSpriteCollection([useNodeMaterial])](#new_InstancedSpriteCollection_new)
296
+ * [new InstancedSpriteCollection([options])](#new_InstancedSpriteCollection_new)
274
297
  * [.useNodeMaterial](#InstancedSpriteCollection+useNodeMaterial) : <code>boolean</code>
275
298
  * [.type](#InstancedSpriteCollection+type) : <code>string</code>
276
299
  * [.isInstancedSpriteCollection](#InstancedSpriteCollection+isInstancedSpriteCollection) : <code>boolean</code>
277
300
  * [.depthTest](#InstancedSpriteCollection+depthTest) : <code>boolean</code>
301
+ * [.depthWrite](#InstancedSpriteCollection+depthWrite) : <code>boolean</code>
278
302
  * [.instancedSprites](#InstancedSpriteCollection+instancedSprites) : [<code>Array.&lt;InstancedSprite&gt;</code>](#InstancedSprite)
279
303
  * [.size](#InstancedSpriteCollection+size) : <code>number</code>
280
304
  * [._setImage(source, sprite)](#InstancedSpriteCollection+_setImage)
281
305
  * [.get(index)](#InstancedSpriteCollection+get) ⇒ [<code>InstancedSprite</code>](#InstancedSprite) \| <code>undefined</code>
282
306
  * [.getByUuid(uuid)](#InstancedSpriteCollection+getByUuid) ⇒ [<code>InstancedSprite</code>](#InstancedSprite) \| <code>undefined</code>
283
- * [.add()](#InstancedSpriteCollection+add) ⇒ [<code>InstancedSprite</code>](#InstancedSprite)
307
+ * [.add(options)](#InstancedSpriteCollection+add) ⇒ [<code>InstancedSprite</code>](#InstancedSprite)
284
308
  * [.remove(sprite)](#InstancedSpriteCollection+remove) ⇒ [<code>InstancedSpriteCollection</code>](#InstancedSpriteCollection)
285
309
  * [.clear()](#InstancedSpriteCollection+clear) ⇒ [<code>InstancedSpriteCollection</code>](#InstancedSpriteCollection)
310
+ * [.reserve(capacity)](#InstancedSpriteCollection+reserve) ⇒ [<code>InstancedSpriteCollection</code>](#InstancedSpriteCollection)
286
311
  * [.forEach(callback)](#InstancedSpriteCollection+forEach) ⇒ [<code>InstancedSpriteCollection</code>](#InstancedSpriteCollection)
287
312
  * [.raycast(raycaster, intersects)](#InstancedSpriteCollection+raycast)
313
+ * [.dispose()](#InstancedSpriteCollection+dispose) ⇒ [<code>InstancedSpriteCollection</code>](#InstancedSpriteCollection)
288
314
 
289
315
  <a name="new_InstancedSpriteCollection_new"></a>
290
316
 
291
- ### new InstancedSpriteCollection([useNodeMaterial])
317
+ ### new InstancedSpriteCollection([options])
292
318
 
293
319
  | Param | Type | Default | Description |
294
320
  | --- | --- | --- | --- |
295
- | [useNodeMaterial] | <code>boolean</code> | <code>false</code> | 是否使用TSL的NodeMaterial,默认false |
321
+ | [options] | <code>object</code> | | 配置项 |
322
+ | [options.useNodeMaterial] | <code>boolean</code> | <code>false</code> | 是否使用TSL的NodeMaterial(WebGPU),默认false |
323
+ | [options.initialSize] | <code>number</code> | <code>1024</code> | 图集初始边长 |
324
+ | [options.maxSize] | <code>number</code> | <code>8192</code> | 图集最大边长 |
325
+ | [options.padding] | <code>number</code> | <code>2</code> | 子图间距 |
296
326
 
297
327
  <a name="InstancedSpriteCollection+useNodeMaterial"></a>
298
328
 
@@ -321,6 +351,13 @@ InstancedSpriteCollection对象标识
321
351
  ### instancedSpriteCollection.depthTest : <code>boolean</code>
322
352
  深度测试开关,默认为true,开启后会进行深度测试以正确处理遮挡关系,但可能会有性能影响;如果关闭则所有InstancedSprite都会被渲染在最前面,适合需要始终显示的UI元素等场景
323
353
 
354
+ **Kind**: instance property of [<code>InstancedSpriteCollection</code>](#InstancedSpriteCollection)
355
+ **Default**: <code>true</code>
356
+ <a name="InstancedSpriteCollection+depthWrite"></a>
357
+
358
+ ### instancedSpriteCollection.depthWrite : <code>boolean</code>
359
+ 深度写入开关,默认为true;多个半透明 Sprite 重叠时,开启深度写入可能导致排序瑕疵(后方 Sprite 被错误遮挡),关闭可缓解,适合半透明标签/粒子等场景
360
+
324
361
  **Kind**: instance property of [<code>InstancedSpriteCollection</code>](#InstancedSpriteCollection)
325
362
  **Default**: <code>true</code>
326
363
  <a name="InstancedSpriteCollection+instancedSprites"></a>
@@ -371,10 +408,15 @@ InstancedSprite实例数量
371
408
 
372
409
  <a name="InstancedSpriteCollection+add"></a>
373
410
 
374
- ### instancedSpriteCollection.add() ⇒ [<code>InstancedSprite</code>](#InstancedSprite)
411
+ ### instancedSpriteCollection.add(options) ⇒ [<code>InstancedSprite</code>](#InstancedSprite)
375
412
  添加InstancedSprite
376
413
 
377
414
  **Kind**: instance method of [<code>InstancedSpriteCollection</code>](#InstancedSpriteCollection)
415
+
416
+ | Param | Type | Description |
417
+ | --- | --- | --- |
418
+ | options | [<code>InstancedSpriteOptions</code>](#InstancedSpriteOptions) | 初始化配置项 |
419
+
378
420
  <a name="InstancedSpriteCollection+remove"></a>
379
421
 
380
422
  ### instancedSpriteCollection.remove(sprite) ⇒ [<code>InstancedSpriteCollection</code>](#InstancedSpriteCollection)
@@ -389,9 +431,20 @@ InstancedSprite实例数量
389
431
  <a name="InstancedSpriteCollection+clear"></a>
390
432
 
391
433
  ### instancedSpriteCollection.clear() ⇒ [<code>InstancedSpriteCollection</code>](#InstancedSpriteCollection)
392
- 移除所有InstancedSprite,并清空所有Mesh的实例数据(Mesh本身保留以便复用)
434
+ 移除所有InstancedSprite,并清空所有Mesh的实例数据(Mesh与图集保留以便复用)
435
+
436
+ **Kind**: instance method of [<code>InstancedSpriteCollection</code>](#InstancedSpriteCollection)
437
+ <a name="InstancedSpriteCollection+reserve"></a>
438
+
439
+ ### instancedSpriteCollection.reserve(capacity) ⇒ [<code>InstancedSpriteCollection</code>](#InstancedSpriteCollection)
440
+ 预分配所有Mesh的容量,避免后续动态扩容
393
441
 
394
442
  **Kind**: instance method of [<code>InstancedSpriteCollection</code>](#InstancedSpriteCollection)
443
+
444
+ | Param | Type | Description |
445
+ | --- | --- | --- |
446
+ | capacity | <code>number</code> | 需要预留的实例数量 |
447
+
395
448
  <a name="InstancedSpriteCollection+forEach"></a>
396
449
 
397
450
  ### instancedSpriteCollection.forEach(callback) ⇒ [<code>InstancedSpriteCollection</code>](#InstancedSpriteCollection)
@@ -415,6 +468,21 @@ Computes intersection points between a casted ray and this sprite.
415
468
  | raycaster | <code>Raycaster</code> | The raycaster. |
416
469
  | intersects | <code>Array.&lt;Object&gt;</code> | The target array that holds the intersection points. |
417
470
 
471
+ <a name="InstancedSpriteCollection+dispose"></a>
472
+
473
+ ### instancedSpriteCollection.dispose() ⇒ [<code>InstancedSpriteCollection</code>](#InstancedSpriteCollection)
474
+ 释放所有 GPU 资源(几何体、材质、图集纹理),并移除所有子 Mesh
475
+
476
+ **Kind**: instance method of [<code>InstancedSpriteCollection</code>](#InstancedSpriteCollection)
477
+ <a name="BillboardCollection"></a>
478
+
479
+ ## BillboardCollection
480
+ **Kind**: global class
481
+ <a name="new_BillboardCollection_new"></a>
482
+
483
+ ### new BillboardCollection()
484
+ InstancedSpriteCollection 的别名。
485
+
418
486
  <a name="InstancedSpriteMaterial"></a>
419
487
 
420
488
  ## InstancedSpriteMaterial ⇐ <code>ShaderMaterial</code>
@@ -428,24 +496,39 @@ InstancedSprite 材质类,以attribute形式传入InstancedSprite对象实例
428
496
  图片纹理
429
497
 
430
498
  **Kind**: instance property of [<code>InstancedSpriteMaterial</code>](#InstancedSpriteMaterial)
499
+ <a name="BillboardMaterial"></a>
500
+
501
+ ## BillboardMaterial
502
+ **Kind**: global class
503
+ <a name="new_BillboardMaterial_new"></a>
504
+
505
+ ### new BillboardMaterial()
506
+ InstancedSpriteMaterial 的别名。
507
+
431
508
  <a name="InstancedSpriteMesh"></a>
432
509
 
433
510
  ## InstancedSpriteMesh ⇐ <code>Mesh</code>
434
511
  InstancedSpriteMesh类,基于InstancedBufferGeometry实现的高性能InstancedSprite渲染组件
435
512
 
513
+ 一张图集纹理对应一个 InstancedSpriteMesh,所有使用该图集的 Sprite 由其统一绘制
514
+
436
515
  **Kind**: global class
437
516
  **Extends**: <code>Mesh</code>
438
517
 
439
518
  * [InstancedSpriteMesh](#InstancedSpriteMesh) ⇐ <code>Mesh</code>
440
519
  * [new InstancedSpriteMesh(collection, texture)](#new_InstancedSpriteMesh_new)
441
520
  * [.type](#InstancedSpriteMesh+type) : <code>string</code>
521
+ * [.frustumCulled](#InstancedSpriteMesh+frustumCulled) : <code>boolean</code>
442
522
  * [.isInstancedSpriteMesh](#InstancedSpriteMesh+isInstancedSpriteMesh) : <code>boolean</code>
443
523
  * [.depthTest](#InstancedSpriteMesh+depthTest) : <code>boolean</code>
524
+ * [.depthWrite](#InstancedSpriteMesh+depthWrite) : <code>boolean</code>
444
525
  * [.instancedSprites](#InstancedSpriteMesh+instancedSprites) : [<code>Array.&lt;InstancedSprite&gt;</code>](#InstancedSprite)
526
+ * [.reserve(capacity)](#InstancedSpriteMesh+reserve) ⇒ [<code>InstancedSpriteMesh</code>](#InstancedSpriteMesh)
445
527
  * [.add(sprite)](#InstancedSpriteMesh+add) ⇒ [<code>InstancedSpriteMesh</code>](#InstancedSpriteMesh)
446
528
  * [.remove(sprite)](#InstancedSpriteMesh+remove) ⇒ [<code>InstancedSpriteMesh</code>](#InstancedSpriteMesh)
447
529
  * [.clear()](#InstancedSpriteMesh+clear) ⇒ [<code>InstancedSpriteMesh</code>](#InstancedSpriteMesh)
448
530
  * [.raycast(raycaster, intersects)](#InstancedSpriteMesh+raycast)
531
+ * [.dispose()](#InstancedSpriteMesh+dispose)
449
532
 
450
533
  <a name="new_InstancedSpriteMesh_new"></a>
451
534
 
@@ -454,7 +537,7 @@ InstancedSpriteMesh类,基于InstancedBufferGeometry实现的高性能Instance
454
537
  | Param | Type | Description |
455
538
  | --- | --- | --- |
456
539
  | collection | [<code>InstancedSpriteCollection</code>](#InstancedSpriteCollection) | 所属的InstancedSpriteCollection实例,必填 |
457
- | texture | <code>Texture</code> | 材质图像纹理,必填 |
540
+ | texture | <code>Texture</code> | 图集纹理,必填 |
458
541
 
459
542
  <a name="InstancedSpriteMesh+type"></a>
460
543
 
@@ -463,6 +546,13 @@ InstancedSpriteMesh类,基于InstancedBufferGeometry实现的高性能Instance
463
546
 
464
547
  **Kind**: instance property of [<code>InstancedSpriteMesh</code>](#InstancedSpriteMesh)
465
548
  **Read only**: true
549
+ <a name="InstancedSpriteMesh+frustumCulled"></a>
550
+
551
+ ### instancedSpriteMesh.frustumCulled : <code>boolean</code>
552
+ 实例化几何体的包围球基于单位四边形(位于原点),不包含实例位置,视锥剔除会把远离原点的实例整批误剔除,因此禁用
553
+
554
+ **Kind**: instance property of [<code>InstancedSpriteMesh</code>](#InstancedSpriteMesh)
555
+ **Default**: <code>false</code>
466
556
  <a name="InstancedSpriteMesh+isInstancedSpriteMesh"></a>
467
557
 
468
558
  ### instancedSpriteMesh.isInstancedSpriteMesh : <code>boolean</code>
@@ -475,6 +565,13 @@ InstancedSpriteMesh对象标识
475
565
  ### instancedSpriteMesh.depthTest : <code>boolean</code>
476
566
  深度测试开关,默认为true,开启后会进行深度测试以正确处理遮挡关系,但可能会有性能影响;如果关闭则所有InstancedSprite都会被渲染在最前面,适合需要始终显示的UI元素等场景
477
567
 
568
+ **Kind**: instance property of [<code>InstancedSpriteMesh</code>](#InstancedSpriteMesh)
569
+ **Default**: <code>true</code>
570
+ <a name="InstancedSpriteMesh+depthWrite"></a>
571
+
572
+ ### instancedSpriteMesh.depthWrite : <code>boolean</code>
573
+ 深度写入开关,默认为true;多个半透明 Sprite 重叠时,开启深度写入可能导致排序瑕疵(后方 Sprite 被错误遮挡),关闭可缓解,适合半透明标签/粒子等场景
574
+
478
575
  **Kind**: instance property of [<code>InstancedSpriteMesh</code>](#InstancedSpriteMesh)
479
576
  **Default**: <code>true</code>
480
577
  <a name="InstancedSpriteMesh+instancedSprites"></a>
@@ -484,6 +581,17 @@ InstancedSprite对象数组
484
581
 
485
582
  **Kind**: instance property of [<code>InstancedSpriteMesh</code>](#InstancedSpriteMesh)
486
583
  **Read only**: true
584
+ <a name="InstancedSpriteMesh+reserve"></a>
585
+
586
+ ### instancedSpriteMesh.reserve(capacity) ⇒ [<code>InstancedSpriteMesh</code>](#InstancedSpriteMesh)
587
+ 预分配容量,避免后续动态扩容(不改变当前实际绘制的实例数量)
588
+
589
+ **Kind**: instance method of [<code>InstancedSpriteMesh</code>](#InstancedSpriteMesh)
590
+
591
+ | Param | Type | Description |
592
+ | --- | --- | --- |
593
+ | capacity | <code>number</code> | 需要预留的实例数量 |
594
+
487
595
  <a name="InstancedSpriteMesh+add"></a>
488
596
 
489
597
  ### instancedSpriteMesh.add(sprite) ⇒ [<code>InstancedSpriteMesh</code>](#InstancedSpriteMesh)
@@ -524,6 +632,21 @@ Computes intersection points between a casted ray and this sprite.
524
632
  | raycaster | <code>Raycaster</code> | The raycaster. |
525
633
  | intersects | <code>Array.&lt;Object&gt;</code> | The target array that holds the intersection points. |
526
634
 
635
+ <a name="InstancedSpriteMesh+dispose"></a>
636
+
637
+ ### instancedSpriteMesh.dispose()
638
+ 释放 GPU 资源
639
+
640
+ **Kind**: instance method of [<code>InstancedSpriteMesh</code>](#InstancedSpriteMesh)
641
+ <a name="BillboardMesh"></a>
642
+
643
+ ## BillboardMesh
644
+ **Kind**: global class
645
+ <a name="new_BillboardMesh_new"></a>
646
+
647
+ ### new BillboardMesh()
648
+ InstancedSpriteMesh 的别名。
649
+
527
650
  <a name="InstancedSpriteNodeMaterial"></a>
528
651
 
529
652
  ## InstancedSpriteNodeMaterial ⇐ <code>NodeMaterial</code>
@@ -542,6 +665,79 @@ InstancedSpriteNodeMaterial 材质类,基于 Three.js TSL (Three Shading Langu
542
665
  图片纹理
543
666
 
544
667
  **Kind**: instance property of [<code>InstancedSpriteNodeMaterial</code>](#InstancedSpriteNodeMaterial)
668
+ <a name="BillboardNodeMaterial"></a>
669
+
670
+ ## BillboardNodeMaterial
671
+ **Kind**: global class
672
+ <a name="new_BillboardNodeMaterial_new"></a>
673
+
674
+ ### new BillboardNodeMaterial()
675
+ InstancedSpriteNodeMaterial 的别名。
676
+
677
+ <a name="TextureAtlas"></a>
678
+
679
+ ## TextureAtlas
680
+ 纹理图集,将多张图片按行(shelf)打包进一张 Canvas 纹理,用于合并 draw call
681
+
682
+ **Kind**: global class
683
+
684
+ * [TextureAtlas](#TextureAtlas)
685
+ * [new TextureAtlas([options])](#new_TextureAtlas_new)
686
+ * [.add(source)](#TextureAtlas+add) ⇒ <code>Object</code> \| <code>null</code>
687
+ * [.getRect(source)](#TextureAtlas+getRect) ⇒ <code>Object</code> \| <code>undefined</code>
688
+ * [.grow()](#TextureAtlas+grow) ⇒ <code>boolean</code>
689
+ * [.getUvRect(rect)](#TextureAtlas+getUvRect) ⇒ <code>Array.&lt;number&gt;</code>
690
+
691
+ <a name="new_TextureAtlas_new"></a>
692
+
693
+ ### new TextureAtlas([options])
694
+
695
+ | Param | Type | Default | Description |
696
+ | --- | --- | --- | --- |
697
+ | [options] | <code>object</code> | | |
698
+ | [options.initialSize] | <code>number</code> | <code>1024</code> | 初始边长(正方形,单位像素) |
699
+ | [options.maxSize] | <code>number</code> | <code>8192</code> | 最大边长,自动扩容到该值后不再增大 |
700
+ | [options.padding] | <code>number</code> | <code>2</code> | 子图间距,防止线性过滤时边缘渗色 |
701
+
702
+ <a name="TextureAtlas+add"></a>
703
+
704
+ ### textureAtlas.add(source) ⇒ <code>Object</code> \| <code>null</code>
705
+ 将图片加入图集,返回其像素矩形;已加入过则返回缓存;图集整体已满则返回null
706
+
707
+ **Kind**: instance method of [<code>TextureAtlas</code>](#TextureAtlas)
708
+
709
+ | Param | Type |
710
+ | --- | --- |
711
+ | source | <code>HTMLImageElement</code> \| <code>HTMLCanvasElement</code> |
712
+
713
+ <a name="TextureAtlas+getRect"></a>
714
+
715
+ ### textureAtlas.getRect(source) ⇒ <code>Object</code> \| <code>undefined</code>
716
+ 获取图片已分配的像素矩形
717
+
718
+ **Kind**: instance method of [<code>TextureAtlas</code>](#TextureAtlas)
719
+
720
+ | Param | Type |
721
+ | --- | --- |
722
+ | source | <code>HTMLImageElement</code> \| <code>HTMLCanvasElement</code> |
723
+
724
+ <a name="TextureAtlas+grow"></a>
725
+
726
+ ### textureAtlas.grow() ⇒ <code>boolean</code>
727
+ 扩容图集(边长翻倍),成功返回true;已达最大尺寸返回false
728
+
729
+ **Kind**: instance method of [<code>TextureAtlas</code>](#TextureAtlas)
730
+ <a name="TextureAtlas+getUvRect"></a>
731
+
732
+ ### textureAtlas.getUvRect(rect) ⇒ <code>Array.&lt;number&gt;</code>
733
+ 将像素矩形转为归一化 UV(uOffset, vOffset, uScale, vScale)
734
+
735
+ **Kind**: instance method of [<code>TextureAtlas</code>](#TextureAtlas)
736
+
737
+ | Param | Type |
738
+ | --- | --- |
739
+ | rect | <code>Object</code> |
740
+
545
741
  <a name="imageLoader"></a>
546
742
 
547
743
  ## imageLoader
package/README.md CHANGED
@@ -2,12 +2,12 @@
2
2
 
3
3
  Three.js 自带的 `Sprite` 不支持 GPU 实例化渲染。当场景中需要同时展示大量标签、图标或提示时,逐个绘制 `Sprite` 会产生大量 draw call,导致帧率明显下降。
4
4
 
5
- `InstancedSprite` 基于 `InstancedBufferGeometry` + 自定义 `ShaderMaterial`(或 TSL `NodeMaterial`)实现实例化渲染。**相同图片的 Sprite 会自动合并到同一个 Mesh,一次 draw call 全部绘制**,极大提升大批量标签的渲染效率。
5
+ `InstancedSprite` 基于 `InstancedBufferGeometry` + 自定义 `ShaderMaterial`(或 TSL `NodeMaterial`)实现实例化渲染。**所有 Sprite 的图片打包进纹理图集,合并为极少数 draw call**,极大提升大批量标签的渲染效率。
6
6
 
7
7
  ## 特性
8
8
 
9
9
  - 🚀 **GPU 实例化**:基于 `InstancedBufferGeometry`,数千个 Sprite 仅需一次 draw call
10
- - 🏷️ **按图自动合批**:`image` 相同的 Sprite 自动归入同一个 `InstancedSpriteMesh` 统一渲染
10
+ - 🏷️ **纹理图集合批**:不同图片打包进同一图集,一个图集(一个 Mesh)一次 draw call;图集满自动新建
11
11
  - ✏️ **属性自动同步**:直接修改 Sprite 的 `position` / `rotation` / `scale` / `color` 等属性,每帧 `update()` 时通过脏检查自动上传至 GPU,无需手动刷新
12
12
  - 🎯 **射线拾取**:内置射线检测,可直接用 `Raycaster` 拾取到具体的 `InstancedSprite` 实例
13
13
  - 🖼️ **像素级透明**:片元着色器自动丢弃完全透明的像素
@@ -32,8 +32,11 @@ import { InstancedSpriteCollection } from "@lijuhong1981/three.instancedsprite";
32
32
  const collection = new InstancedSpriteCollection();
33
33
  scene.add(collection);
34
34
 
35
- // 若使用 WebGPURenderer,传入 true 以启用 TSL 的 NodeMaterial
36
- // const collection = new InstancedSpriteCollection(true);
35
+ // 若使用 WebGPURenderer,通过 useNodeMaterial 启用 TSL 的 NodeMaterial
36
+ // const collection = new InstancedSpriteCollection({ useNodeMaterial: true });
37
+
38
+ // 图集可配置(初始/最大边长、子图间距),默认自动扩容到 8192
39
+ // const collection = new InstancedSpriteCollection({ maxSize: 4096 });
37
40
 
38
41
  // 每帧更新:内部做脏检查,把发生变化的属性同步到 GPU
39
42
  const onAnimate = () => {
@@ -76,16 +79,34 @@ if (intersects.length > 0) {
76
79
  }
77
80
  ```
78
81
 
82
+ ## Billboard 别名
83
+
84
+ 所有 `InstancedSprite*` 类都有对应的 `Billboard*` 别名导出,语义上表示「始终面向相机的广告牌/标签」,用法完全一致:
85
+
86
+ ```js
87
+ import { BillboardCollection, Billboard } from "@lijuhong1981/three.instancedsprite";
88
+
89
+ // BillboardCollection === InstancedSpriteCollection
90
+ const collection = new BillboardCollection();
91
+ scene.add(collection);
92
+
93
+ // Billboard === InstancedSprite
94
+ const billboard = collection.add({ image: './res/icon.png', position: [0, 0, 0] });
95
+ console.log(billboard instanceof Billboard); // true
96
+ ```
97
+
79
98
  ## 主要 API
80
99
 
81
100
  | 类 | 说明 |
82
101
  | --- | --- |
83
- | `InstancedSpriteCollection` | 继承自 `Object3D`,批量管理所有 Sprite;按 `image` 分组并生成对应的 `InstancedSpriteMesh` |
102
+ | `InstancedSpriteCollection` | 继承自 `Object3D`,批量管理所有 Sprite;使用纹理图集合并 draw call |
84
103
  | `InstancedSprite` | 数据模型类,保存单个 Sprite 的全部属性;**不继承 `Object3D`**,不能直接加入 Scene,由 Collection 统一渲染 |
85
- | `InstancedSpriteMesh` | 继承自 `Mesh`,基于 `InstancedBufferGeometry`,同一图片的所有 Sprite 由其统一绘制 |
104
+ | `InstancedSpriteMesh` | 继承自 `Mesh`,基于 `InstancedBufferGeometry`,一张图集对应一个 Mesh,由其统一绘制 |
86
105
  | `InstancedSpriteMaterial` | 继承自 `ShaderMaterial`,以 instanced attribute 形式接收每个 Sprite 的属性(WebGL) |
87
106
  | `InstancedSpriteNodeMaterial` | 继承自 `NodeMaterial`,基于 TSL 实现,功能与 `InstancedSpriteMaterial` 一致(WebGPU) |
88
107
 
108
+ > 以上每个类都有对应的 `Billboard*` 别名导出(如 `BillboardCollection`、`Billboard`),语义上表示「始终面向相机的广告牌/标签」。
109
+
89
110
  ### InstancedSpriteCollection
90
111
 
91
112
  - `add(options)` → `InstancedSprite`:添加并返回一个 Sprite
@@ -117,7 +138,7 @@ if (intersects.length > 0) {
117
138
 
118
139
  ## 工作原理
119
140
 
120
- 1. `InstancedSpriteCollection.add()` 创建 `InstancedSprite` 数据对象,并根据其 `image` 找到(或新建)对应的 `InstancedSpriteMesh`。
141
+ 1. `InstancedSpriteCollection.add()` 创建 `InstancedSprite` 数据对象,并将其 `image` 打包进纹理图集(同一图片只打包一次)。
121
142
  2. `InstancedSpriteMesh` 持有 `InstancedBufferGeometry`,为每个实例分配一组 instanced attribute(位置+显示、锚点+尺寸、缩放+旋转+衰减、颜色+透明度、拾取颜色)。
122
143
  3. 顶点着色器根据实例属性计算 billboard 位置(对齐、旋转、透视缩放),片元着色器采样纹理并应用颜色 / 透明度。
123
144
  4. 每帧调用 `update()`:仅当属性实际发生变化(脏检查)时才更新对应缓冲区,减少 CPU→GPU 传输开销;缓冲区按需自动扩容。
package/index.js CHANGED
@@ -3,3 +3,4 @@ export * from "./src/InstancedSpriteCollection.js";
3
3
  export * from "./src/InstancedSpriteMaterial.js";
4
4
  export * from "./src/InstancedSpriteMesh.js";
5
5
  export * from "./src/InstancedSpriteNodeMaterial.js";
6
+ export * from "./src/TextureAtlas.js";
package/package.json CHANGED
@@ -1,16 +1,22 @@
1
1
  {
2
2
  "name": "@lijuhong1981/three.instancedsprite",
3
- "version": "1.1.0",
3
+ "version": "2.0.0",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "module": "index.js",
7
7
  "main": "index.js",
8
+ "files": [
9
+ "index.js",
10
+ "src/",
11
+ "API.md"
12
+ ],
8
13
  "publishConfig": {
9
14
  "access": "public"
10
15
  },
11
16
  "scripts": {
12
17
  "test": "echo \"Error: no test specified\" && exit 1",
13
- "docs": "jsdoc2md --files src/*.js > API.md"
18
+ "docs": "jsdoc2md --files src/*.js > API.md",
19
+ "dev": "vite test"
14
20
  },
15
21
  "repository": {
16
22
  "type": "git",
@@ -36,6 +42,7 @@
36
42
  "three": ">=0.171.0"
37
43
  },
38
44
  "devDependencies": {
39
- "jsdoc-to-markdown": "^9.1.3"
45
+ "jsdoc-to-markdown": "^9.1.3",
46
+ "vite": "^8.3.3"
40
47
  }
41
- }
48
+ }
@@ -2,7 +2,7 @@ import Check from "@lijuhong1981/jscheck/src/Check.js";
2
2
  import ImageLoader from "@lijuhong1981/jsload/src/ImageLoader.js";
3
3
  import { Loader } from "@lijuhong1981/jsload/src/Loader.js";
4
4
  import setValues from "@lijuhong1981/three.utils/src/setValues.js";
5
- import { Color, InstancedBufferGeometry, MathUtils, Matrix4, Triangle, Vector2, Vector3 } from "three";
5
+ import { Color, InstancedBufferGeometry, MathUtils, Matrix4, Triangle, Vector2, Vector3, Vector4 } from "three";
6
6
 
7
7
  /**
8
8
  * @import InstancedSpriteCollection from "./InstancedSpriteCollection.js";
@@ -169,6 +169,13 @@ class InstancedSprite {
169
169
  */
170
170
  this.imageSize = new Vector2(0, 0);
171
171
  this._imageSize = new Vector2(0, 0);
172
+ /**
173
+ * 图集UV区域(x: u偏移, y: v偏移, z: u缩放, w: v缩放),非图集模式默认为(0,0,1,1)即整张纹理
174
+ * @type {Vector4}
175
+ * @ignore
176
+ */
177
+ this.uvRect = new Vector4(0, 0, 1, 1);
178
+ this._uvRect = new Vector4(0, 0, 1, 1);
172
179
  this._image = null;
173
180
  /**
174
181
  * 拾取颜色,用于GPU拾取,由Picking管理器设置和使用,用户无需关心
@@ -366,3 +373,9 @@ class InstancedSprite {
366
373
 
367
374
  export default InstancedSprite;
368
375
  export { InstancedSprite };
376
+ /**
377
+ * InstancedSprite 的别名(广告牌语义)。
378
+ * @class
379
+ * @name Billboard
380
+ */
381
+ export const Billboard = InstancedSprite;