three-base 2.0.137 → 2.0.145
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/DirectionalLight.d.ts +2 -2
- package/DirectionalLight.js +1 -1
- package/DirectionalLight.ts +70 -0
- package/EventMap.d.ts +103 -0
- package/EventMap.js +17 -0
- package/EventMap.ts +139 -0
- package/EventMesh.ts +60 -0
- package/ExtrudeMesh.js +1 -25
- package/ExtrudeMesh.ts +553 -0
- package/FPScontrol.d.ts +448 -15
- package/FPScontrol.js +1448 -266
- package/FPScontrol.ts +1855 -0
- package/Fire/Fire.d.ts +4 -4
- package/Fire/Fire.js +8 -7
- package/Fire/Fire.ts +89 -0
- package/Fire/{FireGromtry.d.ts → FireGeometry.d.ts} +2 -2
- package/Fire/{FireGromtry.js → FireGeometry.js} +1 -1
- package/Fire/FireGeometry.ts +40 -0
- package/Fire/FireMaterial.d.ts +3 -3
- package/Fire/FireMaterial.js +1 -1
- package/Fire/FireMaterial.ts +89 -0
- package/Fire/index.d.ts +1 -0
- package/Fire/index.js +1 -0
- package/Fire/index.ts +2 -0
- package/GLTFDracoLoader.d.ts +71 -0
- package/GLTFDracoLoader.js +266 -0
- package/GLTFDracoLoader.ts +430 -0
- package/Grass/Grass.d.ts +2 -2
- package/Grass/Grass.ts +38 -0
- package/Grass/index.d.ts +1 -0
- package/Grass/index.js +1 -0
- package/Grass/index.ts +2 -0
- package/Ground1/Ground1.d.ts +2 -3
- package/Ground1/Ground1.js +64 -60
- package/Ground1/Ground1.ts +114 -0
- package/Ground1/index.ts +1 -0
- package/MeshBase.d.ts +1 -0
- package/MeshBase.js +37 -13
- package/MeshBase.ts +253 -0
- package/Mirror.d.ts +3 -3
- package/Mirror.js +7 -3
- package/Mirror.ts +203 -0
- package/MktMesh/MktMesh.d.ts +301 -0
- package/MktMesh/MktMesh.js +1064 -0
- package/MktMesh/MktMesh.ts +1096 -0
- package/MktMesh/assetUrl.d.ts +59 -0
- package/MktMesh/assetUrl.js +154 -0
- package/MktMesh/assetUrl.ts +155 -0
- package/MktMesh/mktMappingShader.d.ts +12 -0
- package/MktMesh/mktMappingShader.js +139 -0
- package/MktMesh/mktMappingShader.ts +139 -0
- package/MktMesh/mktShader.d.ts +263 -0
- package/MktMesh/mktShader.js +1248 -0
- package/MktMesh/mktShader.ts +1344 -0
- package/MktMesh/panoBitmapTexture.d.ts +25 -0
- package/MktMesh/panoBitmapTexture.js +52 -0
- package/MktMesh/panoBitmapTexture.ts +54 -0
- package/MktMesh/panoSlotBind.d.ts +29 -0
- package/MktMesh/panoSlotBind.js +106 -0
- package/MktMesh/panoSlotBind.ts +153 -0
- package/MktMesh/panoSlotRoster.d.ts +22 -0
- package/MktMesh/panoSlotRoster.js +169 -0
- package/MktMesh/panoSlotRoster.ts +168 -0
- package/MktMesh/panoTileStitcher.d.ts +119 -0
- package/MktMesh/panoTileStitcher.js +533 -0
- package/MktMesh/panoTileStitcher.ts +616 -0
- package/MktMesh/types.d.ts +75 -0
- package/MktMesh/types.js +1 -0
- package/MktMesh/types.ts +87 -0
- package/MktMesh/wallCapTessellate.d.ts +33 -0
- package/MktMesh/wallCapTessellate.js +97 -0
- package/MktMesh/wallCapTessellate.ts +68 -0
- package/PipeMesh/PathGeometry.js +9 -2
- package/PipeMesh/PathGeometry.ts +343 -0
- package/PipeMesh/PathPoint.ts +36 -0
- package/PipeMesh/PathPointList.js +1 -0
- package/PipeMesh/PathPointList.ts +227 -0
- package/PipeMesh/PathTubeGeometry.ts +146 -0
- package/PipeMesh/PipeMesh.d.ts +1 -1
- package/PipeMesh/PipeMesh.js +1 -1
- package/PipeMesh/PipeMesh.ts +76 -0
- package/PipeMesh/index.ts +1 -0
- package/PlaneModal1/PlaneModal1.d.ts +16 -13
- package/PlaneModal1/PlaneModal1.js +4 -0
- package/PlaneModal1/PlaneModal1.ts +138 -0
- package/PlaneModal1/index.ts +1 -0
- package/PlaneText.d.ts +2 -14
- package/PlaneText.js +7 -2
- package/PlaneText.ts +55 -0
- package/PlaneWithHtml.d.ts +4 -2
- package/PlaneWithHtml.js +2 -1
- package/PlaneWithHtml.ts +70 -0
- package/PointLight/PointLight.d.ts +3 -4
- package/PointLight/PointLight.js +1 -7
- package/PointLight/PointLight.ts +67 -0
- package/PointLight/index.ts +1 -0
- package/README.md +110 -79
- package/Sky/Sky.ts +22 -0
- package/Sky/index.ts +1 -0
- package/SpotLight.d.ts +2 -2
- package/SpotLight.js +1 -1
- package/SpotLight.ts +74 -0
- package/SpriteModal1/SpriteModal1.d.ts +16 -13
- package/SpriteModal1/SpriteModal1.js +8 -2
- package/SpriteModal1/SpriteModal1.ts +146 -0
- package/SpriteModal1/index.ts +1 -0
- package/SpriteText.d.ts +14 -13
- package/SpriteText.js +22 -9
- package/SpriteText.ts +205 -0
- package/SpriteText2.d.ts +9 -8
- package/SpriteText2.js +57 -32
- package/SpriteText2.ts +258 -0
- package/SpriteText3.d.ts +86 -0
- package/SpriteText3.js +519 -0
- package/SpriteText3.ts +599 -0
- package/SpriteWithHtml.d.ts +4 -2
- package/SpriteWithHtml.ts +50 -0
- package/Text3D/Text3D.js +17 -21
- package/Text3D/Text3D.ts +77 -0
- package/Text3D/fontController.d.ts +10 -9
- package/Text3D/fontController.js +17 -50
- package/Text3D/fontController.ts +209 -0
- package/Text3D/index.ts +1 -0
- package/ThreeBase.d.ts +168 -31
- package/ThreeBase.js +663 -117
- package/ThreeBase.ts +1314 -0
- package/ThreeMouse.d.ts +20 -7
- package/ThreeMouse.js +78 -32
- package/ThreeMouse.ts +472 -0
- package/Transition.d.ts +12 -7
- package/Transition.js +26 -27
- package/Transition.ts +242 -0
- package/Water/Water.js +21 -3
- package/Water/Water.ts +45 -0
- package/Water/index.d.ts +2 -0
- package/Water/index.js +2 -0
- package/Water/index.ts +2 -0
- package/WaterFlow/FloatingDuck.d.ts +88 -0
- package/WaterFlow/FloatingDuck.js +307 -0
- package/WaterFlow/FloatingDuck.ts +445 -0
- package/WaterFlow/GPUFluidSimulation.d.ts +56 -0
- package/WaterFlow/GPUFluidSimulation.js +785 -0
- package/WaterFlow/GPUFluidSimulation.ts +827 -0
- package/WaterFlow/ReservoirSystem.d.ts +106 -0
- package/WaterFlow/ReservoirSystem.js +621 -0
- package/WaterFlow/ReservoirSystem.ts +754 -0
- package/WaterFlow/SPHField.d.ts +35 -0
- package/WaterFlow/SPHField.js +204 -0
- package/WaterFlow/SPHField.ts +228 -0
- package/WaterFlow/ScreenSpaceFluidPass.d.ts +69 -0
- package/WaterFlow/ScreenSpaceFluidPass.js +736 -0
- package/WaterFlow/ScreenSpaceFluidPass.ts +789 -0
- package/WaterFlow/ShallowWaterSurface.d.ts +45 -0
- package/WaterFlow/ShallowWaterSurface.js +441 -0
- package/WaterFlow/ShallowWaterSurface.ts +510 -0
- package/WaterFlow/WaterFlow.d.ts +87 -0
- package/WaterFlow/WaterFlow.js +171 -0
- package/WaterFlow/WaterFlow.ts +219 -0
- package/WaterFlow/types.d.ts +161 -0
- package/WaterFlow/types.js +1 -0
- package/WaterFlow/types.ts +189 -0
- package/WaterFlow/waterFlowPass.d.ts +3 -0
- package/WaterFlow/waterFlowPass.js +20 -0
- package/WaterFlow/waterFlowPass.ts +40 -0
- package/collisionOBB.d.ts +42 -0
- package/collisionOBB.js +112 -0
- package/collisionOBB.ts +108 -0
- package/declare.d.ts +25 -167
- package/index.js +0 -1
- package/index.ts +1 -0
- package/instanced/InstancedBatch.d.ts +57 -0
- package/instanced/InstancedBatch.js +348 -0
- package/instanced/InstancedBatch.ts +406 -0
- package/instanced/InstancedChild.d.ts +174 -0
- package/instanced/InstancedChild.js +264 -0
- package/instanced/InstancedChild.ts +327 -0
- package/instanced/InstancedGroup.d.ts +43 -0
- package/instanced/InstancedGroup.js +126 -0
- package/instanced/InstancedGroup.ts +137 -0
- package/{InstancedMeshBase.d.ts → instanced/InstancedMeshBase.d.ts} +6 -7
- package/{InstancedMeshBase.js → instanced/InstancedMeshBase.js} +36 -47
- package/instanced/InstancedMeshBase.ts +292 -0
- package/instanced/InstancedTemplate.d.ts +46 -0
- package/instanced/InstancedTemplate.js +125 -0
- package/instanced/InstancedTemplate.ts +188 -0
- package/keyControls.d.ts +29 -0
- package/{keyContorls.js → keyControls.js} +10 -7
- package/keyControls.ts +107 -0
- package/lensflare/LensFlare.d.ts +39 -0
- package/lensflare/LensFlare.js +373 -0
- package/lensflare/LensFlare.ts +448 -0
- package/lensflare/lensflare0.png +0 -0
- package/lensflare/lensflare3.png +0 -0
- package/lensflare/lensflare_custom.png +0 -0
- package/lensflare/lensflare_hex_ghost.png +0 -0
- package/lensflare/lensflare_hex_main.png +0 -0
- package/package.json +104 -25
- package/pass/bloom_pass.d.ts +1 -1
- package/pass/bloom_pass.js +127 -40
- package/pass/bloom_pass.ts +243 -0
- package/pass/cover_pass.d.ts +1 -1
- package/pass/cover_pass.js +55 -32
- package/pass/cover_pass.ts +182 -0
- package/pass/debugDepthState.d.ts +20 -0
- package/pass/debugDepthState.js +9 -0
- package/pass/debugDepthState.ts +22 -0
- package/pass/depthTestBias.d.ts +12 -0
- package/pass/depthTestBias.js +12 -0
- package/pass/depthTestBias.ts +12 -0
- package/pass/effectUserData.d.ts +27 -0
- package/pass/effectUserData.js +1 -0
- package/pass/effectUserData.ts +46 -0
- package/pass/frosted_glass_pass.d.ts +1 -1
- package/pass/frosted_glass_pass.js +45 -64
- package/pass/frosted_glass_pass.ts +288 -0
- package/pass/fsQuad.d.ts +2 -2
- package/pass/fsQuad.ts +34 -0
- package/pass/glow_pass.d.ts +1 -1
- package/pass/glow_pass.js +288 -72
- package/pass/glow_pass.ts +654 -0
- package/pass/screen_bloom_pass.d.ts +11 -0
- package/pass/screen_bloom_pass.js +235 -0
- package/pass/screen_bloom_pass.ts +263 -0
- package/pass/ssao_pass.d.ts +78 -3
- package/pass/ssao_pass.js +642 -206
- package/pass/ssao_pass.ts +918 -0
- package/pass/stroke_pass.d.ts +1 -1
- package/pass/stroke_pass.js +187 -116
- package/pass/stroke_pass.ts +638 -0
- package/shaders/FXAAShaderMaterial.js +5 -48
- package/shaders/FXAAShaderMaterial.ts +201 -0
- package/shaders/baseDepthVisShader.d.ts +11 -0
- package/shaders/baseDepthVisShader.js +36 -0
- package/shaders/baseDepthVisShader.ts +36 -0
- package/shaders/baseTextureToRenderShader.js +46 -51
- package/shaders/baseTextureToRenderShader.ts +232 -0
- package/shaders/copyShader.js +2 -3
- package/shaders/copyShader.ts +32 -0
- package/shaders/debugDepthCompareShader.d.ts +14 -0
- package/shaders/debugDepthCompareShader.js +49 -0
- package/shaders/debugDepthCompareShader.ts +50 -0
- package/shaders/debugDepthJudgeShader.d.ts +18 -0
- package/shaders/debugDepthJudgeShader.js +52 -0
- package/shaders/debugDepthJudgeShader.ts +54 -0
- package/shaders/debugExcludedShader.d.ts +13 -0
- package/shaders/debugExcludedShader.js +46 -0
- package/shaders/debugExcludedShader.ts +48 -0
- package/spriteTextBg.d.ts +1 -0
- package/spriteTextBg.js +20 -0
- package/spriteTextBg.ts +20 -0
- package/threeLoader.d.ts +8 -7
- package/threeLoader.js +58 -67
- package/threeLoader.ts +525 -0
- package/threeUtils.d.ts +2 -1
- package/threeUtils.js +24 -25
- package/threeUtils.ts +373 -0
- package/types.d.ts +2 -0
- package/types.js +6 -0
- package/types.ts +8 -0
- package/ApngTexture.d.ts +0 -13
- package/ApngTexture.js +0 -61
- package/ApngTextureManage.d.ts +0 -18
- package/ApngTextureManage.js +0 -87
- package/KeyFrameAnimation.d.ts +0 -25
- package/KeyFrameAnimation.js +0 -78
- package/keyContorls.d.ts +0 -25
- package/lib/draco/draco_decoder.js +0 -34
- package/lib/draco/draco_decoder.wasm +0 -0
- package/lib/draco/draco_wasm_wrapper.js +0 -117
- package/pass/emissive_ao_pass.d.ts +0 -13
- package/pass/emissive_ao_pass.js +0 -370
- package/shaders.d.ts +0 -5
- package/shaders.js +0 -93
package/pass/bloom_pass.js
CHANGED
|
@@ -4,39 +4,54 @@
|
|
|
4
4
|
* @Last Modified by: xiaosihan
|
|
5
5
|
* @Last Modified time: 2025-01-28 05:05:49
|
|
6
6
|
*/
|
|
7
|
-
import { DepthTexture, DepthFormat, LinearFilter, RGBAFormat,
|
|
7
|
+
import { DepthTexture, DepthFormat, LinearFilter, RGBAFormat, UnsignedIntType, WebGLRenderTarget, Scene, Vector2, ShaderChunk, NoBlending, ShaderMaterial, AdditiveBlending } from "three";
|
|
8
8
|
import { UnrealBloomPass } from "three/examples/jsm/postprocessing/UnrealBloomPass";
|
|
9
9
|
import copyShader from "../shaders/copyShader";
|
|
10
10
|
import fsQuad from "./fsQuad";
|
|
11
|
-
// 选中对象的深度纹理
|
|
12
11
|
const selectDepthTexture = (() => {
|
|
13
|
-
const baseDepthTexture = new DepthTexture(
|
|
12
|
+
const baseDepthTexture = new DepthTexture(1024, 1024);
|
|
14
13
|
baseDepthTexture.format = DepthFormat;
|
|
15
|
-
baseDepthTexture.type =
|
|
14
|
+
baseDepthTexture.type = UnsignedIntType;
|
|
16
15
|
baseDepthTexture.anisotropy = 16;
|
|
17
16
|
return baseDepthTexture;
|
|
18
17
|
})();
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
const selectTextureTarget = new WebGLRenderTarget(1024, 1024, {
|
|
19
|
+
minFilter: LinearFilter,
|
|
20
|
+
magFilter: LinearFilter,
|
|
21
|
+
format: RGBAFormat,
|
|
22
|
+
anisotropy: 16,
|
|
23
|
+
// 无 MSAA:mask 颜色与下方 selectDepthTextureTarget(深度)必须同为硬边缘,
|
|
24
|
+
// 否则 mask 边缘平滑而深度硬 → depthTest 判定边界与 mask 视觉边缘错位,bloom 边缘锯齿/摩尔纹。
|
|
25
|
+
// 边缘抗锯齿统一由终处理 FXAA 兜底。
|
|
26
|
+
});
|
|
27
|
+
// 无 MSAA 的深度专用目标:仅用于导出对象深度,供 depthTestShader 做遮挡判定(深度无需抗锯齿)
|
|
28
|
+
const selectDepthTextureTarget = new WebGLRenderTarget(1024, 1024, {
|
|
21
29
|
minFilter: LinearFilter,
|
|
22
30
|
magFilter: LinearFilter,
|
|
23
31
|
format: RGBAFormat,
|
|
24
32
|
depthTexture: selectDepthTexture,
|
|
25
33
|
anisotropy: 16,
|
|
26
34
|
});
|
|
27
|
-
|
|
28
|
-
|
|
35
|
+
const selectDepthTestTextureTarget = new WebGLRenderTarget(1024, 1024, {
|
|
36
|
+
minFilter: LinearFilter,
|
|
37
|
+
magFilter: LinearFilter,
|
|
38
|
+
format: RGBAFormat,
|
|
39
|
+
anisotropy: 16,
|
|
40
|
+
});
|
|
41
|
+
// 独立的 bloom 合成目标:避免 UnrealBloomPass 与 readBuffer 共用同一目标
|
|
42
|
+
// (本版本 UnrealBloomPass 内部把 bloom 叠加回 readBuffer,传入独立 write 目标可规避同目标读写隐患)
|
|
43
|
+
const bloomWriteTarget = new WebGLRenderTarget(1024, 1024, {
|
|
29
44
|
minFilter: LinearFilter,
|
|
30
45
|
magFilter: LinearFilter,
|
|
31
46
|
format: RGBAFormat,
|
|
32
47
|
anisotropy: 16,
|
|
33
48
|
});
|
|
34
|
-
//深度比对纹理
|
|
35
49
|
const depthTestShader = new ShaderMaterial({
|
|
36
50
|
uniforms: {
|
|
37
|
-
map: { value: null },
|
|
38
|
-
baseDepth: { value: null },
|
|
39
|
-
selectDepth: { value: null },
|
|
51
|
+
map: { value: null },
|
|
52
|
+
baseDepth: { value: null },
|
|
53
|
+
selectDepth: { value: null },
|
|
54
|
+
cameraFar: { value: 1000.0 },
|
|
40
55
|
},
|
|
41
56
|
vertexShader: `
|
|
42
57
|
${ShaderChunk.common}
|
|
@@ -53,19 +68,31 @@ const depthTestShader = new ShaderMaterial({
|
|
|
53
68
|
uniform sampler2D map;
|
|
54
69
|
uniform sampler2D baseDepth;
|
|
55
70
|
uniform sampler2D selectDepth;
|
|
71
|
+
uniform float cameraFar;
|
|
56
72
|
varying vec2 vUv;
|
|
57
73
|
void main() {
|
|
58
|
-
|
|
74
|
+
float baseD = texture2D(baseDepth, vUv).r;
|
|
75
|
+
float selD = texture2D(selectDepth, vUv).r;
|
|
76
|
+
// 对数深度反解为线性视图深度后再比对。
|
|
77
|
+
float zBase = pow(cameraFar + 1.0, baseD) - 1.0;
|
|
78
|
+
float zSel = pow(cameraFar + 1.0, selD) - 1.0;
|
|
79
|
+
float bias = max(zSel, 1.0) * 0.0015;
|
|
80
|
+
// 该像素没有泛光对象(selectDepth 仍是清屏值 1.0 → zSel == cameraFar)→ 不参与合成。
|
|
81
|
+
// ⚠️ 旧实现让背景像素「不参与丢弃」,导致没有对象的像素同样输出 map,
|
|
82
|
+
// 而本 shader 输出后由 AdditiveBlending 叠回主画面 → 整个场景被泛光覆盖
|
|
83
|
+
// (与 frosted_glass_pass 的「整屏模糊」是同一个模板 bug)。
|
|
84
|
+
if (zSel >= cameraFar) {
|
|
59
85
|
discard;
|
|
60
86
|
}
|
|
61
|
-
|
|
87
|
+
// 仅丢弃被更近场景几何遮挡的部分(zBase 比 zSel 更近)
|
|
88
|
+
if (zBase < zSel - bias) {
|
|
62
89
|
discard;
|
|
63
90
|
}
|
|
64
91
|
gl_FragColor = texture2D(map, vUv);
|
|
65
92
|
${ShaderChunk.logdepthbuf_fragment}
|
|
66
93
|
}
|
|
67
94
|
`,
|
|
68
|
-
blending: NoBlending,
|
|
95
|
+
blending: NoBlending,
|
|
69
96
|
depthTest: true,
|
|
70
97
|
depthWrite: true,
|
|
71
98
|
transparent: true,
|
|
@@ -73,52 +100,112 @@ const depthTestShader = new ShaderMaterial({
|
|
|
73
100
|
const blendMaterial = copyShader.clone();
|
|
74
101
|
blendMaterial.blending = AdditiveBlending;
|
|
75
102
|
const size = new Vector2();
|
|
76
|
-
// 场景对象
|
|
77
103
|
const scene = new Scene();
|
|
78
104
|
const bloomPass = new UnrealBloomPass(new Vector2(1024, 1024), 1.5, 0.4, 0.85);
|
|
79
|
-
// bloomPass.threshold = params.threshold;
|
|
80
|
-
// bloomPass.strength = params.strength;
|
|
81
|
-
// bloomPass.radius = params.radius;
|
|
82
|
-
// 发光后期通道
|
|
83
105
|
export default function bloom_pass(renderer, camera, object3d, baseRenderTarget, baseDepthTexture, devicePixelRatio) {
|
|
84
106
|
const { bloom_enable = false, bloom_threshold = 1.5, bloom_strength = 0.4, bloom_radius = 0.85, } = object3d.userData;
|
|
85
|
-
// 不满足条件就不渲染发光效果
|
|
86
107
|
if (!bloom_enable || (bloom_strength === 0) || (bloom_radius === 0)) {
|
|
87
108
|
return;
|
|
88
109
|
}
|
|
89
110
|
bloomPass.threshold = bloom_threshold;
|
|
90
111
|
bloomPass.strength = bloom_strength;
|
|
91
112
|
bloomPass.radius = bloom_radius;
|
|
92
|
-
// 保存原帧缓冲区
|
|
93
113
|
const originRenderTarget = renderer.getRenderTarget();
|
|
94
|
-
//
|
|
114
|
+
// 灰度图渲染目标跟随主画面尺寸(= width × effectiveRatio),与 baseRenderTarget 完全一致,
|
|
115
|
+
// 消除灰度图与主画面尺寸不一致导致的放大重采样摩尔纹
|
|
95
116
|
renderer.getSize(size);
|
|
96
117
|
size.multiplyScalar(devicePixelRatio);
|
|
97
118
|
bloomPass.setSize(size.x, size.y);
|
|
98
119
|
selectTextureTarget.setSize(size.x, size.y);
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
120
|
+
selectDepthTextureTarget.setSize(size.x, size.y);
|
|
121
|
+
// 缺陷②修复:three r167 的 WebGLRenderTarget.setSize 不会同步 depthTexture,
|
|
122
|
+
// 需手动把 selectDepthTexture 的尺寸与全屏 baseDepth 对齐,否则深度比例错位导致 bloom 被全部 discard
|
|
123
|
+
selectDepthTexture.image.width = size.x;
|
|
124
|
+
selectDepthTexture.image.height = size.y;
|
|
125
|
+
selectDepthTexture.needsUpdate = true;
|
|
126
|
+
selectDepthTestTextureTarget.setSize(size.x, size.y);
|
|
127
|
+
bloomWriteTarget.setSize(size.x, size.y);
|
|
128
|
+
// 缺陷①修复:离屏单独渲染 object3d 时临时 scene 没有灯光,
|
|
129
|
+
// 而 Text3D 默认材质 metalness:1 无环境贴图,无光照会渲染成全黑,bloom 提取不到亮度。
|
|
130
|
+
// 做法:① 安全挂载并还原 object3d 的 parent(渲染后放回原 parent,避免影响主场景的 matrixWorld);
|
|
131
|
+
// ② 把材质临时切到"自发光显色"(emissive = color, emissiveIntensity = 1),
|
|
132
|
+
// 让被 bloom 的对象按其可见原色参与 bloom,且不受 MeshStandardMaterial 的 metalness 影响,必定可见。
|
|
133
|
+
const parent = object3d.parent;
|
|
134
|
+
scene.add(object3d);
|
|
135
|
+
// object3d 可能是单 Mesh,也可能是 Group(如 InstancedChild 选择代理含多个代理 Mesh)。
|
|
136
|
+
// 统一遍历其下所有网格子节点,收集材质(数组展开、去重、排除 undefined),
|
|
137
|
+
// 避免 Group 无 material 属性时访问 undefined.emissive 抛错。
|
|
138
|
+
const mats = [];
|
|
139
|
+
object3d.traverse((node) => {
|
|
140
|
+
const nodeMesh = node;
|
|
141
|
+
if (nodeMesh.isMesh) {
|
|
142
|
+
const nodeMat = nodeMesh.material;
|
|
143
|
+
if (Array.isArray(nodeMat)) {
|
|
144
|
+
for (const m of nodeMat)
|
|
145
|
+
if (m)
|
|
146
|
+
mats.push(m);
|
|
147
|
+
}
|
|
148
|
+
else if (nodeMat) {
|
|
149
|
+
mats.push(nodeMat);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
const uniqueMats = Array.from(new Set(mats));
|
|
154
|
+
// 暂存每个材质的原 emissive / emissiveIntensity,渲染后还原
|
|
155
|
+
const emissiveBackup = uniqueMats.map((mat) => {
|
|
156
|
+
const m = mat;
|
|
157
|
+
return {
|
|
158
|
+
material: mat,
|
|
159
|
+
emissive: m.emissive ? m.emissive.clone() : null,
|
|
160
|
+
emissiveIntensity: m.emissiveIntensity ?? 0,
|
|
161
|
+
};
|
|
162
|
+
});
|
|
163
|
+
uniqueMats.forEach((mat) => {
|
|
164
|
+
const m = mat;
|
|
165
|
+
if (m.emissive && m.color) {
|
|
166
|
+
m.emissive.copy(m.color);
|
|
167
|
+
m.emissiveIntensity = 1;
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
try {
|
|
171
|
+
renderer.setRenderTarget(selectTextureTarget);
|
|
172
|
+
renderer.clear();
|
|
173
|
+
renderer.render(scene, camera);
|
|
174
|
+
// 单独渲染对象深度到无 MSAA 目标,供 depthTestShader 做遮挡判定(与材质/父节点还原同生命周期)
|
|
175
|
+
renderer.setRenderTarget(selectDepthTextureTarget);
|
|
176
|
+
renderer.clear();
|
|
177
|
+
renderer.render(scene, camera);
|
|
178
|
+
}
|
|
179
|
+
finally {
|
|
180
|
+
// 还原材质 emissive
|
|
181
|
+
emissiveBackup.forEach(({ material, emissive, emissiveIntensity }) => {
|
|
182
|
+
const m = material;
|
|
183
|
+
if (m.emissive) {
|
|
184
|
+
if (emissive) {
|
|
185
|
+
m.emissive.copy(emissive);
|
|
186
|
+
}
|
|
187
|
+
m.emissiveIntensity = emissiveIntensity;
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
// 还原 parent,避免影响主场景里该对象的 matrixWorld
|
|
191
|
+
if (parent) {
|
|
192
|
+
parent.add(object3d);
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
scene.remove(object3d);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
renderer.setRenderTarget(selectDepthTestTextureTarget);
|
|
106
199
|
renderer.clear();
|
|
107
200
|
depthTestShader.uniforms.map.value = baseRenderTarget.texture;
|
|
108
201
|
depthTestShader.uniforms.baseDepth.value = baseDepthTexture;
|
|
109
202
|
depthTestShader.uniforms.selectDepth.value = selectDepthTexture;
|
|
203
|
+
depthTestShader.uniforms.cameraFar.value = camera.far;
|
|
110
204
|
fsQuad.render(renderer, depthTestShader);
|
|
111
|
-
//
|
|
112
|
-
bloomPass.render(renderer,
|
|
113
|
-
// 将发光效果与原始帧缓冲区混合
|
|
205
|
+
// 修复:使用独立 write 目标,避免 UnrealBloomPass 就地读写同一目标导致不出图
|
|
206
|
+
bloomPass.render(renderer, bloomWriteTarget, selectDepthTestTextureTarget, 0, false);
|
|
114
207
|
renderer.setRenderTarget(originRenderTarget);
|
|
115
208
|
renderer.clearDepth();
|
|
116
|
-
blendMaterial.uniforms.map.value =
|
|
209
|
+
blendMaterial.uniforms.map.value = selectDepthTestTextureTarget.texture;
|
|
117
210
|
fsQuad.render(renderer, blendMaterial);
|
|
118
|
-
// 调试代码
|
|
119
|
-
// renderer.setRenderTarget(null);
|
|
120
|
-
// renderer.clearDepth();
|
|
121
|
-
// copyShader.uniforms.map.value = blur2TextureTarget.texture;
|
|
122
|
-
// fsQuad.render(renderer, copyShader);
|
|
123
|
-
// return;
|
|
124
211
|
}
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @Author: xiaosihan
|
|
3
|
+
* @Date: 2024-09-23 21:51:29
|
|
4
|
+
* @Last Modified by: xiaosihan
|
|
5
|
+
* @Last Modified time: 2025-01-28 05:05:49
|
|
6
|
+
*/
|
|
7
|
+
import { DepthTexture, DepthFormat, LinearFilter, RGBAFormat, UnsignedIntType, WebGLRenderTarget, Scene, Vector2, ShaderChunk, NoBlending, ShaderMaterial, AdditiveBlending, WebGLRenderer, Camera, PerspectiveCamera, Object3D, Color, Material, Mesh } from "three";
|
|
8
|
+
import { UnrealBloomPass } from "three/examples/jsm/postprocessing/UnrealBloomPass";
|
|
9
|
+
import copyShader from "../shaders/copyShader";
|
|
10
|
+
import fsQuad from "./fsQuad";
|
|
11
|
+
import { EffectUserData } from "./effectUserData";
|
|
12
|
+
|
|
13
|
+
const selectDepthTexture: DepthTexture = (() => {
|
|
14
|
+
const baseDepthTexture = new DepthTexture(1024, 1024);
|
|
15
|
+
baseDepthTexture.format = DepthFormat;
|
|
16
|
+
baseDepthTexture.type = UnsignedIntType;
|
|
17
|
+
baseDepthTexture.anisotropy = 16;
|
|
18
|
+
return baseDepthTexture;
|
|
19
|
+
})();
|
|
20
|
+
|
|
21
|
+
const selectTextureTarget: WebGLRenderTarget = new WebGLRenderTarget(1024, 1024, {
|
|
22
|
+
minFilter: LinearFilter,
|
|
23
|
+
magFilter: LinearFilter,
|
|
24
|
+
format: RGBAFormat,
|
|
25
|
+
anisotropy: 16,
|
|
26
|
+
// 无 MSAA:mask 颜色与下方 selectDepthTextureTarget(深度)必须同为硬边缘,
|
|
27
|
+
// 否则 mask 边缘平滑而深度硬 → depthTest 判定边界与 mask 视觉边缘错位,bloom 边缘锯齿/摩尔纹。
|
|
28
|
+
// 边缘抗锯齿统一由终处理 FXAA 兜底。
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// 无 MSAA 的深度专用目标:仅用于导出对象深度,供 depthTestShader 做遮挡判定(深度无需抗锯齿)
|
|
32
|
+
const selectDepthTextureTarget: WebGLRenderTarget = new WebGLRenderTarget(1024, 1024, {
|
|
33
|
+
minFilter: LinearFilter,
|
|
34
|
+
magFilter: LinearFilter,
|
|
35
|
+
format: RGBAFormat,
|
|
36
|
+
depthTexture: selectDepthTexture,
|
|
37
|
+
anisotropy: 16,
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const selectDepthTestTextureTarget: WebGLRenderTarget = new WebGLRenderTarget(1024, 1024, {
|
|
41
|
+
minFilter: LinearFilter,
|
|
42
|
+
magFilter: LinearFilter,
|
|
43
|
+
format: RGBAFormat,
|
|
44
|
+
anisotropy: 16,
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// 独立的 bloom 合成目标:避免 UnrealBloomPass 与 readBuffer 共用同一目标
|
|
48
|
+
// (本版本 UnrealBloomPass 内部把 bloom 叠加回 readBuffer,传入独立 write 目标可规避同目标读写隐患)
|
|
49
|
+
const bloomWriteTarget: WebGLRenderTarget = new WebGLRenderTarget(1024, 1024, {
|
|
50
|
+
minFilter: LinearFilter,
|
|
51
|
+
magFilter: LinearFilter,
|
|
52
|
+
format: RGBAFormat,
|
|
53
|
+
anisotropy: 16,
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
const depthTestShader: ShaderMaterial = new ShaderMaterial({
|
|
57
|
+
uniforms: {
|
|
58
|
+
map: { value: null },
|
|
59
|
+
baseDepth: { value: null },
|
|
60
|
+
selectDepth: { value: null },
|
|
61
|
+
cameraFar: { value: 1000.0 },
|
|
62
|
+
},
|
|
63
|
+
vertexShader: `
|
|
64
|
+
${ShaderChunk.common}
|
|
65
|
+
${ShaderChunk.logdepthbuf_pars_vertex}
|
|
66
|
+
varying vec2 vUv;
|
|
67
|
+
void main() {
|
|
68
|
+
vUv = uv;
|
|
69
|
+
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
|
|
70
|
+
${ShaderChunk.logdepthbuf_vertex}
|
|
71
|
+
}
|
|
72
|
+
`,
|
|
73
|
+
fragmentShader: `
|
|
74
|
+
${ShaderChunk.logdepthbuf_pars_fragment}
|
|
75
|
+
uniform sampler2D map;
|
|
76
|
+
uniform sampler2D baseDepth;
|
|
77
|
+
uniform sampler2D selectDepth;
|
|
78
|
+
uniform float cameraFar;
|
|
79
|
+
varying vec2 vUv;
|
|
80
|
+
void main() {
|
|
81
|
+
float baseD = texture2D(baseDepth, vUv).r;
|
|
82
|
+
float selD = texture2D(selectDepth, vUv).r;
|
|
83
|
+
// 对数深度反解为线性视图深度后再比对。
|
|
84
|
+
float zBase = pow(cameraFar + 1.0, baseD) - 1.0;
|
|
85
|
+
float zSel = pow(cameraFar + 1.0, selD) - 1.0;
|
|
86
|
+
float bias = max(zSel, 1.0) * 0.0015;
|
|
87
|
+
// 该像素没有泛光对象(selectDepth 仍是清屏值 1.0 → zSel == cameraFar)→ 不参与合成。
|
|
88
|
+
// ⚠️ 旧实现让背景像素「不参与丢弃」,导致没有对象的像素同样输出 map,
|
|
89
|
+
// 而本 shader 输出后由 AdditiveBlending 叠回主画面 → 整个场景被泛光覆盖
|
|
90
|
+
// (与 frosted_glass_pass 的「整屏模糊」是同一个模板 bug)。
|
|
91
|
+
if (zSel >= cameraFar) {
|
|
92
|
+
discard;
|
|
93
|
+
}
|
|
94
|
+
// 仅丢弃被更近场景几何遮挡的部分(zBase 比 zSel 更近)
|
|
95
|
+
if (zBase < zSel - bias) {
|
|
96
|
+
discard;
|
|
97
|
+
}
|
|
98
|
+
gl_FragColor = texture2D(map, vUv);
|
|
99
|
+
${ShaderChunk.logdepthbuf_fragment}
|
|
100
|
+
}
|
|
101
|
+
`,
|
|
102
|
+
blending: NoBlending,
|
|
103
|
+
depthTest: true,
|
|
104
|
+
depthWrite: true,
|
|
105
|
+
transparent: true,
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
const blendMaterial: ShaderMaterial = copyShader.clone();
|
|
109
|
+
blendMaterial.blending = AdditiveBlending;
|
|
110
|
+
|
|
111
|
+
const size: Vector2 = new Vector2();
|
|
112
|
+
|
|
113
|
+
const scene: Scene = new Scene();
|
|
114
|
+
|
|
115
|
+
const bloomPass: UnrealBloomPass = new UnrealBloomPass(new Vector2(1024, 1024), 1.5, 0.4, 0.85);
|
|
116
|
+
|
|
117
|
+
export default function bloom_pass(
|
|
118
|
+
renderer: WebGLRenderer,
|
|
119
|
+
camera: Camera,
|
|
120
|
+
object3d: Object3D,
|
|
121
|
+
baseRenderTarget: WebGLRenderTarget,
|
|
122
|
+
baseDepthTexture: DepthTexture,
|
|
123
|
+
devicePixelRatio: number
|
|
124
|
+
): void {
|
|
125
|
+
const {
|
|
126
|
+
bloom_enable = false,
|
|
127
|
+
bloom_threshold = 1.5,
|
|
128
|
+
bloom_strength = 0.4,
|
|
129
|
+
bloom_radius = 0.85,
|
|
130
|
+
} = object3d.userData as EffectUserData;
|
|
131
|
+
|
|
132
|
+
if (!bloom_enable || (bloom_strength === 0) || (bloom_radius === 0)) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
bloomPass.threshold = bloom_threshold;
|
|
137
|
+
bloomPass.strength = bloom_strength;
|
|
138
|
+
bloomPass.radius = bloom_radius;
|
|
139
|
+
|
|
140
|
+
const originRenderTarget = renderer.getRenderTarget();
|
|
141
|
+
|
|
142
|
+
// 灰度图渲染目标跟随主画面尺寸(= width × effectiveRatio),与 baseRenderTarget 完全一致,
|
|
143
|
+
// 消除灰度图与主画面尺寸不一致导致的放大重采样摩尔纹
|
|
144
|
+
renderer.getSize(size);
|
|
145
|
+
size.multiplyScalar(devicePixelRatio);
|
|
146
|
+
bloomPass.setSize(size.x, size.y);
|
|
147
|
+
selectTextureTarget.setSize(size.x, size.y);
|
|
148
|
+
selectDepthTextureTarget.setSize(size.x, size.y);
|
|
149
|
+
// 缺陷②修复:three r167 的 WebGLRenderTarget.setSize 不会同步 depthTexture,
|
|
150
|
+
// 需手动把 selectDepthTexture 的尺寸与全屏 baseDepth 对齐,否则深度比例错位导致 bloom 被全部 discard
|
|
151
|
+
selectDepthTexture.image.width = size.x;
|
|
152
|
+
selectDepthTexture.image.height = size.y;
|
|
153
|
+
selectDepthTexture.needsUpdate = true;
|
|
154
|
+
selectDepthTestTextureTarget.setSize(size.x, size.y);
|
|
155
|
+
bloomWriteTarget.setSize(size.x, size.y);
|
|
156
|
+
|
|
157
|
+
// 缺陷①修复:离屏单独渲染 object3d 时临时 scene 没有灯光,
|
|
158
|
+
// 而 Text3D 默认材质 metalness:1 无环境贴图,无光照会渲染成全黑,bloom 提取不到亮度。
|
|
159
|
+
// 做法:① 安全挂载并还原 object3d 的 parent(渲染后放回原 parent,避免影响主场景的 matrixWorld);
|
|
160
|
+
// ② 把材质临时切到"自发光显色"(emissive = color, emissiveIntensity = 1),
|
|
161
|
+
// 让被 bloom 的对象按其可见原色参与 bloom,且不受 MeshStandardMaterial 的 metalness 影响,必定可见。
|
|
162
|
+
const parent = object3d.parent;
|
|
163
|
+
scene.add(object3d);
|
|
164
|
+
|
|
165
|
+
// object3d 可能是单 Mesh,也可能是 Group(如 InstancedChild 选择代理含多个代理 Mesh)。
|
|
166
|
+
// 统一遍历其下所有网格子节点,收集材质(数组展开、去重、排除 undefined),
|
|
167
|
+
// 避免 Group 无 material 属性时访问 undefined.emissive 抛错。
|
|
168
|
+
const mats: Material[] = [];
|
|
169
|
+
object3d.traverse((node: Object3D) => {
|
|
170
|
+
const nodeMesh = node as Mesh;
|
|
171
|
+
if (nodeMesh.isMesh) {
|
|
172
|
+
const nodeMat = nodeMesh.material;
|
|
173
|
+
if (Array.isArray(nodeMat)) {
|
|
174
|
+
for (const m of nodeMat) if (m) mats.push(m);
|
|
175
|
+
} else if (nodeMat) {
|
|
176
|
+
mats.push(nodeMat);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
const uniqueMats = Array.from(new Set(mats));
|
|
181
|
+
|
|
182
|
+
// 暂存每个材质的原 emissive / emissiveIntensity,渲染后还原
|
|
183
|
+
const emissiveBackup = uniqueMats.map((mat) => {
|
|
184
|
+
const m = mat as unknown as { emissive?: Color; emissiveIntensity?: number };
|
|
185
|
+
return {
|
|
186
|
+
material: mat,
|
|
187
|
+
emissive: m.emissive ? m.emissive.clone() : null,
|
|
188
|
+
emissiveIntensity: m.emissiveIntensity ?? 0,
|
|
189
|
+
};
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
uniqueMats.forEach((mat) => {
|
|
193
|
+
const m = mat as unknown as { color?: Color; emissive?: Color; emissiveIntensity?: number };
|
|
194
|
+
if (m.emissive && m.color) {
|
|
195
|
+
m.emissive.copy(m.color);
|
|
196
|
+
m.emissiveIntensity = 1;
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
try {
|
|
201
|
+
renderer.setRenderTarget(selectTextureTarget);
|
|
202
|
+
renderer.clear();
|
|
203
|
+
renderer.render(scene, camera);
|
|
204
|
+
|
|
205
|
+
// 单独渲染对象深度到无 MSAA 目标,供 depthTestShader 做遮挡判定(与材质/父节点还原同生命周期)
|
|
206
|
+
renderer.setRenderTarget(selectDepthTextureTarget);
|
|
207
|
+
renderer.clear();
|
|
208
|
+
renderer.render(scene, camera);
|
|
209
|
+
} finally {
|
|
210
|
+
// 还原材质 emissive
|
|
211
|
+
emissiveBackup.forEach(({ material, emissive, emissiveIntensity }) => {
|
|
212
|
+
const m = material as unknown as { emissive?: Color; emissiveIntensity?: number };
|
|
213
|
+
if (m.emissive) {
|
|
214
|
+
if (emissive) {
|
|
215
|
+
m.emissive.copy(emissive);
|
|
216
|
+
}
|
|
217
|
+
m.emissiveIntensity = emissiveIntensity;
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
// 还原 parent,避免影响主场景里该对象的 matrixWorld
|
|
221
|
+
if (parent) {
|
|
222
|
+
parent.add(object3d);
|
|
223
|
+
} else {
|
|
224
|
+
scene.remove(object3d);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
renderer.setRenderTarget(selectDepthTestTextureTarget);
|
|
229
|
+
renderer.clear();
|
|
230
|
+
depthTestShader.uniforms.map.value = baseRenderTarget.texture;
|
|
231
|
+
depthTestShader.uniforms.baseDepth.value = baseDepthTexture;
|
|
232
|
+
depthTestShader.uniforms.selectDepth.value = selectDepthTexture;
|
|
233
|
+
depthTestShader.uniforms.cameraFar.value = (camera as PerspectiveCamera).far;
|
|
234
|
+
fsQuad.render(renderer, depthTestShader);
|
|
235
|
+
|
|
236
|
+
// 修复:使用独立 write 目标,避免 UnrealBloomPass 就地读写同一目标导致不出图
|
|
237
|
+
bloomPass.render(renderer, bloomWriteTarget, selectDepthTestTextureTarget, 0, false);
|
|
238
|
+
|
|
239
|
+
renderer.setRenderTarget(originRenderTarget);
|
|
240
|
+
renderer.clearDepth();
|
|
241
|
+
blendMaterial.uniforms.map.value = selectDepthTestTextureTarget.texture;
|
|
242
|
+
fsQuad.render(renderer, blendMaterial);
|
|
243
|
+
}
|
package/pass/cover_pass.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DepthTexture, WebGLRenderer, Camera, Object3D } from "three";
|
|
2
2
|
export default function cover_pass(renderer: WebGLRenderer, camera: Camera, object3d: Object3D, baseDepthTexture: DepthTexture, devicePixelRatio: number): void;
|
package/pass/cover_pass.js
CHANGED
|
@@ -10,45 +10,54 @@
|
|
|
10
10
|
* @Last Modified by: xiaosihan
|
|
11
11
|
* @Last Modified time: 2023-05-09 02:33:28
|
|
12
12
|
*/
|
|
13
|
-
import { Color, DepthFormat, DepthTexture, LinearFilter, RGBAFormat, Scene, ShaderChunk, ShaderMaterial,
|
|
13
|
+
import { Color, DepthFormat, DepthTexture, LinearFilter, RGBAFormat, Scene, ShaderChunk, ShaderMaterial, UnsignedIntType, Vector2, WebGLRenderTarget } from "three";
|
|
14
14
|
import fsQuad from "./fsQuad";
|
|
15
|
-
|
|
15
|
+
import { debugDepthState } from "./debugDepthState";
|
|
16
16
|
const selectDepthTexture = (() => {
|
|
17
17
|
const baseDepthTexture = new DepthTexture(1024, 1024);
|
|
18
18
|
baseDepthTexture.format = DepthFormat;
|
|
19
|
-
baseDepthTexture.type =
|
|
19
|
+
baseDepthTexture.type = UnsignedIntType;
|
|
20
20
|
baseDepthTexture.anisotropy = 16;
|
|
21
21
|
return baseDepthTexture;
|
|
22
22
|
})();
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
const selectTextureTarget = new WebGLRenderTarget(1024, 1024, {
|
|
24
|
+
minFilter: LinearFilter,
|
|
25
|
+
magFilter: LinearFilter,
|
|
26
|
+
format: RGBAFormat,
|
|
27
|
+
anisotropy: 16,
|
|
28
|
+
// 无 MSAA:mask 颜色与下方 selectDepthTextureTarget(深度)必须同为硬边缘,
|
|
29
|
+
// 否则 mask 边缘平滑而深度硬 → depthTestShader 判定边界与 mask 视觉边缘错位,覆盖边缘锯齿。
|
|
30
|
+
// 边缘抗锯齿统一由终处理 FXAA 兜底。
|
|
31
|
+
});
|
|
32
|
+
// 无 MSAA 的深度专用目标:仅用于导出对象深度,供 depthTestShader 做遮挡判定(深度无需抗锯齿)
|
|
33
|
+
const selectDepthTextureTarget = new WebGLRenderTarget(1024, 1024, {
|
|
25
34
|
minFilter: LinearFilter,
|
|
26
35
|
magFilter: LinearFilter,
|
|
27
36
|
format: RGBAFormat,
|
|
28
37
|
depthTexture: selectDepthTexture,
|
|
29
38
|
anisotropy: 16,
|
|
30
39
|
});
|
|
31
|
-
|
|
32
|
-
const selectDethpTestTextureTarget = new WebGLRenderTarget(512, 512, {
|
|
40
|
+
const selectDepthTestTextureTarget = new WebGLRenderTarget(1024, 1024, {
|
|
33
41
|
minFilter: LinearFilter,
|
|
34
42
|
magFilter: LinearFilter,
|
|
35
43
|
format: RGBAFormat,
|
|
36
44
|
anisotropy: 16,
|
|
45
|
+
// 无 MSAA:深度测试 mask 无需抗锯齿,去掉以提速
|
|
37
46
|
});
|
|
38
|
-
const blur1TextureTarget = new WebGLRenderTarget(
|
|
47
|
+
const blur1TextureTarget = new WebGLRenderTarget(1024, 1024, {
|
|
39
48
|
minFilter: LinearFilter,
|
|
40
49
|
magFilter: LinearFilter,
|
|
41
50
|
format: RGBAFormat,
|
|
42
51
|
});
|
|
43
52
|
const size = new Vector2();
|
|
44
|
-
//深度比对纹理
|
|
45
53
|
const depthTestShader = new ShaderMaterial({
|
|
46
54
|
uniforms: {
|
|
47
|
-
color: { value: new Color("#440000") },
|
|
48
|
-
opacity: { value: 1 },
|
|
49
|
-
depthTest: { value: true },
|
|
50
|
-
baseDepth: { value: null },
|
|
51
|
-
selectDepth: { value: null },
|
|
55
|
+
color: { value: new Color("#440000") },
|
|
56
|
+
opacity: { value: 1 },
|
|
57
|
+
depthTest: { value: true },
|
|
58
|
+
baseDepth: { value: null },
|
|
59
|
+
selectDepth: { value: null },
|
|
60
|
+
cameraFar: { value: 1000.0 },
|
|
52
61
|
},
|
|
53
62
|
vertexShader: `
|
|
54
63
|
${ShaderChunk.common}
|
|
@@ -56,8 +65,6 @@ const depthTestShader = new ShaderMaterial({
|
|
|
56
65
|
varying vec2 vUv;
|
|
57
66
|
void main() {
|
|
58
67
|
vUv = uv;
|
|
59
|
-
// gl_Position = vec4(position, 1.0);
|
|
60
|
-
// gl_Position = projectionMatrix * modelViewMatrix * instanceMatrix * vec4(position, 1.0);
|
|
61
68
|
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
|
|
62
69
|
${ShaderChunk.logdepthbuf_vertex}
|
|
63
70
|
}
|
|
@@ -69,13 +76,25 @@ const depthTestShader = new ShaderMaterial({
|
|
|
69
76
|
uniform bool depthTest;
|
|
70
77
|
uniform sampler2D baseDepth;
|
|
71
78
|
uniform sampler2D selectDepth;
|
|
79
|
+
uniform float cameraFar;
|
|
72
80
|
varying vec2 vUv;
|
|
73
81
|
void main() {
|
|
74
82
|
if( depthTest ){
|
|
75
|
-
|
|
83
|
+
float coverBaseD = texture2D(baseDepth, vUv).r;
|
|
84
|
+
float coverSelD = texture2D(selectDepth, vUv).r;
|
|
85
|
+
// 对数深度反解成线性视图深度,线性空间做遮挡判定。
|
|
86
|
+
float zBase = pow(cameraFar + 1.0, coverBaseD) - 1.0;
|
|
87
|
+
float zSel = pow(cameraFar + 1.0, coverSelD) - 1.0;
|
|
88
|
+
float bias = max(zSel, 1.0) * 0.0015;
|
|
89
|
+
// 该像素没有覆盖对象(selectDepth 仍是清屏值 1.0 → zSel == cameraFar)→ 不参与合成。
|
|
90
|
+
// ⚠️ 旧实现让背景像素「直接保留覆盖色」,导致没有对象的像素同样输出覆盖色
|
|
91
|
+
// → 整个场景被覆盖色染一层(与 frosted_glass / bloom 是同一个模板 bug)。
|
|
92
|
+
// 语义与下方 depthTest=false 分支的「selectDepth < 1.0 才输出」保持一致。
|
|
93
|
+
if (zSel >= cameraFar) {
|
|
76
94
|
discard;
|
|
77
95
|
}
|
|
78
|
-
|
|
96
|
+
// 仅丢弃被更近场景几何遮挡的部分
|
|
97
|
+
if (zBase < zSel - bias) {
|
|
79
98
|
discard;
|
|
80
99
|
}
|
|
81
100
|
gl_FragColor = vec4(color, opacity);
|
|
@@ -94,28 +113,37 @@ const depthTestShader = new ShaderMaterial({
|
|
|
94
113
|
depthWrite: true,
|
|
95
114
|
transparent: true,
|
|
96
115
|
});
|
|
97
|
-
// 场景对象
|
|
98
116
|
const scene = new Scene();
|
|
99
|
-
// 给模型覆盖一层颜色 后处理通道
|
|
100
117
|
export default function cover_pass(renderer, camera, object3d, baseDepthTexture, devicePixelRatio) {
|
|
101
|
-
const { cover_enable = false, cover_color = "#04fa12", cover_opacity = 1, cover_depth_test = true,
|
|
102
|
-
} = object3d.userData;
|
|
118
|
+
const { cover_enable = false, cover_color = "#04fa12", cover_opacity = 1, cover_depth_test = true, } = object3d.userData;
|
|
103
119
|
if (!cover_enable || cover_opacity === 0) {
|
|
104
120
|
return;
|
|
105
121
|
}
|
|
106
|
-
// 保存原帧缓冲区
|
|
107
122
|
const originRenderTarget = renderer.getRenderTarget();
|
|
108
|
-
//
|
|
123
|
+
// 灰度图渲染目标跟随主画面尺寸(= width × effectiveRatio),与 baseRenderTarget 完全一致,
|
|
124
|
+
// 消除灰度图与主画面尺寸不一致导致的放大重采样摩尔纹
|
|
109
125
|
renderer.getSize(size);
|
|
110
126
|
size.multiplyScalar(devicePixelRatio);
|
|
111
127
|
selectTextureTarget.setSize(size.x, size.y);
|
|
112
|
-
|
|
128
|
+
selectDepthTextureTarget.setSize(size.x, size.y);
|
|
129
|
+
// 缺陷修复:three r167 的 WebGLRenderTarget.setSize 不会同步 depthTexture,
|
|
130
|
+
// 需手动把 selectDepthTexture 尺寸与全屏 baseDepth 对齐,否则深度比例错位导致颜色覆盖被错误 discard
|
|
131
|
+
selectDepthTexture.image.width = size.x;
|
|
132
|
+
selectDepthTexture.image.height = size.y;
|
|
133
|
+
selectDepthTexture.needsUpdate = true;
|
|
134
|
+
selectDepthTestTextureTarget.setSize(size.x, size.y);
|
|
113
135
|
blur1TextureTarget.setSize(size.x, size.y);
|
|
114
136
|
renderer.setRenderTarget(selectTextureTarget);
|
|
115
137
|
scene.children = [object3d];
|
|
116
138
|
renderer.clear();
|
|
117
139
|
renderer.render(scene, camera);
|
|
118
|
-
|
|
140
|
+
// 单独渲染对象深度到无 MSAA 目标,供 depthTestShader 做遮挡判定
|
|
141
|
+
renderer.setRenderTarget(selectDepthTextureTarget);
|
|
142
|
+
scene.children = [object3d];
|
|
143
|
+
renderer.clear();
|
|
144
|
+
renderer.render(scene, camera);
|
|
145
|
+
// 调试:记录选区深度,供面板「深度判定图 / 辉光深度比对」排查 cover 的遮挡判定
|
|
146
|
+
debugDepthState.lastSelectDepth = selectDepthTexture;
|
|
119
147
|
renderer.setRenderTarget(originRenderTarget);
|
|
120
148
|
renderer.clearDepth();
|
|
121
149
|
depthTestShader.uniforms.color.value.set(cover_color);
|
|
@@ -123,11 +151,6 @@ export default function cover_pass(renderer, camera, object3d, baseDepthTexture,
|
|
|
123
151
|
depthTestShader.uniforms.depthTest.value = cover_depth_test;
|
|
124
152
|
depthTestShader.uniforms.baseDepth.value = baseDepthTexture;
|
|
125
153
|
depthTestShader.uniforms.selectDepth.value = selectDepthTexture;
|
|
154
|
+
depthTestShader.uniforms.cameraFar.value = camera.far;
|
|
126
155
|
fsQuad.render(renderer, depthTestShader);
|
|
127
|
-
// 调试代码
|
|
128
|
-
// renderer.setRenderTarget(null);
|
|
129
|
-
// renderer.clearDepth();
|
|
130
|
-
// copyShader.uniforms.map.value = blur2TextureTarget.texture;
|
|
131
|
-
// fsQuad.render(renderer, copyShader);
|
|
132
|
-
// return;
|
|
133
156
|
}
|