three-base 2.0.169 → 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 (124) hide show
  1. package/FPScontrol.d.ts +55 -30
  2. package/FPScontrol.js +278 -225
  3. package/FPScontrol.ts +177 -127
  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 +8 -3
  10. package/MktMesh/MktMesh.js +43 -14
  11. package/MktMesh/MktMesh.ts +40 -14
  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/MktMesh/types.d.ts +5 -1
  25. package/MktMesh/types.ts +5 -1
  26. package/PipeMesh/PipeJoint.d.ts +22 -0
  27. package/PipeMesh/PipeJoint.js +33 -0
  28. package/PipeMesh/PipeJoint.ts +38 -0
  29. package/PipeMesh/PipeMesh.d.ts +94 -22
  30. package/PipeMesh/PipeMesh.js +192 -53
  31. package/PipeMesh/PipeMesh.ts +223 -76
  32. package/PipeMesh/PipeStraight.d.ts +19 -0
  33. package/PipeMesh/PipeStraight.js +34 -0
  34. package/PipeMesh/PipeStraight.ts +45 -0
  35. package/PipeMesh/axisSnap.d.ts +52 -0
  36. package/PipeMesh/axisSnap.js +52 -0
  37. package/PipeMesh/axisSnap.ts +93 -0
  38. package/PipeMesh/directRoute.d.ts +85 -0
  39. package/PipeMesh/directRoute.js +126 -0
  40. package/PipeMesh/directRoute.ts +190 -0
  41. package/PipeMesh/index.d.ts +6 -0
  42. package/PipeMesh/index.js +6 -0
  43. package/PipeMesh/index.ts +7 -1
  44. package/PipeMesh/pipeMaterial.d.ts +16 -0
  45. package/PipeMesh/pipeMaterial.js +23 -0
  46. package/PipeMesh/pipeMaterial.ts +26 -0
  47. package/ThreeBase.d.ts +2 -49
  48. package/ThreeBase.js +43 -164
  49. package/ThreeBase.ts +1176 -1314
  50. package/instanced/InstancedBatch.d.ts +14 -1
  51. package/instanced/InstancedBatch.js +53 -3
  52. package/instanced/InstancedBatch.ts +62 -3
  53. package/instanced/InstancedChild.d.ts +24 -0
  54. package/instanced/InstancedChild.js +40 -0
  55. package/instanced/InstancedChild.ts +41 -0
  56. package/instanced/InstancedGroup.d.ts +48 -0
  57. package/instanced/InstancedGroup.js +45 -1
  58. package/instanced/InstancedGroup.ts +85 -0
  59. package/package.json +2 -7
  60. package/pass/bloom_pass.js +7 -14
  61. package/pass/bloom_pass.ts +7 -16
  62. package/pass/cover_pass.js +7 -15
  63. package/pass/cover_pass.ts +7 -17
  64. package/pass/debugDepthState.d.ts +16 -8
  65. package/pass/debugDepthState.js +4 -0
  66. package/pass/debugDepthState.ts +27 -9
  67. package/pass/glow_pass.js +19 -110
  68. package/pass/glow_pass.ts +19 -115
  69. package/pass/ssao_pass.d.ts +14 -59
  70. package/pass/ssao_pass.js +66 -171
  71. package/pass/ssao_pass.ts +63 -207
  72. package/pass/stroke_pass.js +13 -16
  73. package/pass/stroke_pass.ts +14 -18
  74. package/shaders/baseDepthVisShader.d.ts +1 -1
  75. package/shaders/baseDepthVisShader.js +1 -1
  76. package/shaders/baseDepthVisShader.ts +1 -1
  77. package/shaders/debugDepthCompareShader.d.ts +2 -2
  78. package/shaders/debugDepthCompareShader.js +2 -2
  79. package/shaders/debugDepthCompareShader.ts +2 -2
  80. package/shaders/debugDepthJudgeShader.d.ts +1 -1
  81. package/shaders/debugDepthJudgeShader.js +1 -1
  82. package/shaders/debugDepthJudgeShader.ts +1 -1
  83. package/PipeMesh/PathGeometry.d.ts +0 -44
  84. package/PipeMesh/PathGeometry.js +0 -307
  85. package/PipeMesh/PathGeometry.ts +0 -343
  86. package/PipeMesh/PathPoint.d.ts +0 -17
  87. package/PipeMesh/PathPoint.js +0 -31
  88. package/PipeMesh/PathPoint.ts +0 -36
  89. package/PipeMesh/PathPointList.d.ts +0 -31
  90. package/PipeMesh/PathPointList.js +0 -209
  91. package/PipeMesh/PathPointList.ts +0 -227
  92. package/PipeMesh/PathTubeGeometry.d.ts +0 -25
  93. package/PipeMesh/PathTubeGeometry.js +0 -130
  94. package/PipeMesh/PathTubeGeometry.ts +0 -146
  95. package/WaterFlow/FloatingDuck.d.ts +0 -88
  96. package/WaterFlow/FloatingDuck.js +0 -307
  97. package/WaterFlow/FloatingDuck.ts +0 -445
  98. package/WaterFlow/GPUFluidSimulation.d.ts +0 -56
  99. package/WaterFlow/GPUFluidSimulation.js +0 -785
  100. package/WaterFlow/GPUFluidSimulation.ts +0 -827
  101. package/WaterFlow/ReservoirSystem.d.ts +0 -106
  102. package/WaterFlow/ReservoirSystem.js +0 -621
  103. package/WaterFlow/ReservoirSystem.ts +0 -754
  104. package/WaterFlow/SPHField.d.ts +0 -35
  105. package/WaterFlow/SPHField.js +0 -204
  106. package/WaterFlow/SPHField.ts +0 -228
  107. package/WaterFlow/ScreenSpaceFluidPass.d.ts +0 -69
  108. package/WaterFlow/ScreenSpaceFluidPass.js +0 -736
  109. package/WaterFlow/ScreenSpaceFluidPass.ts +0 -789
  110. package/WaterFlow/ShallowWaterSurface.d.ts +0 -45
  111. package/WaterFlow/ShallowWaterSurface.js +0 -441
  112. package/WaterFlow/ShallowWaterSurface.ts +0 -510
  113. package/WaterFlow/WaterFlow.d.ts +0 -87
  114. package/WaterFlow/WaterFlow.js +0 -171
  115. package/WaterFlow/WaterFlow.ts +0 -219
  116. package/WaterFlow/types.d.ts +0 -161
  117. package/WaterFlow/types.js +0 -1
  118. package/WaterFlow/types.ts +0 -189
  119. package/WaterFlow/waterFlowPass.d.ts +0 -3
  120. package/WaterFlow/waterFlowPass.js +0 -20
  121. package/WaterFlow/waterFlowPass.ts +0 -40
  122. package/shaders/debugExcludedShader.d.ts +0 -13
  123. package/shaders/debugExcludedShader.js +0 -46
  124. package/shaders/debugExcludedShader.ts +0 -48
package/ThreeBase.js CHANGED
@@ -18,17 +18,14 @@ import frosted_glass_pass from "./pass/frosted_glass_pass";
18
18
  import { flushLensflareOverlays } from "./lensflare/LensFlare";
19
19
  import glow_pass from "./pass/glow_pass";
20
20
  import stroke_pass from "./pass/stroke_pass";
21
- import ssao_pass, { renderAoDepthPass, renderExcludedMaskPass, visibleDepthOptions } from "./pass/ssao_pass";
21
+ import ssao_pass, { renderVisibleDepthPass } from "./pass/ssao_pass";
22
22
  import screenBloomPass from "./pass/screen_bloom_pass";
23
23
  import copyShader from "./shaders/copyShader";
24
24
  import { baseTextureToRenderShader } from "./shaders/baseTextureToRenderShader";
25
25
  import baseDepthVisShader from "./shaders/baseDepthVisShader";
26
26
  import debugDepthCompareShader from "./shaders/debugDepthCompareShader";
27
27
  import debugDepthJudgeShader from "./shaders/debugDepthJudgeShader";
28
- import debugExcludedShader from "./shaders/debugExcludedShader";
29
28
  import { debugDepthState } from "./pass/debugDepthState";
30
- import { WaterFlow } from "./WaterFlow/WaterFlow";
31
- import waterFlowPass from "./WaterFlow/waterFlowPass";
32
29
  import threeLoader from "./threeLoader";
33
30
  import threeUtils from "./threeUtils";
34
31
  import fsQuad from "./pass/fsQuad";
@@ -78,21 +75,23 @@ export default class ThreeBase extends EventDispatcher {
78
75
  // 全局超采样/分辨率倍率(SSAA):base / 深度 / 法线 / 效果 mask / 屏幕合成 全部按
79
76
  // effectiveRatio × resolution 内部超采样渲染,终处理 FXAA 降采样输出到屏幕。
80
77
  // 全链路同倍率 → 各 RT 严格 1:1 对齐:几何锯齿、效果边缘锯齿、辉光漏光(深度 vs mask 错位)、
81
- // mask 合成 UV 缩放错位、SSAO 深度错位变黑 一并消除。默认 2 = 每维 2×、总像素 4×;
82
- // 代价全链路填充 ×4(base + 深度 + 法线 + 后处理 SSAO/cover/frosted)。要省性能整体降 1
83
- // (关超采样,仅 FXAA 兜底,几何硬边锯齿回弹)。历史坑:baseRenderScale/auxRenderScale/
84
- // effectRenderScale 三参各自为政,倍率不同步必错位,故统一为单参数 resolution 管全局。
78
+ // mask 合成 UV 缩放错位、SSAO 深度错位变黑 一并消除。
79
+ // ⭐ 默认 1(原生分辨率):2026-10-21 皇上旨「有点卡,分辨率改成 1」。原默认 2 = 每维 2×、
80
+ // 总像素 4×,全链路填充 ×4 且 35 张 RT 显存约 1.1 GB(1920×1080 画布)。降到 1 后填充与显存
81
+ // 均降约 75%,几何硬边锯齿由终处理 FXAA 兜底。需要纹理摩尔纹治本时,面板上再调回 2。
82
+ // 历史坑:baseRenderScale/auxRenderScale/effectRenderScale 三参各自为政,倍率不同步必错位,
83
+ // 故统一为单参数 resolution 管全局。
85
84
  // ⚠️ 必须用 getter/setter,不能是普通字段:所有 RT 尺寸只在 updateRenderTargetSizes()
86
85
  // 里按 effectiveRatio × resolution 计算,而该方法过去只被 setSize()(容器尺寸变化)调用
87
86
  // → 运行时改 resolution 不会重建任何 RT,画面毫无变化(表现为"调分辨率没感觉")。
88
87
  // 故 setter 里改动倍率后立刻重建全部 RT。
89
- _resolution = 2;
88
+ _resolution = 1;
90
89
  get resolution() {
91
90
  return this._resolution;
92
91
  }
93
92
  set resolution(value) {
94
93
  // 夹到合理区间:0 或负值会让 RT 尺寸为 0,WebGL 报 framebuffer incomplete
95
- const next = Math.min(4, Math.max(0.25, Number.isFinite(value) ? value : 2));
94
+ const next = Math.min(4, Math.max(0.25, Number.isFinite(value) ? value : 1));
96
95
  if (next === this._resolution) {
97
96
  return;
98
97
  }
@@ -239,19 +238,6 @@ export default class ThreeBase extends EventDispatcher {
239
238
  });
240
239
  return baseRenderTarget;
241
240
  })();
242
- /** 可选的屏幕空间水流对象(WaterFlow)。默认 null;调用 enableWaterFlow() 后创建。启用时
243
- * 每帧消费 baseRenderTarget/baseDepthTexture,把水面合成进后处理链(不额外渲染主场景)。 */
244
- waterFlow = null;
245
- _waterFlowLastTime = 0;
246
- waterFlowElapsed = 0;
247
- // 调试用:被排除面 mask 渲染目标(仅「排除面标记」调试档使用,尺寸随主渲染目标同步)
248
- excludedMaskRenderTarget = new WebGLRenderTarget(128, 128, {
249
- minFilter: LinearFilter,
250
- magFilter: LinearFilter,
251
- format: RGBAFormat,
252
- stencilBuffer: false,
253
- depthBuffer: false,
254
- });
255
241
  // 深度专用渲染目标(无 MSAA,深度值稳定,供后处理深度比对使用)
256
242
  depthRenderTarget = new WebGLRenderTarget(128, 128, {
257
243
  minFilter: LinearFilter,
@@ -260,12 +246,14 @@ export default class ThreeBase extends EventDispatcher {
260
246
  stencilBuffer: false,
261
247
  depthTexture: this.baseDepthTexture,
262
248
  });
263
- // AO 深度纹理(含地板):**不再单独渲染一遍** —— 它挂在 normalRenderTarget 上当 depth attachment,
264
- // 法线 pass(renderAoNormalPass,includeFloor=true)渲染时深度由光栅器顺带写入,白拿一张含地板深度。
265
- // (2026-09-14 优化:删掉原 ssao_pass 内那次 renderAoDepthPass(true),每帧省一次全场景遍历。)
266
- // SSAO 的 GTAO 采样它(地板保留为实体 → 接触 AO),合成时再与 depthRenderTarget
267
- // (地板排除 = 可见深度)比对,作废"透过半透明地板看到的实体"上的地板接触 AO。
268
- // 见 three-base/pass/ssao_pass.ts 的复合守卫说明。
249
+ // AO 深度纹理:**不再单独渲染一遍** —— 它挂在 normalRenderTarget 上当 depth attachment,
250
+ // 法线 pass(renderAoNormalPass)渲染时深度由光栅器顺带写入,白拿一张。
251
+ // (2026-09-14 优化:删掉原 ssao_pass 内那次独立的深度 pass,每帧省一次全场景遍历。)
252
+ // SSAO 的 GTAO 采样它(与法线同源);合成时再与 depthRenderTarget(可见深度 = 各物体自身材质渲染)
253
+ // 比对:AO 侧更近说明那像素记到屏幕上不可见的面(抠图空隙 / 单面墙背面)→ 作废该像素 AO。
254
+ // ⚠️ 2026-10-18 皇上旨「所有的对象都要进入到深度图里面了,不需要用参数过滤掉了」⇒ 这张 AO 深度
255
+ // 和 baseDepthTexture 都收全场景对象(含地板、含半透明面、含 sprite/线条/点);原 excludeTransparent
256
+ // 参数与 userData.aoFloor 特例整条删除。见 three-base/pass/ssao_pass.ts 文件头(代价清单写在那里)。
269
257
  aoDepthTexture = (() => {
270
258
  const t = new DepthTexture(4096, 4096);
271
259
  t.format = DepthFormat;
@@ -276,29 +264,13 @@ export default class ThreeBase extends EventDispatcher {
276
264
  /**
277
265
  * 调试用:深度预览模式。由面板「深度调试」切换,便于逐一看各深度图排查"深度测试全部失效"根因。
278
266
  * - "none" :正常渲染(默认)
279
- * - "global" :仅预览全局深度图(baseDepthTexture,排除地板)。全白=深度为空→renderAoDepthPass 没写进深度。
280
- * - "ao" :仅预览 AO 深度图(aoDepthTexture = 法线 pass 顺带写入的含地板深度)。用于确认深度管线本身是否工作。
267
+ * - "global" :仅预览可见深度图(baseDepthTexture;2026-10-18 起收全场景对象,含地板)。全白=深度为空→renderVisibleDepthPass 没写进深度。
268
+ * - "ao" :仅预览 AO 深度图(aoDepthTexture = 法线 pass 顺带写入)。用于确认深度管线本身是否工作。
281
269
  * - "compare" :R=全局 base 深度,G=最近一次 glow/stroke 选区 select 深度。两路任一全白即该侧写入失败。
282
- * - "excluded":深度图灰度 + 「被排除出深度图的面」叠红(红=该面写不进深度,永远挡不住后处理)。
283
- * 物体区域(G 暗)若 B 全黑 → 判定从不触发;再看该区 R/G 谁大即可定位是谁缺深度。
284
270
  * 兼容旧控制台入口:设置 `window.__BASE_DEPTH_VIS = true` 等价于切到 "global"。
285
271
  * 通用控制台入口:任意页面都可 `window.__TB_DEBUG_DEPTH = "judge"`(优先级高于面板属性)。
286
272
  */
287
273
  debugDepthPreview = "none";
288
- /**
289
- * 可见深度图是否包含「标了 userData.aoFloor 的地板」(如 Ground1)。
290
- *
291
- * 默认 false —— 原设计:地板可透视,透过地板看到的物体照常显示(不被地板挡住)。
292
- * 置 true 后地板会写进 baseDepthTexture,**被地板挡住的描边/辉光/毛玻璃/覆盖色会被正确遮挡**。
293
- * 排查"怎么都挡不住"时先开这个试一下:若开了就正常,说明挡你的正是可透视地板。
294
- */
295
- get baseDepthIncludeFloor() {
296
- return visibleDepthOptions.includeFloor;
297
- }
298
- set baseDepthIncludeFloor(v) {
299
- visibleDepthOptions.includeFloor = v;
300
- this.needRender = true;
301
- }
302
274
  // 法线专用渲染目标(无 MSAA,存储视图空间法线,供 GTAO 风格 SSAO 使用真实法线)
303
275
  normalRenderTarget = new WebGLRenderTarget(128, 128, {
304
276
  minFilter: LinearFilter,
@@ -544,11 +516,8 @@ export default class ThreeBase extends EventDispatcher {
544
516
  // 强制同步为 depthRenderTarget 尺寸,下面再手动对齐一次避免首帧抖动。
545
517
  this.depthRenderTarget.setSize(w, h);
546
518
  this.normalRenderTarget.setSize(w, h);
547
- this.excludedMaskRenderTarget.setSize(w, h);
548
519
  // 屏幕合成目标:同样跟随 resolution,全链路 1:1 对齐
549
520
  this.screenRenderTarget.setSize(w, h);
550
- // 水流后处理目标跟随同倍率重建(pass 内部粒子 RT 仍按 scale 降采样,compositeTarget 全分辨率)
551
- this.waterFlow?.resize(w, h);
552
521
  this.baseDepthTexture.image.width = w;
553
522
  this.baseDepthTexture.image.height = h;
554
523
  // 立即渲染一帧,避免静态场景下改了倍率却停在旧画面
@@ -620,92 +589,7 @@ export default class ThreeBase extends EventDispatcher {
620
589
  return axesHelper;
621
590
  })();
622
591
  init() {
623
- // 屏幕空间水流:?waterflow=1 时自动启用(默认关闭,需显式 enableWaterFlow 或此 URL 参数)。
624
- // 创建后每帧消费 base 深度 + 后处理合成画面,把水面合成进后处理链,不自渲染主场景。
625
- try {
626
- const params = new URLSearchParams(typeof location !== 'undefined' ? location.search : '');
627
- if (params.get('waterflow') === '1') {
628
- this.enableWaterFlow();
629
- }
630
- }
631
- catch (_e) {
632
- // 非浏览器环境(如 Node 测试/SSR)忽略
633
- }
634
- }
635
- /**
636
- * 启用屏幕空间水流(GPGPU 粒子流体)。默认关闭,需显式调用或携带 ?waterflow=1。
637
- * 创建后每帧自动消费 base 深度 + 当前合成画面,把水面合成进后处理链,不自渲染主场景。
638
- * @param options.size 粒子网格边长(size×size 粒子),越大越细腻、越费
639
- * @param options.speed 射流初速
640
- * @param options.aperture 喷嘴开度
641
- * @param options.nozzle 喷流起点坐标 [x,y,z],默认 [0.58,1.55,0]
642
- * @param options.jetDirection 喷流方向(轴向,会被归一化),默认 [1,0,0](沿 +X)
643
- * @param options.collision 是否开启粒子与 basin/地面碰撞回弹,默认 true
644
- */
645
- enableWaterFlow(options = {}) {
646
- if (this.waterFlow) {
647
- console.warn('[ThreeBase] WaterFlow 已启用,重复调用无效');
648
- return;
649
- }
650
- const { size = 200, speed = 2.4, aperture = 0.78, nozzle, jetDirection, collision = true, } = options;
651
- const waterFlow = new WaterFlow(this.renderer, {
652
- size,
653
- speed,
654
- aperture,
655
- nozzle: nozzle ? new Vector3(nozzle[0], nozzle[1], nozzle[2]) : undefined,
656
- jetDirection: jetDirection ? new Vector3(jetDirection[0], jetDirection[1], jetDirection[2]) : undefined,
657
- collision,
658
- });
659
- if (!waterFlow.supported) {
660
- console.warn('[ThreeBase] 当前环境不支持浮点纹理,WaterFlow 未启用');
661
- waterFlow.dispose();
662
- return;
663
- }
664
- // 创建 pass 并注入基础纹理(externalBase 模式);后续每帧 renderInto 会刷新注入的纹理。
665
- // ⚠️ 2026-10-08(WaterFlow 全量 TS 化):ScreenSpaceFluidPass 内部按透视相机建模
666
- // (setSize 读 camera.fov 算 pointScale、depthMaterial 走 projectionMatrix 重建深度),
667
- // 故此处显式窄化。getCamera() 在 cameraType==="orthographicCamera" 时会返回
668
- // OrthographicCamera —— 原 JS 同样会把 fov=undefined 传进去(pointScale 变 NaN),
669
- // 本次**只补类型、未改运行时行为**,保持与线上一致。
670
- waterFlow.createPass(this.scene, this.getCamera(), {
671
- colorTexture: this.baseRenderTarget.texture,
672
- depthTexture: this.baseDepthTexture,
673
- depthMode: 'logarithmic',
674
- });
675
- // 首帧按当前容器尺寸对齐(后续 setSize/resolution 变化由 updateRenderTargetSizes 兜底)。
676
- const w = Math.max(1, Math.round(this.size.x * this.effectiveRatio * this._resolution));
677
- const h = Math.max(1, Math.round(this.size.y * this.effectiveRatio * this._resolution));
678
- if (this.size.x > 1 && this.size.y > 1)
679
- waterFlow.resize(w, h);
680
- this.waterFlow = waterFlow;
681
- this._waterFlowLastTime = 0;
682
- this.waterFlowElapsed = 0;
683
- console.info('[ThreeBase] WaterFlow 已启用');
684
- }
685
- /** 运行时改喷流起点(喷嘴)坐标(WaterFlow 已启用时有效) */
686
- setWaterFlowNozzle(x, y, z) {
687
- this.waterFlow?.setNozzle(x, y, z);
688
- }
689
- /** 运行时改喷流方向(轴向,会被归一化) */
690
- setWaterFlowJetDirection(x, y, z) {
691
- this.waterFlow?.setJetDirection(x, y, z);
692
- }
693
- /** 运行时开关粒子与 basin/地面碰撞回弹 */
694
- setWaterFlowCollision(enabled) {
695
- this.waterFlow?.setCollision(enabled);
696
- }
697
- /**
698
- * 关闭屏幕空间水流并释放其 GPU 资源(enableWaterFlow 的反操作)。
699
- * 切走页面时必须调用,否则其它页面 render 仍会合成水面(this.waterFlow 非空)。
700
- */
701
- disableWaterFlow() {
702
- if (!this.waterFlow)
703
- return;
704
- this.waterFlow.dispose();
705
- this.waterFlow = null;
706
- this._waterFlowLastTime = 0;
707
- this.waterFlowElapsed = 0;
708
- console.info('[ThreeBase] WaterFlow 已关闭');
592
+ // 生命周期钩子:子类重写后调用 super.init()。当前无内置初始化动作。
709
593
  }
710
594
  // 重置控制器的位置
711
595
  resetLookAt({ position = this.perspectiveCamera.position, center = this.controls.target, }) {
@@ -972,17 +856,6 @@ export default class ThreeBase extends EventDispatcher {
972
856
  return; // 标识未渲染
973
857
  }
974
858
  this.needRender = false;
975
- // 水流模拟推进:独立于相机控制,按真实帧间隔累计时间推进 GPGPU 粒子模拟。
976
- // 默认 this.waterFlow 为 null(关闭),调用 enableWaterFlow() 或 ?waterflow=1 才创建。
977
- if (this.waterFlow && this.waterFlow.supported) {
978
- const wnow = performance.now();
979
- const wdt = this._waterFlowLastTime > 0
980
- ? Math.min((wnow - this._waterFlowLastTime) / 1000, 0.05)
981
- : 1 / 60;
982
- this._waterFlowLastTime = wnow;
983
- this.waterFlowElapsed += wdt;
984
- this.waterFlow.update(wdt, this.waterFlowElapsed);
985
- }
986
859
  if (this.controls.enabled) {
987
860
  // 让 OrbitControls 始终接管"当前渲染相机":OrbitControls 构造时只绑定了
988
861
  // perspectiveCamera,但渲染相机随 cameraType 切换。若切到正交相机时仍让 OrbitControls
@@ -1019,10 +892,11 @@ export default class ThreeBase extends EventDispatcher {
1019
892
  this.renderer.setRenderTarget(this.baseRenderTarget);
1020
893
  this.renderer.clear();
1021
894
  this.renderer.render(this.scene, camera);
1022
- // 深度 pass:固定排除非实体表面后渲到 depthRenderTarget(生成 baseDepthTexture)。
895
+ // 可见深度 pass:用各物体自身材质渲染整个场景(2026-10-18 起不再排除任何对象:含地板、
896
+ // 含半透明面、含 sprite/线条/点),产出 baseDepthTexture 供描边/发光/覆盖/磨砂做遮挡判定。
1023
897
  // 必须在 base render 之后、所有依赖深度的特效(描边/发光/覆盖/磨砂)之前更新,
1024
898
  // 否则这些特效会用到上一帧旧深度 → 遮挡判定错乱。法线 pass 已收进 ssao_pass 内部。
1025
- renderAoDepthPass(this.renderer, camera, this.scene, this.depthRenderTarget);
899
+ renderVisibleDepthPass(this.renderer, camera, this.scene, this.depthRenderTarget);
1026
900
  // 切回 baseRenderTarget,后处理 pass 需要把效果叠加到颜色渲染目标上
1027
901
  this.renderer.setRenderTarget(this.baseRenderTarget);
1028
902
  // 效果 mask 灰度图尺寸 = effectiveRatio × resolution,与 baseRenderTarget / baseDepthTexture 同倍率,
@@ -1069,12 +943,6 @@ export default class ThreeBase extends EventDispatcher {
1069
943
  }
1070
944
  // 一次性处理所有支持毛玻璃特效的对象
1071
945
  frosted_glass_pass(this.renderer, camera, this.scene, this.baseRenderTarget, this.baseDepthTexture, dpr);
1072
- // 屏幕空间水流:消费 base 深度 + 当前合成画面(含 ssao/覆盖/磨砂),把水面合成进
1073
- // screenRenderTarget。插在磨砂之后、screenBloom 之前,使水面高光也能被泛光处理。
1074
- // 默认关闭(this.waterFlow 为 null 时不产生任何开销)。
1075
- if (this.waterFlow && this.waterFlow.supported) {
1076
- waterFlowPass(this.renderer, camera, this.scene, this.baseRenderTarget, this.baseDepthTexture, this.waterFlow);
1077
- }
1078
946
  // 屏幕空间辉光(经典 gaussian bloom):纯颜色、无深度依赖,把亮度超阈值的部分做
1079
947
  // 连续高斯模糊后加性叠加回 screenRenderTarget。单分辨率多迭代,柔和均匀、无 mip 分层。
1080
948
  if (this.bloom.enable) {
@@ -1088,12 +956,16 @@ export default class ThreeBase extends EventDispatcher {
1088
956
  // 分辨率按实际帧缓冲像素(已乘 dpr)设置,修复高分屏下 FXAA 采样比例偏大失效的问题。
1089
957
  // ⚠️ 深度调试预览(面板「深度调试」切换,定位"深度测试全部失效"根因):
1090
958
  // 旧控制台入口 `window.__BASE_DEPTH_VIS = true` 仍可用,等价于切到 "global"。
1091
- // global → baseDepthTexture 灰度。全白=深度为空(renderAoDepthPass 没写进)→后处理一律显示在前;有灰阶=深度正常,问题在比对侧。
1092
- // ao → aoDepthTexture 灰度(含地板)。确认深度管线本身是否工作(GTAO 是否拿到正确深度)。
959
+ // global → baseDepthTexture 灰度(含全部对象,含地板)。全白=深度为空(renderVisibleDepthPass 没写进)→后处理一律显示在前;有灰阶=深度正常,问题在比对侧。
960
+ // ao → aoDepthTexture 灰度(同样含全部对象)。确认深度管线本身是否工作(GTAO 是否拿到正确深度)。
1093
961
  // compare → R=全局 base 深度,G=最近一次 glow/stroke 选区的 select 深度。两路任一全白即该侧写入失败。
1094
962
  // judge → R=base 原始深度、G=select 原始深度、B=判定结果(1=判为被遮挡应 discard)。
963
+ // strokeSelect → 【描边步骤 1】选区本体深度(selectDepthTexture),白色=空背景、灰=物体本体。
964
+ // strokeSelectBlur → 【描边步骤 5.5】描边外扩后的选区深度(selectDepthBlurTextureTarget),
965
+ // 物体轮廓比本体档更胖一圈即外扩生效。
1095
966
  // 通用控制台入口(任意页面可用,优先级高于面板属性):
1096
- // `window.__TB_DEBUG_DEPTH = "global" | "ao" | "compare" | "judge"`,设回 "none" 恢复。
967
+ // `window.__TB_DEBUG_DEPTH = "global" | "ao" | "compare" | "judge" | "strokeSelect" | "strokeSelectBlur"`,
968
+ // 设回 "none" 恢复。
1097
969
  const dbgWin = window.__TB_DEBUG_DEPTH;
1098
970
  const dbgMode = window.__BASE_DEPTH_VIS
1099
971
  ? "global"
@@ -1122,12 +994,19 @@ export default class ThreeBase extends EventDispatcher {
1122
994
  debugDepthState.lastSelectDepth ?? this.baseDepthTexture;
1123
995
  fsQuad.render(this.renderer, debugDepthJudgeShader);
1124
996
  }
1125
- else if (dbgMode === "excluded") {
1126
- // 先渲「被排除面 mask」,再与深度图叠加:红=挡不住任何后处理的面
1127
- renderExcludedMaskPass(this.renderer, camera, this.scene, this.excludedMaskRenderTarget);
1128
- debugExcludedShader.uniforms.tDepth.value = this.baseDepthTexture;
1129
- debugExcludedShader.uniforms.tMask.value = this.excludedMaskRenderTarget.texture;
1130
- fsQuad.render(this.renderer, debugExcludedShader);
997
+ else if (dbgMode === "strokeSelect") {
998
+ // 描边步骤 1:选区本体深度(selectDepthTexture,挂在 mask 目标上当 depth attachment,
999
+ // 由那趟光栅化顺带写入 ⇒ 零额外渲染代价)。
1000
+ baseDepthVisShader.uniforms.tDepth.value =
1001
+ debugDepthState.lastSelectDepth ?? this.baseDepthTexture;
1002
+ fsQuad.render(this.renderer, baseDepthVisShader);
1003
+ }
1004
+ else if (dbgMode === "strokeSelectBlur") {
1005
+ // 描边步骤 5.5:外扩后的选区深度(RGBA8 目标,对数深度存在 .r 通道)。
1006
+ // 与本体档对比看:外扩生效时物体轮廓会「胖一圈」,被遮挡的外扩环则被判 discard 后不参与。
1007
+ baseDepthVisShader.uniforms.tDepth.value =
1008
+ debugDepthState.lastSelectBlurDepth ?? this.baseDepthTexture;
1009
+ fsQuad.render(this.renderer, baseDepthVisShader);
1131
1010
  }
1132
1011
  flushLensflareOverlays(this.renderer, camera);
1133
1012
  return;