s3m-three 0.4.18 → 0.4.20
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/dist/browser/assets/s3mWorker-DvAUA8NJ.js +1 -0
- package/dist/browser/s3m-three.iife.ext-three.js +619 -304
- package/dist/browser/s3m-three.iife.js +647 -332
- package/dist/core/Draco.d.ts.map +1 -1
- package/dist/core/Draco.js +0 -1
- package/dist/core/Draco.js.map +1 -1
- package/dist/core/GaussianSplat.d.ts +64 -0
- package/dist/core/GaussianSplat.d.ts.map +1 -0
- package/dist/core/GaussianSplat.js +139 -0
- package/dist/core/GaussianSplat.js.map +1 -0
- package/dist/core/S3M1Parser.d.ts +1 -1
- package/dist/core/S3M1Parser.d.ts.map +1 -1
- package/dist/core/S3M1Parser.js +320 -25
- package/dist/core/S3M1Parser.js.map +1 -1
- package/dist/core/S3MBParser.d.ts.map +1 -1
- package/dist/core/S3MBParser.js +13 -0
- package/dist/core/S3MBParser.js.map +1 -1
- package/dist/core/S3MBlockParser.d.ts.map +1 -1
- package/dist/core/S3MBlockParser.js +83 -28
- package/dist/core/S3MBlockParser.js.map +1 -1
- package/dist/core/SplatLod.d.ts +36 -0
- package/dist/core/SplatLod.d.ts.map +1 -0
- package/dist/core/SplatLod.js +54 -0
- package/dist/core/SplatLod.js.map +1 -0
- package/dist/core/SplatProjection.d.ts +75 -0
- package/dist/core/SplatProjection.d.ts.map +1 -0
- package/dist/core/SplatProjection.js +162 -0
- package/dist/core/SplatProjection.js.map +1 -0
- package/dist/core/SplatSort.d.ts +26 -0
- package/dist/core/SplatSort.d.ts.map +1 -0
- package/dist/core/SplatSort.js +61 -0
- package/dist/core/SplatSort.js.map +1 -0
- package/dist/core/TexCoordZ.d.ts +94 -0
- package/dist/core/TexCoordZ.d.ts.map +1 -0
- package/dist/core/TexCoordZ.js +125 -0
- package/dist/core/TexCoordZ.js.map +1 -0
- package/dist/core/TextureDecode.d.ts +19 -0
- package/dist/core/TextureDecode.d.ts.map +1 -1
- package/dist/core/TextureDecode.js +53 -11
- package/dist/core/TextureDecode.js.map +1 -1
- package/dist/core/TileGeometry.d.ts +39 -0
- package/dist/core/TileGeometry.d.ts.map +1 -1
- package/dist/core/TileGeometry.js +133 -14
- package/dist/core/TileGeometry.js.map +1 -1
- package/dist/core/degradations.d.ts +37 -0
- package/dist/core/degradations.d.ts.map +1 -0
- package/dist/core/degradations.js +32 -0
- package/dist/core/degradations.js.map +1 -0
- package/dist/core/types.d.ts +36 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/render/DatasetManager.d.ts +11 -0
- package/dist/render/DatasetManager.d.ts.map +1 -1
- package/dist/render/DatasetManager.js +2 -0
- package/dist/render/DatasetManager.js.map +1 -1
- package/dist/render/FeatureStyleManager.d.ts.map +1 -1
- package/dist/render/FeatureStyleManager.js +7 -5
- package/dist/render/FeatureStyleManager.js.map +1 -1
- package/dist/render/GeometryBuilder.d.ts +31 -0
- package/dist/render/GeometryBuilder.d.ts.map +1 -1
- package/dist/render/GeometryBuilder.js +229 -6
- package/dist/render/GeometryBuilder.js.map +1 -1
- package/dist/render/Picker.d.ts.map +1 -1
- package/dist/render/Picker.js +19 -5
- package/dist/render/Picker.js.map +1 -1
- package/dist/render/S3MViewer.d.ts +106 -379
- package/dist/render/S3MViewer.d.ts.map +1 -1
- package/dist/render/S3MViewer.js +324 -1494
- package/dist/render/S3MViewer.js.map +1 -1
- package/dist/render/SplatMaterial.d.ts +103 -0
- package/dist/render/SplatMaterial.d.ts.map +1 -0
- package/dist/render/SplatMaterial.js +388 -0
- package/dist/render/SplatMaterial.js.map +1 -0
- package/dist/render/SplatSorter.d.ts +14 -0
- package/dist/render/SplatSorter.d.ts.map +1 -0
- package/dist/render/SplatSorter.js +66 -0
- package/dist/render/SplatSorter.js.map +1 -0
- package/dist/render/StyleMaterial.d.ts +48 -0
- package/dist/render/StyleMaterial.d.ts.map +1 -1
- package/dist/render/StyleMaterial.js +292 -69
- package/dist/render/StyleMaterial.js.map +1 -1
- package/dist/render/TextureFactory.d.ts +10 -0
- package/dist/render/TextureFactory.d.ts.map +1 -1
- package/dist/render/TextureFactory.js +35 -5
- package/dist/render/TextureFactory.js.map +1 -1
- package/dist/render/lightingPreset.d.ts +53 -0
- package/dist/render/lightingPreset.d.ts.map +1 -0
- package/dist/render/lightingPreset.js +36 -0
- package/dist/render/lightingPreset.js.map +1 -0
- package/dist/render/materialAlpha.d.ts +51 -0
- package/dist/render/materialAlpha.d.ts.map +1 -0
- package/dist/render/materialAlpha.js +68 -0
- package/dist/render/materialAlpha.js.map +1 -0
- package/dist/render/viewer/EdgeDecorator.d.ts +206 -0
- package/dist/render/viewer/EdgeDecorator.d.ts.map +1 -0
- package/dist/render/viewer/EdgeDecorator.js +628 -0
- package/dist/render/viewer/EdgeDecorator.js.map +1 -0
- package/dist/render/viewer/HeightIndex.d.ts +36 -0
- package/dist/render/viewer/HeightIndex.d.ts.map +1 -0
- package/dist/render/viewer/HeightIndex.js +98 -0
- package/dist/render/viewer/HeightIndex.js.map +1 -0
- package/dist/render/viewer/LightRig.d.ts +88 -0
- package/dist/render/viewer/LightRig.d.ts.map +1 -0
- package/dist/render/viewer/LightRig.js +229 -0
- package/dist/render/viewer/LightRig.js.map +1 -0
- package/dist/render/viewer/PickService.d.ts +109 -0
- package/dist/render/viewer/PickService.d.ts.map +1 -0
- package/dist/render/viewer/PickService.js +591 -0
- package/dist/render/viewer/PickService.js.map +1 -0
- package/dist/render/viewer/SelectionDecorator.d.ts +84 -0
- package/dist/render/viewer/SelectionDecorator.d.ts.map +1 -0
- package/dist/render/viewer/SelectionDecorator.js +339 -0
- package/dist/render/viewer/SelectionDecorator.js.map +1 -0
- package/dist/render/viewer/SplatLayer.d.ts +26 -0
- package/dist/render/viewer/SplatLayer.d.ts.map +1 -0
- package/dist/render/viewer/SplatLayer.js +44 -0
- package/dist/render/viewer/SplatLayer.js.map +1 -0
- package/dist/render/viewer/types.d.ts +250 -0
- package/dist/render/viewer/types.d.ts.map +1 -0
- package/dist/render/viewer/types.js +3 -0
- package/dist/render/viewer/types.js.map +1 -0
- package/dist/tileset/S3MTileset.d.ts +42 -1
- package/dist/tileset/S3MTileset.d.ts.map +1 -1
- package/dist/tileset/S3MTileset.js +52 -2
- package/dist/tileset/S3MTileset.js.map +1 -1
- package/dist/vendor/browser-node-stub.js +10 -0
- package/dist/worker/s3mWorker.js +1166 -979
- package/dist/worker/s3mWorker.js.map +1 -1
- package/docs/API.md +55 -1
- package/docs/FORMAT-NOTES.md +362 -0
- package/package.json +1 -1
- package/src/core/Draco.ts +1 -2
- package/src/core/GaussianSplat.ts +175 -0
- package/src/core/S3M1Parser.ts +330 -24
- package/src/core/S3MBParser.ts +18 -0
- package/src/core/S3MBlockParser.ts +83 -27
- package/src/core/SplatLod.ts +83 -0
- package/src/core/SplatProjection.ts +231 -0
- package/src/core/SplatSort.ts +92 -0
- package/src/core/TexCoordZ.ts +160 -0
- package/src/core/TextureDecode.ts +63 -11
- package/src/core/TileGeometry.ts +151 -14
- package/src/core/degradations.ts +74 -0
- package/src/core/types.ts +32 -0
- package/src/index.ts +8 -1
- package/src/render/DatasetManager.ts +10 -0
- package/src/render/FeatureStyleManager.ts +8 -6
- package/src/render/GeometryBuilder.ts +271 -7
- package/src/render/Picker.ts +21 -5
- package/src/render/S3MViewer.ts +358 -1727
- package/src/render/SplatMaterial.ts +433 -0
- package/src/render/SplatSorter.ts +66 -0
- package/src/render/StyleMaterial.ts +339 -69
- package/src/render/TextureFactory.ts +39 -5
- package/src/render/lightingPreset.ts +76 -0
- package/src/render/materialAlpha.ts +75 -0
- package/src/render/viewer/EdgeDecorator.ts +722 -0
- package/src/render/viewer/HeightIndex.ts +94 -0
- package/src/render/viewer/LightRig.ts +267 -0
- package/src/render/viewer/PickService.ts +651 -0
- package/src/render/viewer/SelectionDecorator.ts +377 -0
- package/src/render/viewer/SplatLayer.ts +44 -0
- package/src/render/viewer/types.ts +258 -0
- package/src/tileset/S3MTileset.ts +78 -2
- package/src/vendor/browser-node-stub.js +10 -0
- package/dist/browser/assets/s3mWorker-BjPOUgjg.js +0 -1
|
@@ -31,6 +31,16 @@ export function setMaxAnisotropy(n: number, cap = Infinity): void {
|
|
|
31
31
|
anisotropyCap = Number.isFinite(cap) && cap > 0 ? Math.max(1, cap) : Infinity;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
/**
|
|
35
|
+
* 单独调各向异性上限(只影响之后创建的纹理)。
|
|
36
|
+
* supermap 预设会设成 1 —— 官方 iClient3D 不开各向异性,斜视角直接采高 mip
|
|
37
|
+
* 平均成纯色;我们默认拉满(Infinity)是为了倾斜摄影立面清晰度,代价是
|
|
38
|
+
* 米制平铺纹理的远处高频纹(点阵/砖缝)被硬保下来,怎么调光照都"不像官方"。
|
|
39
|
+
*/
|
|
40
|
+
export function setAnisotropyCap(cap: number): void {
|
|
41
|
+
anisotropyCap = Number.isFinite(cap) && cap > 0 ? Math.max(1, cap) : Infinity;
|
|
42
|
+
}
|
|
43
|
+
|
|
34
44
|
/**
|
|
35
45
|
* 纹理长边像素上限(默认 Infinity = 不限制)。
|
|
36
46
|
* 只作用于非图集的 RGBA / WebP 产物,见 `core/TextureDecode.ts` 的 `maxSize`。
|
|
@@ -86,6 +96,24 @@ async function decodeTexture(
|
|
|
86
96
|
return decodeTextureData(tex, { compressed, maxSize });
|
|
87
97
|
}
|
|
88
98
|
|
|
99
|
+
/**
|
|
100
|
+
* 纹理是否做 sRGB→linear 解码。
|
|
101
|
+
*
|
|
102
|
+
* 默认 true(three 线性 PBR 管线的正确姿势)。`lightingPreset: 'supermap'` 会关掉它:
|
|
103
|
+
* 官方 iClient3D 把贴图字节值**不解码**直接进 shader、在 sRGB 数值空间做 Lambert 直乘,
|
|
104
|
+
* 要逐像素对齐就得让字节值原样进来(输出端由 StyleMaterial 的 S3M_DIRECT_COLOR 抵消)。
|
|
105
|
+
*/
|
|
106
|
+
let srgbTextureDecode = true;
|
|
107
|
+
|
|
108
|
+
/** 切换纹理解码(只影响之后创建的纹理,已上传 GPU 的不受影响) */
|
|
109
|
+
export function setSrgbTextureDecode(v: boolean): void {
|
|
110
|
+
srgbTextureDecode = v;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export function getSrgbTextureDecode(): boolean {
|
|
114
|
+
return srgbTextureDecode;
|
|
115
|
+
}
|
|
116
|
+
|
|
89
117
|
function configure<T extends THREE.Texture>(tex: T, srgb = true): T {
|
|
90
118
|
tex.wrapS = THREE.RepeatWrapping;
|
|
91
119
|
tex.wrapT = THREE.RepeatWrapping;
|
|
@@ -94,7 +122,7 @@ function configure<T extends THREE.Texture>(tex: T, srgb = true): T {
|
|
|
94
122
|
tex.generateMipmaps = true;
|
|
95
123
|
// 各向异性过滤对斜视角立面清晰度的提升比提高分辨率更直接
|
|
96
124
|
tex.anisotropy = anisotropyCap === Infinity ? maxAnisotropy : Math.min(maxAnisotropy, anisotropyCap);
|
|
97
|
-
if (srgb) tex.colorSpace = THREE.SRGBColorSpace;
|
|
125
|
+
if (srgb && srgbTextureDecode) tex.colorSpace = THREE.SRGBColorSpace;
|
|
98
126
|
tex.flipY = false;
|
|
99
127
|
tex.needsUpdate = true;
|
|
100
128
|
return tex;
|
|
@@ -145,12 +173,16 @@ export async function createTexture(tex: S3MTexture | null | undefined): Promise
|
|
|
145
173
|
texture = new THREE.Texture(data.bitmap);
|
|
146
174
|
} else if (data.blocks && data.blockFormat) {
|
|
147
175
|
// DXT 块直传:GPU 硬件解压,省 4~8 倍上传带宽与显存。压缩纹理不能 generateMipmaps
|
|
148
|
-
// (WebGL
|
|
149
|
-
//
|
|
176
|
+
// (WebGL 限制)——所以**数据自带的内联 mip 链**(官方 iClient3D 逐层上传的那条)
|
|
177
|
+
// 必须切出来一起传,否则远处只有 level0 可采,高频纹/点阵全保留,永远"糊"不出
|
|
178
|
+
// 官方那种平均色;s3mHasAlpha 走 alphaTest 的 DXT1 1bit alpha 历史上没开过,
|
|
179
|
+
// DXT5 的 hasAlpha 由 decodeTextureData 判定
|
|
150
180
|
const format =
|
|
151
181
|
data.blockFormat === 'dxt1' ? THREE.RGB_S3TC_DXT1_Format : THREE.RGBA_S3TC_DXT5_Format;
|
|
152
182
|
texture = new THREE.CompressedTexture(
|
|
153
|
-
|
|
183
|
+
data.mipmaps && data.mipmaps.length > 1
|
|
184
|
+
? data.mipmaps.map((m) => ({ data: m.data, width: m.width, height: m.height }))
|
|
185
|
+
: [{ data: data.blocks, width: data.width, height: data.height }],
|
|
154
186
|
data.width,
|
|
155
187
|
data.height,
|
|
156
188
|
format,
|
|
@@ -165,7 +197,9 @@ export async function createTexture(tex: S3MTexture | null | undefined): Promise
|
|
|
165
197
|
const configured = isAtlas ? configureAtlas(texture) : configure(texture);
|
|
166
198
|
if (data.blocks) {
|
|
167
199
|
configured.generateMipmaps = false;
|
|
168
|
-
|
|
200
|
+
// 带链 → 三线性取链上高层级(官方同款平均效果);纯 level0 才退回 Linear 兜底
|
|
201
|
+
configured.minFilter =
|
|
202
|
+
data.mipmaps && data.mipmaps.length > 1 ? THREE.LinearMipmapLinearFilter : THREE.LinearFilter;
|
|
169
203
|
}
|
|
170
204
|
// flipY 为真即 S3MBLOCK 图集(见 core/types.ts),必须无 mip
|
|
171
205
|
return { texture: configured, decoded: data.kind };
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 光照预设。
|
|
3
|
+
*
|
|
4
|
+
* 默认那套(ambient 0.4 / hemi 0.8 / key 1.0 / fill 0.35)是为「线性 PBR 管线」
|
|
5
|
+
* 调的,亮部线性总量约 2.55。超图官方 iClient3D 走的是完全不同的着色模型
|
|
6
|
+
* (`S3MTiles/Shaders/S3MTilesFS.js`):
|
|
7
|
+
*
|
|
8
|
+
* ```glsl
|
|
9
|
+
* const vec3 SunLightColor = vec3(0.8);
|
|
10
|
+
* const vec3 AmbientLightColor = vec3(0.7);
|
|
11
|
+
* return uDiffuseColor.rgb * (SunLightColor * max(dot(n, L), 0.0) + AmbientLightColor * uAmbientColor.rgb);
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* 也就是**在 sRGB 数值空间里直接做 Lambert**,因子范围 0.7 ~ 1.5,没有 gamma 编码、
|
|
15
|
+
* 没有 tonemap。我们在线性空间乘、最后再做 linear→sRGB,同一个中间灰(sRGB 0.5):
|
|
16
|
+
*
|
|
17
|
+
* | | 官方 | 我们(默认) |
|
|
18
|
+
* |---|---|---|
|
|
19
|
+
* | 背光 | 0.5 × 0.7 = 0.35 | (0.214 × 0.8)^(1/2.2) ≈ 0.455 |
|
|
20
|
+
* | 受光 | 0.5 × 1.5 = 0.75 | (0.214 × 2.55)^(1/2.2) ≈ 0.76 |
|
|
21
|
+
*
|
|
22
|
+
* 暗部被 gamma 抬亮 30%,动态范围被压到 0.7~1.0,于是「发灰、饱和度低」。
|
|
23
|
+
*
|
|
24
|
+
* `'supermap'` 预设把线性光照总量重新压到与官方 sRGB 因子等效的区间:
|
|
25
|
+
* 0.7^2.2 ≈ 0.46(背光)到 1.5^2.2 ≈ 2.44(受光)。这不是逐像素复刻官方的
|
|
26
|
+
* sRGB 直乘(那需要放弃 PBR、改 `outputColorSpace = LinearSRGB`),
|
|
27
|
+
* 而是只动光源、可逆、不碰材质。
|
|
28
|
+
*/
|
|
29
|
+
export type LightingPreset = 'default' | 'supermap';
|
|
30
|
+
|
|
31
|
+
export interface PresetLightIntensities {
|
|
32
|
+
ambientIntensity: number;
|
|
33
|
+
hemisphereIntensity: number;
|
|
34
|
+
keyLightIntensity: number;
|
|
35
|
+
fillLightIntensity: number;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** 现有默认值,一字节不改 */
|
|
39
|
+
export const DEFAULT_LIGHT_PRESET: PresetLightIntensities = {
|
|
40
|
+
ambientIntensity: 0.4,
|
|
41
|
+
hemisphereIntensity: 0.8,
|
|
42
|
+
keyLightIntensity: 1.0,
|
|
43
|
+
fillLightIntensity: 0.35,
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* 对齐官方观感:几乎只留平行光 + 极低环境光。
|
|
48
|
+
*
|
|
49
|
+
* 背光总和 = 0.12 + 0.20 + 0.15 = 0.47(≈ 0.7^2.2)
|
|
50
|
+
* 受光总和 = 0.47 + 1.95 = 2.42(≈ 1.5^2.2)
|
|
51
|
+
*/
|
|
52
|
+
export const SUPERMAP_LIGHT_PRESET: PresetLightIntensities = {
|
|
53
|
+
ambientIntensity: 0.12,
|
|
54
|
+
hemisphereIntensity: 0.2,
|
|
55
|
+
keyLightIntensity: 1.95,
|
|
56
|
+
fillLightIntensity: 0.15,
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export const LIGHT_PRESETS: Record<LightingPreset, PresetLightIntensities> = {
|
|
60
|
+
default: DEFAULT_LIGHT_PRESET,
|
|
61
|
+
supermap: SUPERMAP_LIGHT_PRESET,
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
/** 预设名 → 强度组合;未知值回落默认,避免拼错名字把场景变全黑 */
|
|
65
|
+
export function resolveLightingPreset(preset?: string | null): PresetLightIntensities {
|
|
66
|
+
if (preset && Object.prototype.hasOwnProperty.call(LIGHT_PRESETS, preset)) {
|
|
67
|
+
return LIGHT_PRESETS[preset as LightingPreset];
|
|
68
|
+
}
|
|
69
|
+
return DEFAULT_LIGHT_PRESET;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** 线性总辐照度(供测试与调试:受光面 / 背光面) */
|
|
73
|
+
export function presetLinearRange(p: PresetLightIntensities): { shadow: number; lit: number } {
|
|
74
|
+
const shadow = p.ambientIntensity + p.hemisphereIntensity + p.fillLightIntensity;
|
|
75
|
+
return { shadow, lit: shadow + p.keyLightIntensity };
|
|
76
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* S3MB 材质透明判定。
|
|
3
|
+
*
|
|
4
|
+
* 官方把 alphaMode 定义成三个**小写**枚举(`S3MTiles/Enum/AlphaMode.js`):
|
|
5
|
+
* ```
|
|
6
|
+
* OPAQUE: 'opaque' BLEND: 'blend' MASK: 'mask'
|
|
7
|
+
* ```
|
|
8
|
+
* 而 S3M 规范文档里写的是 `AM_OPAQUE / AM_BLEND / AM_MASK`。线上数据用的是前者
|
|
9
|
+
* (`3D-BIMbuilding-2` 的 `WhiteMaterial_1` 就是 `"alphaMode": "blend"`),
|
|
10
|
+
* 所以两种写法都要认,否则 blend 材质会被当成不透明 —— 表现就是「透明度不见了」。
|
|
11
|
+
*
|
|
12
|
+
* 另外还有一条官方没写进规范、但数据里真实存在的透明度来源:**顶点色 alpha**。
|
|
13
|
+
* SMID 4421 的材质无纹理、`diffuse.a = 1`,顶点色是 u8 `(0,128,192,63)`,
|
|
14
|
+
* 也就是 alpha ≈ 0.247。官方片元 `outColor = baseColorWithAlpha * uDiffuseColor`
|
|
15
|
+
* 里 `baseColorWithAlpha = vColor`(vec4),alpha 就靠这条路传下去。
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
export type S3MAlphaMode = 'opaque' | 'blend' | 'mask';
|
|
19
|
+
|
|
20
|
+
/** 归一化 alphaMode:兼容小写枚举与规范里的 `AM_` 前缀,未知值一律按不透明处理 */
|
|
21
|
+
export function resolveAlphaMode(raw: unknown): S3MAlphaMode {
|
|
22
|
+
const s = String(raw ?? '').trim().toLowerCase().replace(/^am_/, '');
|
|
23
|
+
return s === 'blend' || s === 'mask' ? s : 'opaque';
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface MaterialAlphaInput {
|
|
27
|
+
/** 材质原始 alphaMode('blend' / 'AM_BLEND' / 'mask' / 'opaque' …) */
|
|
28
|
+
alphaMode?: unknown;
|
|
29
|
+
/** 材质 diffuse.a,缺省视为 1 */
|
|
30
|
+
diffuseAlpha?: number;
|
|
31
|
+
/** 材质 transparentsorting(配置开启透明度优化时官方也按透明处理) */
|
|
32
|
+
transparentSorting?: boolean;
|
|
33
|
+
/** 该几何顶点色 alpha 的最小值:<1 说明有半透明顶点 */
|
|
34
|
+
vertexAlphaMin?: number;
|
|
35
|
+
/** 内置水面材质且块里没有像素(我们自己的兜底上色) */
|
|
36
|
+
isWaterWithoutMap?: boolean;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* 是否走透明(alpha 混合)管线。
|
|
41
|
+
*
|
|
42
|
+
* - `blend`:官方 `isTransparent = true`,进 TRANSLUCENT pass;
|
|
43
|
+
* - `mask`:官方也算透明,但它是**镂空**语义(alphaTest)。我们保持不透明队列 +
|
|
44
|
+
* alphaTest,否则树叶/栏杆之间会因 `depthWrite: false` 互相穿透;
|
|
45
|
+
* - 顶点色 alpha < 1:4421 这类"材质不透明但顶点半透明"的数据必须走混合。
|
|
46
|
+
*/
|
|
47
|
+
export function isTransparentMaterial(input: MaterialAlphaInput): boolean {
|
|
48
|
+
const mode = resolveAlphaMode(input.alphaMode);
|
|
49
|
+
if (mode === 'blend') return true;
|
|
50
|
+
if (mode === 'mask') return false;
|
|
51
|
+
if (input.transparentSorting === true) return true;
|
|
52
|
+
if (input.isWaterWithoutMap === true) return true;
|
|
53
|
+
if ((input.diffuseAlpha ?? 1) < 0.999) return true;
|
|
54
|
+
if ((input.vertexAlphaMin ?? 1) < 0.999) return true;
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* 顶点色 alpha 的最小值:材质要不要开混合,取决于这块几何里有没有半透明顶点。
|
|
60
|
+
*
|
|
61
|
+
* 顶点数在几千到几万量级,一次线性扫描即可;只在建材质时算一次(每个 primitive 一次)。
|
|
62
|
+
* 没有 alpha 分量(老数据的 RGB)按 1 处理 —— 不能因为读不到就当成 0,那会整片全透明。
|
|
63
|
+
*/
|
|
64
|
+
export function minVertexAlpha(color: { array: ArrayLike<number>; components?: number } | undefined): number {
|
|
65
|
+
if (!color || !color.array || color.array.length === 0) return 1;
|
|
66
|
+
const comp = color.components ?? 4;
|
|
67
|
+
if (comp < 4) return 1;
|
|
68
|
+
let min = 1;
|
|
69
|
+
for (let i = 3; i < color.array.length; i += comp) {
|
|
70
|
+
const a = color.array[i]!;
|
|
71
|
+
if (a < min) min = a;
|
|
72
|
+
if (min <= 0.999) return min; // 已经确定要透明,提前退出
|
|
73
|
+
}
|
|
74
|
+
return min;
|
|
75
|
+
}
|