@openspecui/web 0.9.3 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/dist/assets/BufferResource-CVUoegR6.js +185 -0
  2. package/dist/assets/CanvasRenderer-BEIcB8i1.js +1 -0
  3. package/dist/assets/Filter-Bu_qhr6H.js +1 -0
  4. package/dist/assets/RenderTargetSystem-DWouFDxU.js +172 -0
  5. package/dist/assets/WebGLRenderer-6FH_N1FV.js +156 -0
  6. package/dist/assets/WebGPURenderer-B8sJk3Sv.js +41 -0
  7. package/dist/assets/browserAll-CLKeV1yb.js +14 -0
  8. package/dist/assets/gemini-Bk-V9kKu.png +0 -0
  9. package/dist/assets/{index-Bp00uZNc.js → index-BE5-y0_g.js} +1 -1
  10. package/{dist-ssg/client/assets/index-CCfVkFzN.js → dist/assets/index-BPCTI2mG.js} +1 -1
  11. package/dist/assets/{index-BsTieXqQ.js → index-BRp8MJ9v.js} +1 -1
  12. package/dist/assets/{index-8c6bEJ99.js → index-BlZ-sasH.js} +1 -1
  13. package/dist/assets/{index-Bafja8o4.js → index-Bp_dnlLF.js} +1 -1
  14. package/{dist-ssg/client/assets/index-ftYom_wU.js → dist/assets/index-BtNuxyw4.js} +1 -1
  15. package/dist/assets/index-Bv7pWR8R.js +7 -0
  16. package/{dist-ssg/client/assets/index-D3mXuuih.js → dist/assets/index-Byr3HkRi.js} +1 -1
  17. package/dist/assets/index-CEHMo0EU.js +1385 -0
  18. package/dist/assets/{index-eA_XNQ_L.js → index-CEKSUzvw.js} +1 -1
  19. package/dist/assets/index-CEf9wXLh.css +1 -0
  20. package/{dist-ssg/client/assets/index-ArhptQw0.js → dist/assets/index-CX13iBBs.js} +1 -1
  21. package/dist/assets/index-CoOT7eZ9.js +1 -0
  22. package/{dist-ssg/client/assets/index-B1hpa--1.js → dist/assets/index-D4AU46yO.js} +1 -1
  23. package/dist/assets/{index-BvGAWAqS.js → index-DXRZmZm8.js} +1 -1
  24. package/{dist-ssg/client/assets/index-AbWe21oh.js → dist/assets/index-eQZwF8qE.js} +1 -1
  25. package/dist/assets/{index-gvPT4BlL.js → index-mWXhCp9j.js} +1 -1
  26. package/dist/assets/webworkerAll-DjWoTx9g.js +83 -0
  27. package/dist/index.html +2 -2
  28. package/dist-ssg/client/.vite/ssr-manifest.json +3094 -504
  29. package/dist-ssg/client/assets/BufferResource-CVUoegR6.js +185 -0
  30. package/dist-ssg/client/assets/CanvasRenderer-BEIcB8i1.js +1 -0
  31. package/dist-ssg/client/assets/Filter-Bu_qhr6H.js +1 -0
  32. package/dist-ssg/client/assets/RenderTargetSystem-DWouFDxU.js +172 -0
  33. package/dist-ssg/client/assets/WebGLRenderer-6FH_N1FV.js +156 -0
  34. package/dist-ssg/client/assets/WebGPURenderer-B8sJk3Sv.js +41 -0
  35. package/dist-ssg/client/assets/browserAll-CLKeV1yb.js +14 -0
  36. package/dist-ssg/client/assets/gemini-Bk-V9kKu.png +0 -0
  37. package/dist-ssg/client/assets/{index-Bp00uZNc.js → index-BE5-y0_g.js} +1 -1
  38. package/{dist/assets/index-CCfVkFzN.js → dist-ssg/client/assets/index-BPCTI2mG.js} +1 -1
  39. package/dist-ssg/client/assets/{index-BsTieXqQ.js → index-BRp8MJ9v.js} +1 -1
  40. package/dist-ssg/client/assets/{index-8c6bEJ99.js → index-BlZ-sasH.js} +1 -1
  41. package/dist-ssg/client/assets/{index-Bafja8o4.js → index-Bp_dnlLF.js} +1 -1
  42. package/{dist/assets/index-ftYom_wU.js → dist-ssg/client/assets/index-BtNuxyw4.js} +1 -1
  43. package/dist-ssg/client/assets/index-Bv7pWR8R.js +7 -0
  44. package/{dist/assets/index-D3mXuuih.js → dist-ssg/client/assets/index-Byr3HkRi.js} +1 -1
  45. package/dist-ssg/client/assets/index-CEHMo0EU.js +1385 -0
  46. package/dist-ssg/client/assets/{index-eA_XNQ_L.js → index-CEKSUzvw.js} +1 -1
  47. package/dist-ssg/client/assets/index-CEf9wXLh.css +1 -0
  48. package/{dist/assets/index-ArhptQw0.js → dist-ssg/client/assets/index-CX13iBBs.js} +1 -1
  49. package/dist-ssg/client/assets/index-CoOT7eZ9.js +1 -0
  50. package/{dist/assets/index-B1hpa--1.js → dist-ssg/client/assets/index-D4AU46yO.js} +1 -1
  51. package/dist-ssg/client/assets/{index-BvGAWAqS.js → index-DXRZmZm8.js} +1 -1
  52. package/{dist/assets/index-AbWe21oh.js → dist-ssg/client/assets/index-eQZwF8qE.js} +1 -1
  53. package/dist-ssg/client/assets/{index-gvPT4BlL.js → index-mWXhCp9j.js} +1 -1
  54. package/dist-ssg/client/assets/webworkerAll-DjWoTx9g.js +83 -0
  55. package/dist-ssg/client/index.html +2 -2
  56. package/dist-ssg/server/assets/BufferResource-BXrsGVSz.js +592 -0
  57. package/dist-ssg/server/assets/CanvasRenderer-D9aMd7WV.js +1530 -0
  58. package/dist-ssg/server/assets/Filter-ClU0-pLL.js +80 -0
  59. package/dist-ssg/server/assets/RenderTargetSystem-CVz6i60H.js +3037 -0
  60. package/dist-ssg/server/assets/WebGLRenderer-B0I5TP5d.js +3887 -0
  61. package/dist-ssg/server/assets/WebGPURenderer-DCgUFny7.js +2146 -0
  62. package/dist-ssg/server/assets/browserAll-BixK1BYs.js +2691 -0
  63. package/dist-ssg/server/assets/{index-BUANIFyF.js → index-3uSTc-o9.js} +3 -1
  64. package/dist-ssg/server/assets/{index-D0JVKGRJ.js → index-8uE7RyRi.js} +3 -1
  65. package/dist-ssg/server/assets/{index-DCGDP0cs.js → index-BDzDVVaf.js} +2 -0
  66. package/dist-ssg/server/assets/{index-oPcprgZH.js → index-BkJYfA64.js} +3 -1
  67. package/dist-ssg/server/assets/{index-CAP0cmVO.js → index-BvGNqnLD.js} +3 -1
  68. package/dist-ssg/server/assets/{index-DsfT46da.js → index-BvURgefh.js} +3 -1
  69. package/dist-ssg/server/assets/{index-Dk9q2o0C.js → index-C2CuXbSQ.js} +3 -1
  70. package/dist-ssg/server/assets/{index-Cmnd0jiw.js → index-C3RtR5EA.js} +3 -1
  71. package/dist-ssg/server/assets/{index-CFKaffPZ.js → index-CZtnphnE.js} +3 -1
  72. package/dist-ssg/server/assets/{index-D6n8WPGB.js → index-D0DRToHj.js} +3 -1
  73. package/dist-ssg/server/assets/{index-mJoWrrNO.js → index-D5MdLWau.js} +3 -1
  74. package/dist-ssg/server/assets/{index-Brcpp_nj.js → index-DBYODvy4.js} +3 -1
  75. package/dist-ssg/server/assets/{index-DYmgiM6_.js → index-DL23PkQi.js} +3 -1
  76. package/dist-ssg/server/assets/{index-CnRKREoz.js → index-DfcLdBOi.js} +3 -1
  77. package/dist-ssg/server/assets/{index-Bzw5T-vd.js → index-O2XMojWG.js} +3 -1
  78. package/dist-ssg/server/assets/init-CnkBvt-J.js +666 -0
  79. package/dist-ssg/server/assets/webworkerAll-DNiMFaVV.js +12 -0
  80. package/dist-ssg/server/entry-server.js +87120 -34846
  81. package/package.json +23 -5
  82. package/dist/assets/index-D-Urq2hl.css +0 -1
  83. package/dist/assets/index-DFOLYN6W.js +0 -1
  84. package/dist/assets/index-DpxkOmNJ.js +0 -7
  85. package/dist/assets/index-YZ-iXB95.js +0 -309
  86. package/dist-ssg/client/assets/index-D-Urq2hl.css +0 -1
  87. package/dist-ssg/client/assets/index-DFOLYN6W.js +0 -1
  88. package/dist-ssg/client/assets/index-DpxkOmNJ.js +0 -7
  89. package/dist-ssg/client/assets/index-YZ-iXB95.js +0 -309
@@ -0,0 +1,666 @@
1
+ import { G as GpuProgram, u as GlProgram, y as ExtensionType, M as Matrix, U as UniformGroup, B as BindGroup, T as TexturePool, z as Texture, A as Geometry, R as RendererType, D as warn, F as Bounds, H as extensions } from "../entry-server.js";
2
+ import { F as Filter } from "./Filter-ClU0-pLL.js";
3
+ var vertex = "in vec2 aPosition;\nout vec2 vTextureCoord;\n\nuniform vec4 uInputSize;\nuniform vec4 uOutputFrame;\nuniform vec4 uOutputTexture;\n\nvec4 filterVertexPosition( void )\n{\n vec2 position = aPosition * uOutputFrame.zw + uOutputFrame.xy;\n \n position.x = position.x * (2.0 / uOutputTexture.x) - 1.0;\n position.y = position.y * (2.0*uOutputTexture.z / uOutputTexture.y) - uOutputTexture.z;\n\n return vec4(position, 0.0, 1.0);\n}\n\nvec2 filterTextureCoord( void )\n{\n return aPosition * (uOutputFrame.zw * uInputSize.zw);\n}\n\nvoid main(void)\n{\n gl_Position = filterVertexPosition();\n vTextureCoord = filterTextureCoord();\n}\n";
4
+ var fragment = "in vec2 vTextureCoord;\nout vec4 finalColor;\nuniform sampler2D uTexture;\nvoid main() {\n finalColor = texture(uTexture, vTextureCoord);\n}\n";
5
+ var source = "struct GlobalFilterUniforms {\n uInputSize: vec4<f32>,\n uInputPixel: vec4<f32>,\n uInputClamp: vec4<f32>,\n uOutputFrame: vec4<f32>,\n uGlobalFrame: vec4<f32>,\n uOutputTexture: vec4<f32>,\n};\n\n@group(0) @binding(0) var <uniform> gfu: GlobalFilterUniforms;\n@group(0) @binding(1) var uTexture: texture_2d<f32>;\n@group(0) @binding(2) var uSampler: sampler;\n\nstruct VSOutput {\n @builtin(position) position: vec4<f32>,\n @location(0) uv: vec2<f32>\n};\n\nfn filterVertexPosition(aPosition: vec2<f32>) -> vec4<f32>\n{\n var position = aPosition * gfu.uOutputFrame.zw + gfu.uOutputFrame.xy;\n\n position.x = position.x * (2.0 / gfu.uOutputTexture.x) - 1.0;\n position.y = position.y * (2.0 * gfu.uOutputTexture.z / gfu.uOutputTexture.y) - gfu.uOutputTexture.z;\n\n return vec4(position, 0.0, 1.0);\n}\n\nfn filterTextureCoord(aPosition: vec2<f32>) -> vec2<f32>\n{\n return aPosition * (gfu.uOutputFrame.zw * gfu.uInputSize.zw);\n}\n\n@vertex\nfn mainVertex(\n @location(0) aPosition: vec2<f32>,\n) -> VSOutput {\n return VSOutput(\n filterVertexPosition(aPosition),\n filterTextureCoord(aPosition)\n );\n}\n\n@fragment\nfn mainFragment(\n @location(0) uv: vec2<f32>,\n) -> @location(0) vec4<f32> {\n return textureSample(uTexture, uSampler, uv);\n}\n";
6
+ class PassthroughFilter extends Filter {
7
+ constructor() {
8
+ const gpuProgram = GpuProgram.from({
9
+ vertex: { source, entryPoint: "mainVertex" },
10
+ fragment: { source, entryPoint: "mainFragment" },
11
+ name: "passthrough-filter"
12
+ });
13
+ const glProgram = GlProgram.from({
14
+ vertex,
15
+ fragment,
16
+ name: "passthrough-filter"
17
+ });
18
+ super({
19
+ gpuProgram,
20
+ glProgram
21
+ });
22
+ }
23
+ }
24
+ class FilterPipe {
25
+ constructor(renderer) {
26
+ this._renderer = renderer;
27
+ }
28
+ push(filterEffect, container, instructionSet) {
29
+ const renderPipes = this._renderer.renderPipes;
30
+ renderPipes.batch.break(instructionSet);
31
+ instructionSet.add({
32
+ renderPipeId: "filter",
33
+ canBundle: false,
34
+ action: "pushFilter",
35
+ container,
36
+ filterEffect
37
+ });
38
+ }
39
+ pop(_filterEffect, _container, instructionSet) {
40
+ this._renderer.renderPipes.batch.break(instructionSet);
41
+ instructionSet.add({
42
+ renderPipeId: "filter",
43
+ action: "popFilter",
44
+ canBundle: false
45
+ });
46
+ }
47
+ execute(instruction) {
48
+ if (instruction.action === "pushFilter") {
49
+ this._renderer.filter.push(instruction);
50
+ } else if (instruction.action === "popFilter") {
51
+ this._renderer.filter.pop();
52
+ }
53
+ }
54
+ destroy() {
55
+ this._renderer = null;
56
+ }
57
+ }
58
+ FilterPipe.extension = {
59
+ type: [
60
+ ExtensionType.WebGLPipes,
61
+ ExtensionType.WebGPUPipes,
62
+ ExtensionType.CanvasPipes
63
+ ],
64
+ name: "filter"
65
+ };
66
+ const tempProjectionMatrix = new Matrix();
67
+ function getGlobalRenderableBounds(renderables, bounds) {
68
+ bounds.clear();
69
+ const actualMatrix = bounds.matrix;
70
+ for (let i = 0; i < renderables.length; i++) {
71
+ const renderable = renderables[i];
72
+ if (renderable.globalDisplayStatus < 7) {
73
+ continue;
74
+ }
75
+ const renderGroup = renderable.renderGroup ?? renderable.parentRenderGroup;
76
+ if (renderGroup?.isCachedAsTexture) {
77
+ bounds.matrix = tempProjectionMatrix.copyFrom(renderGroup.textureOffsetInverseTransform).append(renderable.worldTransform);
78
+ } else if (renderGroup?._parentCacheAsTextureRenderGroup) {
79
+ bounds.matrix = tempProjectionMatrix.copyFrom(renderGroup._parentCacheAsTextureRenderGroup.inverseWorldTransform).append(renderable.groupTransform);
80
+ } else {
81
+ bounds.matrix = renderable.worldTransform;
82
+ }
83
+ bounds.addBounds(renderable.bounds);
84
+ }
85
+ bounds.matrix = actualMatrix;
86
+ return bounds;
87
+ }
88
+ const quadGeometry = new Geometry({
89
+ attributes: {
90
+ aPosition: {
91
+ buffer: new Float32Array([0, 0, 1, 0, 1, 1, 0, 1]),
92
+ format: "float32x2",
93
+ stride: 2 * 4,
94
+ offset: 0
95
+ }
96
+ },
97
+ indexBuffer: new Uint32Array([0, 1, 2, 0, 2, 3])
98
+ });
99
+ class FilterData {
100
+ constructor() {
101
+ this.skip = false;
102
+ this.inputTexture = null;
103
+ this.backTexture = null;
104
+ this.filters = null;
105
+ this.bounds = new Bounds();
106
+ this.container = null;
107
+ this.blendRequired = false;
108
+ this.outputRenderSurface = null;
109
+ this.globalFrame = { x: 0, y: 0, width: 0, height: 0 };
110
+ this.firstEnabledIndex = -1;
111
+ this.lastEnabledIndex = -1;
112
+ }
113
+ }
114
+ class FilterSystem {
115
+ constructor(renderer) {
116
+ this._filterStackIndex = 0;
117
+ this._filterStack = [];
118
+ this._filterGlobalUniforms = new UniformGroup({
119
+ uInputSize: { value: new Float32Array(4), type: "vec4<f32>" },
120
+ uInputPixel: { value: new Float32Array(4), type: "vec4<f32>" },
121
+ uInputClamp: { value: new Float32Array(4), type: "vec4<f32>" },
122
+ uOutputFrame: { value: new Float32Array(4), type: "vec4<f32>" },
123
+ uGlobalFrame: { value: new Float32Array(4), type: "vec4<f32>" },
124
+ uOutputTexture: { value: new Float32Array(4), type: "vec4<f32>" }
125
+ });
126
+ this._globalFilterBindGroup = new BindGroup({});
127
+ this.renderer = renderer;
128
+ }
129
+ /**
130
+ * The back texture of the currently active filter. Requires the filter to have `blendRequired` set to true.
131
+ * @readonly
132
+ */
133
+ get activeBackTexture() {
134
+ return this._activeFilterData?.backTexture;
135
+ }
136
+ /**
137
+ * Pushes a filter instruction onto the filter stack.
138
+ * @param instruction - The instruction containing the filter effect and container.
139
+ * @internal
140
+ */
141
+ push(instruction) {
142
+ const renderer = this.renderer;
143
+ const filters = instruction.filterEffect.filters;
144
+ const filterData = this._pushFilterData();
145
+ filterData.skip = false;
146
+ filterData.filters = filters;
147
+ filterData.container = instruction.container;
148
+ filterData.outputRenderSurface = renderer.renderTarget.renderSurface;
149
+ const colorTextureSource = renderer.renderTarget.renderTarget.colorTexture.source;
150
+ const rootResolution = colorTextureSource.resolution;
151
+ const rootAntialias = colorTextureSource.antialias;
152
+ if (filters.every((filter) => !filter.enabled)) {
153
+ filterData.skip = true;
154
+ return;
155
+ }
156
+ const bounds = filterData.bounds;
157
+ this._calculateFilterArea(instruction, bounds);
158
+ this._calculateFilterBounds(filterData, renderer.renderTarget.rootViewPort, rootAntialias, rootResolution, 1);
159
+ if (filterData.skip) {
160
+ return;
161
+ }
162
+ const previousFilterData = this._getPreviousFilterData();
163
+ const globalResolution = this._findFilterResolution(rootResolution);
164
+ let offsetX = 0;
165
+ let offsetY = 0;
166
+ if (previousFilterData) {
167
+ offsetX = previousFilterData.bounds.minX;
168
+ offsetY = previousFilterData.bounds.minY;
169
+ }
170
+ this._calculateGlobalFrame(
171
+ filterData,
172
+ offsetX,
173
+ offsetY,
174
+ globalResolution,
175
+ colorTextureSource.width,
176
+ colorTextureSource.height
177
+ );
178
+ this._setupFilterTextures(filterData, bounds, renderer, previousFilterData);
179
+ }
180
+ /**
181
+ * Applies filters to a texture.
182
+ *
183
+ * This method takes a texture and a list of filters, applies the filters to the texture,
184
+ * and returns the resulting texture.
185
+ * @param {object} params - The parameters for applying filters.
186
+ * @param {Texture} params.texture - The texture to apply filters to.
187
+ * @param {Filter[]} params.filters - The filters to apply.
188
+ * @returns {Texture} The resulting texture after all filters have been applied.
189
+ * @example
190
+ *
191
+ * ```ts
192
+ * // Create a texture and a list of filters
193
+ * const texture = new Texture(...);
194
+ * const filters = [new BlurFilter(), new ColorMatrixFilter()];
195
+ *
196
+ * // Apply the filters to the texture
197
+ * const resultTexture = filterSystem.applyToTexture({ texture, filters });
198
+ *
199
+ * // Use the resulting texture
200
+ * sprite.texture = resultTexture;
201
+ * ```
202
+ *
203
+ * Key Points:
204
+ * 1. padding is not currently supported here - so clipping may occur with filters that use padding.
205
+ * 2. If all filters are disabled or skipped, the original texture is returned.
206
+ */
207
+ generateFilteredTexture({ texture, filters }) {
208
+ const filterData = this._pushFilterData();
209
+ this._activeFilterData = filterData;
210
+ filterData.skip = false;
211
+ filterData.filters = filters;
212
+ const colorTextureSource = texture.source;
213
+ const rootResolution = colorTextureSource.resolution;
214
+ const rootAntialias = colorTextureSource.antialias;
215
+ if (filters.every((filter) => !filter.enabled)) {
216
+ filterData.skip = true;
217
+ return texture;
218
+ }
219
+ const bounds = filterData.bounds;
220
+ bounds.addRect(texture.frame);
221
+ this._calculateFilterBounds(filterData, bounds.rectangle, rootAntialias, rootResolution, 0);
222
+ if (filterData.skip) {
223
+ return texture;
224
+ }
225
+ const globalResolution = rootResolution;
226
+ const offsetX = 0;
227
+ const offsetY = 0;
228
+ this._calculateGlobalFrame(
229
+ filterData,
230
+ offsetX,
231
+ offsetY,
232
+ globalResolution,
233
+ colorTextureSource.width,
234
+ colorTextureSource.height
235
+ );
236
+ filterData.outputRenderSurface = TexturePool.getOptimalTexture(
237
+ bounds.width,
238
+ bounds.height,
239
+ filterData.resolution,
240
+ filterData.antialias
241
+ );
242
+ filterData.backTexture = Texture.EMPTY;
243
+ filterData.inputTexture = texture;
244
+ const renderer = this.renderer;
245
+ renderer.renderTarget.finishRenderPass();
246
+ this._applyFiltersToTexture(filterData, true);
247
+ const outputTexture = filterData.outputRenderSurface;
248
+ outputTexture.source.alphaMode = "premultiplied-alpha";
249
+ return outputTexture;
250
+ }
251
+ /** @internal */
252
+ pop() {
253
+ const renderer = this.renderer;
254
+ const filterData = this._popFilterData();
255
+ if (filterData.skip) {
256
+ return;
257
+ }
258
+ renderer.globalUniforms.pop();
259
+ renderer.renderTarget.finishRenderPass();
260
+ this._activeFilterData = filterData;
261
+ this._applyFiltersToTexture(filterData, false);
262
+ if (filterData.blendRequired) {
263
+ TexturePool.returnTexture(filterData.backTexture);
264
+ }
265
+ TexturePool.returnTexture(filterData.inputTexture);
266
+ }
267
+ /**
268
+ * Copies the last render surface to a texture.
269
+ * @param lastRenderSurface - The last render surface to copy from.
270
+ * @param bounds - The bounds of the area to copy.
271
+ * @param previousBounds - The previous bounds to use for offsetting the copy.
272
+ */
273
+ getBackTexture(lastRenderSurface, bounds, previousBounds) {
274
+ const backgroundResolution = lastRenderSurface.colorTexture.source._resolution;
275
+ const backTexture = TexturePool.getOptimalTexture(
276
+ bounds.width,
277
+ bounds.height,
278
+ backgroundResolution,
279
+ false
280
+ );
281
+ let x = bounds.minX;
282
+ let y = bounds.minY;
283
+ if (previousBounds) {
284
+ x -= previousBounds.minX;
285
+ y -= previousBounds.minY;
286
+ }
287
+ x = Math.floor(x * backgroundResolution);
288
+ y = Math.floor(y * backgroundResolution);
289
+ const width = Math.ceil(bounds.width * backgroundResolution);
290
+ const height = Math.ceil(bounds.height * backgroundResolution);
291
+ this.renderer.renderTarget.copyToTexture(
292
+ lastRenderSurface,
293
+ backTexture,
294
+ { x, y },
295
+ { width, height },
296
+ { x: 0, y: 0 }
297
+ );
298
+ return backTexture;
299
+ }
300
+ /**
301
+ * Applies a filter to a texture.
302
+ * @param filter - The filter to apply.
303
+ * @param input - The input texture.
304
+ * @param output - The output render surface.
305
+ * @param clear - Whether to clear the output surface before applying the filter.
306
+ */
307
+ applyFilter(filter, input, output, clear) {
308
+ const renderer = this.renderer;
309
+ const filterData = this._activeFilterData;
310
+ const outputRenderSurface = filterData.outputRenderSurface;
311
+ const isFinalTarget = outputRenderSurface === output;
312
+ const rootResolution = renderer.renderTarget.rootRenderTarget.colorTexture.source._resolution;
313
+ const resolution = this._findFilterResolution(rootResolution);
314
+ let offsetX = 0;
315
+ let offsetY = 0;
316
+ if (isFinalTarget) {
317
+ const offset = this._findPreviousFilterOffset();
318
+ offsetX = offset.x;
319
+ offsetY = offset.y;
320
+ }
321
+ this._updateFilterUniforms(input, output, filterData, offsetX, offsetY, resolution, isFinalTarget, clear);
322
+ const filterToApply = filter.enabled ? filter : this._getPassthroughFilter();
323
+ this._setupBindGroupsAndRender(filterToApply, input, renderer);
324
+ }
325
+ /**
326
+ * Multiply _input normalized coordinates_ to this matrix to get _sprite texture normalized coordinates_.
327
+ *
328
+ * Use `outputMatrix * vTextureCoord` in the shader.
329
+ * @param outputMatrix - The matrix to output to.
330
+ * @param {Sprite} sprite - The sprite to map to.
331
+ * @returns The mapped matrix.
332
+ */
333
+ calculateSpriteMatrix(outputMatrix, sprite) {
334
+ const data = this._activeFilterData;
335
+ const mappedMatrix = outputMatrix.set(
336
+ data.inputTexture._source.width,
337
+ 0,
338
+ 0,
339
+ data.inputTexture._source.height,
340
+ data.bounds.minX,
341
+ data.bounds.minY
342
+ );
343
+ const worldTransform = sprite.worldTransform.copyTo(Matrix.shared);
344
+ const renderGroup = sprite.renderGroup || sprite.parentRenderGroup;
345
+ if (renderGroup && renderGroup.cacheToLocalTransform) {
346
+ worldTransform.prepend(renderGroup.cacheToLocalTransform);
347
+ }
348
+ worldTransform.invert();
349
+ mappedMatrix.prepend(worldTransform);
350
+ mappedMatrix.scale(
351
+ 1 / sprite.texture.orig.width,
352
+ 1 / sprite.texture.orig.height
353
+ );
354
+ mappedMatrix.translate(sprite.anchor.x, sprite.anchor.y);
355
+ return mappedMatrix;
356
+ }
357
+ destroy() {
358
+ this._passthroughFilter?.destroy(true);
359
+ this._passthroughFilter = null;
360
+ }
361
+ _getPassthroughFilter() {
362
+ this._passthroughFilter ?? (this._passthroughFilter = new PassthroughFilter());
363
+ return this._passthroughFilter;
364
+ }
365
+ /**
366
+ * Sets up the bind groups and renders the filter.
367
+ * @param filter - The filter to apply
368
+ * @param input - The input texture
369
+ * @param renderer - The renderer instance
370
+ */
371
+ _setupBindGroupsAndRender(filter, input, renderer) {
372
+ if (renderer.renderPipes.uniformBatch) {
373
+ const batchUniforms = renderer.renderPipes.uniformBatch.getUboResource(this._filterGlobalUniforms);
374
+ this._globalFilterBindGroup.setResource(batchUniforms, 0);
375
+ } else {
376
+ this._globalFilterBindGroup.setResource(this._filterGlobalUniforms, 0);
377
+ }
378
+ this._globalFilterBindGroup.setResource(input.source, 1);
379
+ this._globalFilterBindGroup.setResource(input.source.style, 2);
380
+ filter.groups[0] = this._globalFilterBindGroup;
381
+ renderer.encoder.draw({
382
+ geometry: quadGeometry,
383
+ shader: filter,
384
+ state: filter._state,
385
+ topology: "triangle-list"
386
+ });
387
+ if (renderer.type === RendererType.WEBGL) {
388
+ renderer.renderTarget.finishRenderPass();
389
+ }
390
+ }
391
+ /**
392
+ * Sets up the filter textures including input texture and back texture if needed.
393
+ * @param filterData - The filter data to update
394
+ * @param bounds - The bounds for the texture
395
+ * @param renderer - The renderer instance
396
+ * @param previousFilterData - The previous filter data for back texture calculation
397
+ */
398
+ _setupFilterTextures(filterData, bounds, renderer, previousFilterData) {
399
+ filterData.backTexture = Texture.EMPTY;
400
+ filterData.inputTexture = TexturePool.getOptimalTexture(
401
+ bounds.width,
402
+ bounds.height,
403
+ filterData.resolution,
404
+ filterData.antialias
405
+ );
406
+ if (filterData.blendRequired) {
407
+ renderer.renderTarget.finishRenderPass();
408
+ const renderTarget = renderer.renderTarget.getRenderTarget(filterData.outputRenderSurface);
409
+ filterData.backTexture = this.getBackTexture(renderTarget, bounds, previousFilterData?.bounds);
410
+ }
411
+ renderer.renderTarget.bind(filterData.inputTexture, true);
412
+ renderer.globalUniforms.push({
413
+ offset: bounds
414
+ });
415
+ }
416
+ /**
417
+ * Calculates and sets the global frame for the filter.
418
+ * @param filterData - The filter data to update
419
+ * @param offsetX - The X offset
420
+ * @param offsetY - The Y offset
421
+ * @param globalResolution - The global resolution
422
+ * @param sourceWidth - The source texture width
423
+ * @param sourceHeight - The source texture height
424
+ */
425
+ _calculateGlobalFrame(filterData, offsetX, offsetY, globalResolution, sourceWidth, sourceHeight) {
426
+ const globalFrame = filterData.globalFrame;
427
+ globalFrame.x = offsetX * globalResolution;
428
+ globalFrame.y = offsetY * globalResolution;
429
+ globalFrame.width = sourceWidth * globalResolution;
430
+ globalFrame.height = sourceHeight * globalResolution;
431
+ }
432
+ /**
433
+ * Updates the filter uniforms with the current filter state.
434
+ * @param input - The input texture
435
+ * @param output - The output render surface
436
+ * @param filterData - The current filter data
437
+ * @param offsetX - The X offset for positioning
438
+ * @param offsetY - The Y offset for positioning
439
+ * @param resolution - The current resolution
440
+ * @param isFinalTarget - Whether this is the final render target
441
+ * @param clear - Whether to clear the output surface
442
+ */
443
+ _updateFilterUniforms(input, output, filterData, offsetX, offsetY, resolution, isFinalTarget, clear) {
444
+ const uniforms = this._filterGlobalUniforms.uniforms;
445
+ const outputFrame = uniforms.uOutputFrame;
446
+ const inputSize = uniforms.uInputSize;
447
+ const inputPixel = uniforms.uInputPixel;
448
+ const inputClamp = uniforms.uInputClamp;
449
+ const globalFrame = uniforms.uGlobalFrame;
450
+ const outputTexture = uniforms.uOutputTexture;
451
+ if (isFinalTarget) {
452
+ outputFrame[0] = filterData.bounds.minX - offsetX;
453
+ outputFrame[1] = filterData.bounds.minY - offsetY;
454
+ } else {
455
+ outputFrame[0] = 0;
456
+ outputFrame[1] = 0;
457
+ }
458
+ outputFrame[2] = input.frame.width;
459
+ outputFrame[3] = input.frame.height;
460
+ inputSize[0] = input.source.width;
461
+ inputSize[1] = input.source.height;
462
+ inputSize[2] = 1 / inputSize[0];
463
+ inputSize[3] = 1 / inputSize[1];
464
+ inputPixel[0] = input.source.pixelWidth;
465
+ inputPixel[1] = input.source.pixelHeight;
466
+ inputPixel[2] = 1 / inputPixel[0];
467
+ inputPixel[3] = 1 / inputPixel[1];
468
+ inputClamp[0] = 0.5 * inputPixel[2];
469
+ inputClamp[1] = 0.5 * inputPixel[3];
470
+ inputClamp[2] = input.frame.width * inputSize[2] - 0.5 * inputPixel[2];
471
+ inputClamp[3] = input.frame.height * inputSize[3] - 0.5 * inputPixel[3];
472
+ const rootTexture = this.renderer.renderTarget.rootRenderTarget.colorTexture;
473
+ globalFrame[0] = offsetX * resolution;
474
+ globalFrame[1] = offsetY * resolution;
475
+ globalFrame[2] = rootTexture.source.width * resolution;
476
+ globalFrame[3] = rootTexture.source.height * resolution;
477
+ if (output instanceof Texture) output.source.resource = null;
478
+ const renderTarget = this.renderer.renderTarget.getRenderTarget(output);
479
+ this.renderer.renderTarget.bind(output, !!clear);
480
+ if (output instanceof Texture) {
481
+ outputTexture[0] = output.frame.width;
482
+ outputTexture[1] = output.frame.height;
483
+ } else {
484
+ outputTexture[0] = renderTarget.width;
485
+ outputTexture[1] = renderTarget.height;
486
+ }
487
+ outputTexture[2] = renderTarget.isRoot ? -1 : 1;
488
+ this._filterGlobalUniforms.update();
489
+ }
490
+ /**
491
+ * Finds the correct resolution by looking back through the filter stack.
492
+ * @param rootResolution - The fallback root resolution to use
493
+ * @returns The resolution from the previous filter or root resolution
494
+ */
495
+ _findFilterResolution(rootResolution) {
496
+ let currentIndex = this._filterStackIndex - 1;
497
+ while (currentIndex > 0 && this._filterStack[currentIndex].skip) {
498
+ --currentIndex;
499
+ }
500
+ return currentIndex > 0 && this._filterStack[currentIndex].inputTexture ? this._filterStack[currentIndex].inputTexture.source._resolution : rootResolution;
501
+ }
502
+ /**
503
+ * Finds the offset from the previous non-skipped filter in the stack.
504
+ * @returns The offset coordinates from the previous filter
505
+ */
506
+ _findPreviousFilterOffset() {
507
+ let offsetX = 0;
508
+ let offsetY = 0;
509
+ let lastIndex = this._filterStackIndex;
510
+ while (lastIndex > 0) {
511
+ lastIndex--;
512
+ const prevFilterData = this._filterStack[lastIndex];
513
+ if (!prevFilterData.skip) {
514
+ offsetX = prevFilterData.bounds.minX;
515
+ offsetY = prevFilterData.bounds.minY;
516
+ break;
517
+ }
518
+ }
519
+ return { x: offsetX, y: offsetY };
520
+ }
521
+ /**
522
+ * Calculates the filter area bounds based on the instruction type.
523
+ * @param instruction - The filter instruction
524
+ * @param bounds - The bounds object to populate
525
+ */
526
+ _calculateFilterArea(instruction, bounds) {
527
+ if (instruction.renderables) {
528
+ getGlobalRenderableBounds(instruction.renderables, bounds);
529
+ } else if (instruction.filterEffect.filterArea) {
530
+ bounds.clear();
531
+ bounds.addRect(instruction.filterEffect.filterArea);
532
+ bounds.applyMatrix(instruction.container.worldTransform);
533
+ } else {
534
+ instruction.container.getFastGlobalBounds(true, bounds);
535
+ }
536
+ if (instruction.container) {
537
+ const renderGroup = instruction.container.renderGroup || instruction.container.parentRenderGroup;
538
+ const filterFrameTransform = renderGroup.cacheToLocalTransform;
539
+ if (filterFrameTransform) {
540
+ bounds.applyMatrix(filterFrameTransform);
541
+ }
542
+ }
543
+ }
544
+ _applyFiltersToTexture(filterData, clear) {
545
+ const inputTexture = filterData.inputTexture;
546
+ const bounds = filterData.bounds;
547
+ const filters = filterData.filters;
548
+ const firstEnabled = filterData.firstEnabledIndex;
549
+ const lastEnabled = filterData.lastEnabledIndex;
550
+ this._globalFilterBindGroup.setResource(inputTexture.source.style, 2);
551
+ this._globalFilterBindGroup.setResource(filterData.backTexture.source, 3);
552
+ if (firstEnabled === lastEnabled) {
553
+ filters[firstEnabled].apply(this, inputTexture, filterData.outputRenderSurface, clear);
554
+ } else {
555
+ let flip = filterData.inputTexture;
556
+ const tempTexture = TexturePool.getOptimalTexture(
557
+ bounds.width,
558
+ bounds.height,
559
+ flip.source._resolution,
560
+ false
561
+ );
562
+ let flop = tempTexture;
563
+ for (let i = firstEnabled; i < lastEnabled; i++) {
564
+ const filter = filters[i];
565
+ if (!filter.enabled) continue;
566
+ filter.apply(this, flip, flop, true);
567
+ const t = flip;
568
+ flip = flop;
569
+ flop = t;
570
+ }
571
+ filters[lastEnabled].apply(this, flip, filterData.outputRenderSurface, clear);
572
+ TexturePool.returnTexture(tempTexture);
573
+ }
574
+ }
575
+ _calculateFilterBounds(filterData, viewPort, rootAntialias, rootResolution, paddingMultiplier) {
576
+ const renderer = this.renderer;
577
+ const bounds = filterData.bounds;
578
+ const filters = filterData.filters;
579
+ let resolution = Infinity;
580
+ let padding = 0;
581
+ let antialias = true;
582
+ let blendRequired = false;
583
+ let enabled = false;
584
+ let clipToViewport = true;
585
+ let firstEnabledIndex = -1;
586
+ let lastEnabledIndex = -1;
587
+ for (let i = 0; i < filters.length; i++) {
588
+ const filter = filters[i];
589
+ if (!filter.enabled) continue;
590
+ if (firstEnabledIndex === -1) firstEnabledIndex = i;
591
+ lastEnabledIndex = i;
592
+ resolution = Math.min(resolution, filter.resolution === "inherit" ? rootResolution : filter.resolution);
593
+ padding += filter.padding;
594
+ if (filter.antialias === "off") {
595
+ antialias = false;
596
+ } else if (filter.antialias === "inherit") {
597
+ antialias && (antialias = rootAntialias);
598
+ }
599
+ if (!filter.clipToViewport) {
600
+ clipToViewport = false;
601
+ }
602
+ const isCompatible = !!(filter.compatibleRenderers & renderer.type);
603
+ if (!isCompatible) {
604
+ enabled = false;
605
+ break;
606
+ }
607
+ if (filter.blendRequired && !(renderer.backBuffer?.useBackBuffer ?? true)) {
608
+ warn("Blend filter requires backBuffer on WebGL renderer to be enabled. Set `useBackBuffer: true` in the renderer options.");
609
+ enabled = false;
610
+ break;
611
+ }
612
+ enabled = true;
613
+ blendRequired || (blendRequired = filter.blendRequired);
614
+ }
615
+ if (!enabled) {
616
+ filterData.skip = true;
617
+ return;
618
+ }
619
+ if (clipToViewport) {
620
+ bounds.fitBounds(0, viewPort.width / rootResolution, 0, viewPort.height / rootResolution);
621
+ }
622
+ bounds.scale(resolution).ceil().scale(1 / resolution).pad((padding | 0) * paddingMultiplier);
623
+ if (!bounds.isPositive) {
624
+ filterData.skip = true;
625
+ return;
626
+ }
627
+ filterData.antialias = antialias;
628
+ filterData.resolution = resolution;
629
+ filterData.blendRequired = blendRequired;
630
+ filterData.firstEnabledIndex = firstEnabledIndex;
631
+ filterData.lastEnabledIndex = lastEnabledIndex;
632
+ }
633
+ _popFilterData() {
634
+ this._filterStackIndex--;
635
+ return this._filterStack[this._filterStackIndex];
636
+ }
637
+ _getPreviousFilterData() {
638
+ let previousFilterData;
639
+ let index = this._filterStackIndex - 1;
640
+ while (index > 0) {
641
+ index--;
642
+ previousFilterData = this._filterStack[index];
643
+ if (!previousFilterData.skip) {
644
+ break;
645
+ }
646
+ }
647
+ return previousFilterData;
648
+ }
649
+ _pushFilterData() {
650
+ let filterData = this._filterStack[this._filterStackIndex];
651
+ if (!filterData) {
652
+ filterData = this._filterStack[this._filterStackIndex] = new FilterData();
653
+ }
654
+ this._filterStackIndex++;
655
+ return filterData;
656
+ }
657
+ }
658
+ FilterSystem.extension = {
659
+ type: [
660
+ ExtensionType.WebGLSystem,
661
+ ExtensionType.WebGPUSystem
662
+ ],
663
+ name: "filter"
664
+ };
665
+ extensions.add(FilterSystem);
666
+ extensions.add(FilterPipe);
@@ -0,0 +1,12 @@
1
+ import "../entry-server.js";
2
+ import "./init-CnkBvt-J.js";
3
+ import "util";
4
+ import "crypto";
5
+ import "async_hooks";
6
+ import "stream";
7
+ import "process";
8
+ import "buffer";
9
+ import "node:process";
10
+ import "node:path";
11
+ import "node:url";
12
+ import "./Filter-ClU0-pLL.js";