three-base 2.0.172 → 2.0.180

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.
Files changed (127) hide show
  1. package/FPScontrol.d.ts +15 -24
  2. package/FPScontrol.js +63 -87
  3. package/FPScontrol.ts +64 -88
  4. package/Ground1/Ground1.d.ts +4 -2
  5. package/Ground1/Ground1.js +77 -57
  6. package/Ground1/Ground1.ts +77 -57
  7. package/Mirror.js +0 -4
  8. package/Mirror.ts +0 -4
  9. package/MktMesh/MktMesh.d.ts +3 -2
  10. package/MktMesh/MktMesh.js +27 -8
  11. package/MktMesh/MktMesh.ts +24 -8
  12. package/MktMesh/boxLine2.d.ts +42 -0
  13. package/MktMesh/boxLine2.js +185 -0
  14. package/MktMesh/boxLine2.ts +222 -0
  15. package/MktMesh/imagePlane.d.ts +60 -0
  16. package/MktMesh/imagePlane.js +158 -0
  17. package/MktMesh/imagePlane.ts +203 -0
  18. package/MktMesh/imageTileLoader.d.ts +19 -0
  19. package/MktMesh/imageTileLoader.js +55 -0
  20. package/MktMesh/imageTileLoader.ts +64 -0
  21. package/MktMesh/mktMappingShader.d.ts +6 -5
  22. package/MktMesh/mktMappingShader.js +26 -19
  23. package/MktMesh/mktMappingShader.ts +28 -19
  24. package/MktMesh/mktShader.d.ts +127 -58
  25. package/MktMesh/mktShader.js +192 -117
  26. package/MktMesh/mktShader.ts +251 -127
  27. package/MktMesh/modelSlot.d.ts +123 -0
  28. package/MktMesh/modelSlot.js +339 -0
  29. package/MktMesh/modelSlot.ts +383 -0
  30. package/MktMesh/panoSlotRoster.d.ts +2 -2
  31. package/MktMesh/panoSlotRoster.js +9 -7
  32. package/MktMesh/panoSlotRoster.ts +9 -7
  33. package/MktMesh/panoTileStitcher.d.ts +20 -13
  34. package/MktMesh/panoTileStitcher.js +97 -76
  35. package/MktMesh/panoTileStitcher.ts +119 -90
  36. package/PipeMesh/PipeJoint.d.ts +22 -0
  37. package/PipeMesh/PipeJoint.js +33 -0
  38. package/PipeMesh/PipeJoint.ts +38 -0
  39. package/PipeMesh/PipeMesh.d.ts +94 -22
  40. package/PipeMesh/PipeMesh.js +192 -53
  41. package/PipeMesh/PipeMesh.ts +223 -76
  42. package/PipeMesh/PipeStraight.d.ts +19 -0
  43. package/PipeMesh/PipeStraight.js +34 -0
  44. package/PipeMesh/PipeStraight.ts +45 -0
  45. package/PipeMesh/axisSnap.d.ts +52 -0
  46. package/PipeMesh/axisSnap.js +52 -0
  47. package/PipeMesh/axisSnap.ts +93 -0
  48. package/PipeMesh/directRoute.d.ts +85 -0
  49. package/PipeMesh/directRoute.js +126 -0
  50. package/PipeMesh/directRoute.ts +190 -0
  51. package/PipeMesh/index.d.ts +6 -0
  52. package/PipeMesh/index.js +6 -0
  53. package/PipeMesh/index.ts +7 -1
  54. package/PipeMesh/pipeMaterial.d.ts +16 -0
  55. package/PipeMesh/pipeMaterial.js +23 -0
  56. package/PipeMesh/pipeMaterial.ts +26 -0
  57. package/ThreeBase.d.ts +1 -39
  58. package/ThreeBase.js +38 -147
  59. package/ThreeBase.ts +1176 -1302
  60. package/instanced/InstancedBatch.d.ts +14 -1
  61. package/instanced/InstancedBatch.js +53 -3
  62. package/instanced/InstancedBatch.ts +62 -3
  63. package/instanced/InstancedChild.d.ts +24 -0
  64. package/instanced/InstancedChild.js +40 -0
  65. package/instanced/InstancedChild.ts +41 -0
  66. package/instanced/InstancedGroup.d.ts +48 -0
  67. package/instanced/InstancedGroup.js +45 -1
  68. package/instanced/InstancedGroup.ts +85 -0
  69. package/package.json +22 -7
  70. package/pass/debugDepthState.d.ts +16 -8
  71. package/pass/debugDepthState.js +4 -0
  72. package/pass/debugDepthState.ts +27 -9
  73. package/pass/glow_pass.js +11 -94
  74. package/pass/glow_pass.ts +11 -97
  75. package/pass/ssao_pass.d.ts +9 -23
  76. package/pass/ssao_pass.js +41 -128
  77. package/pass/ssao_pass.ts +36 -166
  78. package/pass/stroke_pass.js +3 -0
  79. package/pass/stroke_pass.ts +4 -0
  80. package/shaders/debugDepthCompareShader.d.ts +1 -1
  81. package/shaders/debugDepthCompareShader.js +1 -1
  82. package/shaders/debugDepthCompareShader.ts +1 -1
  83. package/shaders/debugDepthJudgeShader.d.ts +1 -1
  84. package/shaders/debugDepthJudgeShader.js +1 -1
  85. package/shaders/debugDepthJudgeShader.ts +1 -1
  86. package/PipeMesh/PathGeometry.d.ts +0 -44
  87. package/PipeMesh/PathGeometry.js +0 -307
  88. package/PipeMesh/PathGeometry.ts +0 -343
  89. package/PipeMesh/PathPoint.d.ts +0 -17
  90. package/PipeMesh/PathPoint.js +0 -31
  91. package/PipeMesh/PathPoint.ts +0 -36
  92. package/PipeMesh/PathPointList.d.ts +0 -31
  93. package/PipeMesh/PathPointList.js +0 -209
  94. package/PipeMesh/PathPointList.ts +0 -227
  95. package/PipeMesh/PathTubeGeometry.d.ts +0 -25
  96. package/PipeMesh/PathTubeGeometry.js +0 -130
  97. package/PipeMesh/PathTubeGeometry.ts +0 -146
  98. package/WaterFlow/FloatingDuck.d.ts +0 -88
  99. package/WaterFlow/FloatingDuck.js +0 -307
  100. package/WaterFlow/FloatingDuck.ts +0 -445
  101. package/WaterFlow/GPUFluidSimulation.d.ts +0 -56
  102. package/WaterFlow/GPUFluidSimulation.js +0 -785
  103. package/WaterFlow/GPUFluidSimulation.ts +0 -827
  104. package/WaterFlow/ReservoirSystem.d.ts +0 -106
  105. package/WaterFlow/ReservoirSystem.js +0 -621
  106. package/WaterFlow/ReservoirSystem.ts +0 -754
  107. package/WaterFlow/SPHField.d.ts +0 -35
  108. package/WaterFlow/SPHField.js +0 -204
  109. package/WaterFlow/SPHField.ts +0 -228
  110. package/WaterFlow/ScreenSpaceFluidPass.d.ts +0 -69
  111. package/WaterFlow/ScreenSpaceFluidPass.js +0 -736
  112. package/WaterFlow/ScreenSpaceFluidPass.ts +0 -789
  113. package/WaterFlow/ShallowWaterSurface.d.ts +0 -45
  114. package/WaterFlow/ShallowWaterSurface.js +0 -441
  115. package/WaterFlow/ShallowWaterSurface.ts +0 -510
  116. package/WaterFlow/WaterFlow.d.ts +0 -87
  117. package/WaterFlow/WaterFlow.js +0 -171
  118. package/WaterFlow/WaterFlow.ts +0 -219
  119. package/WaterFlow/types.d.ts +0 -161
  120. package/WaterFlow/types.js +0 -1
  121. package/WaterFlow/types.ts +0 -189
  122. package/WaterFlow/waterFlowPass.d.ts +0 -3
  123. package/WaterFlow/waterFlowPass.js +0 -20
  124. package/WaterFlow/waterFlowPass.ts +0 -40
  125. package/shaders/debugExcludedShader.d.ts +0 -15
  126. package/shaders/debugExcludedShader.js +0 -48
  127. package/shaders/debugExcludedShader.ts +0 -50
@@ -14,6 +14,46 @@ const PICK_EVENT_TYPES = [
14
14
  "mouseup",
15
15
  ];
16
16
 
17
+ /** 一个 batch 的合并情况快照(详见 `InstancedGroup.snapshot`) */
18
+ export interface InstancedBatchSnapshot {
19
+ /** 分桶键:`geo:<geometryUuid>/<materialUuid>` 或 `url:<glb>:anim:<剪辑名>` */
20
+ key: string;
21
+ /** 本桶里的逻辑实例数(InstancedChild) */
22
+ childCount: number;
23
+ /** 真实 InstancedMesh 个数 = 本桶一帧的 draw call 数(GLB 多 submesh ⇒ 大于 1) */
24
+ drawCalls: number;
25
+ /** 实例缓冲容量(只增不减) */
26
+ capacity: number;
27
+ /** GLB 模板是否已就绪;false ⇒ 实例已登记但还没画出来 */
28
+ ready: boolean;
29
+ /** 每个 InstancedMesh 实际写入的实例数(与 drawCalls 一一对应) */
30
+ counts: number[];
31
+ /** 子实例的可读标签(name 优先,其次构造器名) */
32
+ children: string[];
33
+ /** 首个 InstancedMesh 的几何类型名(如 `BoxGeometry`);模板未就绪时为空串 */
34
+ geomType: string;
35
+ /** 首个 InstancedMesh 的材质类型名(多材质为 `多材质`);模板未就绪时为空串 */
36
+ matType: string;
37
+ }
38
+
39
+ /** 一个 InstancedGroup 的合并总览 */
40
+ export interface InstancedGroupSnapshot {
41
+ /** 本组归属 tag;undefined = ThreeBase 默认组(只收未声明归属的实例) */
42
+ owner?: string;
43
+ batches: InstancedBatchSnapshot[];
44
+ /** 已收进各 batch 的实例总数 */
45
+ merged: number;
46
+ /** 全局注册表里的 InstancedChild 总数(含归属其他组的) */
47
+ registryTotal: number;
48
+ /**
49
+ * 累计创建过的 InstancedChild 总数(只增不减,dispose 不回退)。
50
+ * 与 `registryTotal` 配对即得「已销毁 = createdTotal - registryTotal」。
51
+ */
52
+ createdTotal: number;
53
+ /** 归属本组却没进任何 batch 的实例数:正常恒为 0,非 0 说明分桶/收集有漏 */
54
+ leaked: number;
55
+ }
56
+
17
57
  /**
18
58
  * 固定在 ThreeBase.scene 里的分组器。每帧收集所有 InstancedChild,按 batchKey(glb+当前生效动画)分组,
19
59
  * 为每个 key 创建/复用 InstancedBatch,把实例的世界矩阵 / 颜色同步进真实 InstancedMesh。
@@ -118,6 +158,51 @@ export default class InstancedGroup extends Object3D {
118
158
  }
119
159
  }
120
160
 
161
+ /**
162
+ * 只读快照:本组当前的合并情况,供调试面板画拓扑图。
163
+ *
164
+ * 归属判定(哪些注册表实例该由本组收集)刻意留在这里而不是让调用方自己判 ——
165
+ * 规则与 `_accepts` 必须同源,否则面板报的「未合并数」会与实际渲染不符。
166
+ *
167
+ * ⚠️ 子实例标签取 `name`,其次取构造器名:业务子类若没设 `name`,生产构建(压缩后)
168
+ * 构造器名会变成短标识符。要在拓扑图里认出实例,请给实例设 `name`(同 [[InstancedChild]] 的控制台可读命名约定)。
169
+ */
170
+ snapshot(): InstancedGroupSnapshot {
171
+ const batches: InstancedBatchSnapshot[] = [];
172
+ let merged = 0;
173
+ for (const batch of this.batches.values()) {
174
+ const childCount = batch.childCount;
175
+ merged += childCount;
176
+ const first = batch.pickables[0];
177
+ const mat = first?.material;
178
+ batches.push({
179
+ key: batch.key,
180
+ childCount,
181
+ drawCalls: batch.pickables.length,
182
+ capacity: batch.capacity,
183
+ ready: batch.ready,
184
+ counts: batch.pickables.map((im) => im.count),
185
+ children: batch.childrenView.map((c) => c.name || c.constructor.name),
186
+ geomType: first?.geometry.type ?? "",
187
+ matType: Array.isArray(mat) ? "多材质" : mat?.type ?? "",
188
+ });
189
+ }
190
+ let accepted = 0;
191
+ for (const child of instancedChildRegistry) {
192
+ if (this._accepts(child)) {
193
+ accepted++;
194
+ }
195
+ }
196
+ return {
197
+ owner: this.owner,
198
+ batches,
199
+ merged,
200
+ registryTotal: instancedChildRegistry.size,
201
+ createdTotal: InstancedChild.createdTotal,
202
+ leaked: accepted - merged,
203
+ };
204
+ }
205
+
121
206
  /**
122
207
  * 释放本组的全部 batch(实例缓冲 + 从组内摘除 mesh)。
123
208
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "three-base",
3
- "version": "2.0.172",
3
+ "version": "2.0.180",
4
4
  "description": "A Three.js extension library providing common 3D components, animations, materials, and utilities",
5
5
  "author": "xiaosihan",
6
6
  "publishConfig": {
@@ -32,6 +32,26 @@
32
32
  "import": "./MktMesh/MktMesh.js",
33
33
  "require": "./MktMesh/MktMesh.js"
34
34
  },
35
+ "./MktMesh/imagePlane": {
36
+ "types": "./MktMesh/imagePlane.d.ts",
37
+ "import": "./MktMesh/imagePlane.js",
38
+ "require": "./MktMesh/imagePlane.js"
39
+ },
40
+ "./MktMesh/imageTileLoader": {
41
+ "types": "./MktMesh/imageTileLoader.d.ts",
42
+ "import": "./MktMesh/imageTileLoader.js",
43
+ "require": "./MktMesh/imageTileLoader.js"
44
+ },
45
+ "./MktMesh/modelSlot": {
46
+ "types": "./MktMesh/modelSlot.d.ts",
47
+ "import": "./MktMesh/modelSlot.js",
48
+ "require": "./MktMesh/modelSlot.js"
49
+ },
50
+ "./MktMesh/boxLine2": {
51
+ "types": "./MktMesh/boxLine2.d.ts",
52
+ "import": "./MktMesh/boxLine2.js",
53
+ "require": "./MktMesh/boxLine2.js"
54
+ },
35
55
  "./InstancedMeshBase": "./instanced/InstancedMeshBase.js",
36
56
  "./threeLoader": "./threeLoader.js",
37
57
  "./threeUtils": "./threeUtils.js",
@@ -76,12 +96,8 @@
76
96
  "./shaders/baseDepthVis": "./shaders/baseDepthVisShader.js",
77
97
  "./shaders/debugDepthCompare": "./shaders/debugDepthCompareShader.js",
78
98
  "./shaders/debugDepthJudge": "./shaders/debugDepthJudgeShader.js",
79
- "./shaders/debugExcluded": "./shaders/debugExcludedShader.js",
80
99
  "./Fire/FireGeometry": "./Fire/FireGeometry.js",
81
- "./Fire/FireMaterial": "./Fire/FireMaterial.js",
82
- "./WaterFlow": "./WaterFlow/WaterFlow.js",
83
- "./WaterFlow/WaterFlow": "./WaterFlow/WaterFlow.js",
84
- "./WaterFlow/waterFlowPass": "./WaterFlow/waterFlowPass.js"
100
+ "./Fire/FireMaterial": "./Fire/FireMaterial.js"
85
101
  },
86
102
  "files": [
87
103
  "*.ts",
@@ -99,7 +115,6 @@
99
115
  "SpriteModal1/",
100
116
  "Text3D/",
101
117
  "Water/",
102
- "WaterFlow/",
103
118
  "instanced/",
104
119
  "lensflare/",
105
120
  "pass/",
@@ -1,20 +1,28 @@
1
- import type { DepthTexture } from "three";
1
+ import type { DepthTexture, Texture } from "three";
2
2
  /**
3
3
  * 深度调试预览模式(面板按钮与控制台 `window.__TB_DEBUG_DEPTH` 共用同一枚举):
4
- * - "none" :正常渲染(默认)
5
- * - "global" :可见深度图(baseDepthTexture,各物体自身材质渲染,含地板)
6
- * - "ao" :AO 深度图(aoDepthTexture,法线 pass 顺带写入,override 渲染)
7
- * - "compare" :R=base 深度、G=选区 select 深度(对数反解后归一化)
8
- * - "judge" :R=base 原始深度、G=select 原始深度、B=判定结果(1=判为被遮挡应 discard)
9
- * - "excluded":深度图灰度 + 「被排除出深度图的面」叠红(红=挡不住任何后处理)
4
+ * - "none" :正常渲染(默认)
5
+ * - "global" :可见深度图(baseDepthTexture,各物体自身材质渲染;2026-10-18 起收全场景对象,含地板)
6
+ * - "ao" :AO 深度图(aoDepthTexture,法线 pass 顺带写入,override 渲染,同样收全场景对象)
7
+ * - "compare" :R=base 深度、G=选区 select 深度(对数反解后归一化)
8
+ * - "judge" :R=base 原始深度、G=select 原始深度、B=判定结果(1=判为被遮挡应 discard)
9
+ * - "strokeSelect" :【描边步骤 1】选区本体深度(selectDepthTexture,mask 那趟光栅化顺带写入)
10
+ * - "strokeSelectBlur":【描边步骤 5.5】描边外扩后的选区深度(selectDepthBlurTextureTarget,
11
+ * RGBA8 的 R 通道存对数深度,外扩环取邻域最近深度)
12
+ * ⚠️ 2026-10-18 皇上旨「所有的对象都要进入到深度图里面了,不需要用参数过滤掉了」⇒ 原 "excluded"
13
+ * 档(把被排除的面叠红)连同 ssao_pass 的排除判据整条删除,已无「写不进深度图的面」可标。
10
14
  */
11
- export type DebugDepthMode = "none" | "global" | "ao" | "compare" | "judge" | "excluded";
15
+ export type DebugDepthMode = "none" | "global" | "ao" | "compare" | "judge" | "strokeSelect" | "strokeSelectBlur";
12
16
  /**
13
17
  * 调试用全局状态:记录最近一次 glow_pass / stroke_pass 渲染的「选区自身深度图」(selectDepth)。
14
18
  * 供 ThreeBase 渲染末尾的「辉光深度比对」调试视图读取(R=全局 base 深度,G=选区 select 深度),
15
19
  * 让用户一眼看出到底是「全局 base 深度没写进」还是「选区自身深度没写进」。
16
20
  * 由各 pass 在渲染完 selectDepth 后写入;每帧会被最后一个被处理的可见对象覆盖(调试够用)。
21
+ *
22
+ * lastSelectBlurDepth:描边专属(步骤 5.5 外扩后的选区深度)。它是 RGBA8 目标(不是 DepthTexture),
23
+ * 深度值存在 .r 通道里 —— 可视化时同样取 .r 即可。glow/cover/frosted 没有这一步,故只有 stroke_pass 写。
17
24
  */
18
25
  export declare const debugDepthState: {
19
26
  lastSelectDepth: DepthTexture | null;
27
+ lastSelectBlurDepth: Texture | null;
20
28
  };
@@ -3,7 +3,11 @@
3
3
  * 供 ThreeBase 渲染末尾的「辉光深度比对」调试视图读取(R=全局 base 深度,G=选区 select 深度),
4
4
  * 让用户一眼看出到底是「全局 base 深度没写进」还是「选区自身深度没写进」。
5
5
  * 由各 pass 在渲染完 selectDepth 后写入;每帧会被最后一个被处理的可见对象覆盖(调试够用)。
6
+ *
7
+ * lastSelectBlurDepth:描边专属(步骤 5.5 外扩后的选区深度)。它是 RGBA8 目标(不是 DepthTexture),
8
+ * 深度值存在 .r 通道里 —— 可视化时同样取 .r 即可。glow/cover/frosted 没有这一步,故只有 stroke_pass 写。
6
9
  */
7
10
  export const debugDepthState = {
8
11
  lastSelectDepth: null,
12
+ lastSelectBlurDepth: null,
9
13
  };
@@ -1,22 +1,40 @@
1
- import type { DepthTexture } from "three";
1
+ import type { DepthTexture, Texture } from "three";
2
2
 
3
3
  /**
4
4
  * 深度调试预览模式(面板按钮与控制台 `window.__TB_DEBUG_DEPTH` 共用同一枚举):
5
- * - "none" :正常渲染(默认)
6
- * - "global" :可见深度图(baseDepthTexture,各物体自身材质渲染,含地板)
7
- * - "ao" :AO 深度图(aoDepthTexture,法线 pass 顺带写入,override 渲染)
8
- * - "compare" :R=base 深度、G=选区 select 深度(对数反解后归一化)
9
- * - "judge" :R=base 原始深度、G=select 原始深度、B=判定结果(1=判为被遮挡应 discard)
10
- * - "excluded":深度图灰度 + 「被排除出深度图的面」叠红(红=挡不住任何后处理)
5
+ * - "none" :正常渲染(默认)
6
+ * - "global" :可见深度图(baseDepthTexture,各物体自身材质渲染;2026-10-18 起收全场景对象,含地板)
7
+ * - "ao" :AO 深度图(aoDepthTexture,法线 pass 顺带写入,override 渲染,同样收全场景对象)
8
+ * - "compare" :R=base 深度、G=选区 select 深度(对数反解后归一化)
9
+ * - "judge" :R=base 原始深度、G=select 原始深度、B=判定结果(1=判为被遮挡应 discard)
10
+ * - "strokeSelect" :【描边步骤 1】选区本体深度(selectDepthTexture,mask 那趟光栅化顺带写入)
11
+ * - "strokeSelectBlur":【描边步骤 5.5】描边外扩后的选区深度(selectDepthBlurTextureTarget,
12
+ * RGBA8 的 R 通道存对数深度,外扩环取邻域最近深度)
13
+ * ⚠️ 2026-10-18 皇上旨「所有的对象都要进入到深度图里面了,不需要用参数过滤掉了」⇒ 原 "excluded"
14
+ * 档(把被排除的面叠红)连同 ssao_pass 的排除判据整条删除,已无「写不进深度图的面」可标。
11
15
  */
12
- export type DebugDepthMode = "none" | "global" | "ao" | "compare" | "judge" | "excluded";
16
+ export type DebugDepthMode =
17
+ | "none"
18
+ | "global"
19
+ | "ao"
20
+ | "compare"
21
+ | "judge"
22
+ | "strokeSelect"
23
+ | "strokeSelectBlur";
13
24
 
14
25
  /**
15
26
  * 调试用全局状态:记录最近一次 glow_pass / stroke_pass 渲染的「选区自身深度图」(selectDepth)。
16
27
  * 供 ThreeBase 渲染末尾的「辉光深度比对」调试视图读取(R=全局 base 深度,G=选区 select 深度),
17
28
  * 让用户一眼看出到底是「全局 base 深度没写进」还是「选区自身深度没写进」。
18
29
  * 由各 pass 在渲染完 selectDepth 后写入;每帧会被最后一个被处理的可见对象覆盖(调试够用)。
30
+ *
31
+ * lastSelectBlurDepth:描边专属(步骤 5.5 外扩后的选区深度)。它是 RGBA8 目标(不是 DepthTexture),
32
+ * 深度值存在 .r 通道里 —— 可视化时同样取 .r 即可。glow/cover/frosted 没有这一步,故只有 stroke_pass 写。
19
33
  */
20
- export const debugDepthState: { lastSelectDepth: DepthTexture | null } = {
34
+ export const debugDepthState: {
35
+ lastSelectDepth: DepthTexture | null;
36
+ lastSelectBlurDepth: Texture | null;
37
+ } = {
21
38
  lastSelectDepth: null,
39
+ lastSelectBlurDepth: null,
22
40
  };
package/pass/glow_pass.js CHANGED
@@ -43,24 +43,13 @@ const blur2TextureTarget = new WebGLRenderTarget(1024, 1024, {
43
43
  magFilter: LinearFilter,
44
44
  format: RGBAFormat,
45
45
  });
46
- // 外扩深度临时/结果目标:depthMinBlurShader 把本体深度图随 mask 一起外扩,
47
- // 外扩区取邻域最近深度(忽略背景 1.0),使外扩区 selD<1.0,depthTest 才能正确判遮挡(不漏光)。
48
- const selectDepthBlurTmpTextureTarget = new WebGLRenderTarget(1024, 1024, {
49
- minFilter: LinearFilter,
50
- magFilter: LinearFilter,
51
- format: RGBAFormat,
52
- });
53
- const selectDepthBlurTextureTarget = new WebGLRenderTarget(1024, 1024, {
54
- minFilter: LinearFilter,
55
- magFilter: LinearFilter,
56
- format: RGBAFormat,
57
- });
58
- // 外扩辉光经深度测试后的结果(步骤 5.6):独立 target,避免回写 blur1 触发历史回归 bug
59
- const blurDepthTestTextureTarget = new WebGLRenderTarget(1024, 1024, {
60
- minFilter: LinearFilter,
61
- magFilter: LinearFilter,
62
- format: RGBAFormat,
63
- });
46
+ // ⭐ 2026-10-25 皇上旨「步骤 5.6 外扩辉光再判遮挡 不要这不」:
47
+ // 原「步骤 5.5 深度外扩(min-blur)+ 5.6 外扩辉光再判遮挡」整段删除,连同
48
+ // selectDepthBlurTmp / selectDepthBlur / blurDepthTest 三个 RT 与 depthMinBlurShader。
49
+ // 原因:min-blur 的膨胀窗口是 ±10×radius 的方形(radius = glow_width×2,与单趟高斯采样步长同源),
50
+ // 而模糊迭代 N 次后等效扩散按 σ√N 增长 ⇒ 窗口外那圈光的 selD 仍是「背景 1.0」,
51
+ // 被 baseD(天空 0.9) < selD(1.0) 判成「被挡住」→ discard → 光晕被硬切一刀。
52
+ // 代价(已知并接受):物体被更近的物体挡住时,辉光不再从遮挡物前方被裁掉,会透出来。
64
53
  const size = new Vector2();
65
54
  const depthTestShader = new ShaderMaterial({
66
55
  uniforms: {
@@ -204,52 +193,6 @@ const gaussianBlurVShader = new RawShaderMaterial({
204
193
  depthWrite: false,
205
194
  transparent: true,
206
195
  });
207
- // 深度 min-blur(最近深度,忽略背景 1.0):随 mask 一起把深度图向外扩,
208
- // 外扩区 selD = 物体最近深度(<1.0) 而非清屏 1.0,depthTest 在外扩区才能正确判遮挡(不漏光),
209
- // 同时本体区仍靠 depthTestShader 的 EPSILON 容差防自遮挡闪烁(无缝)。separable(direction 控制 H/V)。
210
- const depthMinBlurShader = new ShaderMaterial({
211
- uniforms: {
212
- tDepth: { value: null },
213
- resolution: { value: new Vector2(1 / 512, 1 / 512) },
214
- radius: { value: 1.0 },
215
- direction: { value: new Vector2(1, 0) },
216
- },
217
- vertexShader: `
218
- ${ShaderChunk.common}
219
- ${ShaderChunk.logdepthbuf_pars_vertex}
220
- varying vec2 vUv;
221
- void main() {
222
- vUv = uv;
223
- gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
224
- ${ShaderChunk.logdepthbuf_vertex}
225
- }
226
- `,
227
- fragmentShader: `
228
- ${ShaderChunk.logdepthbuf_pars_fragment}
229
- uniform sampler2D tDepth;
230
- uniform vec2 resolution;
231
- uniform float radius;
232
- uniform vec2 direction;
233
- varying vec2 vUv;
234
- void main() {
235
- float minD = 1.0;
236
- for (int i = -10; i <= 10; i++) {
237
- float x = float(i);
238
- vec2 off = direction * (x * radius * resolution);
239
- float d = texture2D(tDepth, vUv + off).r;
240
- if (d < 0.9999) {
241
- minD = min(minD, d);
242
- }
243
- }
244
- gl_FragColor = vec4(minD, 0.0, 0.0, 1.0);
245
- ${ShaderChunk.logdepthbuf_fragment}
246
- }
247
- `,
248
- blending: NoBlending,
249
- depthTest: false,
250
- depthWrite: false,
251
- transparent: true,
252
- });
253
196
  const glowCompositeShader = new RawShaderMaterial({
254
197
  uniforms: {
255
198
  tDiffuse: { value: null },
@@ -486,9 +429,6 @@ export default function glow_pass(renderer, camera, object3d, baseDepthTexture,
486
429
  selectDepthTestTextureTarget.setSize(size.x, size.y);
487
430
  blur1TextureTarget.setSize(size.x, size.y);
488
431
  blur2TextureTarget.setSize(size.x, size.y);
489
- selectDepthBlurTmpTextureTarget.setSize(size.x, size.y);
490
- selectDepthBlurTextureTarget.setSize(size.x, size.y);
491
- blurDepthTestTextureTarget.setSize(size.x, size.y);
492
432
  // 1. 渲染物体本体 mask(灰度)。⭐ 本体深度由同一趟光栅化顺带写进 selectDepthTexture
493
433
  // (挂在 selectTextureTarget 的 depth attachment 上);原先的第 2 趟「只渲深度」(供 min-blur
494
434
  // 外扩用)与这趟同材质/同相机/同几何 ⇒ 深度逐位相同,2026-10-11 皇上旨简化时删除。
@@ -545,36 +485,13 @@ export default function glow_pass(renderer, camera, object3d, baseDepthTexture,
545
485
  glowCompositeShader.uniforms.threshold.value = glow_threshold;
546
486
  glowCompositeShader.uniforms.intensity.value = glow_intensity;
547
487
  fsQuad.render(renderer, glowCompositeShader);
548
- // 5.5 ⭐ 外扩环深度测试(补齐此前只定义未调用的死代码,与 stroke_pass 同一修复):
549
- // 本体深度随辉光一起外扩(separable H/V,外扩区取邻域最近深度),
550
- // 再用它对外扩后的辉光做一次 depthTest —— 否则外扩环永远不参与遮挡判定,
551
- // 物体被挡住时辉光依旧从遮挡物前方漏出来。
552
- depthMinBlurShader.uniforms.resolution.value.set(1 / size.x, 1 / size.y);
553
- depthMinBlurShader.uniforms.radius.value = Math.max(1, blurRadius);
554
- depthMinBlurShader.uniforms.direction.value.set(1, 0);
555
- depthMinBlurShader.uniforms.tDepth.value = selectDepthTexture;
556
- renderer.setRenderTarget(selectDepthBlurTmpTextureTarget);
557
- renderer.clear();
558
- fsQuad.render(renderer, depthMinBlurShader);
559
- depthMinBlurShader.uniforms.direction.value.set(0, 1);
560
- depthMinBlurShader.uniforms.tDepth.value = selectDepthBlurTmpTextureTarget.texture;
561
- renderer.setRenderTarget(selectDepthBlurTextureTarget);
562
- renderer.clear();
563
- fsQuad.render(renderer, depthMinBlurShader);
564
- // 5.6 对外扩后的辉光判遮挡(输出到独立 target,绝不回写 blur1,避免步骤 6 相减归零)
565
- renderer.setRenderTarget(blurDepthTestTextureTarget);
566
- renderer.clear();
567
- depthTestShader.uniforms.map.value = blur1TextureTarget.texture;
568
- depthTestShader.uniforms.baseDepth.value = baseDepthTexture;
569
- depthTestShader.uniforms.selectDepth.value = selectDepthBlurTextureTarget.texture;
570
- depthTestShader.uniforms.cameraFar.value = camera.far;
571
- fsQuad.render(renderer, depthTestShader);
572
- // 6. 合成到屏幕:filterSelect(blur=上色后且已判遮挡的最终外扩辉光, select=深度测试后本体辉光)
573
- // = 仅保留辉光外扩环;本体被减掉。⚠️ blur 必须是最终外扩辉光,绝不能被 depthTest 结果覆盖
488
+ // 6. 合成到屏幕:filterSelect(blur=上色后的外扩辉光 blur1, select=深度测试后本体辉光)
489
+ // = 仅保留辉光外扩环;本体被减掉。⚠️ blur 必须是上色后的 blur1,绝不能被别的结果覆盖
574
490
  // (早期回归:误把 depthTest 结果上色进 blur1 → filterSelect 相减归零 → 辉光全不显示)。
491
+ // ⭐ 2026-10-25 起外扩环不再做第二次遮挡判定(皇上旨删 5.6),blur1 直接就是最终辉光。
575
492
  renderer.setRenderTarget(originRenderTarget);
576
493
  filterSelectShader.uniforms.selectTexture.value = selectDepthTestTextureTarget.texture;
577
- filterSelectShader.uniforms.blurTexture.value = blurDepthTestTextureTarget.texture;
494
+ filterSelectShader.uniforms.blurTexture.value = blur1TextureTarget.texture;
578
495
  filterSelectShader.uniforms.opacity.value = glow_opacity;
579
496
  // glow_additive=true 时用加性混合,光晕叠加到画面呈发光感(很亮那种);否则普通半透明覆盖(默认)
580
497
  filterSelectShader.blending = glow_additive ? AdditiveBlending : NormalBlending;
package/pass/glow_pass.ts CHANGED
@@ -50,24 +50,13 @@ const blur2TextureTarget: WebGLRenderTarget = new WebGLRenderTarget(1024, 1024,
50
50
  format: RGBAFormat,
51
51
  });
52
52
 
53
- // 外扩深度临时/结果目标:depthMinBlurShader 把本体深度图随 mask 一起外扩,
54
- // 外扩区取邻域最近深度(忽略背景 1.0),使外扩区 selD<1.0,depthTest 才能正确判遮挡(不漏光)。
55
- const selectDepthBlurTmpTextureTarget: WebGLRenderTarget = new WebGLRenderTarget(1024, 1024, {
56
- minFilter: LinearFilter,
57
- magFilter: LinearFilter,
58
- format: RGBAFormat,
59
- });
60
- const selectDepthBlurTextureTarget: WebGLRenderTarget = new WebGLRenderTarget(1024, 1024, {
61
- minFilter: LinearFilter,
62
- magFilter: LinearFilter,
63
- format: RGBAFormat,
64
- });
65
- // 外扩辉光经深度测试后的结果(步骤 5.6):独立 target,避免回写 blur1 触发历史回归 bug
66
- const blurDepthTestTextureTarget: WebGLRenderTarget = new WebGLRenderTarget(1024, 1024, {
67
- minFilter: LinearFilter,
68
- magFilter: LinearFilter,
69
- format: RGBAFormat,
70
- });
53
+ // ⭐ 2026-10-25 皇上旨「步骤 5.6 外扩辉光再判遮挡 不要这不」:
54
+ // 原「步骤 5.5 深度外扩(min-blur)+ 5.6 外扩辉光再判遮挡」整段删除,连同
55
+ // selectDepthBlurTmp / selectDepthBlur / blurDepthTest 三个 RT 与 depthMinBlurShader。
56
+ // 原因:min-blur 的膨胀窗口是 ±10×radius 的方形(radius = glow_width×2,与单趟高斯采样步长同源),
57
+ // 而模糊迭代 N 次后等效扩散按 σ√N 增长 ⇒ 窗口外那圈光的 selD 仍是「背景 1.0」,
58
+ // 被 baseD(天空 0.9) < selD(1.0) 判成「被挡住」→ discard → 光晕被硬切一刀。
59
+ // 代价(已知并接受):物体被更近的物体挡住时,辉光不再从遮挡物前方被裁掉,会透出来。
71
60
 
72
61
  const size: Vector2 = new Vector2();
73
62
 
@@ -216,53 +205,6 @@ const gaussianBlurVShader: RawShaderMaterial = new RawShaderMaterial({
216
205
  transparent: true,
217
206
  });
218
207
 
219
- // 深度 min-blur(最近深度,忽略背景 1.0):随 mask 一起把深度图向外扩,
220
- // 外扩区 selD = 物体最近深度(<1.0) 而非清屏 1.0,depthTest 在外扩区才能正确判遮挡(不漏光),
221
- // 同时本体区仍靠 depthTestShader 的 EPSILON 容差防自遮挡闪烁(无缝)。separable(direction 控制 H/V)。
222
- const depthMinBlurShader: ShaderMaterial = new ShaderMaterial({
223
- uniforms: {
224
- tDepth: { value: null },
225
- resolution: { value: new Vector2(1 / 512, 1 / 512) },
226
- radius: { value: 1.0 },
227
- direction: { value: new Vector2(1, 0) },
228
- },
229
- vertexShader: `
230
- ${ShaderChunk.common}
231
- ${ShaderChunk.logdepthbuf_pars_vertex}
232
- varying vec2 vUv;
233
- void main() {
234
- vUv = uv;
235
- gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
236
- ${ShaderChunk.logdepthbuf_vertex}
237
- }
238
- `,
239
- fragmentShader: `
240
- ${ShaderChunk.logdepthbuf_pars_fragment}
241
- uniform sampler2D tDepth;
242
- uniform vec2 resolution;
243
- uniform float radius;
244
- uniform vec2 direction;
245
- varying vec2 vUv;
246
- void main() {
247
- float minD = 1.0;
248
- for (int i = -10; i <= 10; i++) {
249
- float x = float(i);
250
- vec2 off = direction * (x * radius * resolution);
251
- float d = texture2D(tDepth, vUv + off).r;
252
- if (d < 0.9999) {
253
- minD = min(minD, d);
254
- }
255
- }
256
- gl_FragColor = vec4(minD, 0.0, 0.0, 1.0);
257
- ${ShaderChunk.logdepthbuf_fragment}
258
- }
259
- `,
260
- blending: NoBlending,
261
- depthTest: false,
262
- depthWrite: false,
263
- transparent: true,
264
- });
265
-
266
208
  const glowCompositeShader: RawShaderMaterial = new RawShaderMaterial({
267
209
  uniforms: {
268
210
  tDiffuse: { value: null },
@@ -523,9 +465,6 @@ export default function glow_pass(
523
465
  selectDepthTestTextureTarget.setSize(size.x, size.y);
524
466
  blur1TextureTarget.setSize(size.x, size.y);
525
467
  blur2TextureTarget.setSize(size.x, size.y);
526
- selectDepthBlurTmpTextureTarget.setSize(size.x, size.y);
527
- selectDepthBlurTextureTarget.setSize(size.x, size.y);
528
- blurDepthTestTextureTarget.setSize(size.x, size.y);
529
468
 
530
469
  // 1. 渲染物体本体 mask(灰度)。⭐ 本体深度由同一趟光栅化顺带写进 selectDepthTexture
531
470
  // (挂在 selectTextureTarget 的 depth attachment 上);原先的第 2 趟「只渲深度」(供 min-blur
@@ -587,38 +526,13 @@ export default function glow_pass(
587
526
  glowCompositeShader.uniforms.intensity.value = glow_intensity;
588
527
  fsQuad.render(renderer, glowCompositeShader);
589
528
 
590
- // 5.5 ⭐ 外扩环深度测试(补齐此前只定义未调用的死代码,与 stroke_pass 同一修复):
591
- // 本体深度随辉光一起外扩(separable H/V,外扩区取邻域最近深度),
592
- // 再用它对外扩后的辉光做一次 depthTest —— 否则外扩环永远不参与遮挡判定,
593
- // 物体被挡住时辉光依旧从遮挡物前方漏出来。
594
- depthMinBlurShader.uniforms.resolution.value.set(1 / size.x, 1 / size.y);
595
- depthMinBlurShader.uniforms.radius.value = Math.max(1, blurRadius);
596
- depthMinBlurShader.uniforms.direction.value.set(1, 0);
597
- depthMinBlurShader.uniforms.tDepth.value = selectDepthTexture;
598
- renderer.setRenderTarget(selectDepthBlurTmpTextureTarget);
599
- renderer.clear();
600
- fsQuad.render(renderer, depthMinBlurShader);
601
- depthMinBlurShader.uniforms.direction.value.set(0, 1);
602
- depthMinBlurShader.uniforms.tDepth.value = selectDepthBlurTmpTextureTarget.texture;
603
- renderer.setRenderTarget(selectDepthBlurTextureTarget);
604
- renderer.clear();
605
- fsQuad.render(renderer, depthMinBlurShader);
606
-
607
- // 5.6 对外扩后的辉光判遮挡(输出到独立 target,绝不回写 blur1,避免步骤 6 相减归零)
608
- renderer.setRenderTarget(blurDepthTestTextureTarget);
609
- renderer.clear();
610
- depthTestShader.uniforms.map.value = blur1TextureTarget.texture;
611
- depthTestShader.uniforms.baseDepth.value = baseDepthTexture;
612
- depthTestShader.uniforms.selectDepth.value = selectDepthBlurTextureTarget.texture;
613
- depthTestShader.uniforms.cameraFar.value = (camera as PerspectiveCamera).far;
614
- fsQuad.render(renderer, depthTestShader);
615
-
616
- // 6. 合成到屏幕:filterSelect(blur=上色后且已判遮挡的最终外扩辉光, select=深度测试后本体辉光)
617
- // = 仅保留辉光外扩环;本体被减掉。⚠️ blur 必须是最终外扩辉光,绝不能被 depthTest 结果覆盖
529
+ // 6. 合成到屏幕:filterSelect(blur=上色后的外扩辉光 blur1, select=深度测试后本体辉光)
530
+ // = 仅保留辉光外扩环;本体被减掉。⚠️ blur 必须是上色后的 blur1,绝不能被别的结果覆盖
618
531
  // (早期回归:误把 depthTest 结果上色进 blur1 → filterSelect 相减归零 → 辉光全不显示)。
532
+ // ⭐ 2026-10-25 起外扩环不再做第二次遮挡判定(皇上旨删 5.6),blur1 直接就是最终辉光。
619
533
  renderer.setRenderTarget(originRenderTarget);
620
534
  filterSelectShader.uniforms.selectTexture.value = selectDepthTestTextureTarget.texture;
621
- filterSelectShader.uniforms.blurTexture.value = blurDepthTestTextureTarget.texture;
535
+ filterSelectShader.uniforms.blurTexture.value = blur1TextureTarget.texture;
622
536
  filterSelectShader.uniforms.opacity.value = glow_opacity;
623
537
  // glow_additive=true 时用加性混合,光晕叠加到画面呈发光感(很亮那种);否则普通半透明覆盖(默认)
624
538
  filterSelectShader.blending = glow_additive ? AdditiveBlending : NormalBlending;
@@ -1,36 +1,22 @@
1
1
  import { MeshNormalMaterial, Scene, WebGLRenderTarget, WebGLRenderer, Camera } from "three";
2
2
  /**
3
- * 可见深度 pass:固定排除非实体表面后,用**各物体自身的材质**把场景深度渲染到 depthRenderTarget。
3
+ * 可见深度 pass:用**各物体自身的材质**把整个场景的深度渲染到 depthRenderTarget。
4
4
  * depthRenderTarget.depthTexture 即 baseDepthTexture,供描边 / 发光 / 覆盖 / 磨砂的遮挡判定,
5
5
  * 也是 SSAO 合成时「真实可见表面」的参考。
6
- * 排除的非实体对象(sprite/线条/点)在深度图保留 clear 深度(1.0=远),与背景一致;排除的
7
- * 半透明对象则保留其身后不透明几何的深度(身后无几何时同样为 1.0)。均不影响颜色通道渲染。
6
+ * 2026-10-18 起**不排除任何对象**(皇上旨「所有的对象都要进入到深度图里面了,不需要用参数过滤掉了」):
7
+ * 场景里所有对象都参与这一趟,只有使用者自己 `visible = false` 的对象除外(那是显隐意图,本 pass 不碰)。
8
8
  * ⚠️ 名字里的 ao 已不适用(2026-10-11 改名自 renderAoDepthPass):它产出的是**可见深度**,
9
- * AO 自己的深度挂在法线 pass 上(见 renderAoNormalPass),两者只差 excludeTransparent 一个开关。
9
+ * AO 自己的深度挂在法线 pass 上(见 renderAoNormalPass)。
10
10
  */
11
- export declare function renderVisibleDepthPass(renderer: WebGLRenderer, camera: Camera, scene: Scene, depthRenderTarget: WebGLRenderTarget, excludeTransparent?: boolean): void;
11
+ export declare function renderVisibleDepthPass(renderer: WebGLRenderer, camera: Camera, scene: Scene, depthRenderTarget: WebGLRenderTarget): void;
12
12
  /**
13
- * 调试用:把「被排除出可见深度图」的表面单独渲成红色 mask。
14
- *
15
- * 这些面在 renderVisibleDepthPass 里被 hideNonSurface 隐藏,因此**不会写进 baseDepthTexture**,
16
- * 也就永远挡不住描边/辉光/毛玻璃/覆盖色 —— 这正是"深度测试看起来失效"最常见的成因
17
- * (用户以为是 bug,其实是该面被设计成可透视:sprite/线条/点、userData.aoTransparent)。
18
- * ⚠️ 地板不在此列:2026-10-11 起 Ground1 是实心不透明面,正常写进可见深度图。
19
- * 面板「深度调试 → 排除面标记」叠加显示:灰=能挡住的真实遮挡面,红=被排除、挡不住任何东西。
20
- *
21
- * 只渲染 Mesh:sprite / Line2 / Points 在 MeshBasicMaterial override 下渲染异常(见文件头注释),
22
- * 且它们数量少、用户关心的遮挡体基本都是 Mesh,故跳过。
23
- */
24
- export declare function renderExcludedMaskPass(renderer: WebGLRenderer, camera: Camera, scene: Scene, maskRenderTarget: WebGLRenderTarget, excludeTransparent?: boolean): void;
25
- /**
26
- * 法线 pass(仅 SSAO 开启时需要):固定排除非实体表面后,以中性灰清屏 + normalMaterial
27
- * override 将视图空间法线渲染到 normalRenderTarget,供 GTAO 风格 SSAO 使用。
28
- * 排除对象在法线图保留中性灰清屏色 → unpackRGBToNormal(0.5,0.5,0.5)=(0,0,0) →
29
- * SSAO 退化法线守卫判"无遮蔽"(=1),避免精灵弹窗被 AO 乘黑。清屏色用后即还原。
13
+ * 法线 pass(仅 SSAO 开启时需要):以中性灰清屏 + normalMaterial override 将整个场景的
14
+ * 视图空间法线渲染到 normalRenderTarget,供 GTAO 风格 SSAO 使用。
15
+ * 2026-10-18 起同样不排除任何对象(与 renderVisibleDepthPass 一致,见文件头那道旨及其代价清单)。
30
16
  * 深度白拿:normalRenderTarget 挂着 aoDepthTexture 作 depth attachment,这一趟的深度由光栅器
31
17
  * 顺带写入 → 就是 AO 用的深度,无需再单独渲一遍(2026-09-14)。
32
18
  */
33
- export declare function renderAoNormalPass(renderer: WebGLRenderer, camera: Camera, scene: Scene, normalRenderTarget: WebGLRenderTarget, normalMaterial: MeshNormalMaterial, excludeTransparent?: boolean): void;
19
+ export declare function renderAoNormalPass(renderer: WebGLRenderer, camera: Camera, scene: Scene, normalRenderTarget: WebGLRenderTarget, normalMaterial: MeshNormalMaterial): void;
34
20
  export interface SsaoOptions {
35
21
  enable: boolean;
36
22
  debug?: boolean;