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.
- package/FPScontrol.d.ts +55 -30
- package/FPScontrol.js +278 -225
- package/FPScontrol.ts +177 -127
- package/Ground1/Ground1.d.ts +4 -2
- package/Ground1/Ground1.js +77 -57
- package/Ground1/Ground1.ts +77 -57
- package/Mirror.js +0 -4
- package/Mirror.ts +0 -4
- package/MktMesh/MktMesh.d.ts +8 -3
- package/MktMesh/MktMesh.js +43 -14
- package/MktMesh/MktMesh.ts +40 -14
- package/MktMesh/mktMappingShader.d.ts +6 -5
- package/MktMesh/mktMappingShader.js +26 -19
- package/MktMesh/mktMappingShader.ts +28 -19
- package/MktMesh/mktShader.d.ts +127 -58
- package/MktMesh/mktShader.js +192 -117
- package/MktMesh/mktShader.ts +251 -127
- package/MktMesh/panoSlotRoster.d.ts +2 -2
- package/MktMesh/panoSlotRoster.js +9 -7
- package/MktMesh/panoSlotRoster.ts +9 -7
- package/MktMesh/panoTileStitcher.d.ts +20 -13
- package/MktMesh/panoTileStitcher.js +97 -76
- package/MktMesh/panoTileStitcher.ts +119 -90
- package/MktMesh/types.d.ts +5 -1
- package/MktMesh/types.ts +5 -1
- package/PipeMesh/PipeJoint.d.ts +22 -0
- package/PipeMesh/PipeJoint.js +33 -0
- package/PipeMesh/PipeJoint.ts +38 -0
- package/PipeMesh/PipeMesh.d.ts +94 -22
- package/PipeMesh/PipeMesh.js +192 -53
- package/PipeMesh/PipeMesh.ts +223 -76
- package/PipeMesh/PipeStraight.d.ts +19 -0
- package/PipeMesh/PipeStraight.js +34 -0
- package/PipeMesh/PipeStraight.ts +45 -0
- package/PipeMesh/axisSnap.d.ts +52 -0
- package/PipeMesh/axisSnap.js +52 -0
- package/PipeMesh/axisSnap.ts +93 -0
- package/PipeMesh/directRoute.d.ts +85 -0
- package/PipeMesh/directRoute.js +126 -0
- package/PipeMesh/directRoute.ts +190 -0
- package/PipeMesh/index.d.ts +6 -0
- package/PipeMesh/index.js +6 -0
- package/PipeMesh/index.ts +7 -1
- package/PipeMesh/pipeMaterial.d.ts +16 -0
- package/PipeMesh/pipeMaterial.js +23 -0
- package/PipeMesh/pipeMaterial.ts +26 -0
- package/ThreeBase.d.ts +2 -49
- package/ThreeBase.js +43 -164
- package/ThreeBase.ts +1176 -1314
- package/instanced/InstancedBatch.d.ts +14 -1
- package/instanced/InstancedBatch.js +53 -3
- package/instanced/InstancedBatch.ts +62 -3
- package/instanced/InstancedChild.d.ts +24 -0
- package/instanced/InstancedChild.js +40 -0
- package/instanced/InstancedChild.ts +41 -0
- package/instanced/InstancedGroup.d.ts +48 -0
- package/instanced/InstancedGroup.js +45 -1
- package/instanced/InstancedGroup.ts +85 -0
- package/package.json +2 -7
- package/pass/bloom_pass.js +7 -14
- package/pass/bloom_pass.ts +7 -16
- package/pass/cover_pass.js +7 -15
- package/pass/cover_pass.ts +7 -17
- package/pass/debugDepthState.d.ts +16 -8
- package/pass/debugDepthState.js +4 -0
- package/pass/debugDepthState.ts +27 -9
- package/pass/glow_pass.js +19 -110
- package/pass/glow_pass.ts +19 -115
- package/pass/ssao_pass.d.ts +14 -59
- package/pass/ssao_pass.js +66 -171
- package/pass/ssao_pass.ts +63 -207
- package/pass/stroke_pass.js +13 -16
- package/pass/stroke_pass.ts +14 -18
- package/shaders/baseDepthVisShader.d.ts +1 -1
- package/shaders/baseDepthVisShader.js +1 -1
- package/shaders/baseDepthVisShader.ts +1 -1
- package/shaders/debugDepthCompareShader.d.ts +2 -2
- package/shaders/debugDepthCompareShader.js +2 -2
- package/shaders/debugDepthCompareShader.ts +2 -2
- package/shaders/debugDepthJudgeShader.d.ts +1 -1
- package/shaders/debugDepthJudgeShader.js +1 -1
- package/shaders/debugDepthJudgeShader.ts +1 -1
- package/PipeMesh/PathGeometry.d.ts +0 -44
- package/PipeMesh/PathGeometry.js +0 -307
- package/PipeMesh/PathGeometry.ts +0 -343
- package/PipeMesh/PathPoint.d.ts +0 -17
- package/PipeMesh/PathPoint.js +0 -31
- package/PipeMesh/PathPoint.ts +0 -36
- package/PipeMesh/PathPointList.d.ts +0 -31
- package/PipeMesh/PathPointList.js +0 -209
- package/PipeMesh/PathPointList.ts +0 -227
- package/PipeMesh/PathTubeGeometry.d.ts +0 -25
- package/PipeMesh/PathTubeGeometry.js +0 -130
- package/PipeMesh/PathTubeGeometry.ts +0 -146
- package/WaterFlow/FloatingDuck.d.ts +0 -88
- package/WaterFlow/FloatingDuck.js +0 -307
- package/WaterFlow/FloatingDuck.ts +0 -445
- package/WaterFlow/GPUFluidSimulation.d.ts +0 -56
- package/WaterFlow/GPUFluidSimulation.js +0 -785
- package/WaterFlow/GPUFluidSimulation.ts +0 -827
- package/WaterFlow/ReservoirSystem.d.ts +0 -106
- package/WaterFlow/ReservoirSystem.js +0 -621
- package/WaterFlow/ReservoirSystem.ts +0 -754
- package/WaterFlow/SPHField.d.ts +0 -35
- package/WaterFlow/SPHField.js +0 -204
- package/WaterFlow/SPHField.ts +0 -228
- package/WaterFlow/ScreenSpaceFluidPass.d.ts +0 -69
- package/WaterFlow/ScreenSpaceFluidPass.js +0 -736
- package/WaterFlow/ScreenSpaceFluidPass.ts +0 -789
- package/WaterFlow/ShallowWaterSurface.d.ts +0 -45
- package/WaterFlow/ShallowWaterSurface.js +0 -441
- package/WaterFlow/ShallowWaterSurface.ts +0 -510
- package/WaterFlow/WaterFlow.d.ts +0 -87
- package/WaterFlow/WaterFlow.js +0 -171
- package/WaterFlow/WaterFlow.ts +0 -219
- package/WaterFlow/types.d.ts +0 -161
- package/WaterFlow/types.js +0 -1
- package/WaterFlow/types.ts +0 -189
- package/WaterFlow/waterFlowPass.d.ts +0 -3
- package/WaterFlow/waterFlowPass.js +0 -20
- package/WaterFlow/waterFlowPass.ts +0 -40
- package/shaders/debugExcludedShader.d.ts +0 -13
- package/shaders/debugExcludedShader.js +0 -46
- package/shaders/debugExcludedShader.ts +0 -48
package/MktMesh/MktMesh.ts
CHANGED
|
@@ -130,8 +130,9 @@ export default class MktMesh extends Mesh<BufferGeometry, ShaderMaterial> {
|
|
|
130
130
|
* ⇒ 与编辑态 `mktMeshEditRenderer._slotPanos` **同一份算法、同一个常数**(预览看到的那几张 = 编辑器里的那几张,均为 8 个全景槽)。
|
|
131
131
|
* 存**对象引用**不存下标(删点会让下标整体前移,引用不会认错人)。
|
|
132
132
|
* 消费方 = `feedFaceMapping`(墙 8 格);⭐ 10-03 旨② 后预览立方体与墙**共用同一份材质**,
|
|
133
|
-
*
|
|
134
|
-
*
|
|
133
|
+
* ⭐ 10-12 旨后立方体**逐颗自带序号**(`InstancedChild.panoIndex` → 逐实例 `aPanoIndex`),
|
|
134
|
+
* 不再是从前那句「几何没这条 attribute ⇒ `vPanoIndex ≡ 0` ⇒ 全体看 0 号槽那张」;
|
|
135
|
+
* 原来那条「把中心那几张抄给立方体单全景材质」的 `currentTiles` 旁路已整条删除。
|
|
135
136
|
*/
|
|
136
137
|
private _slotPanos: (MktTextureInfo | undefined)[] = [];
|
|
137
138
|
/**
|
|
@@ -141,9 +142,13 @@ export default class MktMesh extends Mesh<BufferGeometry, ShaderMaterial> {
|
|
|
141
142
|
* · 只读 XZ ⇒ 与名册历代那把「水平距离」尺同一把(09-28 旨),高度差不进尺子。
|
|
142
143
|
* · `null` ⇒ 回落 `camera.position`(老口径):发布页那一路没有控制器引用,不注入就一切照旧。
|
|
143
144
|
* · 存的是**引用**(OrbitControls 原地改它那个 Vector3)⇒ 消费方设一次即可,不必每帧重设。
|
|
144
|
-
* ·
|
|
145
|
+
* · 注入的是**世界坐标**;`updateTexture` 里先 `worldToLocal` 换算到本网格局部空间再比距离
|
|
146
|
+
* (全景矩阵与着色器取图的 `vProjPos` 都在局部空间,见那里的 2026-10-11 丙旨说明)。
|
|
147
|
+
* ⛔ 反过来去给全景矩阵乘 `matrixWorld` 是错的:那会让 JS 侧的尺子和 shader 里的取图各走一路。
|
|
145
148
|
*/
|
|
146
149
|
private _rosterCenter: Vector3 | null = null;
|
|
150
|
+
/** 锚点换算到局部空间的落点(每帧复用同一只临时量,避免分配) */
|
|
151
|
+
private _rosterAnchorLocal: Vector3 = new Vector3();
|
|
147
152
|
/**
|
|
148
153
|
* ⭐ 皇上旨 2026-10-03「整套搬进库(彻底同源)」:库侧不再自养「按全景序号取整槽、齐活才写」那一路,
|
|
149
154
|
* 改成与编辑态**同一份换绑策略**(`./panoSlotBind`)+ 同一口径的三张表:
|
|
@@ -716,15 +721,21 @@ export default class MktMesh extends Mesh<BufferGeometry, ShaderMaterial> {
|
|
|
716
721
|
this.activeIndex = -1;
|
|
717
722
|
return;
|
|
718
723
|
}
|
|
719
|
-
|
|
724
|
+
// ⭐ 皇上旨 2026-10-11 丙:尺子的两端必须落在**同一个空间**。注入的锚点是世界坐标,而下面那把尺子量的
|
|
725
|
+
// 全景位置记在本网格的**局部(制图)空间** —— 依据是着色器自己:`vProjPos = uProjInvMatrix·modelMatrix·pos`
|
|
726
|
+
// = M⁻¹·M·pos = 局部(`uProjInvMatrix` 正是 `syncProjInvMatrix` 里那句 `matrixWorld` 求逆),片元再拿
|
|
727
|
+
// `dir = vProjPos - tm[3].xyz` 取图 ⇒ 全景矩阵只可能和 `vProjPos` 同空间,即局部。
|
|
728
|
+
// 所以换算放在**锚点这一端**(`worldToLocal`),⛔ 不去给全景矩阵乘 `matrixWorld`:那是把 JS 的尺子
|
|
729
|
+
// 和 shader 的取图拆成两路。网格无变换时这一步是恒等 ⇒ 老项目逐字不变;有旋转时(消费方给 mkt 加了
|
|
730
|
+
// `rotation.y`)原来会把「往世界的某一头走」量成「往局部的另一头走」,人走到位了名册还不动。
|
|
731
|
+
const ref = this._rosterAnchorLocal.copy(this._rosterCenter ?? camera.position);
|
|
732
|
+
this.worldToLocal(ref);
|
|
720
733
|
const dists: { t: MktTextureInfo; d: number }[] = [];
|
|
721
734
|
for (let i = 0; i < n; i++) {
|
|
722
735
|
const e = this.textures[i].matrix.elements;
|
|
723
736
|
this._tmpV3.set(e[12], e[13], e[14]);
|
|
724
|
-
// ⚠️
|
|
725
|
-
//
|
|
726
|
-
// MktMesh 一有整体变换就会算错「离锚点最近的是哪张」(选错全景)。
|
|
727
|
-
// (2026-09-19 曾误以为它记在模型空间而多乘了一次,趁 MktDevMesh 对齐时一并纠正。)
|
|
737
|
+
// ⚠️ 全景点矩阵记在本网格的局部空间(与 `wallPoints` 同一空间,见上面丙旨那段着色器推导),
|
|
738
|
+
// 所以拿来直接和**已换算到局部**的 `ref` 比距离;⛔ 这里绝不乘 `matrixWorld`(双重变换 = 选错全景)。
|
|
728
739
|
// ⭐ 09-28 09:33 旨:挑图与编辑器取图同一把「**水平距离**」尺(XZ 平面,不含高度差)。
|
|
729
740
|
// const d = this._tmpV3.distanceTo(camera.position); // 旧原理:三维直线距离——全景点同高(y 恒 1.6)时与本式排序等价,注释保留备查
|
|
730
741
|
// ⭐ 10-07 第二十一道旨:尺子的另一端从相机位置换成 `ref`(控制器中心点;未注入时它就是相机位置)。
|
|
@@ -823,6 +834,9 @@ export default class MktMesh extends Mesh<BufferGeometry, ShaderMaterial> {
|
|
|
823
834
|
* ⭐ `rt:` 虚拟键(32 瓦片拼合槽)走拼合器 peek;⛔ 不在这里 pump(每帧驱动点唯一,见 `updateTexture`,
|
|
824
835
|
* 否则一帧画好几格 = 把「每帧只载入一张新纹理」那道闸从后门拆了)。 */
|
|
825
836
|
private _peekTileAt(key: string, original: boolean): Texture | null {
|
|
837
|
+
// ⭐ 2026-10-25:空地址 = 「这个点还没设图片」,不是一条能加载的 URL ⇒ 直接判没有。
|
|
838
|
+
// 放过去会让 ensureTileTexture 拿空串请求当前文档地址、失败后每帧重试。
|
|
839
|
+
if (!key) return null;
|
|
826
840
|
if (isRtStitchKey(key)) {
|
|
827
841
|
const p = rtStitchKeyParts(key);
|
|
828
842
|
if (!p) return null;
|
|
@@ -859,6 +873,8 @@ export default class MktMesh extends Mesh<BufferGeometry, ShaderMaterial> {
|
|
|
859
873
|
* ⚠️ 皇上旨 2026-09-28「加载瓦片的时候, 瓦片纹理不需要添加 oss 的参数」⇒ 真瓦片(`original=true`,现行 32 片/全景)走原图,
|
|
860
874
|
* 整图档才按 ossSize 档缩(`resolveOssUrl`)。 */
|
|
861
875
|
private ensureTileTexture(key: string, original = false): Texture | null {
|
|
876
|
+
// ⭐ 2026-10-25:空地址直接判「没有」,不起载(与编辑态 ensureFloorTexture 同一道闸)。
|
|
877
|
+
if (!key) return null;
|
|
862
878
|
const cached = this._texCache.get(key);
|
|
863
879
|
if (cached) return cached;
|
|
864
880
|
if (cached === null) return null; // 加载中
|
|
@@ -905,8 +921,9 @@ export default class MktMesh extends Mesh<BufferGeometry, ShaderMaterial> {
|
|
|
905
921
|
// `_glRenderer` 还没被 `onBeforeRender` 捕获到(构造后尚未渲染过一帧)⇒ 跳过预上传,
|
|
906
922
|
// 交给 three 在绑定那一帧自己上传 —— 那是改造前的老路径,不会报错,只是那一张没享受「错峰」。
|
|
907
923
|
if (this._glRenderer) this._glRenderer.initTexture(tex);
|
|
908
|
-
} catch
|
|
909
|
-
|
|
924
|
+
} catch {
|
|
925
|
+
// 皇上旨 2026-10-12「日志都去掉」⇒ 这里不再出声;降级路径本身不变(下面照记「已处理」,
|
|
926
|
+
// 最坏退回 three 在绑定那一帧自己上传的老路径)。
|
|
910
927
|
}
|
|
911
928
|
// ⚠️ 成败都记「已处理」。不记 ⇒ 这张永远进不了 `_texUploaded` ⇒ 那一格永远换不上新图,
|
|
912
929
|
// 比「卡一下」严重得多;记了最坏也只是退回 three 在绑定那一帧自己上传的老路径。
|
|
@@ -949,6 +966,17 @@ export default class MktMesh extends Mesh<BufferGeometry, ShaderMaterial> {
|
|
|
949
966
|
continue;
|
|
950
967
|
}
|
|
951
968
|
idxU[s] = this.textures.indexOf(info);
|
|
969
|
+
// ⭐ 2026-10-25 皇上旨「把默认图去掉,图片没有加载的时候就显示纯灰色」:
|
|
970
|
+
// 这个点**没设图片**(url 空且没有切片)⇒ 按空槽喂料,权重 0 ⇒ 片元回落 uFaceMissingColor 中性灰。
|
|
971
|
+
// ⛔ 别把空地址放下去:空 key 会走到 `_peekTileAt` → `ensureTileTexture("")` 发一次空请求
|
|
972
|
+
// (解析成当前文档地址),失败后下一帧再试 = 每帧一个废请求。序号照留(归属还在,只是没图)。
|
|
973
|
+
const hasSource = !!info.url || !!(info.tiles && info.tiles.length > 0);
|
|
974
|
+
if (!hasSource) {
|
|
975
|
+
for (let k = 0; k < RT_STITCH_SLOT_COUNT; k++) panos[base + k] = this._placeholder;
|
|
976
|
+
mats[s].identity();
|
|
977
|
+
ws[s] = 0;
|
|
978
|
+
continue;
|
|
979
|
+
}
|
|
952
980
|
// 各槽喂什么地址 = 「用户选的形态 + 该点有没有切过片」共同决定(whole 或无 tiles ⇒ 各槽同为一张整图)
|
|
953
981
|
const tiles = mktPanoTexUrls(info.url, info.tiles, this._panoTexMode);
|
|
954
982
|
// ⚠️ 「是不是真瓦片」只算一次:喂地址(走不走 OSS 尺寸档)与写 uPanoTiled 共用同一个值
|
|
@@ -1065,12 +1093,10 @@ export default class MktMesh extends Mesh<BufferGeometry, ShaderMaterial> {
|
|
|
1065
1093
|
// setWallPoints 已按位置重算过映射(旧为空 → 全 -1),此处用存档里的逐面指派覆盖。
|
|
1066
1094
|
// 几何拓扑由同一份 wallPoints 重建,面索引与导出时一致 ⇒ 逐面写入即可对齐。
|
|
1067
1095
|
// ⭐ 皇上旨 2026-10-03「补」:长度不符**不再整份丢弃**——按较小长度逐面灌回(存档多出的面丢掉,
|
|
1068
|
-
// 墙变长多出来的那些面保持 setWallPoints
|
|
1096
|
+
// 墙变长多出来的那些面保持 setWallPoints 按位置继承到的值)。
|
|
1097
|
+
// 2026-10-12 旨「日志都去掉」⇒ 这一条不再 warn,差值只按较小者静默还原。
|
|
1069
1098
|
const imported = (data.panoFaceMapping && data.panoFaceMapping.length ? data.panoFaceMapping : []) as number[];
|
|
1070
1099
|
const faceCount = this.panoFaceMapping.length;
|
|
1071
|
-
if (imported.length && imported.length !== faceCount) {
|
|
1072
|
-
console.warn(`[MktMesh] 存档序号映射面数 ${imported.length} ≠ 当前墙体面数 ${faceCount},按较小者逐面还原(差值来自墙点/墙高变化)`);
|
|
1073
|
-
}
|
|
1074
1100
|
const restore = Math.min(imported.length, faceCount);
|
|
1075
1101
|
if (restore > 0) {
|
|
1076
1102
|
for (let f = 0; f < restore; f++) this.panoFaceMapping[f] = imported[f];
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
import { ShaderMaterial } from "three";
|
|
2
2
|
/**
|
|
3
|
-
* ⭐
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
* ⭐ 融合材质的全景点数**上限**:每点占 **3** 张拼合槽纹理(皇上旨 2026-10-23「全景的 RT 由原来的 2 个分成 3 个、
|
|
4
|
+
* 每个 4096×6144、竖直排列 3 个瓦片」⇒ 原图切 3×3=9 片,按**列**分 3 槽)⇒ 点数 × 3 必须 ≤ sampler 硬顶。
|
|
5
|
+
* 本机 `MAX_TEXTURE_IMAGE_UNITS` 实测 **16**:旧版 8 点 × 2 槽 = 16 正好用满,现每点 3 槽 ⇒ 只能取 ⌊16/3⌋ = **5**
|
|
6
|
+
* (5 × 3 = 15)。皇上旨 2026-10-23 在「A」里拍板:保 3 槽不降画质,**同屏全景点数 8 → 5**。
|
|
6
7
|
*
|
|
7
8
|
* ⭐⭐ 2026-10-09 皇上旨「MktMesh 只有映射一种,blend/selected 归编辑器」⇒ 该常量从 `mktShader.ts`
|
|
8
9
|
* **搬到这里**(映射材质的所在地)。它同时是库与编辑器那份 blend 的**共同上限**,两边必须同值。
|
|
9
10
|
*/
|
|
10
|
-
export declare const MKT_PANO_MAX_SLOTS =
|
|
11
|
+
export declare const MKT_PANO_MAX_SLOTS = 5;
|
|
11
12
|
/**
|
|
12
13
|
* 创建「全景序号直取」着色器材质(皇上旨 2026-09-29「三模式三 shader」之二):
|
|
13
14
|
* 编辑器「映射设置模式」的墙材质 + **基类 MktMesh(发布/预览)的固定墙材质**
|
|
14
15
|
* (皇上旨:mktmesh 就只有按照 attribute 配置来显示全景这一种固定的 shader)。
|
|
15
|
-
* uniform 形状与 blend 工厂同档(panoramas[
|
|
16
|
+
* uniform 形状与 blend 工厂同档(panoramas[15]/textureMatrices[5]/weights[5]/uPanoTiled[5])⇒
|
|
16
17
|
* 喂料复用 feedBlendProjection 的槽位指派路(feedFaceMapping),零新喂料路。
|
|
17
18
|
* uFloorCoreRadius/uFloorFadeRange/uFloorOpacity 三根本 shader 不读,但喂料统一入口会写 ⇒ JS 侧留着(静默忽略)。
|
|
18
19
|
*/
|
|
@@ -8,33 +8,42 @@
|
|
|
8
8
|
import { BackSide, Matrix4, ShaderMaterial, Vector3 } from "three";
|
|
9
9
|
import { createPlaceholderTexture, floorVertexShader, RT_STITCH_SLOT_COUNT } from "./mktShader";
|
|
10
10
|
/**
|
|
11
|
-
* ⭐
|
|
12
|
-
*
|
|
13
|
-
*
|
|
11
|
+
* ⭐ 融合材质的全景点数**上限**:每点占 **3** 张拼合槽纹理(皇上旨 2026-10-23「全景的 RT 由原来的 2 个分成 3 个、
|
|
12
|
+
* 每个 4096×6144、竖直排列 3 个瓦片」⇒ 原图切 3×3=9 片,按**列**分 3 槽)⇒ 点数 × 3 必须 ≤ sampler 硬顶。
|
|
13
|
+
* 本机 `MAX_TEXTURE_IMAGE_UNITS` 实测 **16**:旧版 8 点 × 2 槽 = 16 正好用满,现每点 3 槽 ⇒ 只能取 ⌊16/3⌋ = **5**
|
|
14
|
+
* (5 × 3 = 15)。皇上旨 2026-10-23 在「A」里拍板:保 3 槽不降画质,**同屏全景点数 8 → 5**。
|
|
14
15
|
*
|
|
15
16
|
* ⭐⭐ 2026-10-09 皇上旨「MktMesh 只有映射一种,blend/selected 归编辑器」⇒ 该常量从 `mktShader.ts`
|
|
16
17
|
* **搬到这里**(映射材质的所在地)。它同时是库与编辑器那份 blend 的**共同上限**,两边必须同值。
|
|
17
18
|
*/
|
|
18
|
-
export const MKT_PANO_MAX_SLOTS =
|
|
19
|
+
export const MKT_PANO_MAX_SLOTS = 5;
|
|
19
20
|
/**
|
|
20
21
|
* 序号直取片元(皇上旨 2026-09-29「三模式三 shader」之二):
|
|
21
22
|
* 按三角面 aPanoIndex 在 panoIndices 槽里找对应全景纹理 —— **不看距离、不看夹角**(blend 那套打分/归约整段没有)。
|
|
22
|
-
* 槽内采样段(等距柱状投射 +
|
|
23
|
+
* 槽内采样段(等距柱状投射 + 左/中/右 3 张拼合槽 + 采样即线性、不再手动 pow 解码)与 blend **逐字同口径**;改采样口径两处同改。
|
|
23
24
|
* 未设序号 / 序号不在槽里 / 该槽瓦片没绑好(weights≤0)→ uFaceMissingColor 深灰兜底
|
|
24
25
|
* (皇上旨 09-28「装不下就深灰」;weights 闸是 09-29 拆分时补的 —— 原运行时分支没这道闸,
|
|
25
26
|
* 槽没绑好但序号命中会采到 vec3(0) 纯黑,深灰才是钦定兜底色)。
|
|
26
27
|
*/
|
|
27
28
|
function buildFloorMappingFragment(maxPano) {
|
|
28
|
-
// 每个全景点占 **
|
|
29
|
+
// 每个全景点占 **3** 张拼合槽纹理(9 片 3×3 按列分:左列 / 中列 / 右列,每槽竖叠 3 片)⇒ 5 × 3 = 15 ≤ sampler 硬顶 16
|
|
29
30
|
const tileCount = maxPano * RT_STITCH_SLOT_COUNT;
|
|
30
31
|
let slotCalc = ""; // 每槽各自采样出 linK(weights[k]>0 才采;没绑好保持 0,由 facePick 的 weights 闸兜成深灰)
|
|
31
32
|
let slotFacePick = ""; // 逐槽展开「panoIndices[k]==vPanoIndex 则取 lin{k}」(ANGLE 禁动态索引 ⇒ JS 常量展开)
|
|
32
33
|
for (let k = 0; k < maxPano; k++) {
|
|
33
|
-
const base = k * RT_STITCH_SLOT_COUNT; // 本点占
|
|
34
|
+
const base = k * RT_STITCH_SLOT_COUNT; // 本点占 3 个连续纹理槽:base=k*3 .. base+2(顺序 [左列, 中列, 右列])
|
|
35
|
+
// ⚠️ ANGLE(D3D) 禁止动态索引 sampler 数组 ⇒ 展开成「base + 字面量」常量下标 if 链;末条裸 else 兜住 u==1 边界
|
|
36
|
+
const slotSamples = [];
|
|
37
|
+
for (let s = 0; s < RT_STITCH_SLOT_COUNT; s++) {
|
|
38
|
+
const cond = s === RT_STITCH_SLOT_COUNT - 1
|
|
39
|
+
? "else"
|
|
40
|
+
: `${s === 0 ? "if" : "else if"} (tileIdx == ${s})`;
|
|
41
|
+
slotSamples.push(` ${cond} lin${k} = texture2D(panoramas[${base + s}], vec2(panoU, panoV)).rgb;`);
|
|
42
|
+
}
|
|
34
43
|
slotFacePick += `
|
|
35
44
|
if (panoIndices[${k}] >= 0.0 && weights[${k}] > 0.0 && abs(panoIndices[${k}] - vPanoIndex) < 0.5) faceCol = lin${k};`;
|
|
36
45
|
slotCalc += `
|
|
37
|
-
// ── 点槽 ${k}(纹理 ${base}..${base + 1})──
|
|
46
|
+
// ── 点槽 ${k}(纹理 ${base}..${base + RT_STITCH_SLOT_COUNT - 1})──
|
|
38
47
|
vec3 lin${k} = vec3(0.0);
|
|
39
48
|
if (weights[${k}] > 0.0) {
|
|
40
49
|
mat4 tm = textureMatrices[${k}];
|
|
@@ -47,21 +56,19 @@ function buildFloorMappingFragment(maxPano) {
|
|
|
47
56
|
float lat = asin(clamp(dir.y, -1.0, 1.0));
|
|
48
57
|
// 等距柱状线性 v(= 全图 UV),与 blend / 单全景分支**逐字同口径**
|
|
49
58
|
float v = 0.5 + lat * 0.3183098861837907; // 1/PI
|
|
50
|
-
//
|
|
51
|
-
// ⭐ 10-06
|
|
52
|
-
int tileIdx = (u
|
|
53
|
-
float localU =
|
|
54
|
-
// ⛔ 纵向不再减半(槽就是全高)⇒ localV 恒等于 v;写成
|
|
59
|
+
// 三等分经度 -> 拼合槽下标 [左列=0, 中列=1, 右列=2](每槽 = 3×3 网格里一整列、竖 3 片拼成,见 RT_STITCH_SLOT_TILES)
|
|
60
|
+
// ⭐ 10-06 晚旨「竖着不再分块」继续成立、10-23 旨把横向从 2 等分改成 3 等分 ⇒ 槽只随 u 走(与 blend / 单全景分支**逐字同口径**)
|
|
61
|
+
int tileIdx = int(clamp(floor(u * ${RT_STITCH_SLOT_COUNT}.0), 0.0, ${RT_STITCH_SLOT_COUNT - 1}.0));
|
|
62
|
+
float localU = u * ${RT_STITCH_SLOT_COUNT}.0 - float(tileIdx);
|
|
63
|
+
// ⛔ 纵向不再减半(槽就是全高)⇒ localV 恒等于 v;写成 nv/nv-1 = 纵向分辨率白丢一档
|
|
55
64
|
float localV = v;
|
|
56
|
-
// 🧩 该点这
|
|
65
|
+
// 🧩 该点这 3 槽装的是整图(whole 形态 / 没切过片)⇒ 还原成全图 UV 再采样(与 blend 逐字同口径)
|
|
57
66
|
float panoU = (uPanoTiled[${k}] > 0.5) ? localU : u;
|
|
58
67
|
float panoV = (uPanoTiled[${k}] > 0.5) ? localV : v;
|
|
59
|
-
// ⚠️ ANGLE(D3D) 禁止动态索引 sampler 数组:以下 2 个采样下标均为「base + 字面量」常量表达式,编译安全
|
|
60
68
|
// ⭐ 采样即线性(与单全景 / blend / selected 三路同一条口径,10-07 旨「色彩空间统一使用 liner」):纹理都标了
|
|
61
69
|
// colorSpace = SRGBColorSpace ⇒ 硬件上传成 SRGB8_ALPHA8、texture2D 已解码一次;
|
|
62
70
|
// 这里**不再手动 pow 解码**(那遍是二次解码 = 整体压暗),末端只编码一次 ⇒ 与源图逐字节还原。
|
|
63
|
-
|
|
64
|
-
else lin${k} = texture2D(panoramas[${base + 1}], vec2(panoU, panoV)).rgb;
|
|
71
|
+
${slotSamples.join("\n")}
|
|
65
72
|
}`;
|
|
66
73
|
}
|
|
67
74
|
return /* glsl */ `
|
|
@@ -105,13 +112,13 @@ ${slotFacePick}
|
|
|
105
112
|
* 创建「全景序号直取」着色器材质(皇上旨 2026-09-29「三模式三 shader」之二):
|
|
106
113
|
* 编辑器「映射设置模式」的墙材质 + **基类 MktMesh(发布/预览)的固定墙材质**
|
|
107
114
|
* (皇上旨:mktmesh 就只有按照 attribute 配置来显示全景这一种固定的 shader)。
|
|
108
|
-
* uniform 形状与 blend 工厂同档(panoramas[
|
|
115
|
+
* uniform 形状与 blend 工厂同档(panoramas[15]/textureMatrices[5]/weights[5]/uPanoTiled[5])⇒
|
|
109
116
|
* 喂料复用 feedBlendProjection 的槽位指派路(feedFaceMapping),零新喂料路。
|
|
110
117
|
* uFloorCoreRadius/uFloorFadeRange/uFloorOpacity 三根本 shader 不读,但喂料统一入口会写 ⇒ JS 侧留着(静默忽略)。
|
|
111
118
|
*/
|
|
112
119
|
export function createMktFloorMappingShaderMaterial(options = {}) {
|
|
113
120
|
const maxPano = Math.min(options.maxPano ?? MKT_PANO_MAX_SLOTS, MKT_PANO_MAX_SLOTS);
|
|
114
|
-
const tileCount = maxPano * RT_STITCH_SLOT_COUNT; //
|
|
121
|
+
const tileCount = maxPano * RT_STITCH_SLOT_COUNT; // 5 点 × 左/中/右 3 槽 = 15(sampler 硬顶 16)
|
|
115
122
|
const panoramas = [];
|
|
116
123
|
const matrices = [];
|
|
117
124
|
for (let i = 0; i < tileCount; i++)
|
|
@@ -9,34 +9,45 @@ import { BackSide, Matrix4, ShaderMaterial, Vector3 } from "three";
|
|
|
9
9
|
import { createPlaceholderTexture, floorVertexShader, RT_STITCH_SLOT_COUNT } from "./mktShader";
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
* ⭐
|
|
13
|
-
*
|
|
14
|
-
*
|
|
12
|
+
* ⭐ 融合材质的全景点数**上限**:每点占 **3** 张拼合槽纹理(皇上旨 2026-10-23「全景的 RT 由原来的 2 个分成 3 个、
|
|
13
|
+
* 每个 4096×6144、竖直排列 3 个瓦片」⇒ 原图切 3×3=9 片,按**列**分 3 槽)⇒ 点数 × 3 必须 ≤ sampler 硬顶。
|
|
14
|
+
* 本机 `MAX_TEXTURE_IMAGE_UNITS` 实测 **16**:旧版 8 点 × 2 槽 = 16 正好用满,现每点 3 槽 ⇒ 只能取 ⌊16/3⌋ = **5**
|
|
15
|
+
* (5 × 3 = 15)。皇上旨 2026-10-23 在「A」里拍板:保 3 槽不降画质,**同屏全景点数 8 → 5**。
|
|
15
16
|
*
|
|
16
17
|
* ⭐⭐ 2026-10-09 皇上旨「MktMesh 只有映射一种,blend/selected 归编辑器」⇒ 该常量从 `mktShader.ts`
|
|
17
18
|
* **搬到这里**(映射材质的所在地)。它同时是库与编辑器那份 blend 的**共同上限**,两边必须同值。
|
|
18
19
|
*/
|
|
19
|
-
export const MKT_PANO_MAX_SLOTS =
|
|
20
|
+
export const MKT_PANO_MAX_SLOTS = 5;
|
|
20
21
|
|
|
21
22
|
/**
|
|
22
23
|
* 序号直取片元(皇上旨 2026-09-29「三模式三 shader」之二):
|
|
23
24
|
* 按三角面 aPanoIndex 在 panoIndices 槽里找对应全景纹理 —— **不看距离、不看夹角**(blend 那套打分/归约整段没有)。
|
|
24
|
-
* 槽内采样段(等距柱状投射 +
|
|
25
|
+
* 槽内采样段(等距柱状投射 + 左/中/右 3 张拼合槽 + 采样即线性、不再手动 pow 解码)与 blend **逐字同口径**;改采样口径两处同改。
|
|
25
26
|
* 未设序号 / 序号不在槽里 / 该槽瓦片没绑好(weights≤0)→ uFaceMissingColor 深灰兜底
|
|
26
27
|
* (皇上旨 09-28「装不下就深灰」;weights 闸是 09-29 拆分时补的 —— 原运行时分支没这道闸,
|
|
27
28
|
* 槽没绑好但序号命中会采到 vec3(0) 纯黑,深灰才是钦定兜底色)。
|
|
28
29
|
*/
|
|
29
30
|
function buildFloorMappingFragment(maxPano: number): string {
|
|
30
|
-
// 每个全景点占 **
|
|
31
|
+
// 每个全景点占 **3** 张拼合槽纹理(9 片 3×3 按列分:左列 / 中列 / 右列,每槽竖叠 3 片)⇒ 5 × 3 = 15 ≤ sampler 硬顶 16
|
|
31
32
|
const tileCount = maxPano * RT_STITCH_SLOT_COUNT;
|
|
32
33
|
let slotCalc = ""; // 每槽各自采样出 linK(weights[k]>0 才采;没绑好保持 0,由 facePick 的 weights 闸兜成深灰)
|
|
33
34
|
let slotFacePick = ""; // 逐槽展开「panoIndices[k]==vPanoIndex 则取 lin{k}」(ANGLE 禁动态索引 ⇒ JS 常量展开)
|
|
34
35
|
for (let k = 0; k < maxPano; k++) {
|
|
35
|
-
const base = k * RT_STITCH_SLOT_COUNT; // 本点占
|
|
36
|
+
const base = k * RT_STITCH_SLOT_COUNT; // 本点占 3 个连续纹理槽:base=k*3 .. base+2(顺序 [左列, 中列, 右列])
|
|
37
|
+
// ⚠️ ANGLE(D3D) 禁止动态索引 sampler 数组 ⇒ 展开成「base + 字面量」常量下标 if 链;末条裸 else 兜住 u==1 边界
|
|
38
|
+
const slotSamples: string[] = [];
|
|
39
|
+
for (let s = 0; s < RT_STITCH_SLOT_COUNT; s++) {
|
|
40
|
+
const cond = s === RT_STITCH_SLOT_COUNT - 1
|
|
41
|
+
? "else"
|
|
42
|
+
: `${s === 0 ? "if" : "else if"} (tileIdx == ${s})`;
|
|
43
|
+
slotSamples.push(
|
|
44
|
+
` ${cond} lin${k} = texture2D(panoramas[${base + s}], vec2(panoU, panoV)).rgb;`,
|
|
45
|
+
);
|
|
46
|
+
}
|
|
36
47
|
slotFacePick += `
|
|
37
48
|
if (panoIndices[${k}] >= 0.0 && weights[${k}] > 0.0 && abs(panoIndices[${k}] - vPanoIndex) < 0.5) faceCol = lin${k};`;
|
|
38
49
|
slotCalc += `
|
|
39
|
-
// ── 点槽 ${k}(纹理 ${base}..${base + 1})──
|
|
50
|
+
// ── 点槽 ${k}(纹理 ${base}..${base + RT_STITCH_SLOT_COUNT - 1})──
|
|
40
51
|
vec3 lin${k} = vec3(0.0);
|
|
41
52
|
if (weights[${k}] > 0.0) {
|
|
42
53
|
mat4 tm = textureMatrices[${k}];
|
|
@@ -49,21 +60,19 @@ function buildFloorMappingFragment(maxPano: number): string {
|
|
|
49
60
|
float lat = asin(clamp(dir.y, -1.0, 1.0));
|
|
50
61
|
// 等距柱状线性 v(= 全图 UV),与 blend / 单全景分支**逐字同口径**
|
|
51
62
|
float v = 0.5 + lat * 0.3183098861837907; // 1/PI
|
|
52
|
-
//
|
|
53
|
-
// ⭐ 10-06
|
|
54
|
-
int tileIdx = (u
|
|
55
|
-
float localU =
|
|
56
|
-
// ⛔ 纵向不再减半(槽就是全高)⇒ localV 恒等于 v;写成
|
|
63
|
+
// 三等分经度 -> 拼合槽下标 [左列=0, 中列=1, 右列=2](每槽 = 3×3 网格里一整列、竖 3 片拼成,见 RT_STITCH_SLOT_TILES)
|
|
64
|
+
// ⭐ 10-06 晚旨「竖着不再分块」继续成立、10-23 旨把横向从 2 等分改成 3 等分 ⇒ 槽只随 u 走(与 blend / 单全景分支**逐字同口径**)
|
|
65
|
+
int tileIdx = int(clamp(floor(u * ${RT_STITCH_SLOT_COUNT}.0), 0.0, ${RT_STITCH_SLOT_COUNT - 1}.0));
|
|
66
|
+
float localU = u * ${RT_STITCH_SLOT_COUNT}.0 - float(tileIdx);
|
|
67
|
+
// ⛔ 纵向不再减半(槽就是全高)⇒ localV 恒等于 v;写成 nv/nv-1 = 纵向分辨率白丢一档
|
|
57
68
|
float localV = v;
|
|
58
|
-
// 🧩 该点这
|
|
69
|
+
// 🧩 该点这 3 槽装的是整图(whole 形态 / 没切过片)⇒ 还原成全图 UV 再采样(与 blend 逐字同口径)
|
|
59
70
|
float panoU = (uPanoTiled[${k}] > 0.5) ? localU : u;
|
|
60
71
|
float panoV = (uPanoTiled[${k}] > 0.5) ? localV : v;
|
|
61
|
-
// ⚠️ ANGLE(D3D) 禁止动态索引 sampler 数组:以下 2 个采样下标均为「base + 字面量」常量表达式,编译安全
|
|
62
72
|
// ⭐ 采样即线性(与单全景 / blend / selected 三路同一条口径,10-07 旨「色彩空间统一使用 liner」):纹理都标了
|
|
63
73
|
// colorSpace = SRGBColorSpace ⇒ 硬件上传成 SRGB8_ALPHA8、texture2D 已解码一次;
|
|
64
74
|
// 这里**不再手动 pow 解码**(那遍是二次解码 = 整体压暗),末端只编码一次 ⇒ 与源图逐字节还原。
|
|
65
|
-
|
|
66
|
-
else lin${k} = texture2D(panoramas[${base + 1}], vec2(panoU, panoV)).rgb;
|
|
75
|
+
${slotSamples.join("\n")}
|
|
67
76
|
}`;
|
|
68
77
|
}
|
|
69
78
|
return /* glsl */ `
|
|
@@ -108,13 +117,13 @@ ${slotFacePick}
|
|
|
108
117
|
* 创建「全景序号直取」着色器材质(皇上旨 2026-09-29「三模式三 shader」之二):
|
|
109
118
|
* 编辑器「映射设置模式」的墙材质 + **基类 MktMesh(发布/预览)的固定墙材质**
|
|
110
119
|
* (皇上旨:mktmesh 就只有按照 attribute 配置来显示全景这一种固定的 shader)。
|
|
111
|
-
* uniform 形状与 blend 工厂同档(panoramas[
|
|
120
|
+
* uniform 形状与 blend 工厂同档(panoramas[15]/textureMatrices[5]/weights[5]/uPanoTiled[5])⇒
|
|
112
121
|
* 喂料复用 feedBlendProjection 的槽位指派路(feedFaceMapping),零新喂料路。
|
|
113
122
|
* uFloorCoreRadius/uFloorFadeRange/uFloorOpacity 三根本 shader 不读,但喂料统一入口会写 ⇒ JS 侧留着(静默忽略)。
|
|
114
123
|
*/
|
|
115
124
|
export function createMktFloorMappingShaderMaterial(options: { maxPano?: number } = {}): ShaderMaterial {
|
|
116
125
|
const maxPano = Math.min(options.maxPano ?? MKT_PANO_MAX_SLOTS, MKT_PANO_MAX_SLOTS);
|
|
117
|
-
const tileCount = maxPano * RT_STITCH_SLOT_COUNT; //
|
|
126
|
+
const tileCount = maxPano * RT_STITCH_SLOT_COUNT; // 5 点 × 左/中/右 3 槽 = 15(sampler 硬顶 16)
|
|
118
127
|
const panoramas: import("three").Texture[] = [];
|
|
119
128
|
const matrices: Matrix4[] = [];
|
|
120
129
|
for (let i = 0; i < tileCount; i++) panoramas.push(createPlaceholderTexture());
|