three-base 2.0.172 → 2.0.175

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 (115) 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/mktMappingShader.d.ts +6 -5
  13. package/MktMesh/mktMappingShader.js +26 -19
  14. package/MktMesh/mktMappingShader.ts +28 -19
  15. package/MktMesh/mktShader.d.ts +127 -58
  16. package/MktMesh/mktShader.js +192 -117
  17. package/MktMesh/mktShader.ts +251 -127
  18. package/MktMesh/panoSlotRoster.d.ts +2 -2
  19. package/MktMesh/panoSlotRoster.js +9 -7
  20. package/MktMesh/panoSlotRoster.ts +9 -7
  21. package/MktMesh/panoTileStitcher.d.ts +20 -13
  22. package/MktMesh/panoTileStitcher.js +97 -76
  23. package/MktMesh/panoTileStitcher.ts +119 -90
  24. package/PipeMesh/PipeJoint.d.ts +22 -0
  25. package/PipeMesh/PipeJoint.js +33 -0
  26. package/PipeMesh/PipeJoint.ts +38 -0
  27. package/PipeMesh/PipeMesh.d.ts +94 -22
  28. package/PipeMesh/PipeMesh.js +192 -53
  29. package/PipeMesh/PipeMesh.ts +223 -76
  30. package/PipeMesh/PipeStraight.d.ts +19 -0
  31. package/PipeMesh/PipeStraight.js +34 -0
  32. package/PipeMesh/PipeStraight.ts +45 -0
  33. package/PipeMesh/axisSnap.d.ts +52 -0
  34. package/PipeMesh/axisSnap.js +52 -0
  35. package/PipeMesh/axisSnap.ts +93 -0
  36. package/PipeMesh/directRoute.d.ts +85 -0
  37. package/PipeMesh/directRoute.js +126 -0
  38. package/PipeMesh/directRoute.ts +190 -0
  39. package/PipeMesh/index.d.ts +6 -0
  40. package/PipeMesh/index.js +6 -0
  41. package/PipeMesh/index.ts +7 -1
  42. package/PipeMesh/pipeMaterial.d.ts +16 -0
  43. package/PipeMesh/pipeMaterial.js +23 -0
  44. package/PipeMesh/pipeMaterial.ts +26 -0
  45. package/ThreeBase.d.ts +1 -39
  46. package/ThreeBase.js +38 -147
  47. package/ThreeBase.ts +1176 -1302
  48. package/instanced/InstancedBatch.d.ts +14 -1
  49. package/instanced/InstancedBatch.js +53 -3
  50. package/instanced/InstancedBatch.ts +62 -3
  51. package/instanced/InstancedChild.d.ts +24 -0
  52. package/instanced/InstancedChild.js +40 -0
  53. package/instanced/InstancedChild.ts +41 -0
  54. package/instanced/InstancedGroup.d.ts +48 -0
  55. package/instanced/InstancedGroup.js +45 -1
  56. package/instanced/InstancedGroup.ts +85 -0
  57. package/package.json +2 -7
  58. package/pass/debugDepthState.d.ts +16 -8
  59. package/pass/debugDepthState.js +4 -0
  60. package/pass/debugDepthState.ts +27 -9
  61. package/pass/glow_pass.js +11 -94
  62. package/pass/glow_pass.ts +11 -97
  63. package/pass/ssao_pass.d.ts +9 -23
  64. package/pass/ssao_pass.js +41 -128
  65. package/pass/ssao_pass.ts +36 -166
  66. package/pass/stroke_pass.js +3 -0
  67. package/pass/stroke_pass.ts +4 -0
  68. package/shaders/debugDepthCompareShader.d.ts +1 -1
  69. package/shaders/debugDepthCompareShader.js +1 -1
  70. package/shaders/debugDepthCompareShader.ts +1 -1
  71. package/shaders/debugDepthJudgeShader.d.ts +1 -1
  72. package/shaders/debugDepthJudgeShader.js +1 -1
  73. package/shaders/debugDepthJudgeShader.ts +1 -1
  74. package/PipeMesh/PathGeometry.d.ts +0 -44
  75. package/PipeMesh/PathGeometry.js +0 -307
  76. package/PipeMesh/PathGeometry.ts +0 -343
  77. package/PipeMesh/PathPoint.d.ts +0 -17
  78. package/PipeMesh/PathPoint.js +0 -31
  79. package/PipeMesh/PathPoint.ts +0 -36
  80. package/PipeMesh/PathPointList.d.ts +0 -31
  81. package/PipeMesh/PathPointList.js +0 -209
  82. package/PipeMesh/PathPointList.ts +0 -227
  83. package/PipeMesh/PathTubeGeometry.d.ts +0 -25
  84. package/PipeMesh/PathTubeGeometry.js +0 -130
  85. package/PipeMesh/PathTubeGeometry.ts +0 -146
  86. package/WaterFlow/FloatingDuck.d.ts +0 -88
  87. package/WaterFlow/FloatingDuck.js +0 -307
  88. package/WaterFlow/FloatingDuck.ts +0 -445
  89. package/WaterFlow/GPUFluidSimulation.d.ts +0 -56
  90. package/WaterFlow/GPUFluidSimulation.js +0 -785
  91. package/WaterFlow/GPUFluidSimulation.ts +0 -827
  92. package/WaterFlow/ReservoirSystem.d.ts +0 -106
  93. package/WaterFlow/ReservoirSystem.js +0 -621
  94. package/WaterFlow/ReservoirSystem.ts +0 -754
  95. package/WaterFlow/SPHField.d.ts +0 -35
  96. package/WaterFlow/SPHField.js +0 -204
  97. package/WaterFlow/SPHField.ts +0 -228
  98. package/WaterFlow/ScreenSpaceFluidPass.d.ts +0 -69
  99. package/WaterFlow/ScreenSpaceFluidPass.js +0 -736
  100. package/WaterFlow/ScreenSpaceFluidPass.ts +0 -789
  101. package/WaterFlow/ShallowWaterSurface.d.ts +0 -45
  102. package/WaterFlow/ShallowWaterSurface.js +0 -441
  103. package/WaterFlow/ShallowWaterSurface.ts +0 -510
  104. package/WaterFlow/WaterFlow.d.ts +0 -87
  105. package/WaterFlow/WaterFlow.js +0 -171
  106. package/WaterFlow/WaterFlow.ts +0 -219
  107. package/WaterFlow/types.d.ts +0 -161
  108. package/WaterFlow/types.js +0 -1
  109. package/WaterFlow/types.ts +0 -189
  110. package/WaterFlow/waterFlowPass.d.ts +0 -3
  111. package/WaterFlow/waterFlowPass.js +0 -20
  112. package/WaterFlow/waterFlowPass.ts +0 -40
  113. package/shaders/debugExcludedShader.d.ts +0 -15
  114. package/shaders/debugExcludedShader.js +0 -48
  115. package/shaders/debugExcludedShader.ts +0 -50
package/pass/ssao_pass.js CHANGED
@@ -1,84 +1,41 @@
1
- import { Color, DataTexture, DoubleSide, LinearFilter, MeshBasicMaterial, NoBlending, RGBAFormat, RawShaderMaterial, RepeatWrapping, Vector2, Vector3, WebGLRenderTarget, Matrix4, MultiplyBlending, PerspectiveCamera, OrthographicCamera } from "three";
1
+ import { Color, DataTexture, LinearFilter, NoBlending, RGBAFormat, RawShaderMaterial, RepeatWrapping, Vector2, Vector3, WebGLRenderTarget, Matrix4, MultiplyBlending, PerspectiveCamera, OrthographicCamera } from "three";
2
2
  import fsQuad from "./fsQuad";
3
+ // ---------------------------------------------------------------------------
4
+ // AO 数据准备 pass(深度 / 法线)
5
+ // 这些逻辑原本散落在 ThreeBase.render() 里,现收敛到此模块,ThreeBase 只调用下面两个函数。
6
+ // ⭐ 2026-10-18 皇上旨「所有的对象都要进入到深度图里面了,不需要用参数过滤掉了」⇒ 本模块原本的排除
7
+ // 逻辑**整条删除**(含 excludeTransparent 参数、按材质 transparent 的判据、userData.aoFloor /
8
+ // aoTransparent / aoOpaque 三个标记、sprite/线条/点的无条件排除),两张深度图都收全场景对象。
9
+ // 历史上这些排除是给 AO 兜底的,删掉后已知代价(皇上看过源码依据后确认接受):
10
+ // - 半透明面(玻璃、霓虹灯管、光晕、特效载体)也参与 AO → 透过它们看到的实体可能被乘黑;
11
+ // - sprite / 线条 / 点在 MeshNormalMaterial override 下法线不可信 → 该区域 AO 可能出黑块;
12
+ // - 地板(Ground1)重新写进可见深度图 → 透过地板看到的实体,其描边/辉光/覆盖色/磨砂会被裁掉。
13
+ // 10-12 旨「装饰地板需要透明」这次只保留**外观**(transparent + 径向 alpha 淡出 + depthWrite),
14
+ // 遮挡侧的 aoFloor 例外随本旨拆除。
15
+ // 出问题时用面板「深度调试 → 全局深度图 / AO深度图」两档定位是哪一侧。护栏:test/depthDebug.test.js J 组。
16
+ // 两张图仍然都存在、不能合并(现在两者渲染范围一致,差别只剩「用什么材质渲染」):
17
+ // - 可见深度(renderVisibleDepthPass,用各物体**自身材质**渲染):自身材质 ⇒ 单面墙只记正面、
18
+ // alpha 抠图(树叶、带 discard 的自定义 shader)只记真正可见的像素 —— 特效遮挡必须吃这份保真度。
19
+ // - AO 深度(normalRenderTarget 的 depth attachment,法线 pass 顺带白拿):override 材质是
20
+ // DoubleSide 且不做物体自己的 alpha discard,只能配法线给 GTAO 用;合成时靠 outputShader 那条
21
+ // 「AO 侧比可见深度更近 → 作废该像素 AO」的守卫兜住两套渲染结果的错位(别当死代码删)。
22
+ // ---------------------------------------------------------------------------
3
23
  /**
4
- * 判断是否为「可透视的半透明表面」——这类表面不该在世界空间 AO 里充当实体。
5
- * 让它进入深度/法线图,被它遮挡的区域会发黑,成因分两种:
6
- * a) transparent:true + opacity<1(毛玻璃、透明装饰):深度图与法线图都落在半透明表面上,
7
- * GTAO 在其表面算自遮蔽(褶皱、紧贴其它几何的窄缝)→ 这份 AO 被乘到「透过它看到的
8
- * 实体」上 → 该区域发黑。
9
- * b) transparent:true + depthWrite:false(霓虹灯管、光晕、叠加面):深度图保留身后几何(远),
10
- * 但法线 pass 用 overrideMaterial(MeshNormalMaterial 默认 depthWrite:true)会强行把它的
11
- * 法线写进去(近)→ 深度与法线指的不是同一个点 → GTAO 几乎必然算错发黑。
12
- * 故 AO 那一趟统一隐藏这些面:该像素的法线即身后不透明几何,AO 由真实可见几何决定;
13
- * 身后是背景时深度为 1.0,shader 守卫直接判「无遮蔽」(=1),不会发黑。
14
- *
15
- * 判据只看 material.transparent 本身,不再依赖 opacity / depthWrite(2026-08-30 修正):
16
- * 大量半透明是自定义 ShaderMaterial,alpha 由 shader 算出来,而材质的 opacity 仍是默认 1、
17
- * depthWrite 仍是 true —— 典型如聚光灯光斑、effectMaterial1,靠材质属性完全读不出来,
18
- * 会被漏判并继续污染 AO。
19
- * 代价:Mirror 这类「标了 transparent 但 shader 实际输出 alpha=1.0」的实心反射面会被误排除,
20
- * 故 Mirror 在构造函数里显式标记 userData.aoOpaque = true 保留(见各 Mirror 实现)。
21
- * 其余特例同样可用 userData.aoTransparent=true 强制排除 / userData.aoOpaque=true 强制保留。
22
- *
23
- * @param excludeTransparent 两道 pass 的唯一差别,取值就是它名字的含义:
24
- * - false(可见深度 / 描边/辉光/毛玻璃/覆盖色遮挡判定):透明面**当实体**参与遮挡。
25
- * ⚠️ 关键(2026-09-06 回归根因):three-base 大量面(玻璃、特效载体、alpha 贴图实体、
26
- * 半透明墙)都标了 transparent:true;若在此排除,它们就不再遮挡身后特效,所有依赖
27
- * baseDepthTexture 的深度测试全部失效、一律显示在前面。
28
- * - true(AO 深度 + 法线):透明面排除,避免 GTAO 在其上算错发黑。
29
- * ⚠️ 2026-10-11 起此参数原名 includeFloor(地板特例已整条拆除,见文件头),别再当"地板开关"读。
30
- */
31
- const isSeeThroughSurface = (obj, excludeTransparent = false) => {
32
- const o = obj;
33
- const userData = o.userData;
34
- if (userData && userData.aoOpaque === true)
35
- return false;
36
- if (userData && userData.aoTransparent === true)
37
- return true;
38
- const mat = o.material;
39
- if (!mat)
40
- return false;
41
- const list = Array.isArray(mat) ? mat : [mat];
42
- const transparent = list.some((m) => m !== null && m.transparent === true);
43
- return excludeTransparent && transparent;
44
- };
45
- const isNonSurface = (obj, excludeTransparent = false) => {
46
- const o = obj;
47
- if (o.isSprite === true || o.isLine === true || o.isLine2 === true || o.isLineSegments2 === true || o.isPoints === true) {
48
- return true;
49
- }
50
- return isSeeThroughSurface(obj, excludeTransparent);
51
- };
52
- const hideNonSurface = (scene, excludeTransparent = false) => {
53
- const list = [];
54
- scene.traverse((obj) => {
55
- if (isNonSurface(obj, excludeTransparent)) {
56
- list.push({ obj, prev: obj.visible });
57
- obj.visible = false;
58
- }
59
- });
60
- return list;
61
- };
62
- const restoreVisibility = (list) => {
63
- list.forEach(({ obj, prev }) => (obj.visible = prev));
64
- };
65
- /**
66
- * 可见深度 pass:固定排除非实体表面后,用**各物体自身的材质**把场景深度渲染到 depthRenderTarget。
24
+ * 可见深度 pass:用**各物体自身的材质**把整个场景的深度渲染到 depthRenderTarget。
67
25
  * depthRenderTarget.depthTexture 即 baseDepthTexture,供描边 / 发光 / 覆盖 / 磨砂的遮挡判定,
68
26
  * 也是 SSAO 合成时「真实可见表面」的参考。
69
- * 排除的非实体对象(sprite/线条/点)在深度图保留 clear 深度(1.0=远),与背景一致;排除的
70
- * 半透明对象则保留其身后不透明几何的深度(身后无几何时同样为 1.0)。均不影响颜色通道渲染。
27
+ * 2026-10-18 起**不排除任何对象**(皇上旨「所有的对象都要进入到深度图里面了,不需要用参数过滤掉了」):
28
+ * 场景里所有对象都参与这一趟,只有使用者自己 `visible = false` 的对象除外(那是显隐意图,本 pass 不碰)。
71
29
  * ⚠️ 名字里的 ao 已不适用(2026-10-11 改名自 renderAoDepthPass):它产出的是**可见深度**,
72
- * AO 自己的深度挂在法线 pass 上(见 renderAoNormalPass),两者只差 excludeTransparent 一个开关。
30
+ * AO 自己的深度挂在法线 pass 上(见 renderAoNormalPass)。
73
31
  */
74
- export function renderVisibleDepthPass(renderer, camera, scene, depthRenderTarget, excludeTransparent = false) {
75
- const hidden = hideNonSurface(scene, excludeTransparent);
76
- // ⚠️ 深度预通道铁律:必须让所有「未被排除」的可见表面都写入深度,深度图才有真实的几何遮挡信息。
32
+ export function renderVisibleDepthPass(renderer, camera, scene, depthRenderTarget) {
33
+ // ⚠️ 深度预通道铁律:必须让所有可见表面都写入深度,深度图才有真实的几何遮挡信息。
77
34
  // 透明材质(特效载体、半透明墙、alpha 贴图实体等)大多 transparent:true 且 depthWrite:false,
78
35
  // 若不强转,它们不会写进 baseDepthTexture → 深度图只剩不透明几何 → 描边/辉光/毛玻璃/覆盖色
79
- // 依赖 baseDepthTexture 的遮挡判定全部失效、一律显示在前(即本次回归根因)。
80
- // 被显式标记的面(userData.aoTransparent)已在 hideNonSurface 中隐藏,
81
- // 此处根本不会触及,故不影响 see-through 设计;其余透明面强制写深度 = 作为实体参与遮挡,符合预期。
36
+ // 依赖 baseDepthTexture 的遮挡判定全部失效、一律显示在前(即 2026-09-06 那次回归根因)。
37
+ // 只强转 Mesh:sprite / 线条 / 点的材质默认就是 depthWrite:true,且叠加式光晕一旦强写深度会在
38
+ // 深度图上打洞、错误遮挡身后特效,故沿用原判据范围,不扩大。
82
39
  const depthWriteRestore = [];
83
40
  scene.traverse((obj) => {
84
41
  const mesh = obj;
@@ -98,60 +55,16 @@ export function renderVisibleDepthPass(renderer, camera, scene, depthRenderTarge
98
55
  renderer.render(scene, camera);
99
56
  // 还原 depthWrite,避免污染后续颜色通道渲染的透明混合
100
57
  depthWriteRestore.forEach(({ mat, val }) => { mat.depthWrite = val; });
101
- restoreVisibility(hidden);
102
58
  renderer.setRenderTarget(prevRenderTarget);
103
59
  }
104
60
  /**
105
- * 调试用:把「被排除出可见深度图」的表面单独渲成红色 mask。
106
- *
107
- * 这些面在 renderVisibleDepthPass 里被 hideNonSurface 隐藏,因此**不会写进 baseDepthTexture**,
108
- * 也就永远挡不住描边/辉光/毛玻璃/覆盖色 —— 这正是"深度测试看起来失效"最常见的成因
109
- * (用户以为是 bug,其实是该面被设计成可透视:sprite/线条/点、userData.aoTransparent)。
110
- * ⚠️ 地板不在此列:2026-10-11 起 Ground1 是实心不透明面,正常写进可见深度图。
111
- * 面板「深度调试 → 排除面标记」叠加显示:灰=能挡住的真实遮挡面,红=被排除、挡不住任何东西。
112
- *
113
- * 只渲染 Mesh:sprite / Line2 / Points 在 MeshBasicMaterial override 下渲染异常(见文件头注释),
114
- * 且它们数量少、用户关心的遮挡体基本都是 Mesh,故跳过。
115
- */
116
- export function renderExcludedMaskPass(renderer, camera, scene, maskRenderTarget, excludeTransparent = false) {
117
- const maskMaterial = new MeshBasicMaterial({
118
- color: 0xff0000,
119
- depthTest: false,
120
- depthWrite: false,
121
- side: DoubleSide,
122
- });
123
- const prevVisible = [];
124
- scene.traverse((obj) => {
125
- const isMesh = obj.isMesh === true;
126
- prevVisible.push({ obj, prev: obj.visible });
127
- // 只显示「被排除的 Mesh」:其余一律隐藏,得到纯黑底 + 红面的 mask
128
- obj.visible = isMesh && isNonSurface(obj, excludeTransparent);
129
- });
130
- const prevOverride = scene.overrideMaterial;
131
- const prevTarget = renderer.getRenderTarget();
132
- const prevClear = renderer.getClearColor(new Color());
133
- const prevAlpha = renderer.getClearAlpha();
134
- scene.overrideMaterial = maskMaterial;
135
- renderer.setRenderTarget(maskRenderTarget);
136
- renderer.setClearColor(0x000000, 1);
137
- renderer.clear();
138
- renderer.render(scene, camera);
139
- renderer.setClearColor(prevClear, prevAlpha);
140
- renderer.setRenderTarget(prevTarget);
141
- scene.overrideMaterial = prevOverride;
142
- restoreVisibility(prevVisible);
143
- maskMaterial.dispose();
144
- }
145
- /**
146
- * 法线 pass(仅 SSAO 开启时需要):固定排除非实体表面后,以中性灰清屏 + normalMaterial
147
- * override 将视图空间法线渲染到 normalRenderTarget,供 GTAO 风格 SSAO 使用。
148
- * 排除对象在法线图保留中性灰清屏色 → unpackRGBToNormal(0.5,0.5,0.5)=(0,0,0) →
149
- * SSAO 退化法线守卫判"无遮蔽"(=1),避免精灵弹窗被 AO 乘黑。清屏色用后即还原。
61
+ * 法线 pass(仅 SSAO 开启时需要):以中性灰清屏 + normalMaterial override 将整个场景的
62
+ * 视图空间法线渲染到 normalRenderTarget,供 GTAO 风格 SSAO 使用。
63
+ * 2026-10-18 起同样不排除任何对象(与 renderVisibleDepthPass 一致,见文件头那道旨及其代价清单)。
150
64
  * 深度白拿:normalRenderTarget 挂着 aoDepthTexture 作 depth attachment,这一趟的深度由光栅器
151
65
  * 顺带写入 → 就是 AO 用的深度,无需再单独渲一遍(2026-09-14)。
152
66
  */
153
- export function renderAoNormalPass(renderer, camera, scene, normalRenderTarget, normalMaterial, excludeTransparent = false) {
154
- const hidden = hideNonSurface(scene, excludeTransparent);
67
+ export function renderAoNormalPass(renderer, camera, scene, normalRenderTarget, normalMaterial) {
155
68
  // ⚠️ 2026-10-11 删掉了这里原有的「强制 depthWrite=true」整段遍历:scene.overrideMaterial 生效后,
156
69
  // three 用的是 **override 材质**的渲染状态(WebGLRenderer.renderObjects:
157
70
  // `material = overrideMaterial === null ? renderItem.material : overrideMaterial`,setDepthState 吃它),
@@ -167,7 +80,6 @@ export function renderAoNormalPass(renderer, camera, scene, normalRenderTarget,
167
80
  scene.overrideMaterial = normalMaterial;
168
81
  renderer.render(scene, camera);
169
82
  scene.overrideMaterial = null;
170
- restoreVisibility(hidden);
171
83
  renderer.setClearColor(prevClearColor, prevClearAlpha);
172
84
  renderer.setRenderTarget(prevRenderTarget);
173
85
  }
@@ -667,8 +579,10 @@ const outputShader = new RawShaderMaterial({
667
579
  // (override 材质:DoubleSide、不做物体自己的 alpha discard)记到一个**屏幕上根本不可见**的面
668
580
  // —— 典型如树叶抠图的空隙、单面墙的背面。此时深度与法线指的不是人眼看到的那个点,
669
581
  // GTAO 算出的 AO 不可信 → 视为无遮蔽(=1)。
670
- // ⚠️ 2026-10-11:本守卫原本主要防「可透视地板挡住身后实体」,那条特例已随地板进深度图而作废,
671
- // 现在它守的是上面这类 override/自身材质两套渲染结果的错位,别当死代码删。
582
+ // ⚠️ 2026-10-18:两张图的渲染范围已统一(皇上旨「所有的对象都要进入到深度图里面了」⇒ excludeTransparent
583
+ // 参数与 aoFloor 特例整条拆除),本守卫不再承担「地板的接触 AO 别乘黑身后实体」这类职责,
584
+ // 它守的是上面那类 override 材质 / 自身材质两套渲染结果的错位(抠图空隙、单面墙背面、
585
+ // DoubleSide 记到背面),别当死代码删。
672
586
  // 仅在最终合成时生效;debug 模式直接看 GTAO 原始 AO 图,便于排查。
673
587
  float dColor = texture2D(tColorDepth, vUv).r;
674
588
  float dAo = texture2D(tAoDepth, vUv).r;
@@ -701,15 +615,14 @@ export default function ssao_pass(renderer, camera, scene, depthRenderTarget, no
701
615
  // 故 AO 直接乘进 base,描边/发光/覆盖/磨砂都叠在 AO 之上不被压暗;末尾统一 FXAA 输出到屏幕,
702
616
  // 覆盖 SSAO 自身的硬边。改动调用顺序时,本 pass 无需修改(输出到"绑定的那个目标"即可)。
703
617
  const originRenderTarget = renderer.getRenderTarget();
704
- // 法线 pass(excludeTransparent=true):隐式透明面不参与 AO,免得 GTAO 在其上算自遮蔽把
705
- // 身后实体乘黑;地板/其它不透明面照常保留 —— 接触 AO 需要地板的视图空间法线。
618
+ // 法线 pass:整个场景都渲(2026-10-18 起不再按 transparent / aoFloor 排除任何面,见文件头那道旨)。
706
619
  // ⭐ 深度白拿(2026-09-14 优化):normalRenderTarget 挂着 aoDepthTexture 作 depth attachment,
707
620
  // 这一次渲染的深度由光栅器顺带写入 → 直接就是 AO 深度,**不再单独渲一遍深度 pass**。
708
- // (原先法线 pass 之后还要再渲一遍「AO 深度」——它与法线 pass 的排除集完全相同,
621
+ // (原先法线 pass 之后还要再渲一遍「AO 深度」——它与法线 pass 的渲染集完全相同,
709
622
  // 属于重复遍历全场景,2026-09-14 已删。)
710
623
  // ⚠️ 这一趟的深度是 override 材质写的(DoubleSide、不做物体自己的 alpha discard),
711
624
  // 所以只能给 AO 用;特效遮挡吃的是下面那张「用自身材质渲染」的可见深度。
712
- renderAoNormalPass(renderer, camera, scene, normalRenderTarget, normalMaterial, true);
625
+ renderAoNormalPass(renderer, camera, scene, normalRenderTarget, normalMaterial);
713
626
  // 可见深度(用各物体自身材质渲染,含地板)= baseDepthTexture:描边/辉光/毛玻璃/覆盖色的遮挡参考,
714
627
  // 也是复合守卫里「真实可见表面」的参考。
715
628
  const colorDepthTexture = depthRenderTarget.depthTexture;
package/pass/ssao_pass.ts CHANGED
@@ -1,123 +1,48 @@
1
- import { Color, DataTexture, DoubleSide, LinearFilter, Material, MeshBasicMaterial, MeshNormalMaterial, NoBlending, Object3D, RGBAFormat, RawShaderMaterial, RepeatWrapping, Scene, Vector2, Vector3, WebGLRenderTarget, Matrix4, MultiplyBlending, WebGLRenderer, Camera, PerspectiveCamera, OrthographicCamera, DepthTexture, Texture } from "three";
1
+ import { Color, DataTexture, LinearFilter, Material, MeshNormalMaterial, NoBlending, Object3D, RGBAFormat, RawShaderMaterial, RepeatWrapping, Scene, Vector2, Vector3, WebGLRenderTarget, Matrix4, MultiplyBlending, WebGLRenderer, Camera, PerspectiveCamera, OrthographicCamera, DepthTexture, Texture } from "three";
2
2
  import fsQuad from "./fsQuad";
3
3
 
4
4
  // ---------------------------------------------------------------------------
5
5
  // AO 数据准备 pass(深度 / 法线)
6
6
  // 这些逻辑原本散落在 ThreeBase.render() 里,现收敛到此模块,ThreeBase 只调用下面两个函数。
7
- // 固定排除两类不参与世界空间 AO 的对象,它们若写进深度/法线图,SSAO 会在其区域算错
8
- // AO 被乘黑:
9
- // 1) 非实体表面:sprite 及其子类、线条类(Line / Line2 等 fat-line)、点类(Points)。
10
- // - sprite 是广告牌式 UI,不该写世界空间深度,且会错误遮挡身后几何;
11
- // - 线条/点类在 MeshNormalMaterial override 下渲染异常(fat-line 实例段属性未处理、
12
- // Points 无面法线),法线错乱 → GTAO 算出近 0 AO 被 Multiply 乘黑。
13
- // 2) 可透视的半透明表面(详见 isSeeThroughSurface):会让「被它遮挡的区域」发黑。
14
- // 故在深度/法线 pass 前临时隐藏,pass 后恢复(记录 prev visible 避免误改用户隐藏的 UI)。
15
- //
16
- // ⭐ 2026-10-11 皇上旨「物体的深度都要进深度图」:原先地板(Ground1 标 userData.aoFloor)被
17
- // 特例从可见深度图里排除 —— 那是因为它当年是「径向 alpha 淡出的半透明地板」,透过去看到的实体
18
- // 不该被它挡住。但 2026-09-20 二旨早已把 Ground1 改成 transparent:false 的实心深灰地板,那条例外
19
- // 的理由随之作废(判据还走在 material.transparent 之前,读不出来),故整条拆除:
20
- // 现在地板在两张图里都是实体 —— 可见深度图(特效遮挡判定)与 AO 深度图都有它,
21
- // 被地板挡住的描边/辉光/覆盖色/磨砂会被正确裁掉(=皇上要的行为)。
22
- // 两张图仍然都存在,但差别只剩「材质标了 transparent 的面」,且各自都是必须的,不能合并:
23
- // - 可见深度(renderVisibleDepthPass,用各物体**自身材质**渲染):透明面当实体(否则 2026-09-06
24
- // 那类「所有深度测试一律显示在前面」的回归复发);自身材质渲染 ⇒ 单面墙只记正面、
7
+ // ⭐ 2026-10-18 皇上旨「所有的对象都要进入到深度图里面了,不需要用参数过滤掉了」⇒ 本模块原本的排除
8
+ // 逻辑**整条删除**(含 excludeTransparent 参数、按材质 transparent 的判据、userData.aoFloor /
9
+ // aoTransparent / aoOpaque 三个标记、sprite/线条/点的无条件排除),两张深度图都收全场景对象。
10
+ // 历史上这些排除是给 AO 兜底的,删掉后已知代价(皇上看过源码依据后确认接受):
11
+ // - 半透明面(玻璃、霓虹灯管、光晕、特效载体)也参与 AO → 透过它们看到的实体可能被乘黑;
12
+ // - sprite / 线条 / 点在 MeshNormalMaterial override 下法线不可信 → 该区域 AO 可能出黑块;
13
+ // - 地板(Ground1)重新写进可见深度图 → 透过地板看到的实体,其描边/辉光/覆盖色/磨砂会被裁掉。
14
+ // 10-12 旨「装饰地板需要透明」这次只保留**外观**(transparent + 径向 alpha 淡出 + depthWrite),
15
+ // 遮挡侧的 aoFloor 例外随本旨拆除。
16
+ // 出问题时用面板「深度调试 → 全局深度图 / AO深度图」两档定位是哪一侧。护栏:test/depthDebug.test.js J 组。
17
+ // 两张图仍然都存在、不能合并(现在两者渲染范围一致,差别只剩「用什么材质渲染」):
18
+ // - 可见深度(renderVisibleDepthPass,用各物体**自身材质**渲染):自身材质 ⇒ 单面墙只记正面、
25
19
  // alpha 抠图(树叶、带 discard 的自定义 shader)只记真正可见的像素 —— 特效遮挡必须吃这份保真度。
26
- // - AO 深度(normalRenderTarget 的 depth attachment,法线 pass 顺带白拿):隐式透明面被排除,
27
- // 免得 GTAO 在半透明面上算自遮蔽把身后实体乘黑;法线必须由片元着色器写,这一趟省不掉。
28
- // 用 isSprite / isLine / isLine2 / isLineSegments2 / isPoints 属性判断而非 instanceof:
29
- // 避免 three 子类场景下 instanceof 命中不到(如 SpriteText 等自定义 sprite 子类、
30
- // Line2 继承自 Mesh 非 Line)。
20
+ // - AO 深度(normalRenderTarget 的 depth attachment,法线 pass 顺带白拿):override 材质是
21
+ // DoubleSide 且不做物体自己的 alpha discard,只能配法线给 GTAO 用;合成时靠 outputShader 那条
22
+ // 「AO 侧比可见深度更近 → 作废该像素 AO」的守卫兜住两套渲染结果的错位(别当死代码删)。
31
23
  // ---------------------------------------------------------------------------
32
24
 
33
- type HiddenEntry = { obj: Object3D; prev: boolean };
34
-
35
- /**
36
- * 判断是否为「可透视的半透明表面」——这类表面不该在世界空间 AO 里充当实体。
37
- * 让它进入深度/法线图,被它遮挡的区域会发黑,成因分两种:
38
- * a) transparent:true + opacity<1(毛玻璃、透明装饰):深度图与法线图都落在半透明表面上,
39
- * GTAO 在其表面算自遮蔽(褶皱、紧贴其它几何的窄缝)→ 这份 AO 被乘到「透过它看到的
40
- * 实体」上 → 该区域发黑。
41
- * b) transparent:true + depthWrite:false(霓虹灯管、光晕、叠加面):深度图保留身后几何(远),
42
- * 但法线 pass 用 overrideMaterial(MeshNormalMaterial 默认 depthWrite:true)会强行把它的
43
- * 法线写进去(近)→ 深度与法线指的不是同一个点 → GTAO 几乎必然算错发黑。
44
- * 故 AO 那一趟统一隐藏这些面:该像素的法线即身后不透明几何,AO 由真实可见几何决定;
45
- * 身后是背景时深度为 1.0,shader 守卫直接判「无遮蔽」(=1),不会发黑。
46
- *
47
- * 判据只看 material.transparent 本身,不再依赖 opacity / depthWrite(2026-08-30 修正):
48
- * 大量半透明是自定义 ShaderMaterial,alpha 由 shader 算出来,而材质的 opacity 仍是默认 1、
49
- * depthWrite 仍是 true —— 典型如聚光灯光斑、effectMaterial1,靠材质属性完全读不出来,
50
- * 会被漏判并继续污染 AO。
51
- * 代价:Mirror 这类「标了 transparent 但 shader 实际输出 alpha=1.0」的实心反射面会被误排除,
52
- * 故 Mirror 在构造函数里显式标记 userData.aoOpaque = true 保留(见各 Mirror 实现)。
53
- * 其余特例同样可用 userData.aoTransparent=true 强制排除 / userData.aoOpaque=true 强制保留。
54
- *
55
- * @param excludeTransparent 两道 pass 的唯一差别,取值就是它名字的含义:
56
- * - false(可见深度 / 描边/辉光/毛玻璃/覆盖色遮挡判定):透明面**当实体**参与遮挡。
57
- * ⚠️ 关键(2026-09-06 回归根因):three-base 大量面(玻璃、特效载体、alpha 贴图实体、
58
- * 半透明墙)都标了 transparent:true;若在此排除,它们就不再遮挡身后特效,所有依赖
59
- * baseDepthTexture 的深度测试全部失效、一律显示在前面。
60
- * - true(AO 深度 + 法线):透明面排除,避免 GTAO 在其上算错发黑。
61
- * ⚠️ 2026-10-11 起此参数原名 includeFloor(地板特例已整条拆除,见文件头),别再当"地板开关"读。
62
- */
63
- const isSeeThroughSurface = (obj: Object3D, excludeTransparent = false): boolean => {
64
- const o = obj as Object3D & { material?: Material | Material[] };
65
- const userData = o.userData as { aoTransparent?: boolean; aoOpaque?: boolean } | undefined;
66
- if (userData && userData.aoOpaque === true) return false;
67
- if (userData && userData.aoTransparent === true) return true;
68
- const mat = o.material;
69
- if (!mat) return false;
70
- const list: Material[] = Array.isArray(mat) ? mat : [mat];
71
- const transparent = list.some((m) => m !== null && m.transparent === true);
72
- return excludeTransparent && transparent;
73
- };
74
-
75
- const isNonSurface = (obj: Object3D, excludeTransparent = false): boolean => {
76
- const o = obj as { isSprite?: boolean; isLine?: boolean; isLine2?: boolean; isLineSegments2?: boolean; isPoints?: boolean };
77
- if (o.isSprite === true || o.isLine === true || o.isLine2 === true || o.isLineSegments2 === true || o.isPoints === true) {
78
- return true;
79
- }
80
- return isSeeThroughSurface(obj, excludeTransparent);
81
- };
82
-
83
- const hideNonSurface = (scene: Object3D, excludeTransparent = false): HiddenEntry[] => {
84
- const list: HiddenEntry[] = [];
85
- scene.traverse((obj: Object3D) => {
86
- if (isNonSurface(obj, excludeTransparent)) {
87
- list.push({ obj, prev: obj.visible });
88
- obj.visible = false;
89
- }
90
- });
91
- return list;
92
- };
93
-
94
- const restoreVisibility = (list: HiddenEntry[]): void => {
95
- list.forEach(({ obj, prev }) => (obj.visible = prev));
96
- };
97
-
98
25
  /**
99
- * 可见深度 pass:固定排除非实体表面后,用**各物体自身的材质**把场景深度渲染到 depthRenderTarget。
26
+ * 可见深度 pass:用**各物体自身的材质**把整个场景的深度渲染到 depthRenderTarget。
100
27
  * depthRenderTarget.depthTexture 即 baseDepthTexture,供描边 / 发光 / 覆盖 / 磨砂的遮挡判定,
101
28
  * 也是 SSAO 合成时「真实可见表面」的参考。
102
- * 排除的非实体对象(sprite/线条/点)在深度图保留 clear 深度(1.0=远),与背景一致;排除的
103
- * 半透明对象则保留其身后不透明几何的深度(身后无几何时同样为 1.0)。均不影响颜色通道渲染。
29
+ * 2026-10-18 起**不排除任何对象**(皇上旨「所有的对象都要进入到深度图里面了,不需要用参数过滤掉了」):
30
+ * 场景里所有对象都参与这一趟,只有使用者自己 `visible = false` 的对象除外(那是显隐意图,本 pass 不碰)。
104
31
  * ⚠️ 名字里的 ao 已不适用(2026-10-11 改名自 renderAoDepthPass):它产出的是**可见深度**,
105
- * AO 自己的深度挂在法线 pass 上(见 renderAoNormalPass),两者只差 excludeTransparent 一个开关。
32
+ * AO 自己的深度挂在法线 pass 上(见 renderAoNormalPass)。
106
33
  */
107
34
  export function renderVisibleDepthPass(
108
35
  renderer: WebGLRenderer,
109
36
  camera: Camera,
110
37
  scene: Scene,
111
- depthRenderTarget: WebGLRenderTarget,
112
- excludeTransparent = false
38
+ depthRenderTarget: WebGLRenderTarget
113
39
  ): void {
114
- const hidden = hideNonSurface(scene, excludeTransparent);
115
- // ⚠️ 深度预通道铁律:必须让所有「未被排除」的可见表面都写入深度,深度图才有真实的几何遮挡信息。
40
+ // ⚠️ 深度预通道铁律:必须让所有可见表面都写入深度,深度图才有真实的几何遮挡信息。
116
41
  // 透明材质(特效载体、半透明墙、alpha 贴图实体等)大多 transparent:true 且 depthWrite:false,
117
42
  // 若不强转,它们不会写进 baseDepthTexture → 深度图只剩不透明几何 → 描边/辉光/毛玻璃/覆盖色
118
- // 依赖 baseDepthTexture 的遮挡判定全部失效、一律显示在前(即本次回归根因)。
119
- // 被显式标记的面(userData.aoTransparent)已在 hideNonSurface 中隐藏,
120
- // 此处根本不会触及,故不影响 see-through 设计;其余透明面强制写深度 = 作为实体参与遮挡,符合预期。
43
+ // 依赖 baseDepthTexture 的遮挡判定全部失效、一律显示在前(即 2026-09-06 那次回归根因)。
44
+ // 只强转 Mesh:sprite / 线条 / 点的材质默认就是 depthWrite:true,且叠加式光晕一旦强写深度会在
45
+ // 深度图上打洞、错误遮挡身后特效,故沿用原判据范围,不扩大。
121
46
  const depthWriteRestore: { mat: Material; val: boolean }[] = [];
122
47
  scene.traverse((obj: Object3D) => {
123
48
  const mesh = obj as Object3D & { isMesh?: boolean; material?: Material | Material[] };
@@ -136,66 +61,13 @@ export function renderVisibleDepthPass(
136
61
  renderer.render(scene, camera);
137
62
  // 还原 depthWrite,避免污染后续颜色通道渲染的透明混合
138
63
  depthWriteRestore.forEach(({ mat, val }) => { mat.depthWrite = val; });
139
- restoreVisibility(hidden);
140
64
  renderer.setRenderTarget(prevRenderTarget);
141
65
  }
142
66
 
143
67
  /**
144
- * 调试用:把「被排除出可见深度图」的表面单独渲成红色 mask。
145
- *
146
- * 这些面在 renderVisibleDepthPass 里被 hideNonSurface 隐藏,因此**不会写进 baseDepthTexture**,
147
- * 也就永远挡不住描边/辉光/毛玻璃/覆盖色 —— 这正是"深度测试看起来失效"最常见的成因
148
- * (用户以为是 bug,其实是该面被设计成可透视:sprite/线条/点、userData.aoTransparent)。
149
- * ⚠️ 地板不在此列:2026-10-11 起 Ground1 是实心不透明面,正常写进可见深度图。
150
- * 面板「深度调试 → 排除面标记」叠加显示:灰=能挡住的真实遮挡面,红=被排除、挡不住任何东西。
151
- *
152
- * 只渲染 Mesh:sprite / Line2 / Points 在 MeshBasicMaterial override 下渲染异常(见文件头注释),
153
- * 且它们数量少、用户关心的遮挡体基本都是 Mesh,故跳过。
154
- */
155
- export function renderExcludedMaskPass(
156
- renderer: WebGLRenderer,
157
- camera: Camera,
158
- scene: Scene,
159
- maskRenderTarget: WebGLRenderTarget,
160
- excludeTransparent = false
161
- ): void {
162
- const maskMaterial = new MeshBasicMaterial({
163
- color: 0xff0000,
164
- depthTest: false,
165
- depthWrite: false,
166
- side: DoubleSide,
167
- });
168
- const prevVisible: HiddenEntry[] = [];
169
- scene.traverse((obj: Object3D) => {
170
- const isMesh = (obj as Object3D & { isMesh?: boolean }).isMesh === true;
171
- prevVisible.push({ obj, prev: obj.visible });
172
- // 只显示「被排除的 Mesh」:其余一律隐藏,得到纯黑底 + 红面的 mask
173
- obj.visible = isMesh && isNonSurface(obj, excludeTransparent);
174
- });
175
-
176
- const prevOverride = scene.overrideMaterial;
177
- const prevTarget = renderer.getRenderTarget();
178
- const prevClear = renderer.getClearColor(new Color());
179
- const prevAlpha = renderer.getClearAlpha();
180
-
181
- scene.overrideMaterial = maskMaterial;
182
- renderer.setRenderTarget(maskRenderTarget);
183
- renderer.setClearColor(0x000000, 1);
184
- renderer.clear();
185
- renderer.render(scene, camera);
186
-
187
- renderer.setClearColor(prevClear, prevAlpha);
188
- renderer.setRenderTarget(prevTarget);
189
- scene.overrideMaterial = prevOverride;
190
- restoreVisibility(prevVisible);
191
- maskMaterial.dispose();
192
- }
193
-
194
- /**
195
- * 法线 pass(仅 SSAO 开启时需要):固定排除非实体表面后,以中性灰清屏 + normalMaterial
196
- * override 将视图空间法线渲染到 normalRenderTarget,供 GTAO 风格 SSAO 使用。
197
- * 排除对象在法线图保留中性灰清屏色 → unpackRGBToNormal(0.5,0.5,0.5)=(0,0,0) →
198
- * SSAO 退化法线守卫判"无遮蔽"(=1),避免精灵弹窗被 AO 乘黑。清屏色用后即还原。
68
+ * 法线 pass(仅 SSAO 开启时需要):以中性灰清屏 + normalMaterial override 将整个场景的
69
+ * 视图空间法线渲染到 normalRenderTarget,供 GTAO 风格 SSAO 使用。
70
+ * 2026-10-18 起同样不排除任何对象(与 renderVisibleDepthPass 一致,见文件头那道旨及其代价清单)。
199
71
  * 深度白拿:normalRenderTarget 挂着 aoDepthTexture 作 depth attachment,这一趟的深度由光栅器
200
72
  * 顺带写入 → 就是 AO 用的深度,无需再单独渲一遍(2026-09-14)。
201
73
  */
@@ -204,10 +76,8 @@ export function renderAoNormalPass(
204
76
  camera: Camera,
205
77
  scene: Scene,
206
78
  normalRenderTarget: WebGLRenderTarget,
207
- normalMaterial: MeshNormalMaterial,
208
- excludeTransparent = false
79
+ normalMaterial: MeshNormalMaterial
209
80
  ): void {
210
- const hidden = hideNonSurface(scene, excludeTransparent);
211
81
  // ⚠️ 2026-10-11 删掉了这里原有的「强制 depthWrite=true」整段遍历:scene.overrideMaterial 生效后,
212
82
  // three 用的是 **override 材质**的渲染状态(WebGLRenderer.renderObjects:
213
83
  // `material = overrideMaterial === null ? renderItem.material : overrideMaterial`,setDepthState 吃它),
@@ -223,7 +93,6 @@ export function renderAoNormalPass(
223
93
  scene.overrideMaterial = normalMaterial;
224
94
  renderer.render(scene, camera);
225
95
  scene.overrideMaterial = null;
226
- restoreVisibility(hidden);
227
96
  renderer.setClearColor(prevClearColor, prevClearAlpha);
228
97
  renderer.setRenderTarget(prevRenderTarget);
229
98
  }
@@ -734,8 +603,10 @@ const outputShader: RawShaderMaterial = new RawShaderMaterial({
734
603
  // (override 材质:DoubleSide、不做物体自己的 alpha discard)记到一个**屏幕上根本不可见**的面
735
604
  // —— 典型如树叶抠图的空隙、单面墙的背面。此时深度与法线指的不是人眼看到的那个点,
736
605
  // GTAO 算出的 AO 不可信 → 视为无遮蔽(=1)。
737
- // ⚠️ 2026-10-11:本守卫原本主要防「可透视地板挡住身后实体」,那条特例已随地板进深度图而作废,
738
- // 现在它守的是上面这类 override/自身材质两套渲染结果的错位,别当死代码删。
606
+ // ⚠️ 2026-10-18:两张图的渲染范围已统一(皇上旨「所有的对象都要进入到深度图里面了」⇒ excludeTransparent
607
+ // 参数与 aoFloor 特例整条拆除),本守卫不再承担「地板的接触 AO 别乘黑身后实体」这类职责,
608
+ // 它守的是上面那类 override 材质 / 自身材质两套渲染结果的错位(抠图空隙、单面墙背面、
609
+ // DoubleSide 记到背面),别当死代码删。
739
610
  // 仅在最终合成时生效;debug 模式直接看 GTAO 原始 AO 图,便于排查。
740
611
  float dColor = texture2D(tColorDepth, vUv).r;
741
612
  float dAo = texture2D(tAoDepth, vUv).r;
@@ -804,15 +675,14 @@ export default function ssao_pass(
804
675
  // 覆盖 SSAO 自身的硬边。改动调用顺序时,本 pass 无需修改(输出到"绑定的那个目标"即可)。
805
676
  const originRenderTarget = renderer.getRenderTarget();
806
677
 
807
- // 法线 pass(excludeTransparent=true):隐式透明面不参与 AO,免得 GTAO 在其上算自遮蔽把
808
- // 身后实体乘黑;地板/其它不透明面照常保留 —— 接触 AO 需要地板的视图空间法线。
678
+ // 法线 pass:整个场景都渲(2026-10-18 起不再按 transparent / aoFloor 排除任何面,见文件头那道旨)。
809
679
  // ⭐ 深度白拿(2026-09-14 优化):normalRenderTarget 挂着 aoDepthTexture 作 depth attachment,
810
680
  // 这一次渲染的深度由光栅器顺带写入 → 直接就是 AO 深度,**不再单独渲一遍深度 pass**。
811
- // (原先法线 pass 之后还要再渲一遍「AO 深度」——它与法线 pass 的排除集完全相同,
681
+ // (原先法线 pass 之后还要再渲一遍「AO 深度」——它与法线 pass 的渲染集完全相同,
812
682
  // 属于重复遍历全场景,2026-09-14 已删。)
813
683
  // ⚠️ 这一趟的深度是 override 材质写的(DoubleSide、不做物体自己的 alpha discard),
814
684
  // 所以只能给 AO 用;特效遮挡吃的是下面那张「用自身材质渲染」的可见深度。
815
- renderAoNormalPass(renderer, camera, scene, normalRenderTarget, normalMaterial, true);
685
+ renderAoNormalPass(renderer, camera, scene, normalRenderTarget, normalMaterial);
816
686
 
817
687
  // 可见深度(用各物体自身材质渲染,含地板)= baseDepthTexture:描边/辉光/毛玻璃/覆盖色的遮挡参考,
818
688
  // 也是复合守卫里「真实可见表面」的参考。
@@ -574,6 +574,9 @@ export default function stroke_pass(renderer, camera, object3d, baseDepthTexture
574
574
  depthMinBlurShader.uniforms.tDepth.value = selectDepthBlurTmpTextureTarget.texture;
575
575
  renderer.setRenderTarget(selectDepthBlurTextureTarget);
576
576
  fsQuad.render(renderer, depthMinBlurShader);
577
+ // 调试:记录「外扩后的选区深度」,供面板「深度图(分步)」的步骤 5.5 档读取。
578
+ // 它是 RGBA8 目标、对数深度存在 .r 里(与 DepthTexture 取 .r 的读法一致)。
579
+ debugDepthState.lastSelectBlurDepth = selectDepthBlurTextureTarget.texture;
577
580
  // 5.6 对外扩后的描边判遮挡:被更近几何挡住的外扩环像素 discard。
578
581
  // ⚠️ 输出到独立 target,绝不回写 blur1(历史回归 bug:blur1 被 depthTest 结果覆盖
579
582
  // 会导致步骤 6 相减归零、描边全不显示)。
@@ -608,6 +608,10 @@ export default function stroke_pass(
608
608
  renderer.setRenderTarget(selectDepthBlurTextureTarget);
609
609
  fsQuad.render(renderer, depthMinBlurShader);
610
610
 
611
+ // 调试:记录「外扩后的选区深度」,供面板「深度图(分步)」的步骤 5.5 档读取。
612
+ // 它是 RGBA8 目标、对数深度存在 .r 里(与 DepthTexture 取 .r 的读法一致)。
613
+ debugDepthState.lastSelectBlurDepth = selectDepthBlurTextureTarget.texture;
614
+
611
615
  // 5.6 对外扩后的描边判遮挡:被更近几何挡住的外扩环像素 discard。
612
616
  // ⚠️ 输出到独立 target,绝不回写 blur1(历史回归 bug:blur1 被 depthTest 结果覆盖
613
617
  // 会导致步骤 6 相减归零、描边全不显示)。
@@ -2,7 +2,7 @@ import { ShaderMaterial } from "three";
2
2
  /**
3
3
  * 调试用:把「全局 base 深度」与「最近一次 glow/stroke 选区的 select 深度」并排显示,
4
4
  * 用于排查"深度测试全部失效"根因:
5
- * R = 全局 base 深度(baseDepthTexture,排除地板)
5
+ * R = 全局 base 深度(baseDepthTexture,2026-10-18 起含全部对象、含地板)
6
6
  * G = 选区自身深度(selectDepthTexture,由 glow_pass/stroke_pass 渲染后写入 debugDepthState)
7
7
  * 两路都用 `pow(cameraFar+1, d)-1` 反推到近似线性视深再归一化(背景≈1 → 黄白)。
8
8
  * - R 全白、G 也有内容 → 全局 base 深度没写进(renderVisibleDepthPass 失效),但选区深度正常;
@@ -2,7 +2,7 @@ import { ShaderChunk, ShaderMaterial } from "three";
2
2
  /**
3
3
  * 调试用:把「全局 base 深度」与「最近一次 glow/stroke 选区的 select 深度」并排显示,
4
4
  * 用于排查"深度测试全部失效"根因:
5
- * R = 全局 base 深度(baseDepthTexture,排除地板)
5
+ * R = 全局 base 深度(baseDepthTexture,2026-10-18 起含全部对象、含地板)
6
6
  * G = 选区自身深度(selectDepthTexture,由 glow_pass/stroke_pass 渲染后写入 debugDepthState)
7
7
  * 两路都用 `pow(cameraFar+1, d)-1` 反推到近似线性视深再归一化(背景≈1 → 黄白)。
8
8
  * - R 全白、G 也有内容 → 全局 base 深度没写进(renderVisibleDepthPass 失效),但选区深度正常;
@@ -3,7 +3,7 @@ import { ShaderChunk, ShaderMaterial } from "three";
3
3
  /**
4
4
  * 调试用:把「全局 base 深度」与「最近一次 glow/stroke 选区的 select 深度」并排显示,
5
5
  * 用于排查"深度测试全部失效"根因:
6
- * R = 全局 base 深度(baseDepthTexture,排除地板)
6
+ * R = 全局 base 深度(baseDepthTexture,2026-10-18 起含全部对象、含地板)
7
7
  * G = 选区自身深度(selectDepthTexture,由 glow_pass/stroke_pass 渲染后写入 debugDepthState)
8
8
  * 两路都用 `pow(cameraFar+1, d)-1` 反推到近似线性视深再归一化(背景≈1 → 黄白)。
9
9
  * - R 全白、G 也有内容 → 全局 base 深度没写进(renderVisibleDepthPass 失效),但选区深度正常;
@@ -3,7 +3,7 @@ import { ShaderMaterial } from "three";
3
3
  * 调试用:把「深度测试判定」本身画出来,用于定位"后处理深度测试全部失效"。
4
4
  *
5
5
  * 通道语义(全部为**原始**深度值,不做对数反解,避免饱和丢信息):
6
- * R = 全局 base 深度(baseDepthTexture,排除地板)
6
+ * R = 全局 base 深度(baseDepthTexture,2026-10-18 起含全部对象、含地板)
7
7
  * G = 选区自身深度(selectDepthTexture,glow/stroke 渲染后写入 debugDepthState)
8
8
  * B = 判定结果:baseD < selD - bias ? 1 : 0
9
9
  * 与 stroke_pass 的 depthTestShader 同一判定式(bias = 0.0006):
@@ -4,7 +4,7 @@ import { DEPTH_TEST_BIAS } from "../pass/depthTestBias";
4
4
  * 调试用:把「深度测试判定」本身画出来,用于定位"后处理深度测试全部失效"。
5
5
  *
6
6
  * 通道语义(全部为**原始**深度值,不做对数反解,避免饱和丢信息):
7
- * R = 全局 base 深度(baseDepthTexture,排除地板)
7
+ * R = 全局 base 深度(baseDepthTexture,2026-10-18 起含全部对象、含地板)
8
8
  * G = 选区自身深度(selectDepthTexture,glow/stroke 渲染后写入 debugDepthState)
9
9
  * B = 判定结果:baseD < selD - bias ? 1 : 0
10
10
  * 与 stroke_pass 的 depthTestShader 同一判定式(bias = 0.0006):
@@ -5,7 +5,7 @@ import { DEPTH_TEST_BIAS } from "../pass/depthTestBias";
5
5
  * 调试用:把「深度测试判定」本身画出来,用于定位"后处理深度测试全部失效"。
6
6
  *
7
7
  * 通道语义(全部为**原始**深度值,不做对数反解,避免饱和丢信息):
8
- * R = 全局 base 深度(baseDepthTexture,排除地板)
8
+ * R = 全局 base 深度(baseDepthTexture,2026-10-18 起含全部对象、含地板)
9
9
  * G = 选区自身深度(selectDepthTexture,glow/stroke 渲染后写入 debugDepthState)
10
10
  * B = 判定结果:baseD < selD - bias ? 1 : 0
11
11
  * 与 stroke_pass 的 depthTestShader 同一判定式(bias = 0.0006):
@@ -1,44 +0,0 @@
1
- import { Usage } from 'three/src/constants.js';
2
- import type { PathPointList } from './PathPointList.js';
3
- import { BufferGeometry } from 'three/src/core/BufferGeometry.js';
4
- export interface Options {
5
- radius?: number;
6
- width?: number;
7
- progress?: number;
8
- radialSegments?: number;
9
- startRad?: number;
10
- arrow?: boolean;
11
- side?: 'both' | 'left' | 'right';
12
- }
13
- export interface PathGeometryParam {
14
- pathPointList: PathPointList;
15
- options: Options;
16
- usage: Usage;
17
- transparent: boolean;
18
- }
19
- /**
20
- * PathGeometry
21
- */
22
- declare class PathGeometry extends BufferGeometry {
23
- /**
24
- * @param {Object|Number} initData - If initData is number, geometry init by empty data and set it as the max vertex. If initData is Object, it contains pathPointList and options.
25
- * @param {Boolean} [generateUv2=false]
26
- */
27
- constructor(initData: PathGeometryParam, generateUv2?: boolean);
28
- _initByMaxVertex(maxVertex: number, generateUv2: boolean): void;
29
- _initByData(pathPointList: PathPointList, options: Options, usage: Usage, generateUv2: boolean): void;
30
- /**
31
- * Update geometry by PathPointList instance
32
- * @param {PathPointList} pathPointList
33
- * @param {Object} options
34
- * @param {Number} [options.width=0.1]
35
- * @param {Number} [options.progress=1]
36
- * @param {Boolean} [options.arrow=true]
37
- * @param {String} [options.side='both'] - "left"/"right"/"both"
38
- */
39
- update(pathPointList: PathPointList, options: Options): void;
40
- _resizeAttribute(name: string, len: number): void;
41
- _resizeIndex(len: number): void;
42
- _updateAttributes(position: Array<number>, normal: Array<number>, uv: Array<number>, uv2: Array<number> | null, indices: Array<number>): void;
43
- }
44
- export { PathGeometry };