@taole/giftstage 0.3.2 → 0.3.3
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/README.md +96 -85
- package/dist/gift-stage.cjs +609 -609
- package/dist/gift-stage.es.js +611 -610
- package/package.json +3 -3
package/dist/gift-stage.es.js
CHANGED
|
@@ -85,186 +85,186 @@ void main() {\r
|
|
|
85
85
|
vec4 c = texture(u_atlas, v_uv);\r
|
|
86
86
|
fragColor = vec4(c.rgb * v_color.rgb * v_color.a, c.a * v_color.a);\r
|
|
87
87
|
}\r
|
|
88
|
-
`, RE = `#version 300 es
|
|
89
|
-
precision highp float
|
|
90
|
-
precision highp int
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
* Table-aware SVGA instanced vertex stage
|
|
94
|
-
|
|
95
|
-
* The frame table is a RGBA32F/NEAREST texture with three texels per
|
|
96
|
-
* (sprite, frame) row
|
|
97
|
-
* texel 0 = layoutW, layoutH, a, b
|
|
98
|
-
* texel 1 = c, d, tx, ty
|
|
99
|
-
* texel 2 = alpha, 0, 0, 0
|
|
100
|
-
|
|
101
|
-
* Static sprite metadata is a second RGBA32F/NEAREST texture with two texels
|
|
102
|
-
* per row
|
|
103
|
-
* texel 0 = atlas UV min.xy / max.xy
|
|
104
|
-
* texel 1 = sourceSpriteIndex, atlasPage, flags, reserved
|
|
105
|
-
|
|
106
|
-
* One draw covers a single atlas page of one slot. \`gl_InstanceID\` selects a
|
|
107
|
-
* metadata row (\`u_spriteBase + gl_InstanceID\`), so the only per-frame CPU
|
|
108
|
-
* state is the slot transform/opacity/clip and the authoritative frame index
|
|
109
|
-
|
|
110
|
-
layout(location = 0) in vec2 a_corner
|
|
111
|
-
// Optional Hybrid scheduling row. Direct draws leave these attributes disabled
|
|
112
|
-
// and use the uniform slot state below
|
|
113
|
-
layout(location = 1) in vec4 a_instanceParent
|
|
114
|
-
layout(location = 2) in vec4 a_instanceTranslateOpacityFrame
|
|
115
|
-
layout(location = 3) in vec4 a_instanceClipRect
|
|
116
|
-
/** x=clipEnabled, y=metadataRow, z=atlasPage, w=present.
|
|
117
|
-
layout(location = 4) in vec4 a_instanceInfo
|
|
118
|
-
|
|
119
|
-
uniform mat4 u_projection
|
|
120
|
-
uniform highp sampler2D u_frameTable
|
|
121
|
-
uniform highp sampler2D u_spriteMetadata
|
|
122
|
-
|
|
123
|
-
* Canonical compact state (four RGBA32F texels / 16 floats)
|
|
124
|
-
* affine; translate+opacity+frame; clip rect; clipEnabled+metadataBase+atlasPage+track+1
|
|
125
|
-
|
|
126
|
-
uniform highp sampler2D u_slotStates
|
|
127
|
-
/** x = frameCount, y = spriteCount, z = texels per frame (3), w = default frame.
|
|
128
|
-
uniform ivec4 u_tableInfo
|
|
129
|
-
/** x/y = frame-table texture width/height in texels.
|
|
130
|
-
uniform ivec2 u_frameTableSize
|
|
131
|
-
/** x/y = sprite metadata texture width/height in texels.
|
|
132
|
-
uniform ivec2 u_spriteMetadataSize
|
|
133
|
-
uniform int u_spriteMetadataTexelsPerRow
|
|
134
|
-
uniform ivec2 u_slotStateSize
|
|
135
|
-
/** First static metadata row consumed by this slot/page draw.
|
|
136
|
-
uniform int u_spriteBase
|
|
137
|
-
/** Authoritative SVGA frame selected by RenderManager/PlaybackScope.
|
|
138
|
-
uniform int u_frameIndex
|
|
139
|
-
uniform vec4 u_parentAffine
|
|
140
|
-
uniform vec2 u_parentTranslate
|
|
141
|
-
uniform float u_slotOpacity
|
|
142
|
-
/** Atlas page for this draw; negative means metadata page filtering is disabled.
|
|
143
|
-
uniform int u_atlasPage
|
|
144
|
-
uniform vec4 u_clipRect
|
|
145
|
-
uniform float u_clipEnabled
|
|
146
|
-
/** WebGL's gl_FragCoord has a bottom-left origin; input clip rects are top-left.
|
|
147
|
-
uniform float u_canvasHeight
|
|
148
|
-
uniform float u_instanceStateEnabled
|
|
149
|
-
uniform float u_compactSlotStateEnabled
|
|
150
|
-
uniform int u_spritesPerSlot
|
|
151
|
-
|
|
152
|
-
out vec2 v_uv
|
|
153
|
-
out vec4 v_color
|
|
154
|
-
flat out vec4 v_clipRect
|
|
155
|
-
flat out float v_clipEnabled
|
|
156
|
-
out vec2 v_localPosition
|
|
157
|
-
flat out vec4 v_localClipRect
|
|
158
|
-
flat out float v_localClipEnabled
|
|
159
|
-
|
|
160
|
-
ivec2 texelCoord(int linearIndex, ivec2 textureSize) {
|
|
161
|
-
int width = max(textureSize.x, 1)
|
|
162
|
-
return ivec2(linearIndex - (linearIndex / width) * width, linearIndex / width)
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
void main() {
|
|
166
|
-
int frameCount = max(u_tableInfo.x, 1)
|
|
167
|
-
int spriteCount = max(u_tableInfo.y, 1)
|
|
168
|
-
bool instanceState = u_instanceStateEnabled > 0.5
|
|
169
|
-
bool compactSlotState = u_compactSlotStateEnabled > 0.5
|
|
170
|
-
int spritesPerSlot = max(u_spritesPerSlot, 1)
|
|
171
|
-
int slotStateIndex = gl_InstanceID / spritesPerSlot
|
|
172
|
-
int spriteWithinSlot = gl_InstanceID - slotStateIndex * spritesPerSlot
|
|
173
|
-
vec4 compactParent = vec4(0.0)
|
|
174
|
-
vec4 compactTranslateOpacityFrame = vec4(0.0)
|
|
175
|
-
vec4 compactClip = vec4(0.0)
|
|
176
|
-
vec4 compactInfo = vec4(0.0)
|
|
177
|
-
if (compactSlotState) {
|
|
178
|
-
int compactBase = slotStateIndex * 4
|
|
179
|
-
compactParent = texelFetch(u_slotStates, texelCoord(compactBase, u_slotStateSize), 0)
|
|
180
|
-
compactTranslateOpacityFrame = texelFetch(u_slotStates, texelCoord(compactBase + 1, u_slotStateSize), 0)
|
|
181
|
-
compactClip = texelFetch(u_slotStates, texelCoord(compactBase + 2, u_slotStateSize), 0)
|
|
182
|
-
compactInfo = texelFetch(u_slotStates, texelCoord(compactBase + 3, u_slotStateSize), 0)
|
|
183
|
-
}
|
|
184
|
-
int metadataRow = instanceState
|
|
185
|
-
? max(int(a_instanceInfo.y + 0.5), 0)
|
|
186
|
-
: compactSlotState
|
|
187
|
-
? max(u_spriteBase + spriteWithinSlot, 0)
|
|
188
|
-
: max(u_spriteBase + gl_InstanceID, 0)
|
|
189
|
-
int metadataStride = max(u_spriteMetadataTexelsPerRow, 2)
|
|
190
|
-
int metadataTexel = metadataRow * metadataStride
|
|
191
|
-
vec4 metadata0 = texelFetch(
|
|
192
|
-
u_spriteMetadata
|
|
193
|
-
texelCoord(metadataTexel, u_spriteMetadataSize)
|
|
194
|
-
0
|
|
195
|
-
)
|
|
196
|
-
vec4 metadata1 = texelFetch(
|
|
197
|
-
u_spriteMetadata
|
|
198
|
-
texelCoord(metadataTexel + 1, u_spriteMetadataSize)
|
|
199
|
-
0
|
|
200
|
-
)
|
|
201
|
-
vec4 metadata2 = metadataStride >= 3
|
|
202
|
-
? texelFetch(u_spriteMetadata, texelCoord(metadataTexel + 2, u_spriteMetadataSize), 0)
|
|
203
|
-
: vec4(0.0)
|
|
204
|
-
// Metadata carries the source sprite index so a page-specific range can
|
|
205
|
-
// represent non-contiguous atlas pages. Its y component is the atlas page
|
|
206
|
-
int spriteIndex = clamp(int(max(metadata1.x, 0.0) + 0.5), 0, spriteCount - 1)
|
|
207
|
-
int frameIndex = instanceState
|
|
208
|
-
? int(a_instanceTranslateOpacityFrame.w + 0.5)
|
|
209
|
-
: compactSlotState
|
|
210
|
-
? int(compactTranslateOpacityFrame.w + 0.5)
|
|
211
|
-
: u_frameIndex
|
|
212
|
-
if (frameIndex < 0) frameIndex = u_tableInfo.w
|
|
213
|
-
frameIndex = clamp(frameIndex, 0, frameCount - 1)
|
|
214
|
-
|
|
215
|
-
int row = spriteIndex * frameCount + frameIndex
|
|
216
|
-
int frameTexel = row * u_tableInfo.z
|
|
217
|
-
vec4 frame0 = texelFetch(u_frameTable, texelCoord(frameTexel, u_frameTableSize), 0)
|
|
218
|
-
vec4 frame1 = texelFetch(u_frameTable, texelCoord(frameTexel + 1, u_frameTableSize), 0)
|
|
219
|
-
vec4 frame2 = texelFetch(u_frameTable, texelCoord(frameTexel + 2, u_frameTableSize), 0)
|
|
220
|
-
|
|
221
|
-
float layoutW = frame0.x
|
|
222
|
-
float layoutH = frame0.y
|
|
223
|
-
vec2 local = vec2(
|
|
224
|
-
frame0.z * layoutW * a_corner.x + frame1.x * layoutH * a_corner.y + frame1.z
|
|
225
|
-
frame0.w * layoutW * a_corner.x + frame1.y * layoutH * a_corner.y + frame1.w
|
|
226
|
-
)
|
|
227
|
-
|
|
228
|
-
vec4 parentAffine = instanceState
|
|
229
|
-
? a_instanceParent
|
|
230
|
-
: compactSlotState ? compactParent : u_parentAffine
|
|
231
|
-
vec2 parentTranslate = instanceState
|
|
232
|
-
? a_instanceTranslateOpacityFrame.xy
|
|
233
|
-
: compactSlotState ? compactTranslateOpacityFrame.xy : u_parentTranslate
|
|
234
|
-
float slotOpacity = instanceState
|
|
235
|
-
? a_instanceTranslateOpacityFrame.z
|
|
236
|
-
: compactSlotState ? compactTranslateOpacityFrame.z : u_slotOpacity
|
|
237
|
-
int atlasPage = instanceState
|
|
238
|
-
? int(a_instanceInfo.z + 0.5)
|
|
239
|
-
: compactSlotState
|
|
240
|
-
? (compactInfo.z < -0.5 ? -1 : int(compactInfo.z + 0.5))
|
|
241
|
-
: u_atlasPage
|
|
242
|
-
vec4 clipRect = instanceState
|
|
243
|
-
? a_instanceClipRect
|
|
244
|
-
: compactSlotState ? compactClip : u_clipRect
|
|
245
|
-
float clipEnabled = instanceState
|
|
246
|
-
? a_instanceInfo.x
|
|
247
|
-
: compactSlotState ? compactInfo.x : u_clipEnabled
|
|
248
|
-
vec2 world = vec2(
|
|
249
|
-
parentAffine.x * local.x + parentAffine.z * local.y + parentTranslate.x
|
|
250
|
-
parentAffine.y * local.x + parentAffine.w * local.y + parentTranslate.y
|
|
251
|
-
)
|
|
252
|
-
|
|
253
|
-
gl_Position = u_projection * vec4(world, 0.0, 1.0)
|
|
254
|
-
v_uv = mix(metadata0.xy, metadata0.zw, a_corner)
|
|
255
|
-
bool pageMatches = atlasPage < 0 || int(max(metadata1.y, 0.0) + 0.5) == atlasPage
|
|
256
|
-
int metadataFlags = int(max(metadata1.z, 0.0) + 0.5)
|
|
257
|
-
bool metadataPresent = (metadataFlags & 1) == 0
|
|
258
|
-
float pageAlpha = pageMatches && metadataPresent ? 1.0 : 0.0
|
|
259
|
-
float effectiveAlpha = frame2.x * slotOpacity * pageAlpha
|
|
260
|
-
// Match the CPU reference's strict \`< 0.05\` visibility cutoff
|
|
261
|
-
v_color = vec4(1.0, 1.0, 1.0, effectiveAlpha >= 0.05 ? effectiveAlpha : 0.0)
|
|
262
|
-
v_clipRect = clipRect
|
|
263
|
-
v_clipEnabled = clipEnabled
|
|
264
|
-
v_localPosition = vec2(layoutW * a_corner.x, layoutH * a_corner.y)
|
|
265
|
-
v_localClipRect = metadata2
|
|
266
|
-
v_localClipEnabled = (metadataFlags & 2) != 0 ? 1.0 : 0.0
|
|
267
|
-
}
|
|
88
|
+
`, RE = `#version 300 es\r
|
|
89
|
+
precision highp float;\r
|
|
90
|
+
precision highp int;\r
|
|
91
|
+
\r
|
|
92
|
+
/**\r
|
|
93
|
+
* Table-aware SVGA instanced vertex stage.\r
|
|
94
|
+
*\r
|
|
95
|
+
* The frame table is a RGBA32F/NEAREST texture with three texels per\r
|
|
96
|
+
* (sprite, frame) row:\r
|
|
97
|
+
* texel 0 = layoutW, layoutH, a, b\r
|
|
98
|
+
* texel 1 = c, d, tx, ty\r
|
|
99
|
+
* texel 2 = alpha, 0, 0, 0\r
|
|
100
|
+
*\r
|
|
101
|
+
* Static sprite metadata is a second RGBA32F/NEAREST texture with two texels\r
|
|
102
|
+
* per row:\r
|
|
103
|
+
* texel 0 = atlas UV min.xy / max.xy\r
|
|
104
|
+
* texel 1 = sourceSpriteIndex, atlasPage, flags, reserved\r
|
|
105
|
+
*\r
|
|
106
|
+
* One draw covers a single atlas page of one slot. \`gl_InstanceID\` selects a\r
|
|
107
|
+
* metadata row (\`u_spriteBase + gl_InstanceID\`), so the only per-frame CPU\r
|
|
108
|
+
* state is the slot transform/opacity/clip and the authoritative frame index.\r
|
|
109
|
+
*/\r
|
|
110
|
+
layout(location = 0) in vec2 a_corner;\r
|
|
111
|
+
// Optional Hybrid scheduling row. Direct draws leave these attributes disabled\r
|
|
112
|
+
// and use the uniform slot state below.\r
|
|
113
|
+
layout(location = 1) in vec4 a_instanceParent;\r
|
|
114
|
+
layout(location = 2) in vec4 a_instanceTranslateOpacityFrame;\r
|
|
115
|
+
layout(location = 3) in vec4 a_instanceClipRect;\r
|
|
116
|
+
/** x=clipEnabled, y=metadataRow, z=atlasPage, w=present. */\r
|
|
117
|
+
layout(location = 4) in vec4 a_instanceInfo;\r
|
|
118
|
+
\r
|
|
119
|
+
uniform mat4 u_projection;\r
|
|
120
|
+
uniform highp sampler2D u_frameTable;\r
|
|
121
|
+
uniform highp sampler2D u_spriteMetadata;\r
|
|
122
|
+
/**\r
|
|
123
|
+
* Canonical compact state (four RGBA32F texels / 16 floats):\r
|
|
124
|
+
* affine; translate+opacity+frame; clip rect; clipEnabled+metadataBase+atlasPage+track+1.\r
|
|
125
|
+
*/\r
|
|
126
|
+
uniform highp sampler2D u_slotStates;\r
|
|
127
|
+
/** x = frameCount, y = spriteCount, z = texels per frame (3), w = default frame. */\r
|
|
128
|
+
uniform ivec4 u_tableInfo;\r
|
|
129
|
+
/** x/y = frame-table texture width/height in texels. */\r
|
|
130
|
+
uniform ivec2 u_frameTableSize;\r
|
|
131
|
+
/** x/y = sprite metadata texture width/height in texels. */\r
|
|
132
|
+
uniform ivec2 u_spriteMetadataSize;\r
|
|
133
|
+
uniform int u_spriteMetadataTexelsPerRow;\r
|
|
134
|
+
uniform ivec2 u_slotStateSize;\r
|
|
135
|
+
/** First static metadata row consumed by this slot/page draw. */\r
|
|
136
|
+
uniform int u_spriteBase;\r
|
|
137
|
+
/** Authoritative SVGA frame selected by RenderManager/PlaybackScope. */\r
|
|
138
|
+
uniform int u_frameIndex;\r
|
|
139
|
+
uniform vec4 u_parentAffine;\r
|
|
140
|
+
uniform vec2 u_parentTranslate;\r
|
|
141
|
+
uniform float u_slotOpacity;\r
|
|
142
|
+
/** Atlas page for this draw; negative means metadata page filtering is disabled. */\r
|
|
143
|
+
uniform int u_atlasPage;\r
|
|
144
|
+
uniform vec4 u_clipRect;\r
|
|
145
|
+
uniform float u_clipEnabled;\r
|
|
146
|
+
/** WebGL's gl_FragCoord has a bottom-left origin; input clip rects are top-left. */\r
|
|
147
|
+
uniform float u_canvasHeight;\r
|
|
148
|
+
uniform float u_instanceStateEnabled;\r
|
|
149
|
+
uniform float u_compactSlotStateEnabled;\r
|
|
150
|
+
uniform int u_spritesPerSlot;\r
|
|
151
|
+
\r
|
|
152
|
+
out vec2 v_uv;\r
|
|
153
|
+
out vec4 v_color;\r
|
|
154
|
+
flat out vec4 v_clipRect;\r
|
|
155
|
+
flat out float v_clipEnabled;\r
|
|
156
|
+
out vec2 v_localPosition;\r
|
|
157
|
+
flat out vec4 v_localClipRect;\r
|
|
158
|
+
flat out float v_localClipEnabled;\r
|
|
159
|
+
\r
|
|
160
|
+
ivec2 texelCoord(int linearIndex, ivec2 textureSize) {\r
|
|
161
|
+
int width = max(textureSize.x, 1);\r
|
|
162
|
+
return ivec2(linearIndex - (linearIndex / width) * width, linearIndex / width);\r
|
|
163
|
+
}\r
|
|
164
|
+
\r
|
|
165
|
+
void main() {\r
|
|
166
|
+
int frameCount = max(u_tableInfo.x, 1);\r
|
|
167
|
+
int spriteCount = max(u_tableInfo.y, 1);\r
|
|
168
|
+
bool instanceState = u_instanceStateEnabled > 0.5;\r
|
|
169
|
+
bool compactSlotState = u_compactSlotStateEnabled > 0.5;\r
|
|
170
|
+
int spritesPerSlot = max(u_spritesPerSlot, 1);\r
|
|
171
|
+
int slotStateIndex = gl_InstanceID / spritesPerSlot;\r
|
|
172
|
+
int spriteWithinSlot = gl_InstanceID - slotStateIndex * spritesPerSlot;\r
|
|
173
|
+
vec4 compactParent = vec4(0.0);\r
|
|
174
|
+
vec4 compactTranslateOpacityFrame = vec4(0.0);\r
|
|
175
|
+
vec4 compactClip = vec4(0.0);\r
|
|
176
|
+
vec4 compactInfo = vec4(0.0);\r
|
|
177
|
+
if (compactSlotState) {\r
|
|
178
|
+
int compactBase = slotStateIndex * 4;\r
|
|
179
|
+
compactParent = texelFetch(u_slotStates, texelCoord(compactBase, u_slotStateSize), 0);\r
|
|
180
|
+
compactTranslateOpacityFrame = texelFetch(u_slotStates, texelCoord(compactBase + 1, u_slotStateSize), 0);\r
|
|
181
|
+
compactClip = texelFetch(u_slotStates, texelCoord(compactBase + 2, u_slotStateSize), 0);\r
|
|
182
|
+
compactInfo = texelFetch(u_slotStates, texelCoord(compactBase + 3, u_slotStateSize), 0);\r
|
|
183
|
+
}\r
|
|
184
|
+
int metadataRow = instanceState\r
|
|
185
|
+
? max(int(a_instanceInfo.y + 0.5), 0)\r
|
|
186
|
+
: compactSlotState\r
|
|
187
|
+
? max(u_spriteBase + spriteWithinSlot, 0)\r
|
|
188
|
+
: max(u_spriteBase + gl_InstanceID, 0);\r
|
|
189
|
+
int metadataStride = max(u_spriteMetadataTexelsPerRow, 2);\r
|
|
190
|
+
int metadataTexel = metadataRow * metadataStride;\r
|
|
191
|
+
vec4 metadata0 = texelFetch(\r
|
|
192
|
+
u_spriteMetadata,\r
|
|
193
|
+
texelCoord(metadataTexel, u_spriteMetadataSize),\r
|
|
194
|
+
0\r
|
|
195
|
+
);\r
|
|
196
|
+
vec4 metadata1 = texelFetch(\r
|
|
197
|
+
u_spriteMetadata,\r
|
|
198
|
+
texelCoord(metadataTexel + 1, u_spriteMetadataSize),\r
|
|
199
|
+
0\r
|
|
200
|
+
);\r
|
|
201
|
+
vec4 metadata2 = metadataStride >= 3\r
|
|
202
|
+
? texelFetch(u_spriteMetadata, texelCoord(metadataTexel + 2, u_spriteMetadataSize), 0)\r
|
|
203
|
+
: vec4(0.0);\r
|
|
204
|
+
// Metadata carries the source sprite index so a page-specific range can\r
|
|
205
|
+
// represent non-contiguous atlas pages. Its y component is the atlas page.\r
|
|
206
|
+
int spriteIndex = clamp(int(max(metadata1.x, 0.0) + 0.5), 0, spriteCount - 1);\r
|
|
207
|
+
int frameIndex = instanceState\r
|
|
208
|
+
? int(a_instanceTranslateOpacityFrame.w + 0.5)\r
|
|
209
|
+
: compactSlotState\r
|
|
210
|
+
? int(compactTranslateOpacityFrame.w + 0.5)\r
|
|
211
|
+
: u_frameIndex;\r
|
|
212
|
+
if (frameIndex < 0) frameIndex = u_tableInfo.w;\r
|
|
213
|
+
frameIndex = clamp(frameIndex, 0, frameCount - 1);\r
|
|
214
|
+
\r
|
|
215
|
+
int row = spriteIndex * frameCount + frameIndex;\r
|
|
216
|
+
int frameTexel = row * u_tableInfo.z;\r
|
|
217
|
+
vec4 frame0 = texelFetch(u_frameTable, texelCoord(frameTexel, u_frameTableSize), 0);\r
|
|
218
|
+
vec4 frame1 = texelFetch(u_frameTable, texelCoord(frameTexel + 1, u_frameTableSize), 0);\r
|
|
219
|
+
vec4 frame2 = texelFetch(u_frameTable, texelCoord(frameTexel + 2, u_frameTableSize), 0);\r
|
|
220
|
+
\r
|
|
221
|
+
float layoutW = frame0.x;\r
|
|
222
|
+
float layoutH = frame0.y;\r
|
|
223
|
+
vec2 local = vec2(\r
|
|
224
|
+
frame0.z * layoutW * a_corner.x + frame1.x * layoutH * a_corner.y + frame1.z,\r
|
|
225
|
+
frame0.w * layoutW * a_corner.x + frame1.y * layoutH * a_corner.y + frame1.w\r
|
|
226
|
+
);\r
|
|
227
|
+
\r
|
|
228
|
+
vec4 parentAffine = instanceState\r
|
|
229
|
+
? a_instanceParent\r
|
|
230
|
+
: compactSlotState ? compactParent : u_parentAffine;\r
|
|
231
|
+
vec2 parentTranslate = instanceState\r
|
|
232
|
+
? a_instanceTranslateOpacityFrame.xy\r
|
|
233
|
+
: compactSlotState ? compactTranslateOpacityFrame.xy : u_parentTranslate;\r
|
|
234
|
+
float slotOpacity = instanceState\r
|
|
235
|
+
? a_instanceTranslateOpacityFrame.z\r
|
|
236
|
+
: compactSlotState ? compactTranslateOpacityFrame.z : u_slotOpacity;\r
|
|
237
|
+
int atlasPage = instanceState\r
|
|
238
|
+
? int(a_instanceInfo.z + 0.5)\r
|
|
239
|
+
: compactSlotState\r
|
|
240
|
+
? (compactInfo.z < -0.5 ? -1 : int(compactInfo.z + 0.5))\r
|
|
241
|
+
: u_atlasPage;\r
|
|
242
|
+
vec4 clipRect = instanceState\r
|
|
243
|
+
? a_instanceClipRect\r
|
|
244
|
+
: compactSlotState ? compactClip : u_clipRect;\r
|
|
245
|
+
float clipEnabled = instanceState\r
|
|
246
|
+
? a_instanceInfo.x\r
|
|
247
|
+
: compactSlotState ? compactInfo.x : u_clipEnabled;\r
|
|
248
|
+
vec2 world = vec2(\r
|
|
249
|
+
parentAffine.x * local.x + parentAffine.z * local.y + parentTranslate.x,\r
|
|
250
|
+
parentAffine.y * local.x + parentAffine.w * local.y + parentTranslate.y\r
|
|
251
|
+
);\r
|
|
252
|
+
\r
|
|
253
|
+
gl_Position = u_projection * vec4(world, 0.0, 1.0);\r
|
|
254
|
+
v_uv = mix(metadata0.xy, metadata0.zw, a_corner);\r
|
|
255
|
+
bool pageMatches = atlasPage < 0 || int(max(metadata1.y, 0.0) + 0.5) == atlasPage;\r
|
|
256
|
+
int metadataFlags = int(max(metadata1.z, 0.0) + 0.5);\r
|
|
257
|
+
bool metadataPresent = (metadataFlags & 1) == 0;\r
|
|
258
|
+
float pageAlpha = pageMatches && metadataPresent ? 1.0 : 0.0;\r
|
|
259
|
+
float effectiveAlpha = frame2.x * slotOpacity * pageAlpha;\r
|
|
260
|
+
// Match the CPU reference's strict \`< 0.05\` visibility cutoff.\r
|
|
261
|
+
v_color = vec4(1.0, 1.0, 1.0, effectiveAlpha >= 0.05 ? effectiveAlpha : 0.0);\r
|
|
262
|
+
v_clipRect = clipRect;\r
|
|
263
|
+
v_clipEnabled = clipEnabled;\r
|
|
264
|
+
v_localPosition = vec2(layoutW * a_corner.x, layoutH * a_corner.y);\r
|
|
265
|
+
v_localClipRect = metadata2;\r
|
|
266
|
+
v_localClipEnabled = (metadataFlags & 2) != 0 ? 1.0 : 0.0;\r
|
|
267
|
+
}\r
|
|
268
268
|
`, uE = `#version 300 es
|
|
269
269
|
precision highp float;
|
|
270
270
|
|
|
@@ -791,67 +791,67 @@ void main() {\r
|
|
|
791
791
|
float coverage = 1.0 - smoothstep(0.45, 1.0, distanceToCenter);\r
|
|
792
792
|
outColor = v_color * coverage;\r
|
|
793
793
|
}\r
|
|
794
|
-
`, TE = `#version 300 es
|
|
795
|
-
precision highp float
|
|
796
|
-
|
|
797
|
-
layout(location = 0) in vec2 a_corner
|
|
798
|
-
layout(location = 1) in vec4 a_birthLifePosition
|
|
799
|
-
layout(location = 2) in vec4 a_velocityAcceleration
|
|
800
|
-
layout(location = 3) in vec4 a_scaleRotation
|
|
801
|
-
layout(location = 4) in vec4 a_color
|
|
802
|
-
layout(location = 5) in vec4 a_sizeAnchor
|
|
803
|
-
layout(location = 6) in vec4 a_uvRect
|
|
804
|
-
|
|
805
|
-
uniform mat4 u_projection
|
|
806
|
-
uniform float u_time
|
|
807
|
-
uniform float u_globalAlpha
|
|
808
|
-
uniform float u_sizeEnvelope
|
|
809
|
-
uniform float u_fadeMode
|
|
810
|
-
uniform vec2 u_cssScale
|
|
811
|
-
|
|
812
|
-
out vec2 v_uv
|
|
813
|
-
out vec4 v_modulation
|
|
814
|
-
|
|
815
|
-
void main() {
|
|
816
|
-
float age = u_time - a_birthLifePosition.x
|
|
817
|
-
float life = max(a_birthLifePosition.y, 0.0001)
|
|
818
|
-
bool alive = age >= 0.0 && age <= life
|
|
819
|
-
float safeAge = max(age, 0.0)
|
|
820
|
-
vec2 position = a_birthLifePosition.zw
|
|
821
|
-
+ a_velocityAcceleration.xy * safeAge
|
|
822
|
-
+ 0.5 * a_velocityAcceleration.zw * safeAge * safeAge
|
|
823
|
-
float scale = max(0.04, a_scaleRotation.x + a_scaleRotation.y * safeAge) * u_sizeEnvelope
|
|
824
|
-
vec2 unitCorner = a_corner + 0.5
|
|
825
|
-
vec2 local = (unitCorner - a_sizeAnchor.zw) * a_sizeAnchor.xy * scale
|
|
826
|
-
float angle = a_scaleRotation.z + a_scaleRotation.w * safeAge
|
|
827
|
-
float c = cos(angle)
|
|
828
|
-
float s = sin(angle)
|
|
829
|
-
vec2 rotated = vec2(c * local.x - s * local.y, s * local.x + c * local.y)
|
|
830
|
-
float progress = clamp(safeAge / life, 0.0, 1.0)
|
|
831
|
-
float fade = u_fadeMode > 0.5
|
|
832
|
-
? min(safeAge / 0.04, 1.0) * pow(1.0 - progress, 0.78)
|
|
833
|
-
: 1.0
|
|
834
|
-
if (!alive) {
|
|
835
|
-
position = vec2(-100000.0)
|
|
836
|
-
fade = 0.0
|
|
837
|
-
}
|
|
838
|
-
gl_Position = u_projection * vec4((position + rotated) * u_cssScale, 0.0, 1.0)
|
|
839
|
-
v_uv = mix(a_uvRect.xy, a_uvRect.zw, unitCorner)
|
|
840
|
-
float alpha = a_color.a * fade * u_globalAlpha
|
|
841
|
-
v_modulation = vec4(a_color.rgb * alpha, alpha)
|
|
842
|
-
}
|
|
843
|
-
`, vE = `#version 300 es
|
|
844
|
-
precision highp float
|
|
845
|
-
|
|
846
|
-
uniform sampler2D u_atlas
|
|
847
|
-
in vec2 v_uv
|
|
848
|
-
in vec4 v_modulation
|
|
849
|
-
out vec4 outColor
|
|
850
|
-
|
|
851
|
-
void main() {
|
|
852
|
-
vec4 sampled = texture(u_atlas, v_uv)
|
|
853
|
-
outColor = vec4(sampled.rgb * v_modulation.rgb, sampled.a * v_modulation.a)
|
|
854
|
-
}
|
|
794
|
+
`, TE = `#version 300 es\r
|
|
795
|
+
precision highp float;\r
|
|
796
|
+
\r
|
|
797
|
+
layout(location = 0) in vec2 a_corner;\r
|
|
798
|
+
layout(location = 1) in vec4 a_birthLifePosition;\r
|
|
799
|
+
layout(location = 2) in vec4 a_velocityAcceleration;\r
|
|
800
|
+
layout(location = 3) in vec4 a_scaleRotation;\r
|
|
801
|
+
layout(location = 4) in vec4 a_color;\r
|
|
802
|
+
layout(location = 5) in vec4 a_sizeAnchor;\r
|
|
803
|
+
layout(location = 6) in vec4 a_uvRect;\r
|
|
804
|
+
\r
|
|
805
|
+
uniform mat4 u_projection;\r
|
|
806
|
+
uniform float u_time;\r
|
|
807
|
+
uniform float u_globalAlpha;\r
|
|
808
|
+
uniform float u_sizeEnvelope;\r
|
|
809
|
+
uniform float u_fadeMode;\r
|
|
810
|
+
uniform vec2 u_cssScale;\r
|
|
811
|
+
\r
|
|
812
|
+
out vec2 v_uv;\r
|
|
813
|
+
out vec4 v_modulation;\r
|
|
814
|
+
\r
|
|
815
|
+
void main() {\r
|
|
816
|
+
float age = u_time - a_birthLifePosition.x;\r
|
|
817
|
+
float life = max(a_birthLifePosition.y, 0.0001);\r
|
|
818
|
+
bool alive = age >= 0.0 && age <= life;\r
|
|
819
|
+
float safeAge = max(age, 0.0);\r
|
|
820
|
+
vec2 position = a_birthLifePosition.zw\r
|
|
821
|
+
+ a_velocityAcceleration.xy * safeAge\r
|
|
822
|
+
+ 0.5 * a_velocityAcceleration.zw * safeAge * safeAge;\r
|
|
823
|
+
float scale = max(0.04, a_scaleRotation.x + a_scaleRotation.y * safeAge) * u_sizeEnvelope;\r
|
|
824
|
+
vec2 unitCorner = a_corner + 0.5;\r
|
|
825
|
+
vec2 local = (unitCorner - a_sizeAnchor.zw) * a_sizeAnchor.xy * scale;\r
|
|
826
|
+
float angle = a_scaleRotation.z + a_scaleRotation.w * safeAge;\r
|
|
827
|
+
float c = cos(angle);\r
|
|
828
|
+
float s = sin(angle);\r
|
|
829
|
+
vec2 rotated = vec2(c * local.x - s * local.y, s * local.x + c * local.y);\r
|
|
830
|
+
float progress = clamp(safeAge / life, 0.0, 1.0);\r
|
|
831
|
+
float fade = u_fadeMode > 0.5\r
|
|
832
|
+
? min(safeAge / 0.04, 1.0) * pow(1.0 - progress, 0.78)\r
|
|
833
|
+
: 1.0;\r
|
|
834
|
+
if (!alive) {\r
|
|
835
|
+
position = vec2(-100000.0);\r
|
|
836
|
+
fade = 0.0;\r
|
|
837
|
+
}\r
|
|
838
|
+
gl_Position = u_projection * vec4((position + rotated) * u_cssScale, 0.0, 1.0);\r
|
|
839
|
+
v_uv = mix(a_uvRect.xy, a_uvRect.zw, unitCorner);\r
|
|
840
|
+
float alpha = a_color.a * fade * u_globalAlpha;\r
|
|
841
|
+
v_modulation = vec4(a_color.rgb * alpha, alpha);\r
|
|
842
|
+
}\r
|
|
843
|
+
`, vE = `#version 300 es\r
|
|
844
|
+
precision highp float;\r
|
|
845
|
+
\r
|
|
846
|
+
uniform sampler2D u_atlas;\r
|
|
847
|
+
in vec2 v_uv;\r
|
|
848
|
+
in vec4 v_modulation;\r
|
|
849
|
+
out vec4 outColor;\r
|
|
850
|
+
\r
|
|
851
|
+
void main() {\r
|
|
852
|
+
vec4 sampled = texture(u_atlas, v_uv);\r
|
|
853
|
+
outColor = vec4(sampled.rgb * v_modulation.rgb, sampled.a * v_modulation.a);\r
|
|
854
|
+
}\r
|
|
855
855
|
`, WE = `/** SVGA atlas variant for premultiplied RGBA atlas textures. */\r
|
|
856
856
|
struct Uniforms {\r
|
|
857
857
|
projection: mat4x4f,\r
|
|
@@ -1357,78 +1357,78 @@ fn fs(input: VOut) -> @location(0) vec4f {\r
|
|
|
1357
1357
|
let coverage = 1.0 - smoothstep(0.45, 1.0, distanceToCenter);\r
|
|
1358
1358
|
return input.color * coverage;\r
|
|
1359
1359
|
}\r
|
|
1360
|
-
`, gi = `struct Globals {
|
|
1361
|
-
projection: mat4x4f
|
|
1362
|
-
}
|
|
1363
|
-
|
|
1364
|
-
@group(0) @binding(0) var<uniform> globals: Globals
|
|
1365
|
-
@group(0) @binding(1) var<storage, read> instanceData: array<f32
|
|
1366
|
-
@group(1) @binding(0) var atlasTexture: texture_2d<f32
|
|
1367
|
-
@group(1) @binding(1) var atlasSampler: sampler
|
|
1368
|
-
|
|
1369
|
-
struct VIn {
|
|
1370
|
-
@location(0) corner: vec2f
|
|
1371
|
-
}
|
|
1372
|
-
|
|
1373
|
-
struct VOut {
|
|
1374
|
-
@builtin(position) position: vec4f
|
|
1375
|
-
@location(0) uv: vec2f
|
|
1376
|
-
@location(1) modulation: vec4f
|
|
1377
|
-
}
|
|
1378
|
-
|
|
1379
|
-
@vertex
|
|
1380
|
-
fn vs(input: VIn, @builtin(instance_index) instance: u32) -> VOut {
|
|
1381
|
-
let base = 8u + instance * 24u
|
|
1382
|
-
let birth = instanceData[base]
|
|
1383
|
-
let life = max(instanceData[base + 1u], 0.0001)
|
|
1384
|
-
let age = instanceData[0] - birth
|
|
1385
|
-
let safeAge = max(age, 0.0)
|
|
1386
|
-
var position = vec2f(instanceData[base + 2u], instanceData[base + 3u])
|
|
1387
|
-
+ vec2f(instanceData[base + 4u], instanceData[base + 5u]) * safeAge
|
|
1388
|
-
+ 0.5 * vec2f(instanceData[base + 6u], instanceData[base + 7u]) * safeAge * safeAge
|
|
1389
|
-
let scale = max(0.04, instanceData[base + 8u] + instanceData[base + 9u] * safeAge)
|
|
1390
|
-
* instanceData[2]
|
|
1391
|
-
let unitCorner = input.corner + vec2f(0.5)
|
|
1392
|
-
let anchor = vec2f(instanceData[base + 18u], instanceData[base + 19u])
|
|
1393
|
-
let spriteSize = vec2f(instanceData[base + 16u], instanceData[base + 17u])
|
|
1394
|
-
let local = (unitCorner - anchor) * spriteSize * scale
|
|
1395
|
-
let angle = instanceData[base + 10u] + instanceData[base + 11u] * safeAge
|
|
1396
|
-
let c = cos(angle)
|
|
1397
|
-
let s = sin(angle)
|
|
1398
|
-
let rotated = vec2f(c * local.x - s * local.y, s * local.x + c * local.y)
|
|
1399
|
-
let progress = clamp(safeAge / life, 0.0, 1.0)
|
|
1400
|
-
var fade = select(
|
|
1401
|
-
1.0
|
|
1402
|
-
min(safeAge / 0.04, 1.0) * pow(1.0 - progress, 0.78)
|
|
1403
|
-
instanceData[3] > 0.5
|
|
1404
|
-
)
|
|
1405
|
-
if (age < 0.0 || age > life) {
|
|
1406
|
-
position = vec2f(-100000.0)
|
|
1407
|
-
fade = 0.0
|
|
1408
|
-
}
|
|
1409
|
-
let cssScale = vec2f(instanceData[4], instanceData[5])
|
|
1410
|
-
let alpha = instanceData[base + 15u] * fade * instanceData[1]
|
|
1411
|
-
var output: VOut
|
|
1412
|
-
output.position = globals.projection * vec4f((position + rotated) * cssScale, 0.0, 1.0)
|
|
1413
|
-
output.uv = mix(
|
|
1414
|
-
vec2f(instanceData[base + 20u], instanceData[base + 21u])
|
|
1415
|
-
vec2f(instanceData[base + 22u], instanceData[base + 23u])
|
|
1416
|
-
unitCorner
|
|
1417
|
-
)
|
|
1418
|
-
output.modulation = vec4f(
|
|
1419
|
-
instanceData[base + 12u] * alpha
|
|
1420
|
-
instanceData[base + 13u] * alpha
|
|
1421
|
-
instanceData[base + 14u] * alpha
|
|
1422
|
-
alpha
|
|
1423
|
-
)
|
|
1424
|
-
return output
|
|
1425
|
-
}
|
|
1426
|
-
|
|
1427
|
-
@fragment
|
|
1428
|
-
fn fs(input: VOut) -> @location(0) vec4f {
|
|
1429
|
-
let sampled = textureSample(atlasTexture, atlasSampler, input.uv)
|
|
1430
|
-
return vec4f(sampled.rgb * input.modulation.rgb, sampled.a * input.modulation.a)
|
|
1431
|
-
}
|
|
1360
|
+
`, gi = `struct Globals {\r
|
|
1361
|
+
projection: mat4x4f,\r
|
|
1362
|
+
}\r
|
|
1363
|
+
\r
|
|
1364
|
+
@group(0) @binding(0) var<uniform> globals: Globals;\r
|
|
1365
|
+
@group(0) @binding(1) var<storage, read> instanceData: array<f32>;\r
|
|
1366
|
+
@group(1) @binding(0) var atlasTexture: texture_2d<f32>;\r
|
|
1367
|
+
@group(1) @binding(1) var atlasSampler: sampler;\r
|
|
1368
|
+
\r
|
|
1369
|
+
struct VIn {\r
|
|
1370
|
+
@location(0) corner: vec2f,\r
|
|
1371
|
+
}\r
|
|
1372
|
+
\r
|
|
1373
|
+
struct VOut {\r
|
|
1374
|
+
@builtin(position) position: vec4f,\r
|
|
1375
|
+
@location(0) uv: vec2f,\r
|
|
1376
|
+
@location(1) modulation: vec4f,\r
|
|
1377
|
+
}\r
|
|
1378
|
+
\r
|
|
1379
|
+
@vertex\r
|
|
1380
|
+
fn vs(input: VIn, @builtin(instance_index) instance: u32) -> VOut {\r
|
|
1381
|
+
let base = 8u + instance * 24u;\r
|
|
1382
|
+
let birth = instanceData[base];\r
|
|
1383
|
+
let life = max(instanceData[base + 1u], 0.0001);\r
|
|
1384
|
+
let age = instanceData[0] - birth;\r
|
|
1385
|
+
let safeAge = max(age, 0.0);\r
|
|
1386
|
+
var position = vec2f(instanceData[base + 2u], instanceData[base + 3u])\r
|
|
1387
|
+
+ vec2f(instanceData[base + 4u], instanceData[base + 5u]) * safeAge\r
|
|
1388
|
+
+ 0.5 * vec2f(instanceData[base + 6u], instanceData[base + 7u]) * safeAge * safeAge;\r
|
|
1389
|
+
let scale = max(0.04, instanceData[base + 8u] + instanceData[base + 9u] * safeAge)\r
|
|
1390
|
+
* instanceData[2];\r
|
|
1391
|
+
let unitCorner = input.corner + vec2f(0.5);\r
|
|
1392
|
+
let anchor = vec2f(instanceData[base + 18u], instanceData[base + 19u]);\r
|
|
1393
|
+
let spriteSize = vec2f(instanceData[base + 16u], instanceData[base + 17u]);\r
|
|
1394
|
+
let local = (unitCorner - anchor) * spriteSize * scale;\r
|
|
1395
|
+
let angle = instanceData[base + 10u] + instanceData[base + 11u] * safeAge;\r
|
|
1396
|
+
let c = cos(angle);\r
|
|
1397
|
+
let s = sin(angle);\r
|
|
1398
|
+
let rotated = vec2f(c * local.x - s * local.y, s * local.x + c * local.y);\r
|
|
1399
|
+
let progress = clamp(safeAge / life, 0.0, 1.0);\r
|
|
1400
|
+
var fade = select(\r
|
|
1401
|
+
1.0,\r
|
|
1402
|
+
min(safeAge / 0.04, 1.0) * pow(1.0 - progress, 0.78),\r
|
|
1403
|
+
instanceData[3] > 0.5,\r
|
|
1404
|
+
);\r
|
|
1405
|
+
if (age < 0.0 || age > life) {\r
|
|
1406
|
+
position = vec2f(-100000.0);\r
|
|
1407
|
+
fade = 0.0;\r
|
|
1408
|
+
}\r
|
|
1409
|
+
let cssScale = vec2f(instanceData[4], instanceData[5]);\r
|
|
1410
|
+
let alpha = instanceData[base + 15u] * fade * instanceData[1];\r
|
|
1411
|
+
var output: VOut;\r
|
|
1412
|
+
output.position = globals.projection * vec4f((position + rotated) * cssScale, 0.0, 1.0);\r
|
|
1413
|
+
output.uv = mix(\r
|
|
1414
|
+
vec2f(instanceData[base + 20u], instanceData[base + 21u]),\r
|
|
1415
|
+
vec2f(instanceData[base + 22u], instanceData[base + 23u]),\r
|
|
1416
|
+
unitCorner,\r
|
|
1417
|
+
);\r
|
|
1418
|
+
output.modulation = vec4f(\r
|
|
1419
|
+
instanceData[base + 12u] * alpha,\r
|
|
1420
|
+
instanceData[base + 13u] * alpha,\r
|
|
1421
|
+
instanceData[base + 14u] * alpha,\r
|
|
1422
|
+
alpha,\r
|
|
1423
|
+
);\r
|
|
1424
|
+
return output;\r
|
|
1425
|
+
}\r
|
|
1426
|
+
\r
|
|
1427
|
+
@fragment\r
|
|
1428
|
+
fn fs(input: VOut) -> @location(0) vec4f {\r
|
|
1429
|
+
let sampled = textureSample(atlasTexture, atlasSampler, input.uv);\r
|
|
1430
|
+
return vec4f(sampled.rgb * input.modulation.rgb, sampled.a * input.modulation.a);\r
|
|
1431
|
+
}\r
|
|
1432
1432
|
`, Ii = `struct Globals {\r
|
|
1433
1433
|
projection: mat4x4f,\r
|
|
1434
1434
|
}\r
|
|
@@ -1773,292 +1773,292 @@ fn applyMotionPoint(point: vec2f, center: vec2f, scale: vec2f, cosine: f32, sine
|
|
|
1773
1773
|
svgaMotionInstancedPremul: Ii,
|
|
1774
1774
|
svgaFrameTableShape: Bi,
|
|
1775
1775
|
svgaFrameTableClipMask: Ci
|
|
1776
|
-
}, Qi = `/// SVGA timeline/table variant for premultiplied RGBA atlas textures
|
|
1777
|
-
|
|
1778
|
-
/// The frame table and sprite metadata are resident storage buffers. A draw
|
|
1779
|
-
/// submits one instance per sprite. Direct draws derive the sprite index from
|
|
1780
|
-
/// the GPU instance index and only upload the slot/global uniform. Hybrid
|
|
1781
|
-
/// draws can additionally bind compact CPU-precompiled scheduling rows that
|
|
1782
|
-
/// omit the SVGA child matrix and alpha fetched from the frame table
|
|
1783
|
-
|
|
1784
|
-
/// Frame table: three vec4 values per (sprite, frame)
|
|
1785
|
-
/// 0: layoutW, layoutH, a, b
|
|
1786
|
-
/// 1: c, d, tx, ty
|
|
1787
|
-
/// 2: alpha, reserved, reserved, reserved
|
|
1788
|
-
|
|
1789
|
-
/// Sprite metadata: two vec4 values per draw sprite
|
|
1790
|
-
/// 0: atlas UV min.xy / max.xy
|
|
1791
|
-
/// 1: source sprite index, atlas page, flags, reserved
|
|
1792
|
-
|
|
1793
|
-
/// Uniform layout
|
|
1794
|
-
/// projection mat4x4f (64 bytes)
|
|
1795
|
-
/// parentAffine vec4f (a, b, c, d)
|
|
1796
|
-
/// translateOpacityFrame vec4f (tx, ty, opacity, frameIndex)
|
|
1797
|
-
/// clipRect vec4f (top-left x0, y0, x1, y1)
|
|
1798
|
-
/// drawInfo vec4u (metadataBase, drawSpriteCount, clipEnabled, trackIndex+1)
|
|
1799
|
-
/// tableInfo vec4u (frameCount, spriteCount, vec4sPerFrame, 0)
|
|
1800
|
-
/// batchInfo vec4u (spritesPerSlot, metadataVec4Stride, stateMode, 0)
|
|
1801
|
-
|
|
1802
|
-
struct Globals {
|
|
1803
|
-
projection: mat4x4f
|
|
1804
|
-
parentAffine: vec4f
|
|
1805
|
-
translateOpacityFrame: vec4f
|
|
1806
|
-
clipRect: vec4f
|
|
1807
|
-
drawInfo: vec4u
|
|
1808
|
-
tableInfo: vec4u
|
|
1809
|
-
batchInfo: vec4u
|
|
1810
|
-
}
|
|
1811
|
-
|
|
1812
|
-
struct MotionGlobals {
|
|
1813
|
-
timeMs: f32
|
|
1814
|
-
sampleIntervalMs: f32
|
|
1815
|
-
sampleCount: f32
|
|
1816
|
-
cssScaleX: f32
|
|
1817
|
-
cssScaleY: f32
|
|
1818
|
-
pad0: f32
|
|
1819
|
-
pad1: f32
|
|
1820
|
-
pad2: f32
|
|
1821
|
-
}
|
|
1822
|
-
|
|
1823
|
-
@group(0) @binding(0) var<uniform> globals: Globals
|
|
1824
|
-
@group(0) @binding(1) var<storage, read> frameTable: array<vec4f
|
|
1825
|
-
@group(0) @binding(2) var<storage, read> spriteMetadata: array<vec4f
|
|
1826
|
-
@group(0) @binding(3) var<storage, read> motionData: array<f32
|
|
1827
|
-
@group(0) @binding(4) var<uniform> motionGlobals: MotionGlobals
|
|
1828
|
-
// Canonical four-vec4 / 16-float slot row: affine; translate+opacity+frame
|
|
1829
|
-
// clip rect; clipEnabled+metadataBase+atlasPage+motionTrack+1
|
|
1830
|
-
// Optional Hybrid scheduling rows use this exact schema per draw instance
|
|
1831
|
-
// Direct draws bind a harmless dummy slice and leave drawInfo bit 1 clear
|
|
1832
|
-
@group(0) @binding(5) var<storage, read> hybridInstances: array<vec4f
|
|
1833
|
-
@group(1) @binding(0) var atlasTex: texture_2d<f32
|
|
1834
|
-
@group(1) @binding(1) var atlasSampler: sampler
|
|
1835
|
-
|
|
1836
|
-
struct VIn {
|
|
1837
|
-
@location(0) corner: vec2f
|
|
1838
|
-
}
|
|
1839
|
-
|
|
1840
|
-
struct VOut {
|
|
1841
|
-
@builtin(position) pos: vec4f
|
|
1842
|
-
@location(0) uv: vec2f
|
|
1843
|
-
@location(1) color: vec4f
|
|
1844
|
-
@location(2) @interpolate(flat) clipRect: vec4f
|
|
1845
|
-
@location(3) @interpolate(flat) clipEnabled: f32
|
|
1846
|
-
@location(4) localPosition: vec2f
|
|
1847
|
-
@location(5) @interpolate(flat) localClipRect: vec4f
|
|
1848
|
-
@location(6) @interpolate(flat) localClipEnabled: f32
|
|
1849
|
-
}
|
|
1850
|
-
|
|
1851
|
-
fn readFrameValue(index: u32) -> vec4f {
|
|
1852
|
-
return frameTable[index]
|
|
1853
|
-
}
|
|
1854
|
-
|
|
1855
|
-
fn sampleMotion(track: u32, channel: u32) -> f32 {
|
|
1856
|
-
let sampleCount = max(u32(motionGlobals.sampleCount), 1u)
|
|
1857
|
-
let samplePosition = clamp(
|
|
1858
|
-
motionGlobals.timeMs / max(motionGlobals.sampleIntervalMs, 0.001)
|
|
1859
|
-
0.0
|
|
1860
|
-
f32(sampleCount - 1u)
|
|
1861
|
-
)
|
|
1862
|
-
let left = u32(floor(samplePosition))
|
|
1863
|
-
let right = min(sampleCount - 1u, left + 1u)
|
|
1864
|
-
let trackBase = track * sampleCount * 8u
|
|
1865
|
-
let leftBase = trackBase + left * 8u
|
|
1866
|
-
let rightBase = trackBase + right * 8u
|
|
1867
|
-
let interpolate = left != right && motionData[leftBase + 7u] > 0.5 && channel < 6u
|
|
1868
|
-
if (!interpolate) {
|
|
1869
|
-
return motionData[leftBase + channel]
|
|
1870
|
-
}
|
|
1871
|
-
let progress = samplePosition - f32(left)
|
|
1872
|
-
return mix(motionData[leftBase + channel], motionData[rightBase + channel], progress)
|
|
1873
|
-
}
|
|
1874
|
-
|
|
1875
|
-
fn applyMotionPoint(
|
|
1876
|
-
point: vec2f
|
|
1877
|
-
center: vec2f
|
|
1878
|
-
scale: vec2f
|
|
1879
|
-
cosine: f32
|
|
1880
|
-
sine: f32
|
|
1881
|
-
) -> vec2f {
|
|
1882
|
-
let scaled = point * scale
|
|
1883
|
-
return center + vec2f(
|
|
1884
|
-
cosine * scaled.x - sine * scaled.y
|
|
1885
|
-
sine * scaled.x + cosine * scaled.y
|
|
1886
|
-
)
|
|
1887
|
-
}
|
|
1888
|
-
|
|
1889
|
-
@vertex
|
|
1890
|
-
fn vs(input: VIn, @builtin(instance_index) instance: u32) -> VOut {
|
|
1891
|
-
let safeInstance = min(instance, max(globals.drawInfo.y, 1u) - 1u)
|
|
1892
|
-
let hybrid = (globals.drawInfo.z & 2u) != 0u
|
|
1893
|
-
let compactSlots = (globals.drawInfo.z & 4u) != 0u
|
|
1894
|
-
let spritesPerSlot = max(globals.batchInfo.x, 1u)
|
|
1895
|
-
let slotStateIndex = select(safeInstance, safeInstance / spritesPerSlot, compactSlots)
|
|
1896
|
-
let hybridBase = slotStateIndex * 4u
|
|
1897
|
-
var hybridParent = vec4f(0.0)
|
|
1898
|
-
var hybridTranslateOpacityFrame = vec4f(0.0)
|
|
1899
|
-
var hybridClip = vec4f(0.0)
|
|
1900
|
-
var hybridInfo = vec4f(0.0)
|
|
1901
|
-
if (hybrid || compactSlots) {
|
|
1902
|
-
hybridParent = hybridInstances[hybridBase]
|
|
1903
|
-
hybridTranslateOpacityFrame = hybridInstances[hybridBase + 1u]
|
|
1904
|
-
hybridClip = hybridInstances[hybridBase + 2u]
|
|
1905
|
-
hybridInfo = hybridInstances[hybridBase + 3u]
|
|
1906
|
-
}
|
|
1907
|
-
let spriteWithinSlot = select(safeInstance, safeInstance % spritesPerSlot, compactSlots)
|
|
1908
|
-
let metadataIndex = select(
|
|
1909
|
-
globals.drawInfo.x + spriteWithinSlot
|
|
1910
|
-
u32(max(hybridInfo.y, 0.0))
|
|
1911
|
-
hybrid
|
|
1912
|
-
)
|
|
1913
|
-
let metadataStride = max(globals.batchInfo.y, 2u)
|
|
1914
|
-
let metadataBase = metadataIndex * metadataStride
|
|
1915
|
-
let metadataUv = spriteMetadata[metadataBase]
|
|
1916
|
-
let metadataSprite = spriteMetadata[metadataBase + 1u]
|
|
1917
|
-
var metadataClip = vec4f(0.0)
|
|
1918
|
-
if (metadataStride >= 3u) {
|
|
1919
|
-
metadataClip = spriteMetadata[metadataBase + 2u]
|
|
1920
|
-
}
|
|
1921
|
-
let metadataPage = metadataSprite.y
|
|
1922
|
-
let metadataFlags = u32(max(metadataSprite.z, 0.0))
|
|
1923
|
-
// The source sprite index is explicit so a page-specific metadata range
|
|
1924
|
-
// can represent non-contiguous atlas pages without duplicating frame rows
|
|
1925
|
-
// A page mismatch is made transparent so an invalid plan cannot sample a
|
|
1926
|
-
// sprite into the wrong atlas page
|
|
1927
|
-
let spriteIndex = u32(max(metadataSprite.x, 0.0))
|
|
1928
|
-
|
|
1929
|
-
let frameCount = max(globals.tableInfo.x, 1u)
|
|
1930
|
-
let spriteCount = max(globals.tableInfo.y, 1u)
|
|
1931
|
-
let safeSprite = min(spriteIndex, spriteCount - 1u)
|
|
1932
|
-
let selectedFrame = select(
|
|
1933
|
-
globals.translateOpacityFrame.w
|
|
1934
|
-
hybridTranslateOpacityFrame.w
|
|
1935
|
-
hybrid || compactSlots
|
|
1936
|
-
)
|
|
1937
|
-
let safeFrame = min(
|
|
1938
|
-
u32(max(selectedFrame, 0.0))
|
|
1939
|
-
frameCount - 1u
|
|
1940
|
-
)
|
|
1941
|
-
let tableBase = (safeSprite * frameCount + safeFrame) * globals.tableInfo.z
|
|
1942
|
-
let frame0 = readFrameValue(tableBase)
|
|
1943
|
-
let frame1 = readFrameValue(tableBase + 1u)
|
|
1944
|
-
let frame2 = readFrameValue(tableBase + 2u)
|
|
1945
|
-
|
|
1946
|
-
let layoutW = frame0.x
|
|
1947
|
-
let layoutH = frame0.y
|
|
1948
|
-
let local = vec2f(
|
|
1949
|
-
frame0.z * layoutW * input.corner.x + frame1.x * layoutH * input.corner.y + frame1.z
|
|
1950
|
-
frame0.w * layoutW * input.corner.x + frame1.y * layoutH * input.corner.y + frame1.w
|
|
1951
|
-
)
|
|
1952
|
-
|
|
1953
|
-
let instanceSlotState = hybrid || compactSlots
|
|
1954
|
-
let parent = select(globals.parentAffine, hybridParent, instanceSlotState)
|
|
1955
|
-
let parentTranslate = select(
|
|
1956
|
-
globals.translateOpacityFrame.xy
|
|
1957
|
-
hybridTranslateOpacityFrame.xy
|
|
1958
|
-
instanceSlotState
|
|
1959
|
-
)
|
|
1960
|
-
let parentLocal = vec2f(
|
|
1961
|
-
parent.x * local.x + parent.z * local.y + parentTranslate.x
|
|
1962
|
-
parent.y * local.x + parent.w * local.y + parentTranslate.y
|
|
1963
|
-
)
|
|
1964
|
-
let instanceTrack = u32(max(hybridInfo.w, 0.0))
|
|
1965
|
-
let selectedTrack = select(globals.drawInfo.w, instanceTrack, compactSlots)
|
|
1966
|
-
let hasParentMotion = selectedTrack > 0u
|
|
1967
|
-
var world = parentLocal
|
|
1968
|
-
var outerClip = select(globals.clipRect, hybridClip, instanceSlotState)
|
|
1969
|
-
let outerClipEnabled = select(
|
|
1970
|
-
f32(globals.drawInfo.z & 1u)
|
|
1971
|
-
hybridInfo.x
|
|
1972
|
-
instanceSlotState
|
|
1973
|
-
)
|
|
1974
|
-
var parentOpacity = select(
|
|
1975
|
-
globals.translateOpacityFrame.z
|
|
1976
|
-
hybridTranslateOpacityFrame.z
|
|
1977
|
-
instanceSlotState
|
|
1978
|
-
)
|
|
1979
|
-
if (hasParentMotion) {
|
|
1980
|
-
let track = selectedTrack - 1u
|
|
1981
|
-
let scale = vec2f(sampleMotion(track, 2u), sampleMotion(track, 3u))
|
|
1982
|
-
let angle = sampleMotion(track, 4u)
|
|
1983
|
-
let cosine = cos(angle)
|
|
1984
|
-
let sine = sin(angle)
|
|
1985
|
-
let center = vec2f(
|
|
1986
|
-
sampleMotion(track, 0u) * motionGlobals.cssScaleX
|
|
1987
|
-
sampleMotion(track, 1u) * motionGlobals.cssScaleY
|
|
1988
|
-
)
|
|
1989
|
-
world = applyMotionPoint(parentLocal, center, scale, cosine, sine)
|
|
1990
|
-
let clip0 = applyMotionPoint(outerClip.xy, center, scale, cosine, sine)
|
|
1991
|
-
let clip1 = applyMotionPoint(vec2f(outerClip.z, outerClip.y), center, scale, cosine, sine)
|
|
1992
|
-
let clip2 = applyMotionPoint(outerClip.zw, center, scale, cosine, sine)
|
|
1993
|
-
let clip3 = applyMotionPoint(vec2f(outerClip.x, outerClip.w), center, scale, cosine, sine)
|
|
1994
|
-
outerClip = vec4f(
|
|
1995
|
-
min(min(clip0.x, clip1.x), min(clip2.x, clip3.x))
|
|
1996
|
-
min(min(clip0.y, clip1.y), min(clip2.y, clip3.y))
|
|
1997
|
-
max(max(clip0.x, clip1.x), max(clip2.x, clip3.x))
|
|
1998
|
-
max(max(clip0.y, clip1.y), max(clip2.y, clip3.y))
|
|
1999
|
-
)
|
|
2000
|
-
let visible = sampleMotion(track, 6u)
|
|
2001
|
-
parentOpacity = sampleMotion(track, 5u) * select(0.0, 1.0, visible > 0.5)
|
|
2002
|
-
}
|
|
2003
|
-
|
|
2004
|
-
var output: VOut
|
|
2005
|
-
output.pos = globals.projection * vec4f(world, 0.0, 1.0)
|
|
2006
|
-
output.uv = mix(metadataUv.xy, metadataUv.zw, input.corner)
|
|
2007
|
-
var pageMatchesValue = globals.tableInfo.w == 0xffffffffu
|
|
2008
|
-
u32(max(metadataPage, 0.0)) == globals.tableInfo.w
|
|
2009
|
-
if (hybrid || compactSlots) {
|
|
2010
|
-
pageMatchesValue = hybridInfo.z < -0.5
|
|
2011
|
-
i32(round(metadataPage)) == i32(round(hybridInfo.z))
|
|
2012
|
-
}
|
|
2013
|
-
let pageMatches = select(
|
|
2014
|
-
0.0
|
|
2015
|
-
1.0
|
|
2016
|
-
pageMatchesValue
|
|
2017
|
-
)
|
|
2018
|
-
let metadataPresent = select(1.0, 0.0, (metadataFlags & 1u) != 0u)
|
|
2019
|
-
// Keep the table path's visibility cutoff identical to the CPU reference
|
|
2020
|
-
// renderer: rows below 0.05 are culled before issuing meaningful color
|
|
2021
|
-
// Exactly 0.05 remains visible (the reference uses a strict \`< 0.05\` test)
|
|
2022
|
-
let effectiveAlpha = frame2.x * parentOpacity * pageMatches * metadataPresent
|
|
2023
|
-
let visibleAlpha = select(0.0, effectiveAlpha, effectiveAlpha >= 0.05)
|
|
2024
|
-
output.color = vec4f(visibleAlpha)
|
|
2025
|
-
output.clipRect = outerClip
|
|
2026
|
-
output.clipEnabled = outerClipEnabled
|
|
2027
|
-
output.localPosition = vec2f(layoutW * input.corner.x, layoutH * input.corner.y)
|
|
2028
|
-
output.localClipRect = metadataClip
|
|
2029
|
-
output.localClipEnabled = select(0.0, 1.0, (metadataFlags & 2u) != 0u)
|
|
2030
|
-
return output
|
|
2031
|
-
}
|
|
2032
|
-
|
|
2033
|
-
@fragment
|
|
2034
|
-
fn fs(input: VOut) -> @location(0) vec4f {
|
|
2035
|
-
if (input.color.a < 0.05) {
|
|
2036
|
-
discard
|
|
2037
|
-
}
|
|
2038
|
-
if (input.clipEnabled > 0.5) {
|
|
2039
|
-
if (
|
|
2040
|
-
input.pos.x < input.clipRect.x
|
|
2041
|
-
input.pos.y < input.clipRect.y
|
|
2042
|
-
input.pos.x >= input.clipRect.z
|
|
2043
|
-
input.pos.y >= input.clipRect.w
|
|
2044
|
-
) {
|
|
2045
|
-
discard
|
|
2046
|
-
}
|
|
2047
|
-
}
|
|
2048
|
-
if (
|
|
2049
|
-
input.localClipEnabled > 0.5
|
|
2050
|
-
(
|
|
2051
|
-
input.localPosition.x < input.localClipRect.x
|
|
2052
|
-
input.localPosition.y < input.localClipRect.y
|
|
2053
|
-
input.localPosition.x >= input.localClipRect.z
|
|
2054
|
-
input.localPosition.y >= input.localClipRect.w
|
|
2055
|
-
)
|
|
2056
|
-
) {
|
|
2057
|
-
discard
|
|
2058
|
-
}
|
|
2059
|
-
let color = textureSample(atlasTex, atlasSampler, input.uv)
|
|
2060
|
-
return vec4f(color.rgb * input.color.a, color.a * input.color.a)
|
|
2061
|
-
}
|
|
1776
|
+
}, Qi = `/// SVGA timeline/table variant for premultiplied RGBA atlas textures.\r
|
|
1777
|
+
///\r
|
|
1778
|
+
/// The frame table and sprite metadata are resident storage buffers. A draw\r
|
|
1779
|
+
/// submits one instance per sprite. Direct draws derive the sprite index from\r
|
|
1780
|
+
/// the GPU instance index and only upload the slot/global uniform. Hybrid\r
|
|
1781
|
+
/// draws can additionally bind compact CPU-precompiled scheduling rows that\r
|
|
1782
|
+
/// omit the SVGA child matrix and alpha fetched from the frame table.\r
|
|
1783
|
+
///\r
|
|
1784
|
+
/// Frame table: three vec4 values per (sprite, frame):\r
|
|
1785
|
+
/// 0: layoutW, layoutH, a, b\r
|
|
1786
|
+
/// 1: c, d, tx, ty\r
|
|
1787
|
+
/// 2: alpha, reserved, reserved, reserved\r
|
|
1788
|
+
///\r
|
|
1789
|
+
/// Sprite metadata: two vec4 values per draw sprite:\r
|
|
1790
|
+
/// 0: atlas UV min.xy / max.xy\r
|
|
1791
|
+
/// 1: source sprite index, atlas page, flags, reserved\r
|
|
1792
|
+
///\r
|
|
1793
|
+
/// Uniform layout:\r
|
|
1794
|
+
/// projection mat4x4f (64 bytes)\r
|
|
1795
|
+
/// parentAffine vec4f (a, b, c, d)\r
|
|
1796
|
+
/// translateOpacityFrame vec4f (tx, ty, opacity, frameIndex)\r
|
|
1797
|
+
/// clipRect vec4f (top-left x0, y0, x1, y1)\r
|
|
1798
|
+
/// drawInfo vec4u (metadataBase, drawSpriteCount, clipEnabled, trackIndex+1)\r
|
|
1799
|
+
/// tableInfo vec4u (frameCount, spriteCount, vec4sPerFrame, 0)\r
|
|
1800
|
+
/// batchInfo vec4u (spritesPerSlot, metadataVec4Stride, stateMode, 0)\r
|
|
1801
|
+
\r
|
|
1802
|
+
struct Globals {\r
|
|
1803
|
+
projection: mat4x4f,\r
|
|
1804
|
+
parentAffine: vec4f,\r
|
|
1805
|
+
translateOpacityFrame: vec4f,\r
|
|
1806
|
+
clipRect: vec4f,\r
|
|
1807
|
+
drawInfo: vec4u,\r
|
|
1808
|
+
tableInfo: vec4u,\r
|
|
1809
|
+
batchInfo: vec4u,\r
|
|
1810
|
+
}\r
|
|
1811
|
+
\r
|
|
1812
|
+
struct MotionGlobals {\r
|
|
1813
|
+
timeMs: f32,\r
|
|
1814
|
+
sampleIntervalMs: f32,\r
|
|
1815
|
+
sampleCount: f32,\r
|
|
1816
|
+
cssScaleX: f32,\r
|
|
1817
|
+
cssScaleY: f32,\r
|
|
1818
|
+
pad0: f32,\r
|
|
1819
|
+
pad1: f32,\r
|
|
1820
|
+
pad2: f32,\r
|
|
1821
|
+
}\r
|
|
1822
|
+
\r
|
|
1823
|
+
@group(0) @binding(0) var<uniform> globals: Globals;\r
|
|
1824
|
+
@group(0) @binding(1) var<storage, read> frameTable: array<vec4f>;\r
|
|
1825
|
+
@group(0) @binding(2) var<storage, read> spriteMetadata: array<vec4f>;\r
|
|
1826
|
+
@group(0) @binding(3) var<storage, read> motionData: array<f32>;\r
|
|
1827
|
+
@group(0) @binding(4) var<uniform> motionGlobals: MotionGlobals;\r
|
|
1828
|
+
// Canonical four-vec4 / 16-float slot row: affine; translate+opacity+frame;\r
|
|
1829
|
+
// clip rect; clipEnabled+metadataBase+atlasPage+motionTrack+1.\r
|
|
1830
|
+
// Optional Hybrid scheduling rows use this exact schema per draw instance.\r
|
|
1831
|
+
// Direct draws bind a harmless dummy slice and leave drawInfo bit 1 clear.\r
|
|
1832
|
+
@group(0) @binding(5) var<storage, read> hybridInstances: array<vec4f>;\r
|
|
1833
|
+
@group(1) @binding(0) var atlasTex: texture_2d<f32>;\r
|
|
1834
|
+
@group(1) @binding(1) var atlasSampler: sampler;\r
|
|
1835
|
+
\r
|
|
1836
|
+
struct VIn {\r
|
|
1837
|
+
@location(0) corner: vec2f,\r
|
|
1838
|
+
}\r
|
|
1839
|
+
\r
|
|
1840
|
+
struct VOut {\r
|
|
1841
|
+
@builtin(position) pos: vec4f,\r
|
|
1842
|
+
@location(0) uv: vec2f,\r
|
|
1843
|
+
@location(1) color: vec4f,\r
|
|
1844
|
+
@location(2) @interpolate(flat) clipRect: vec4f,\r
|
|
1845
|
+
@location(3) @interpolate(flat) clipEnabled: f32,\r
|
|
1846
|
+
@location(4) localPosition: vec2f,\r
|
|
1847
|
+
@location(5) @interpolate(flat) localClipRect: vec4f,\r
|
|
1848
|
+
@location(6) @interpolate(flat) localClipEnabled: f32,\r
|
|
1849
|
+
}\r
|
|
1850
|
+
\r
|
|
1851
|
+
fn readFrameValue(index: u32) -> vec4f {\r
|
|
1852
|
+
return frameTable[index];\r
|
|
1853
|
+
}\r
|
|
1854
|
+
\r
|
|
1855
|
+
fn sampleMotion(track: u32, channel: u32) -> f32 {\r
|
|
1856
|
+
let sampleCount = max(u32(motionGlobals.sampleCount), 1u);\r
|
|
1857
|
+
let samplePosition = clamp(\r
|
|
1858
|
+
motionGlobals.timeMs / max(motionGlobals.sampleIntervalMs, 0.001),\r
|
|
1859
|
+
0.0,\r
|
|
1860
|
+
f32(sampleCount - 1u),\r
|
|
1861
|
+
);\r
|
|
1862
|
+
let left = u32(floor(samplePosition));\r
|
|
1863
|
+
let right = min(sampleCount - 1u, left + 1u);\r
|
|
1864
|
+
let trackBase = track * sampleCount * 8u;\r
|
|
1865
|
+
let leftBase = trackBase + left * 8u;\r
|
|
1866
|
+
let rightBase = trackBase + right * 8u;\r
|
|
1867
|
+
let interpolate = left != right && motionData[leftBase + 7u] > 0.5 && channel < 6u;\r
|
|
1868
|
+
if (!interpolate) {\r
|
|
1869
|
+
return motionData[leftBase + channel];\r
|
|
1870
|
+
}\r
|
|
1871
|
+
let progress = samplePosition - f32(left);\r
|
|
1872
|
+
return mix(motionData[leftBase + channel], motionData[rightBase + channel], progress);\r
|
|
1873
|
+
}\r
|
|
1874
|
+
\r
|
|
1875
|
+
fn applyMotionPoint(\r
|
|
1876
|
+
point: vec2f,\r
|
|
1877
|
+
center: vec2f,\r
|
|
1878
|
+
scale: vec2f,\r
|
|
1879
|
+
cosine: f32,\r
|
|
1880
|
+
sine: f32,\r
|
|
1881
|
+
) -> vec2f {\r
|
|
1882
|
+
let scaled = point * scale;\r
|
|
1883
|
+
return center + vec2f(\r
|
|
1884
|
+
cosine * scaled.x - sine * scaled.y,\r
|
|
1885
|
+
sine * scaled.x + cosine * scaled.y,\r
|
|
1886
|
+
);\r
|
|
1887
|
+
}\r
|
|
1888
|
+
\r
|
|
1889
|
+
@vertex\r
|
|
1890
|
+
fn vs(input: VIn, @builtin(instance_index) instance: u32) -> VOut {\r
|
|
1891
|
+
let safeInstance = min(instance, max(globals.drawInfo.y, 1u) - 1u);\r
|
|
1892
|
+
let hybrid = (globals.drawInfo.z & 2u) != 0u;\r
|
|
1893
|
+
let compactSlots = (globals.drawInfo.z & 4u) != 0u;\r
|
|
1894
|
+
let spritesPerSlot = max(globals.batchInfo.x, 1u);\r
|
|
1895
|
+
let slotStateIndex = select(safeInstance, safeInstance / spritesPerSlot, compactSlots);\r
|
|
1896
|
+
let hybridBase = slotStateIndex * 4u;\r
|
|
1897
|
+
var hybridParent = vec4f(0.0);\r
|
|
1898
|
+
var hybridTranslateOpacityFrame = vec4f(0.0);\r
|
|
1899
|
+
var hybridClip = vec4f(0.0);\r
|
|
1900
|
+
var hybridInfo = vec4f(0.0);\r
|
|
1901
|
+
if (hybrid || compactSlots) {\r
|
|
1902
|
+
hybridParent = hybridInstances[hybridBase];\r
|
|
1903
|
+
hybridTranslateOpacityFrame = hybridInstances[hybridBase + 1u];\r
|
|
1904
|
+
hybridClip = hybridInstances[hybridBase + 2u];\r
|
|
1905
|
+
hybridInfo = hybridInstances[hybridBase + 3u];\r
|
|
1906
|
+
}\r
|
|
1907
|
+
let spriteWithinSlot = select(safeInstance, safeInstance % spritesPerSlot, compactSlots);\r
|
|
1908
|
+
let metadataIndex = select(\r
|
|
1909
|
+
globals.drawInfo.x + spriteWithinSlot,\r
|
|
1910
|
+
u32(max(hybridInfo.y, 0.0)),\r
|
|
1911
|
+
hybrid,\r
|
|
1912
|
+
);\r
|
|
1913
|
+
let metadataStride = max(globals.batchInfo.y, 2u);\r
|
|
1914
|
+
let metadataBase = metadataIndex * metadataStride;\r
|
|
1915
|
+
let metadataUv = spriteMetadata[metadataBase];\r
|
|
1916
|
+
let metadataSprite = spriteMetadata[metadataBase + 1u];\r
|
|
1917
|
+
var metadataClip = vec4f(0.0);\r
|
|
1918
|
+
if (metadataStride >= 3u) {\r
|
|
1919
|
+
metadataClip = spriteMetadata[metadataBase + 2u];\r
|
|
1920
|
+
}\r
|
|
1921
|
+
let metadataPage = metadataSprite.y;\r
|
|
1922
|
+
let metadataFlags = u32(max(metadataSprite.z, 0.0));\r
|
|
1923
|
+
// The source sprite index is explicit so a page-specific metadata range\r
|
|
1924
|
+
// can represent non-contiguous atlas pages without duplicating frame rows.\r
|
|
1925
|
+
// A page mismatch is made transparent so an invalid plan cannot sample a\r
|
|
1926
|
+
// sprite into the wrong atlas page.\r
|
|
1927
|
+
let spriteIndex = u32(max(metadataSprite.x, 0.0));\r
|
|
1928
|
+
\r
|
|
1929
|
+
let frameCount = max(globals.tableInfo.x, 1u);\r
|
|
1930
|
+
let spriteCount = max(globals.tableInfo.y, 1u);\r
|
|
1931
|
+
let safeSprite = min(spriteIndex, spriteCount - 1u);\r
|
|
1932
|
+
let selectedFrame = select(\r
|
|
1933
|
+
globals.translateOpacityFrame.w,\r
|
|
1934
|
+
hybridTranslateOpacityFrame.w,\r
|
|
1935
|
+
hybrid || compactSlots,\r
|
|
1936
|
+
);\r
|
|
1937
|
+
let safeFrame = min(\r
|
|
1938
|
+
u32(max(selectedFrame, 0.0)),\r
|
|
1939
|
+
frameCount - 1u,\r
|
|
1940
|
+
);\r
|
|
1941
|
+
let tableBase = (safeSprite * frameCount + safeFrame) * globals.tableInfo.z;\r
|
|
1942
|
+
let frame0 = readFrameValue(tableBase);\r
|
|
1943
|
+
let frame1 = readFrameValue(tableBase + 1u);\r
|
|
1944
|
+
let frame2 = readFrameValue(tableBase + 2u);\r
|
|
1945
|
+
\r
|
|
1946
|
+
let layoutW = frame0.x;\r
|
|
1947
|
+
let layoutH = frame0.y;\r
|
|
1948
|
+
let local = vec2f(\r
|
|
1949
|
+
frame0.z * layoutW * input.corner.x + frame1.x * layoutH * input.corner.y + frame1.z,\r
|
|
1950
|
+
frame0.w * layoutW * input.corner.x + frame1.y * layoutH * input.corner.y + frame1.w,\r
|
|
1951
|
+
);\r
|
|
1952
|
+
\r
|
|
1953
|
+
let instanceSlotState = hybrid || compactSlots;\r
|
|
1954
|
+
let parent = select(globals.parentAffine, hybridParent, instanceSlotState);\r
|
|
1955
|
+
let parentTranslate = select(\r
|
|
1956
|
+
globals.translateOpacityFrame.xy,\r
|
|
1957
|
+
hybridTranslateOpacityFrame.xy,\r
|
|
1958
|
+
instanceSlotState,\r
|
|
1959
|
+
);\r
|
|
1960
|
+
let parentLocal = vec2f(\r
|
|
1961
|
+
parent.x * local.x + parent.z * local.y + parentTranslate.x,\r
|
|
1962
|
+
parent.y * local.x + parent.w * local.y + parentTranslate.y,\r
|
|
1963
|
+
);\r
|
|
1964
|
+
let instanceTrack = u32(max(hybridInfo.w, 0.0));\r
|
|
1965
|
+
let selectedTrack = select(globals.drawInfo.w, instanceTrack, compactSlots);\r
|
|
1966
|
+
let hasParentMotion = selectedTrack > 0u;\r
|
|
1967
|
+
var world = parentLocal;\r
|
|
1968
|
+
var outerClip = select(globals.clipRect, hybridClip, instanceSlotState);\r
|
|
1969
|
+
let outerClipEnabled = select(\r
|
|
1970
|
+
f32(globals.drawInfo.z & 1u),\r
|
|
1971
|
+
hybridInfo.x,\r
|
|
1972
|
+
instanceSlotState,\r
|
|
1973
|
+
);\r
|
|
1974
|
+
var parentOpacity = select(\r
|
|
1975
|
+
globals.translateOpacityFrame.z,\r
|
|
1976
|
+
hybridTranslateOpacityFrame.z,\r
|
|
1977
|
+
instanceSlotState,\r
|
|
1978
|
+
);\r
|
|
1979
|
+
if (hasParentMotion) {\r
|
|
1980
|
+
let track = selectedTrack - 1u;\r
|
|
1981
|
+
let scale = vec2f(sampleMotion(track, 2u), sampleMotion(track, 3u));\r
|
|
1982
|
+
let angle = sampleMotion(track, 4u);\r
|
|
1983
|
+
let cosine = cos(angle);\r
|
|
1984
|
+
let sine = sin(angle);\r
|
|
1985
|
+
let center = vec2f(\r
|
|
1986
|
+
sampleMotion(track, 0u) * motionGlobals.cssScaleX,\r
|
|
1987
|
+
sampleMotion(track, 1u) * motionGlobals.cssScaleY,\r
|
|
1988
|
+
);\r
|
|
1989
|
+
world = applyMotionPoint(parentLocal, center, scale, cosine, sine);\r
|
|
1990
|
+
let clip0 = applyMotionPoint(outerClip.xy, center, scale, cosine, sine);\r
|
|
1991
|
+
let clip1 = applyMotionPoint(vec2f(outerClip.z, outerClip.y), center, scale, cosine, sine);\r
|
|
1992
|
+
let clip2 = applyMotionPoint(outerClip.zw, center, scale, cosine, sine);\r
|
|
1993
|
+
let clip3 = applyMotionPoint(vec2f(outerClip.x, outerClip.w), center, scale, cosine, sine);\r
|
|
1994
|
+
outerClip = vec4f(\r
|
|
1995
|
+
min(min(clip0.x, clip1.x), min(clip2.x, clip3.x)),\r
|
|
1996
|
+
min(min(clip0.y, clip1.y), min(clip2.y, clip3.y)),\r
|
|
1997
|
+
max(max(clip0.x, clip1.x), max(clip2.x, clip3.x)),\r
|
|
1998
|
+
max(max(clip0.y, clip1.y), max(clip2.y, clip3.y)),\r
|
|
1999
|
+
);\r
|
|
2000
|
+
let visible = sampleMotion(track, 6u);\r
|
|
2001
|
+
parentOpacity = sampleMotion(track, 5u) * select(0.0, 1.0, visible > 0.5);\r
|
|
2002
|
+
}\r
|
|
2003
|
+
\r
|
|
2004
|
+
var output: VOut;\r
|
|
2005
|
+
output.pos = globals.projection * vec4f(world, 0.0, 1.0);\r
|
|
2006
|
+
output.uv = mix(metadataUv.xy, metadataUv.zw, input.corner);\r
|
|
2007
|
+
var pageMatchesValue = globals.tableInfo.w == 0xffffffffu ||\r
|
|
2008
|
+
u32(max(metadataPage, 0.0)) == globals.tableInfo.w;\r
|
|
2009
|
+
if (hybrid || compactSlots) {\r
|
|
2010
|
+
pageMatchesValue = hybridInfo.z < -0.5 ||\r
|
|
2011
|
+
i32(round(metadataPage)) == i32(round(hybridInfo.z));\r
|
|
2012
|
+
}\r
|
|
2013
|
+
let pageMatches = select(\r
|
|
2014
|
+
0.0,\r
|
|
2015
|
+
1.0,\r
|
|
2016
|
+
pageMatchesValue,\r
|
|
2017
|
+
);\r
|
|
2018
|
+
let metadataPresent = select(1.0, 0.0, (metadataFlags & 1u) != 0u);\r
|
|
2019
|
+
// Keep the table path's visibility cutoff identical to the CPU reference\r
|
|
2020
|
+
// renderer: rows below 0.05 are culled before issuing meaningful color.\r
|
|
2021
|
+
// Exactly 0.05 remains visible (the reference uses a strict \`< 0.05\` test).\r
|
|
2022
|
+
let effectiveAlpha = frame2.x * parentOpacity * pageMatches * metadataPresent;\r
|
|
2023
|
+
let visibleAlpha = select(0.0, effectiveAlpha, effectiveAlpha >= 0.05);\r
|
|
2024
|
+
output.color = vec4f(visibleAlpha);\r
|
|
2025
|
+
output.clipRect = outerClip;\r
|
|
2026
|
+
output.clipEnabled = outerClipEnabled;\r
|
|
2027
|
+
output.localPosition = vec2f(layoutW * input.corner.x, layoutH * input.corner.y);\r
|
|
2028
|
+
output.localClipRect = metadataClip;\r
|
|
2029
|
+
output.localClipEnabled = select(0.0, 1.0, (metadataFlags & 2u) != 0u);\r
|
|
2030
|
+
return output;\r
|
|
2031
|
+
}\r
|
|
2032
|
+
\r
|
|
2033
|
+
@fragment\r
|
|
2034
|
+
fn fs(input: VOut) -> @location(0) vec4f {\r
|
|
2035
|
+
if (input.color.a < 0.05) {\r
|
|
2036
|
+
discard;\r
|
|
2037
|
+
}\r
|
|
2038
|
+
if (input.clipEnabled > 0.5) {\r
|
|
2039
|
+
if (\r
|
|
2040
|
+
input.pos.x < input.clipRect.x ||\r
|
|
2041
|
+
input.pos.y < input.clipRect.y ||\r
|
|
2042
|
+
input.pos.x >= input.clipRect.z ||\r
|
|
2043
|
+
input.pos.y >= input.clipRect.w\r
|
|
2044
|
+
) {\r
|
|
2045
|
+
discard;\r
|
|
2046
|
+
}\r
|
|
2047
|
+
}\r
|
|
2048
|
+
if (\r
|
|
2049
|
+
input.localClipEnabled > 0.5 &&\r
|
|
2050
|
+
(\r
|
|
2051
|
+
input.localPosition.x < input.localClipRect.x ||\r
|
|
2052
|
+
input.localPosition.y < input.localClipRect.y ||\r
|
|
2053
|
+
input.localPosition.x >= input.localClipRect.z ||\r
|
|
2054
|
+
input.localPosition.y >= input.localClipRect.w\r
|
|
2055
|
+
)\r
|
|
2056
|
+
) {\r
|
|
2057
|
+
discard;\r
|
|
2058
|
+
}\r
|
|
2059
|
+
let color = textureSample(atlasTex, atlasSampler, input.uv);\r
|
|
2060
|
+
return vec4f(color.rgb * input.color.a, color.a * input.color.a);\r
|
|
2061
|
+
}\r
|
|
2062
2062
|
`, tg = Object.freeze({
|
|
2063
2063
|
submitted: !0
|
|
2064
2064
|
});
|
|
@@ -17052,18 +17052,18 @@ async function I(t, e, n, o, s) {
|
|
|
17052
17052
|
}
|
|
17053
17053
|
function v(t, e, n, o, s, i) {
|
|
17054
17054
|
if (n.w <= 0 || n.h <= 0 || i <= 0) return;
|
|
17055
|
-
const l = Math.max(1, Math.floor(i * 0.5)), a = n.x, c = n.y, h = n.w, r = n.h, f = Math.min(l, a), u = Math.min(l, c),
|
|
17056
|
-
e.imageSmoothingEnabled = !1, f > 0 && e.drawImage(t, a, c, 1, r, a - f, c, f, r),
|
|
17055
|
+
const l = Math.max(1, Math.floor(i * 0.5)), a = n.x, c = n.y, h = n.w, r = n.h, f = Math.min(l, a), u = Math.min(l, c), w = Math.min(l, o - (a + h)), d = Math.min(l, s - (c + r)), H = e.imageSmoothingEnabled;
|
|
17056
|
+
e.imageSmoothingEnabled = !1, f > 0 && e.drawImage(t, a, c, 1, r, a - f, c, f, r), w > 0 && e.drawImage(t, a + h - 1, c, 1, r, a + h, c, w, r), u > 0 && e.drawImage(t, a, c, h, 1, a, c - u, h, u), d > 0 && e.drawImage(t, a, c + r - 1, h, 1, a, c + r, h, d), f > 0 && u > 0 && e.drawImage(t, a, c, 1, 1, a - f, c - u, f, u), w > 0 && u > 0 && e.drawImage(t, a + h - 1, c, 1, 1, a + h, c - u, w, u), f > 0 && d > 0 && e.drawImage(t, a, c + r - 1, 1, 1, a - f, c + r, f, d), w > 0 && d > 0 && e.drawImage(t, a + h - 1, c + r - 1, 1, 1, a + h, c + r, w, d), e.imageSmoothingEnabled = H;
|
|
17057
17057
|
}
|
|
17058
17058
|
var E = Object.defineProperty, C = (t, e, n) => e in t ? E(t, e, { enumerable: !0, configurable: !0, writable: !0, value: n }) : t[e] = n, M = (t, e, n) => C(t, typeof e != "symbol" ? e + "" : e, n);
|
|
17059
17059
|
function g() {
|
|
17060
17060
|
return typeof performance != "undefined" ? performance.now() : Date.now();
|
|
17061
17061
|
}
|
|
17062
|
-
function
|
|
17062
|
+
function A(t) {
|
|
17063
17063
|
const e = t != null ? t : 4;
|
|
17064
17064
|
return Number.isFinite(e) ? Math.max(1, Math.min(8, e)) : 4;
|
|
17065
17065
|
}
|
|
17066
|
-
class
|
|
17066
|
+
class S {
|
|
17067
17067
|
constructor(e = 4) {
|
|
17068
17068
|
this.maxSliceMs = e, M(this, "sliceStartedAt", g());
|
|
17069
17069
|
}
|
|
@@ -17071,7 +17071,7 @@ class T {
|
|
|
17071
17071
|
g() - this.sliceStartedAt < this.maxSliceMs || (await new Promise((e) => setTimeout(e, 0)), this.sliceStartedAt = g());
|
|
17072
17072
|
}
|
|
17073
17073
|
}
|
|
17074
|
-
class
|
|
17074
|
+
class T {
|
|
17075
17075
|
constructor() {
|
|
17076
17076
|
M(this, "running", !1), M(this, "tasks", []);
|
|
17077
17077
|
}
|
|
@@ -17090,7 +17090,7 @@ class A {
|
|
|
17090
17090
|
}
|
|
17091
17091
|
}
|
|
17092
17092
|
}
|
|
17093
|
-
const m = self, Y = new
|
|
17093
|
+
const m = self, Y = new T();
|
|
17094
17094
|
async function _(t, e, n, o) {
|
|
17095
17095
|
const s = new OffscreenCanvas(t.atlasW, t.atlasH), i = s.getContext("2d");
|
|
17096
17096
|
if (!i) throw new Error("Atlas worker: 2d context unavailable");
|
|
@@ -17127,7 +17127,7 @@ async function X(t, e) {
|
|
|
17127
17127
|
}
|
|
17128
17128
|
async function $(t) {
|
|
17129
17129
|
var e;
|
|
17130
|
-
const n = [], o = new
|
|
17130
|
+
const n = [], o = new S(A(t.workerTimeSliceMs));
|
|
17131
17131
|
try {
|
|
17132
17132
|
if (typeof OffscreenCanvas == "undefined")
|
|
17133
17133
|
throw new Error("OffscreenCanvas unavailable in atlas worker");
|
|
@@ -17154,7 +17154,7 @@ async function $(t) {
|
|
|
17154
17154
|
for (const r of l) {
|
|
17155
17155
|
const f = await _(r, s, t.padding, o);
|
|
17156
17156
|
t.captureEncodedPng && c.push(B(f));
|
|
17157
|
-
const u = f
|
|
17157
|
+
const u = await createImageBitmap(f, { premultiplyAlpha: "premultiply" });
|
|
17158
17158
|
a.push({
|
|
17159
17159
|
width: r.atlasW,
|
|
17160
17160
|
height: r.atlasH,
|
|
@@ -17202,7 +17202,7 @@ m.onmessage = (t) => {
|
|
|
17202
17202
|
const e = t.data;
|
|
17203
17203
|
!e || e.type !== "build-svga-atlas" || Y.push(() => $(e));
|
|
17204
17204
|
};
|
|
17205
|
-
//# sourceMappingURL=svga-atlas-worker-
|
|
17205
|
+
//# sourceMappingURL=svga-atlas-worker-CkVFsaPa.js.map
|
|
17206
17206
|
`, lQ = typeof self != "undefined" && self.Blob && new Blob(["URL.revokeObjectURL(import.meta.url);", sE], { type: "text/javascript;charset=utf-8" });
|
|
17207
17207
|
function no(C) {
|
|
17208
17208
|
let A;
|
|
@@ -17318,7 +17318,7 @@ function ho() {
|
|
|
17318
17318
|
return NI;
|
|
17319
17319
|
}
|
|
17320
17320
|
function nE() {
|
|
17321
|
-
return typeof Worker != "undefined" && UQ() && typeof
|
|
17321
|
+
return typeof Worker != "undefined" && UQ() && typeof createImageBitmap == "function";
|
|
17322
17322
|
}
|
|
17323
17323
|
async function co(C, A) {
|
|
17324
17324
|
if (!nE())
|
|
@@ -17524,7 +17524,8 @@ async function yo(C, A, g, I, B) {
|
|
|
17524
17524
|
width: o.width,
|
|
17525
17525
|
height: o.height,
|
|
17526
17526
|
filter: "linear",
|
|
17527
|
-
premultiplyAlpha: !0
|
|
17527
|
+
premultiplyAlpha: !0,
|
|
17528
|
+
sourcePremultiplied: !0
|
|
17528
17529
|
});
|
|
17529
17530
|
try {
|
|
17530
17531
|
o.bitmap.close();
|