s3m-three 0.3.6 → 0.3.8
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/anim/Animator.d.ts +111 -0
- package/dist/anim/Animator.d.ts.map +1 -0
- package/dist/anim/Animator.js +382 -0
- package/dist/anim/Animator.js.map +1 -0
- package/dist/anim/Path.d.ts +30 -0
- package/dist/anim/Path.d.ts.map +1 -0
- package/dist/anim/Path.js +100 -0
- package/dist/anim/Path.js.map +1 -0
- package/dist/anim/easing.d.ts +70 -0
- package/dist/anim/easing.d.ts.map +1 -0
- package/dist/anim/easing.js +170 -0
- package/dist/anim/easing.js.map +1 -0
- package/dist/anim/index.d.ts +6 -0
- package/dist/anim/index.d.ts.map +1 -0
- package/dist/anim/index.js +4 -0
- package/dist/anim/index.js.map +1 -0
- package/dist/browser/assets/{s3mWorker-hZY5KqWF.js → s3mWorker-D7AV6O30.js} +1 -1
- package/dist/browser/s3m-three.iife.ext-three.js +60 -22
- package/dist/browser/s3m-three.iife.js +60 -22
- package/dist/core/TextureDecode.d.ts +22 -1
- package/dist/core/TextureDecode.d.ts.map +1 -1
- package/dist/core/TextureDecode.js +47 -3
- package/dist/core/TextureDecode.js.map +1 -1
- package/dist/core/TileGeometry.d.ts +92 -0
- package/dist/core/TileGeometry.d.ts.map +1 -0
- package/dist/core/TileGeometry.js +607 -0
- package/dist/core/TileGeometry.js.map +1 -0
- package/dist/core/types.d.ts +16 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/render/EdgeLines.d.ts +62 -14
- package/dist/render/EdgeLines.d.ts.map +1 -1
- package/dist/render/EdgeLines.js +97 -8
- package/dist/render/EdgeLines.js.map +1 -1
- package/dist/render/FeatureStyleManager.d.ts +17 -1
- package/dist/render/FeatureStyleManager.d.ts.map +1 -1
- package/dist/render/FeatureStyleManager.js +14 -4
- package/dist/render/FeatureStyleManager.js.map +1 -1
- package/dist/render/GeometryBuilder.d.ts +8 -10
- package/dist/render/GeometryBuilder.d.ts.map +1 -1
- package/dist/render/GeometryBuilder.js +77 -555
- package/dist/render/GeometryBuilder.js.map +1 -1
- package/dist/render/MergeVertices.d.ts +7 -0
- package/dist/render/MergeVertices.d.ts.map +1 -1
- package/dist/render/MergeVertices.js +10 -1
- package/dist/render/MergeVertices.js.map +1 -1
- package/dist/render/S3MViewer.d.ts +218 -9
- package/dist/render/S3MViewer.d.ts.map +1 -1
- package/dist/render/S3MViewer.js +772 -68
- package/dist/render/S3MViewer.js.map +1 -1
- package/dist/render/StyleMaterial.d.ts +19 -0
- package/dist/render/StyleMaterial.d.ts.map +1 -1
- package/dist/render/StyleMaterial.js +37 -0
- package/dist/render/StyleMaterial.js.map +1 -1
- package/dist/render/TextureFactory.d.ts +2 -1
- package/dist/render/TextureFactory.d.ts.map +1 -1
- package/dist/render/TextureFactory.js +30 -6
- package/dist/render/TextureFactory.js.map +1 -1
- package/dist/tileset/S3MTileset.d.ts +6 -2
- package/dist/tileset/S3MTileset.d.ts.map +1 -1
- package/dist/tileset/S3MTileset.js +17 -7
- package/dist/tileset/S3MTileset.js.map +1 -1
- package/dist/worker/S3MWorkerClient.d.ts +12 -4
- package/dist/worker/S3MWorkerClient.d.ts.map +1 -1
- package/dist/worker/S3MWorkerClient.js +12 -8
- package/dist/worker/S3MWorkerClient.js.map +1 -1
- package/dist/worker/s3mWorker.js +11 -3
- package/dist/worker/s3mWorker.js.map +1 -1
- package/docs/ANIMATION.md +534 -0
- package/docs/API.md +4 -0
- package/package.json +1 -1
- package/src/anim/Animator.ts +460 -0
- package/src/anim/Path.ts +107 -0
- package/src/anim/easing.ts +195 -0
- package/src/anim/index.ts +10 -0
- package/src/core/TextureDecode.ts +69 -3
- package/src/core/TileGeometry.ts +745 -0
- package/src/core/types.ts +8 -0
- package/src/index.ts +10 -0
- package/src/render/EdgeLines.ts +131 -15
- package/src/render/FeatureStyleManager.ts +12 -4
- package/src/render/GeometryBuilder.ts +91 -617
- package/src/render/MergeVertices.ts +11 -1
- package/src/render/S3MViewer.ts +866 -67
- package/src/render/StyleMaterial.ts +54 -1
- package/src/render/TextureFactory.ts +42 -8
- package/src/tileset/S3MTileset.ts +25 -9
- package/src/worker/S3MWorkerClient.ts +18 -9
- package/src/worker/s3mWorker.ts +24 -6
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 缓动曲线库
|
|
3
|
+
*
|
|
4
|
+
* 纯函数,不依赖 three / DOM,可以单独在 Worker 或 Node 里跑。
|
|
5
|
+
*
|
|
6
|
+
* 三类:
|
|
7
|
+
* 1. 命名曲线 —— CSS 那套 easeIn/Out/InOut × Quad…Bounce,覆盖 90% 场景
|
|
8
|
+
* 2. cubicBezier(x1,y1,x2,y2) —— 与 CSS `cubic-bezier()` 数值对齐,用来做产品级调校
|
|
9
|
+
* 3. steps(n, position) —— 离散跳变,做逐帧动画或「咔哒」感
|
|
10
|
+
*
|
|
11
|
+
* spring 不在这里:它没有「时长」概念,靠物理收敛,所以实现为 Animator 里的一种
|
|
12
|
+
* Track 类型,而不是 (t) => number 的曲线。
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
export type EasingFn = (t: number) => number;
|
|
16
|
+
|
|
17
|
+
/* ------------------------------------------------------------------ 基础 */
|
|
18
|
+
|
|
19
|
+
const c1 = 1.70158;
|
|
20
|
+
const c2 = c1 * 1.525;
|
|
21
|
+
const c3 = c1 + 1;
|
|
22
|
+
const c4 = (2 * Math.PI) / 3;
|
|
23
|
+
const c5 = (2 * Math.PI) / 4.5;
|
|
24
|
+
const n1 = 7.5625;
|
|
25
|
+
const d1 = 2.75;
|
|
26
|
+
|
|
27
|
+
function outBounce(t: number): number {
|
|
28
|
+
if (t < 1 / d1) return n1 * t * t;
|
|
29
|
+
if (t < 2 / d1) {
|
|
30
|
+
const x = t - 1.5 / d1;
|
|
31
|
+
return n1 * x * x + 0.75;
|
|
32
|
+
}
|
|
33
|
+
if (t < 2.5 / d1) {
|
|
34
|
+
const x = t - 2.25 / d1;
|
|
35
|
+
return n1 * x * x + 0.9375;
|
|
36
|
+
}
|
|
37
|
+
const x = t - 2.625 / d1;
|
|
38
|
+
return n1 * x * x + 0.984375;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function inBounce(t: number): number {
|
|
42
|
+
return 1 - outBounce(1 - t);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/* ------------------------------------------------------------------ 曲线表 */
|
|
46
|
+
|
|
47
|
+
const CURVES = {
|
|
48
|
+
linear: (t) => t,
|
|
49
|
+
|
|
50
|
+
easeInQuad: (t) => t * t,
|
|
51
|
+
easeOutQuad: (t) => 1 - (1 - t) * (1 - t),
|
|
52
|
+
easeInOutQuad: (t) => (t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2),
|
|
53
|
+
|
|
54
|
+
easeInCubic: (t) => t * t * t,
|
|
55
|
+
easeOutCubic: (t) => 1 - Math.pow(1 - t, 3),
|
|
56
|
+
easeInOutCubic: (t) => (t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2),
|
|
57
|
+
|
|
58
|
+
easeInQuart: (t) => t * t * t * t,
|
|
59
|
+
easeOutQuart: (t) => 1 - Math.pow(1 - t, 4),
|
|
60
|
+
easeInOutQuart: (t) => (t < 0.5 ? 8 * t * t * t * t : 1 - Math.pow(-2 * t + 2, 4) / 2),
|
|
61
|
+
|
|
62
|
+
easeInQuint: (t) => t * t * t * t * t,
|
|
63
|
+
easeOutQuint: (t) => 1 - Math.pow(1 - t, 5),
|
|
64
|
+
easeInOutQuint: (t) => (t < 0.5 ? 16 * t * t * t * t * t : 1 - Math.pow(-2 * t + 2, 5) / 2),
|
|
65
|
+
|
|
66
|
+
easeInSine: (t) => 1 - Math.cos((t * Math.PI) / 2),
|
|
67
|
+
easeOutSine: (t) => Math.sin((t * Math.PI) / 2),
|
|
68
|
+
easeInOutSine: (t) => -(Math.cos(Math.PI * t) - 1) / 2,
|
|
69
|
+
|
|
70
|
+
easeInExpo: (t) => (t === 0 ? 0 : Math.pow(2, 10 * t - 10)),
|
|
71
|
+
easeOutExpo: (t) => (t === 1 ? 1 : 1 - Math.pow(2, -10 * t)),
|
|
72
|
+
easeInOutExpo: (t) =>
|
|
73
|
+
t === 0 ? 0 : t === 1 ? 1 : t < 0.5 ? Math.pow(2, 20 * t - 10) / 2 : (2 - Math.pow(2, -20 * t + 10)) / 2,
|
|
74
|
+
|
|
75
|
+
easeInCirc: (t) => 1 - Math.sqrt(1 - t * t),
|
|
76
|
+
easeOutCirc: (t) => Math.sqrt(1 - Math.pow(t - 1, 2)),
|
|
77
|
+
easeInOutCirc: (t) =>
|
|
78
|
+
t < 0.5
|
|
79
|
+
? (1 - Math.sqrt(1 - Math.pow(2 * t, 2))) / 2
|
|
80
|
+
: (Math.sqrt(1 - Math.pow(-2 * t + 2, 2)) + 1) / 2,
|
|
81
|
+
|
|
82
|
+
easeInBack: (t) => c3 * t * t * t - c1 * t * t,
|
|
83
|
+
easeOutBack: (t) => 1 + c3 * Math.pow(t - 1, 3) + c1 * Math.pow(t - 1, 2),
|
|
84
|
+
easeInOutBack: (t) =>
|
|
85
|
+
t < 0.5
|
|
86
|
+
? (Math.pow(2 * t, 2) * ((c2 + 1) * 2 * t - c2)) / 2
|
|
87
|
+
: (Math.pow(2 * t - 2, 2) * ((c2 + 1) * (t * 2 - 2) + c2) + 2) / 2,
|
|
88
|
+
|
|
89
|
+
easeInElastic: (t) =>
|
|
90
|
+
t === 0 ? 0 : t === 1 ? 1 : -Math.pow(2, 10 * t - 10) * Math.sin((t * 10 - 10.75) * c4),
|
|
91
|
+
easeOutElastic: (t) =>
|
|
92
|
+
t === 0 ? 0 : t === 1 ? 1 : Math.pow(2, -10 * t) * Math.sin((t * 10 - 0.75) * c4) + 1,
|
|
93
|
+
easeInOutElastic: (t) =>
|
|
94
|
+
t === 0
|
|
95
|
+
? 0
|
|
96
|
+
: t === 1
|
|
97
|
+
? 1
|
|
98
|
+
: t < 0.5
|
|
99
|
+
? -(Math.pow(2, 20 * t - 10) * Math.sin((20 * t - 11.125) * c5)) / 2
|
|
100
|
+
: (Math.pow(2, -20 * t + 10) * Math.sin((20 * t - 11.125) * c5)) / 2 + 1,
|
|
101
|
+
|
|
102
|
+
easeInBounce: inBounce,
|
|
103
|
+
easeOutBounce: outBounce,
|
|
104
|
+
easeInOutBounce: (t) => (t < 0.5 ? (1 - inBounce(1 - 2 * t)) / 2 : (1 + inBounce(2 * t - 1)) / 2),
|
|
105
|
+
} satisfies Record<string, EasingFn>;
|
|
106
|
+
|
|
107
|
+
/** 全部内置曲线名(顺序稳定,方便做下拉框 / 遍历自检) */
|
|
108
|
+
export const EASING_NAMES = Object.keys(CURVES) as EasingName[];
|
|
109
|
+
|
|
110
|
+
export type EasingName = keyof typeof CURVES;
|
|
111
|
+
|
|
112
|
+
/** 按名字取曲线;名字不存在直接抛错,不做静默降级(拼错会变成「没动画」,很难查) */
|
|
113
|
+
export function easing(name: EasingName | EasingFn): EasingFn {
|
|
114
|
+
if (typeof name === 'function') return name;
|
|
115
|
+
const fn = (CURVES as Record<string, EasingFn>)[name];
|
|
116
|
+
if (!fn) throw new Error(`[s3m] 未知的缓动曲线: ${String(name)}`);
|
|
117
|
+
return fn;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/* ------------------------------------------------------------------ 贝塞尔 */
|
|
121
|
+
|
|
122
|
+
const NEWTON_ITERATIONS = 8;
|
|
123
|
+
const NEWTON_MIN_SLOPE = 0.001;
|
|
124
|
+
const SUBDIVISION_PRECISION = 1e-7;
|
|
125
|
+
const SUBDIVISION_MAX_ITERATIONS = 12;
|
|
126
|
+
|
|
127
|
+
const bezA = (a1: number, a2: number): number => 1 - 3 * a2 + 3 * a1;
|
|
128
|
+
const bezB = (a1: number, a2: number): number => 3 * a2 - 6 * a1;
|
|
129
|
+
const bezC = (a1: number): number => 3 * a1;
|
|
130
|
+
|
|
131
|
+
/** 三次贝塞尔在参数 t 处的值(x 或 y 用同一组公式,只是控制点不同) */
|
|
132
|
+
function bezierAt(t: number, a1: number, a2: number): number {
|
|
133
|
+
return ((bezA(a1, a2) * t + bezB(a1, a2)) * t + bezC(a1)) * t;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function bezierSlope(t: number, a1: number, a2: number): number {
|
|
137
|
+
return 3 * bezA(a1, a2) * t * t + 2 * bezB(a1, a2) * t + bezC(a1);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* CSS `cubic-bezier(x1, y1, x2, y2)` 的等价实现。
|
|
142
|
+
*
|
|
143
|
+
* 与浏览器一致:先解 `x(t) = 输入进度` 得到参数 t,再取 `y(t)`。
|
|
144
|
+
* 用牛顿迭代,斜率过小时退化为二分——退化控制点(比如 (0,0,1,1))也稳定。
|
|
145
|
+
*/
|
|
146
|
+
export function cubicBezier(x1: number, y1: number, x2: number, y2: number): EasingFn {
|
|
147
|
+
// 线性特例:控制点落在对角线上时不必迭代
|
|
148
|
+
if (x1 === y1 && x2 === y2) return (t) => t;
|
|
149
|
+
|
|
150
|
+
const solveT = (x: number): number => {
|
|
151
|
+
let t = x;
|
|
152
|
+
for (let i = 0; i < NEWTON_ITERATIONS; i++) {
|
|
153
|
+
const slope = bezierSlope(t, x1, x2);
|
|
154
|
+
if (Math.abs(slope) < NEWTON_MIN_SLOPE) break;
|
|
155
|
+
const err = bezierAt(t, x1, x2) - x;
|
|
156
|
+
if (Math.abs(err) < SUBDIVISION_PRECISION) return t;
|
|
157
|
+
t -= err / slope;
|
|
158
|
+
}
|
|
159
|
+
// 牛顿不收敛:二分兜底
|
|
160
|
+
let lo = 0;
|
|
161
|
+
let hi = 1;
|
|
162
|
+
t = x;
|
|
163
|
+
for (let i = 0; i < SUBDIVISION_MAX_ITERATIONS; i++) {
|
|
164
|
+
const v = bezierAt(t, x1, x2);
|
|
165
|
+
if (Math.abs(v - x) < SUBDIVISION_PRECISION) return t;
|
|
166
|
+
if (v < x) lo = t;
|
|
167
|
+
else hi = t;
|
|
168
|
+
t = (lo + hi) / 2;
|
|
169
|
+
}
|
|
170
|
+
return t;
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
return (t: number): number => {
|
|
174
|
+
if (t <= 0) return 0;
|
|
175
|
+
if (t >= 1) return 1;
|
|
176
|
+
return bezierAt(solveT(t), y1, y2);
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/* ------------------------------------------------------------------ 离散 */
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* 阶梯曲线。
|
|
184
|
+
*
|
|
185
|
+
* @param count 档数
|
|
186
|
+
* @param position 'end' 表示「走完一档才跳」,'start' 表示「一进档就跳」
|
|
187
|
+
*/
|
|
188
|
+
export function steps(count: number, position: 'start' | 'end' = 'end'): EasingFn {
|
|
189
|
+
const n = Math.max(1, Math.floor(count));
|
|
190
|
+
return (t: number): number => {
|
|
191
|
+
const clamped = Math.min(1, Math.max(0, t));
|
|
192
|
+
if (position === 'start') return Math.min(1, (Math.floor(clamped * n) + 1) / n);
|
|
193
|
+
return Math.min(1, Math.floor(clamped * n) / n);
|
|
194
|
+
};
|
|
195
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { Animator } from './Animator.js';
|
|
2
|
+
export type { Channel, SpringSpec, TransitionOptions } from './Animator.js';
|
|
3
|
+
export { Path } from './Path.js';
|
|
4
|
+
export {
|
|
5
|
+
easing,
|
|
6
|
+
cubicBezier,
|
|
7
|
+
steps,
|
|
8
|
+
EASING_NAMES,
|
|
9
|
+
} from './easing.js';
|
|
10
|
+
export type { EasingFn, EasingName } from './easing.js';
|
|
@@ -26,10 +26,25 @@ export interface DecodedTextureData {
|
|
|
26
26
|
/** WEBP 路径的解码结果(ImageBitmap 可 transfer,主线程直接 new THREE.Texture 包) */
|
|
27
27
|
bitmap: ImageBitmap | null;
|
|
28
28
|
hasAlpha: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* 压缩直传模式(decodeTextureData 的 compressed 选项):不解码,原样返回 DXT 块,
|
|
31
|
+
* 主线程用 CompressedTexture 硬件解压上传。与 rgba 互斥。
|
|
32
|
+
*/
|
|
33
|
+
blocks?: Uint8Array;
|
|
34
|
+
blockFormat?: 'dxt1' | 'dxt5';
|
|
29
35
|
/** CRN 转码失败时的原始错误(渲染层负责打 warn) */
|
|
30
36
|
error?: string;
|
|
31
37
|
}
|
|
32
38
|
|
|
39
|
+
export interface DecodeOptions {
|
|
40
|
+
/**
|
|
41
|
+
* 压缩直传:dxt1/dxt5(含 CRN 转码产物)不解码,原样返回 DXT 块。
|
|
42
|
+
* 仅在宿主支持 WEBGL_compressed_texture_s3tc(+srgb) 时开启;
|
|
43
|
+
* flipY 纹理走不了压缩上传(WebGL 对压缩纹理忽略 UNPACK_FLIP_Y),自动回退解码。
|
|
44
|
+
*/
|
|
45
|
+
compressed?: boolean;
|
|
46
|
+
}
|
|
47
|
+
|
|
33
48
|
/** 行序翻转(原地)。S3MBLOCK 图集按 GL 方向存储(v=0 在最后一行),解码后要翻一次行 */
|
|
34
49
|
function flipRows(rgba: Uint8Array, width: number, height: number): void {
|
|
35
50
|
const row = width * 4;
|
|
@@ -92,8 +107,23 @@ function rawRGBA(tex: S3MTexture): { rgba: Uint8Array; hasAlpha: boolean } {
|
|
|
92
107
|
return { rgba: out, hasAlpha: hasAlphaChannel(pixelFormat) };
|
|
93
108
|
}
|
|
94
109
|
|
|
110
|
+
/**
|
|
111
|
+
* DXT 块数据的期望字节数:4×4 对齐块 × 每块字节(DXT1=8,DXT5=16)。
|
|
112
|
+
* S3M 纹理宽高不总是 4 的倍数,驱动按声明尺寸算期望大小——对不上就是
|
|
113
|
+
* GL_INVALID_VALUE: glCompressedTexSubImage2D: The <imageSize> does not match。
|
|
114
|
+
* 压缩直传前必须用这个函数把关,不匹配就回退 RGBA 解码。
|
|
115
|
+
*/
|
|
116
|
+
export function expectedDxtByteLength(width: number, height: number, format: 'dxt1' | 'dxt5'): number {
|
|
117
|
+
const bw = (width + 3) >> 2;
|
|
118
|
+
const bh = (height + 3) >> 2;
|
|
119
|
+
return bw * bh * (format === 'dxt1' ? 8 : 16);
|
|
120
|
+
}
|
|
121
|
+
|
|
95
122
|
/** 主线程 / Worker 共用的解码入口。不抛错:失败与不支持都体现在返回值里 */
|
|
96
|
-
export async function decodeTextureData(
|
|
123
|
+
export async function decodeTextureData(
|
|
124
|
+
tex: S3MTexture,
|
|
125
|
+
options: DecodeOptions = {}
|
|
126
|
+
): Promise<DecodedTextureData> {
|
|
97
127
|
const empty: DecodedTextureData = {
|
|
98
128
|
kind: 'unsupported(0/0)',
|
|
99
129
|
width: 0,
|
|
@@ -106,13 +136,35 @@ export async function decodeTextureData(tex: S3MTexture): Promise<DecodedTexture
|
|
|
106
136
|
|
|
107
137
|
const kind = resolveTextureKind(tex.compressType ?? 0, tex.pixelFormat);
|
|
108
138
|
|
|
139
|
+
// 压缩直传的公共前提:不是 GL 翻行图集(压缩上传无法 flipY)
|
|
140
|
+
const canCompress = options.compressed === true && !tex.flipY;
|
|
141
|
+
|
|
142
|
+
/** 块数据字节数与 4×4 对齐公式一致才允许直传,否则回退解码 */
|
|
143
|
+
const compressible = (data: Uint8Array, w: number, h: number, format: 'dxt1' | 'dxt5'): boolean =>
|
|
144
|
+
data.byteLength === expectedDxtByteLength(w, h, format);
|
|
145
|
+
|
|
109
146
|
if (kind === 'crn') {
|
|
110
147
|
try {
|
|
111
148
|
const crn = await transcodeCRN(tex.data);
|
|
149
|
+
const pf = crn.dxtFormat === 1 ? PixelFormat.DXT1 : PixelFormat.DXT5;
|
|
150
|
+
const fmt = crn.dxtFormat === 1 ? 'dxt1' : 'dxt5';
|
|
151
|
+
if (canCompress && compressible(crn.data, crn.width, crn.height, fmt)) {
|
|
152
|
+
// CRN→DXT 的转码免不了(wasm),但后续的 DXT→RGBA 解块省掉,块数据直传 GPU
|
|
153
|
+
return {
|
|
154
|
+
kind: `crn->dxt${crn.dxtFormat}(c)`,
|
|
155
|
+
width: crn.width,
|
|
156
|
+
height: crn.height,
|
|
157
|
+
rgba: null,
|
|
158
|
+
bitmap: null,
|
|
159
|
+
hasAlpha: pf === PixelFormat.DXT5,
|
|
160
|
+
blocks: crn.data,
|
|
161
|
+
blockFormat: fmt,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
112
164
|
const decoded = decodeDXT({
|
|
113
165
|
width: crn.width,
|
|
114
166
|
height: crn.height,
|
|
115
|
-
pixelFormat:
|
|
167
|
+
pixelFormat: pf,
|
|
116
168
|
data: crn.data,
|
|
117
169
|
});
|
|
118
170
|
return {
|
|
@@ -138,7 +190,21 @@ export async function decodeTextureData(tex: S3MTexture): Promise<DecodedTexture
|
|
|
138
190
|
}
|
|
139
191
|
|
|
140
192
|
if (kind === 'dxt1' || kind === 'dxt3' || kind === 'dxt4' || kind === 'dxt5') {
|
|
141
|
-
const
|
|
193
|
+
const pf = dxtPixelFormatOf(kind);
|
|
194
|
+
// dxt3/dxt4 少见,不进直传白名单;块长与 4×4 对齐公式不符的也回退解码
|
|
195
|
+
if (canCompress && (kind === 'dxt1' || kind === 'dxt5') && compressible(tex.data, tex.width, tex.height, kind)) {
|
|
196
|
+
return {
|
|
197
|
+
kind: `${kind}(c)`,
|
|
198
|
+
width: tex.width,
|
|
199
|
+
height: tex.height,
|
|
200
|
+
rgba: null,
|
|
201
|
+
bitmap: null,
|
|
202
|
+
hasAlpha: kind === 'dxt5',
|
|
203
|
+
blocks: tex.data,
|
|
204
|
+
blockFormat: kind,
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
const decoded = decodeDXT({ ...tex, pixelFormat: pf });
|
|
142
208
|
return { kind, width: tex.width, height: tex.height, rgba: decoded.rgba, bitmap: null, hasAlpha: decoded.hasAlpha };
|
|
143
209
|
}
|
|
144
210
|
|