@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 +207 -11
- package/README.md +28 -7
- package/index.js +1 -0
- package/package.json +11 -4
- package/src/InstancedSprite.js +14 -1
- package/src/InstancedSpriteCollection.js +193 -61
- package/src/InstancedSpriteMaterial.js +9 -2
- package/src/InstancedSpriteMesh.js +130 -45
- package/src/InstancedSpriteNodeMaterial.js +12 -5
- package/src/TextureAtlas.js +125 -0
- package/.gitattributes +0 -2
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
|
|
16
|
-
<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.<Object></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
|
-
*
|
|
267
|
-
*
|
|
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([
|
|
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.<InstancedSprite></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([
|
|
317
|
+
### new InstancedSpriteCollection([options])
|
|
292
318
|
|
|
293
319
|
| Param | Type | Default | Description |
|
|
294
320
|
| --- | --- | --- | --- |
|
|
295
|
-
| [
|
|
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.<Object></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.<InstancedSprite></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.<Object></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.<number></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.<number></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
|
|
5
|
+
`InstancedSprite` 基于 `InstancedBufferGeometry` + 自定义 `ShaderMaterial`(或 TSL `NodeMaterial`)实现实例化渲染。**所有 Sprite 的图片打包进纹理图集,合并为极少数 draw call**,极大提升大批量标签的渲染效率。
|
|
6
6
|
|
|
7
7
|
## 特性
|
|
8
8
|
|
|
9
9
|
- 🚀 **GPU 实例化**:基于 `InstancedBufferGeometry`,数千个 Sprite 仅需一次 draw call
|
|
10
|
-
- 🏷️
|
|
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
|
|
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
|
|
102
|
+
| `InstancedSpriteCollection` | 继承自 `Object3D`,批量管理所有 Sprite;使用纹理图集合并 draw call |
|
|
84
103
|
| `InstancedSprite` | 数据模型类,保存单个 Sprite 的全部属性;**不继承 `Object3D`**,不能直接加入 Scene,由 Collection 统一渲染 |
|
|
85
|
-
| `InstancedSpriteMesh` | 继承自 `Mesh`,基于 `InstancedBufferGeometry
|
|
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`
|
|
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
package/package.json
CHANGED
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lijuhong1981/three.instancedsprite",
|
|
3
|
-
"version": "
|
|
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
|
+
}
|
package/src/InstancedSprite.js
CHANGED
|
@@ -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;
|