@lijuhong1981/three.instancedsprite 1.0.1 → 1.1.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/.gitattributes ADDED
@@ -0,0 +1,2 @@
1
+ *.js text eol=lf
2
+ *.md text eol=lf
package/API.md CHANGED
@@ -282,6 +282,7 @@ InstancedSpriteCollection类,批量管理InstancedSprite实例
282
282
  * [.getByUuid(uuid)](#InstancedSpriteCollection+getByUuid) ⇒ [<code>InstancedSprite</code>](#InstancedSprite) \| <code>undefined</code>
283
283
  * [.add()](#InstancedSpriteCollection+add) ⇒ [<code>InstancedSprite</code>](#InstancedSprite)
284
284
  * [.remove(sprite)](#InstancedSpriteCollection+remove) ⇒ [<code>InstancedSpriteCollection</code>](#InstancedSpriteCollection)
285
+ * [.clear()](#InstancedSpriteCollection+clear) ⇒ [<code>InstancedSpriteCollection</code>](#InstancedSpriteCollection)
285
286
  * [.forEach(callback)](#InstancedSpriteCollection+forEach) ⇒ [<code>InstancedSpriteCollection</code>](#InstancedSpriteCollection)
286
287
  * [.raycast(raycaster, intersects)](#InstancedSpriteCollection+raycast)
287
288
 
@@ -385,6 +386,12 @@ InstancedSprite实例数量
385
386
  | --- | --- |
386
387
  | sprite | [<code>InstancedSprite</code>](#InstancedSprite) |
387
388
 
389
+ <a name="InstancedSpriteCollection+clear"></a>
390
+
391
+ ### instancedSpriteCollection.clear() ⇒ [<code>InstancedSpriteCollection</code>](#InstancedSpriteCollection)
392
+ 移除所有InstancedSprite,并清空所有Mesh的实例数据(Mesh本身保留以便复用)
393
+
394
+ **Kind**: instance method of [<code>InstancedSpriteCollection</code>](#InstancedSpriteCollection)
388
395
  <a name="InstancedSpriteCollection+forEach"></a>
389
396
 
390
397
  ### instancedSpriteCollection.forEach(callback) ⇒ [<code>InstancedSpriteCollection</code>](#InstancedSpriteCollection)
package/README.md CHANGED
@@ -1,55 +1,125 @@
1
- # InstancedSprite
2
-
3
- three自带的Sprite并不支持GPU实例化渲染,当遇到需要在场景中大量展示标签的情况时就会出现帧率下降的问题,所以开发了这个InstancedSprite,以InstancedBufferGeometry+自定义ShaderMaterial的形式实例化渲染InstancedSprite对象,极大的提高了大批量标签展示时的渲染效率。
4
-
5
- ## 安装
6
-
7
- ```bash
8
- npm install @lijuhong1981/three.instancedsprite
9
- ```
10
-
11
- ## 使用
12
-
13
- ```js
14
- import { InstancedSpriteCollection } from "@lijuhong1981/instancedsprite";
15
- ...
16
- // 初始化
17
- const collection = new InstancedSpriteCollection();
18
- // 如果使用的是WebGPURenderer,请添加参数true,以启用TSL的NodeMaterial
19
- // const collection = new InstancedSpriteCollection(true);
20
- ...
21
- // 动画帧更新
22
- const onAnimate = () => {
23
- window.requestAnimationFrame(onAnimate);
24
- ...
25
- // 每帧更新
26
- collection.update();
27
- };
28
- // 添加
29
- const sprite = collection.add(
30
- {
31
- position: [100, 100, 100], //位置
32
- rotation: 0, //旋转
33
- scale: 1.0, //缩放
34
- sizeAttenuation: false, //尺寸跟随相机深度变化
35
- center: [0.5, 0], //中心锚点
36
- color: 0xff0000, //颜色
37
- opacity: 0.5, //不透明度
38
- image: './res/icon.png', //图像地址,相同的image会分配到同一个Mesh下一次性渲染
39
- }
40
- );
41
- // 移除
42
- sprite.remove();
43
- // 或
44
- // collection.remove(sprite);
45
- // 清空
46
- collection.clear();
47
- // 射线检测
48
- raycaster.setFromCamera(ndc, camera)
49
- const intersects = raycaster.intersectObject(collection);
50
- if (intersects.length > 0) {
51
- const pickedSprite = intersects[0].object; //拾取到的InstancedSprite对象
52
- }
53
- ```
54
-
55
- ## [API文档](./API.md)
1
+ # InstancedSprite
2
+
3
+ Three.js 自带的 `Sprite` 不支持 GPU 实例化渲染。当场景中需要同时展示大量标签、图标或提示时,逐个绘制 `Sprite` 会产生大量 draw call,导致帧率明显下降。
4
+
5
+ `InstancedSprite` 基于 `InstancedBufferGeometry` + 自定义 `ShaderMaterial`(或 TSL `NodeMaterial`)实现实例化渲染。**相同图片的 Sprite 会自动合并到同一个 Mesh,一次 draw call 全部绘制**,极大提升大批量标签的渲染效率。
6
+
7
+ ## 特性
8
+
9
+ - 🚀 **GPU 实例化**:基于 `InstancedBufferGeometry`,数千个 Sprite 仅需一次 draw call
10
+ - 🏷️ **按图自动合批**:`image` 相同的 Sprite 自动归入同一个 `InstancedSpriteMesh` 统一渲染
11
+ - ✏️ **属性自动同步**:直接修改 Sprite 的 `position` / `rotation` / `scale` / `color` 等属性,每帧 `update()` 时通过脏检查自动上传至 GPU,无需手动刷新
12
+ - 🎯 **射线拾取**:内置射线检测,可直接用 `Raycaster` 拾取到具体的 `InstancedSprite` 实例
13
+ - 🖼️ **像素级透明**:片元着色器自动丢弃完全透明的像素
14
+ - 🎨 **双渲染后端**:同时支持 WebGL(GLSL `ShaderMaterial`)与 WebGPU(TSL `NodeMaterial`)
15
+ - 📏 **动态扩容**:实例缓冲区按需自动扩容,实例数量无硬性上限
16
+
17
+ ## 安装
18
+
19
+ ```bash
20
+ npm install @lijuhong1981/three.instancedsprite
21
+ ```
22
+
23
+ 依赖 `three`(`>= 0.171.0`)。若使用 WebGPU / TSL 材质,需从 `three/webgpu` 引入相关构建。
24
+
25
+ ## 使用
26
+
27
+ ```js
28
+ import * as THREE from "three";
29
+ import { InstancedSpriteCollection } from "@lijuhong1981/three.instancedsprite";
30
+
31
+ // 初始化(继承自 Object3D,直接加入场景)
32
+ const collection = new InstancedSpriteCollection();
33
+ scene.add(collection);
34
+
35
+ // 若使用 WebGPURenderer,传入 true 以启用 TSL 的 NodeMaterial
36
+ // const collection = new InstancedSpriteCollection(true);
37
+
38
+ // 每帧更新:内部做脏检查,把发生变化的属性同步到 GPU
39
+ const onAnimate = () => {
40
+ window.requestAnimationFrame(onAnimate);
41
+ collection.update();
42
+ };
43
+
44
+ // 添加一个 Sprite
45
+ const sprite = collection.add({
46
+ position: [100, 100, 100], // 位置(世界空间)
47
+ rotation: 0, // 旋转(弧度)
48
+ scale: 1.0, // 缩放
49
+ sizeAttenuation: false, // 尺寸是否跟随相机深度变化(默认 true)
50
+ center: [0.5, 0], // 中心锚点(0-1,默认 (0.5, 0.5))
51
+ color: 0xff0000, // 颜色(默认 0xffffff)
52
+ opacity: 0.5, // 不透明度(0-1,默认 1)
53
+ image: './res/icon.png', // 图片地址,相同 image 会合并到同一个 Mesh 一次渲染
54
+ });
55
+
56
+ // 运行时修改属性(无需手动刷新,update() 会自动同步)
57
+ sprite.position.set(200, 100, 0);
58
+ sprite.color.set(0x00ff00);
59
+ sprite.show = false; // 隐藏(等同于 sprite.visible)
60
+
61
+ // 移除
62
+ sprite.remove();
63
+ // 或
64
+ collection.remove(sprite);
65
+
66
+ // 清空所有 Sprite
67
+ collection.clear();
68
+
69
+ // 射线检测
70
+ const ndc = new THREE.Vector2(/* ... */);
71
+ raycaster.setFromCamera(ndc, camera);
72
+ const intersects = raycaster.intersectObject(collection);
73
+ if (intersects.length > 0) {
74
+ const pickedSprite = intersects[0].object; // 拾取到的 InstancedSprite
75
+ const instanceId = intersects[0].instanceId; // 实例索引
76
+ }
77
+ ```
78
+
79
+ ## 主要 API
80
+
81
+ | 类 | 说明 |
82
+ | --- | --- |
83
+ | `InstancedSpriteCollection` | 继承自 `Object3D`,批量管理所有 Sprite;按 `image` 分组并生成对应的 `InstancedSpriteMesh` |
84
+ | `InstancedSprite` | 数据模型类,保存单个 Sprite 的全部属性;**不继承 `Object3D`**,不能直接加入 Scene,由 Collection 统一渲染 |
85
+ | `InstancedSpriteMesh` | 继承自 `Mesh`,基于 `InstancedBufferGeometry`,同一图片的所有 Sprite 由其统一绘制 |
86
+ | `InstancedSpriteMaterial` | 继承自 `ShaderMaterial`,以 instanced attribute 形式接收每个 Sprite 的属性(WebGL) |
87
+ | `InstancedSpriteNodeMaterial` | 继承自 `NodeMaterial`,基于 TSL 实现,功能与 `InstancedSpriteMaterial` 一致(WebGPU) |
88
+
89
+ ### InstancedSpriteCollection
90
+
91
+ - `add(options)` → `InstancedSprite`:添加并返回一个 Sprite
92
+ - `remove(sprite)`:移除指定 Sprite
93
+ - `clear()`:移除所有 Sprite
94
+ - `get(index)` / `getByUuid(uuid)`:按索引 / uuid 获取
95
+ - `forEach(callback)`:遍历所有 Sprite
96
+ - `update()`:每帧调用,同步属性变化
97
+ - `raycast(raycaster, intersects)`:射线拾取
98
+ - `instancedSprites`:Sprite 数组(只读);`size`:数量(只读)
99
+ - `depthTest`:深度测试开关(默认 `true`;关闭后所有 Sprite 始终渲染在最前,适合 UI 元素)
100
+
101
+ ### InstancedSprite 属性
102
+
103
+ | 属性 | 类型 | 默认值 | 说明 |
104
+ | --- | --- | --- | --- |
105
+ | `position` | `Vector3` | `(0, 0, 0)` | 世界坐标位置 |
106
+ | `scale` | `number` | `1` | 缩放 |
107
+ | `rotation` | `number` | `0` | 旋转(弧度);可用 `rotationDegrees` 以角度读写 |
108
+ | `sizeAttenuation` | `boolean` | `true` | 尺寸是否跟随相机深度变化 |
109
+ | `center` | `Vector2` | `(0.5, 0.5)` | 锚点中心(0-1) |
110
+ | `color` | `Color` | `0xffffff` | 颜色 |
111
+ | `opacity` | `number` | `1` | 不透明度(0-1) |
112
+ | `show` / `visible` | `boolean` | `true` | 是否显示 |
113
+ | `image` | `string \| HTMLImageElement \| HTMLCanvasElement` | - | 图片资源 |
114
+ | `imageSize` / `imageWidth` / `imageHeight` | - | - | 图片尺寸,图片加载完成后可用(只读) |
115
+ | `userData` | `object` | `{}` | 用户自定义数据 |
116
+ | `uuid` | `string` | - | 唯一标识(只读) |
117
+
118
+ ## 工作原理
119
+
120
+ 1. `InstancedSpriteCollection.add()` 创建 `InstancedSprite` 数据对象,并根据其 `image` 找到(或新建)对应的 `InstancedSpriteMesh`。
121
+ 2. `InstancedSpriteMesh` 持有 `InstancedBufferGeometry`,为每个实例分配一组 instanced attribute(位置+显示、锚点+尺寸、缩放+旋转+衰减、颜色+透明度、拾取颜色)。
122
+ 3. 顶点着色器根据实例属性计算 billboard 位置(对齐、旋转、透视缩放),片元着色器采样纹理并应用颜色 / 透明度。
123
+ 4. 每帧调用 `update()`:仅当属性实际发生变化(脏检查)时才更新对应缓冲区,减少 CPU→GPU 传输开销;缓冲区按需自动扩容。
124
+
125
+ ## [API 文档](./API.md)
package/index.js CHANGED
@@ -1,5 +1,5 @@
1
- export * from "./src/InstancedSprite.js";
2
- export * from "./src/InstancedSpriteCollection.js";
3
- export * from "./src/InstancedSpriteMaterial.js";
4
- export * from "./src/InstancedSpriteMesh.js";
5
- export * from "./src/InstancedSpriteNodeMaterial.js";
1
+ export * from "./src/InstancedSprite.js";
2
+ export * from "./src/InstancedSpriteCollection.js";
3
+ export * from "./src/InstancedSpriteMaterial.js";
4
+ export * from "./src/InstancedSpriteMesh.js";
5
+ export * from "./src/InstancedSpriteNodeMaterial.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lijuhong1981/three.instancedsprite",
3
- "version": "1.0.1",
3
+ "version": "1.1.0",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "module": "index.js",
@@ -187,6 +187,22 @@ class InstancedSpriteCollection extends Object3D {
187
187
  }
188
188
  return this;
189
189
  }
190
+ /**
191
+ * 移除所有InstancedSprite,并清空所有Mesh的实例数据(Mesh本身保留以便复用)
192
+ * @returns {InstancedSpriteCollection}
193
+ */
194
+ clear() {
195
+ for (const sprite of this._instancedSprites) {
196
+ sprite._mesh = undefined;
197
+ sprite._instanceIndex = -1;
198
+ }
199
+ this._instancedSprites.length = 0;
200
+ const meshes = this._meshes.values();
201
+ for (const mesh of meshes) {
202
+ mesh.clear();
203
+ }
204
+ return this;
205
+ }
190
206
  /**
191
207
  * 遍历所有的InstancedSprite
192
208
  * @param {Function} callback
@@ -1,147 +1,147 @@
1
- import { ShaderMaterial, Texture } from "three";
2
-
3
- const vertexShader = `
4
- // Three.js ShaderMaterial专用,自动注入uv、position、modelViewMatrix、projectionMatrix
5
- precision highp float;
6
- precision highp int;
7
-
8
- #include <common>
9
- #include <logdepthbuf_pars_vertex>
10
-
11
- // 基础属性
12
- attribute vec4 aPositionAndShow; // xyz: InstancedSprite位置(世界空间),w:显示标志(0/1)
13
- attribute vec4 aCenterAndSize; // xy: 锚点中心(0-1), zw: 图片宽高(像素/米)
14
- attribute vec3 aScaleAndRotationAndSizeAttenuation; // x: 缩放, y: 旋转(弧度), z: 大小跟随相机深度(0/1)
15
- attribute vec4 aColorAndOpacity; // RGBA颜色
16
- attribute vec4 aPickColorAndEnabled; // xyz:拾取颜色,w:是否启用拾取颜色(0/1)
17
-
18
- varying float vShow;
19
- varying vec2 vUv;
20
- varying vec4 vColorAndOpacity;
21
- varying vec4 vPickColorAndEnabled;
22
-
23
- void main() {
24
- // --- 1. 提前解包属性(GPU会自动优化,无性能损失)---
25
- float show = aPositionAndShow.w;
26
- float scale = aScaleAndRotationAndSizeAttenuation.x;
27
- float rotation = aScaleAndRotationAndSizeAttenuation.y;
28
- float sizeAttenuation = aScaleAndRotationAndSizeAttenuation.z;
29
- vec2 center = aCenterAndSize.xy;
30
- vec2 imageSize = aCenterAndSize.zw;
31
-
32
- // --- 2. 输出varying变量 ---
33
- vShow = show;
34
- vUv = uv;
35
- vColorAndOpacity = aColorAndOpacity;
36
- vPickColorAndEnabled = aPickColorAndEnabled;
37
-
38
- // --- 3. 提前隐藏不可见物体(顶点级丢弃,性能最优)---
39
- if (show < 0.5 || imageSize.x <= 0.0 || imageSize.y <= 0.0) {
40
- vShow = 0.0;
41
- gl_Position = vec4(0.0, 0.0, 2.0, 1.0);
42
- return;
43
- }
44
-
45
- // --- 4. 计算模型视图位置 ---
46
- vec4 mvPosition = modelViewMatrix * vec4(aPositionAndShow.xyz, 1.0);
47
-
48
- // --- 5. 深度检查:隐藏相机后面的物体,避免尺寸翻转 ---
49
- float depth = -mvPosition.z;
50
- if (depth <= 0.0) {
51
- vShow = 0.0;
52
- gl_Position = vec4(0.0, 0.0, 2.0, 1.0);
53
- return;
54
- }
55
-
56
- // --- 6. sizeAttenuation检查:大小跟随深度
57
- if (sizeAttenuation < 0.5) {
58
- bool isPerspective = isPerspectiveMatrix( projectionMatrix );
59
- if ( isPerspective ) scale *= depth;
60
- }
61
-
62
- // --- 7. 坐标对齐
63
- float aspectRatio = imageSize.x / imageSize.y;
64
- vec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * aspectRatio * scale;
65
-
66
- // --- 8. 计算旋转
67
- vec2 rotatedPosition;
68
- rotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;
69
- rotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;
70
- mvPosition.xy += rotatedPosition;
71
-
72
- // --- 9. 投影变换 ---
73
- gl_Position = projectionMatrix * mvPosition;
74
-
75
- #include <logdepthbuf_vertex>
76
- }
77
- `;
78
-
79
- const fragmentShader = `
80
- uniform sampler2D uTexture;
81
-
82
- #include <common>
83
- #include <logdepthbuf_pars_fragment>
84
-
85
- varying float vShow;
86
- varying vec2 vUv;
87
- varying vec4 vColorAndOpacity;
88
- varying vec4 vPickColorAndEnabled;
89
-
90
- void main() {
91
- if (vShow < 0.5) {
92
- discard;
93
- }
94
-
95
- float enablePickColor = vPickColorAndEnabled.w;
96
-
97
- if (enablePickColor > 0.5){
98
- gl_FragColor = vec4(vPickColorAndEnabled.xyz, 1.0);
99
- } else {
100
- vec4 texColor = texture2D(uTexture, vUv);
101
- vec4 diffuseColor = texColor * vColorAndOpacity;
102
-
103
- // 丢弃完全透明的像素
104
- if (diffuseColor.a < 0.005) {
105
- discard;
106
- }
107
-
108
- gl_FragColor = diffuseColor;
109
- #include <logdepthbuf_fragment>
110
- #include <tonemapping_fragment>
111
- #include <colorspace_fragment>
112
- }
113
- }
114
- `;
115
-
116
- /**
117
- * InstancedSprite 材质类,以attribute形式传入InstancedSprite对象实例属性
118
- *
119
- * @extends ShaderMaterial
120
- */
121
- class InstancedSpriteMaterial extends ShaderMaterial {
122
- constructor() {
123
- super({
124
- vertexShader,
125
- fragmentShader,
126
- uniforms: {
127
- uTexture: { value: null },
128
- },
129
- transparent: true,
130
- depthTest: true,
131
- depthWrite: true,
132
- });
133
- }
134
- /**
135
- * 图片纹理
136
- * @type {Texture}
137
- */
138
- set texture(value) {
139
- this.uniforms.uTexture.value = value;
140
- }
141
- get texture() {
142
- return this.uniforms.uTexture.value;
143
- }
144
- };
145
-
146
- export default InstancedSpriteMaterial;
1
+ import { ShaderMaterial, Texture } from "three";
2
+
3
+ const vertexShader = `
4
+ // Three.js ShaderMaterial专用,自动注入uv、position、modelViewMatrix、projectionMatrix
5
+ precision highp float;
6
+ precision highp int;
7
+
8
+ #include <common>
9
+ #include <logdepthbuf_pars_vertex>
10
+
11
+ // 基础属性
12
+ attribute vec4 aPositionAndShow; // xyz: InstancedSprite位置(世界空间),w:显示标志(0/1)
13
+ attribute vec4 aCenterAndSize; // xy: 锚点中心(0-1), zw: 图片宽高(像素/米)
14
+ attribute vec3 aScaleAndRotationAndSizeAttenuation; // x: 缩放, y: 旋转(弧度), z: 大小跟随相机深度(0/1)
15
+ attribute vec4 aColorAndOpacity; // RGBA颜色
16
+ attribute vec4 aPickColorAndEnabled; // xyz:拾取颜色,w:是否启用拾取颜色(0/1)
17
+
18
+ varying float vShow;
19
+ varying vec2 vUv;
20
+ varying vec4 vColorAndOpacity;
21
+ varying vec4 vPickColorAndEnabled;
22
+
23
+ void main() {
24
+ // --- 1. 提前解包属性(GPU会自动优化,无性能损失)---
25
+ float show = aPositionAndShow.w;
26
+ float scale = aScaleAndRotationAndSizeAttenuation.x;
27
+ float rotation = aScaleAndRotationAndSizeAttenuation.y;
28
+ float sizeAttenuation = aScaleAndRotationAndSizeAttenuation.z;
29
+ vec2 center = aCenterAndSize.xy;
30
+ vec2 imageSize = aCenterAndSize.zw;
31
+
32
+ // --- 2. 输出varying变量 ---
33
+ vShow = show;
34
+ vUv = uv;
35
+ vColorAndOpacity = aColorAndOpacity;
36
+ vPickColorAndEnabled = aPickColorAndEnabled;
37
+
38
+ // --- 3. 提前隐藏不可见物体(顶点级丢弃,性能最优)---
39
+ if (show < 0.5 || imageSize.x <= 0.0 || imageSize.y <= 0.0) {
40
+ vShow = 0.0;
41
+ gl_Position = vec4(0.0, 0.0, 2.0, 1.0);
42
+ return;
43
+ }
44
+
45
+ // --- 4. 计算模型视图位置 ---
46
+ vec4 mvPosition = modelViewMatrix * vec4(aPositionAndShow.xyz, 1.0);
47
+
48
+ // --- 5. 深度检查:隐藏相机后面的物体,避免尺寸翻转 ---
49
+ float depth = -mvPosition.z;
50
+ if (depth <= 0.0) {
51
+ vShow = 0.0;
52
+ gl_Position = vec4(0.0, 0.0, 2.0, 1.0);
53
+ return;
54
+ }
55
+
56
+ // --- 6. sizeAttenuation检查:大小跟随深度
57
+ if (sizeAttenuation < 0.5) {
58
+ bool isPerspective = isPerspectiveMatrix( projectionMatrix );
59
+ if ( isPerspective ) scale *= depth;
60
+ }
61
+
62
+ // --- 7. 坐标对齐
63
+ float aspectRatio = imageSize.x / imageSize.y;
64
+ vec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * aspectRatio * scale;
65
+
66
+ // --- 8. 计算旋转
67
+ vec2 rotatedPosition;
68
+ rotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;
69
+ rotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;
70
+ mvPosition.xy += rotatedPosition;
71
+
72
+ // --- 9. 投影变换 ---
73
+ gl_Position = projectionMatrix * mvPosition;
74
+
75
+ #include <logdepthbuf_vertex>
76
+ }
77
+ `;
78
+
79
+ const fragmentShader = `
80
+ uniform sampler2D uTexture;
81
+
82
+ #include <common>
83
+ #include <logdepthbuf_pars_fragment>
84
+
85
+ varying float vShow;
86
+ varying vec2 vUv;
87
+ varying vec4 vColorAndOpacity;
88
+ varying vec4 vPickColorAndEnabled;
89
+
90
+ void main() {
91
+ if (vShow < 0.5) {
92
+ discard;
93
+ }
94
+
95
+ float enablePickColor = vPickColorAndEnabled.w;
96
+
97
+ if (enablePickColor > 0.5){
98
+ gl_FragColor = vec4(vPickColorAndEnabled.xyz, 1.0);
99
+ } else {
100
+ vec4 texColor = texture2D(uTexture, vUv);
101
+ vec4 diffuseColor = texColor * vColorAndOpacity;
102
+
103
+ // 丢弃完全透明的像素
104
+ if (diffuseColor.a < 0.005) {
105
+ discard;
106
+ }
107
+
108
+ gl_FragColor = diffuseColor;
109
+ #include <logdepthbuf_fragment>
110
+ #include <tonemapping_fragment>
111
+ #include <colorspace_fragment>
112
+ }
113
+ }
114
+ `;
115
+
116
+ /**
117
+ * InstancedSprite 材质类,以attribute形式传入InstancedSprite对象实例属性
118
+ *
119
+ * @extends ShaderMaterial
120
+ */
121
+ class InstancedSpriteMaterial extends ShaderMaterial {
122
+ constructor() {
123
+ super({
124
+ vertexShader,
125
+ fragmentShader,
126
+ uniforms: {
127
+ uTexture: { value: null },
128
+ },
129
+ transparent: true,
130
+ depthTest: true,
131
+ depthWrite: true,
132
+ });
133
+ }
134
+ /**
135
+ * 图片纹理
136
+ * @type {Texture}
137
+ */
138
+ set texture(value) {
139
+ this.uniforms.uTexture.value = value;
140
+ }
141
+ get texture() {
142
+ return this.uniforms.uTexture.value;
143
+ }
144
+ };
145
+
146
+ export default InstancedSpriteMaterial;
147
147
  export { InstancedSpriteMaterial };