@flighthq/effects-gl 0.2.0 → 0.2.1-next.410.a23f189

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 (60) hide show
  1. package/dist/glBevelEffect.d.ts.map +1 -1
  2. package/dist/glBevelEffect.js +6 -4
  3. package/dist/glBevelEffect.js.map +1 -1
  4. package/dist/glBlendEffect.d.ts +8 -0
  5. package/dist/glBlendEffect.d.ts.map +1 -0
  6. package/dist/glBlendEffect.js +169 -0
  7. package/dist/glBlendEffect.js.map +1 -0
  8. package/dist/glCompositeEffect.d.ts +5 -0
  9. package/dist/glCompositeEffect.d.ts.map +1 -0
  10. package/dist/glCompositeEffect.js +90 -0
  11. package/dist/glCompositeEffect.js.map +1 -0
  12. package/dist/glDropShadowEffect.d.ts.map +1 -1
  13. package/dist/glDropShadowEffect.js +8 -6
  14. package/dist/glDropShadowEffect.js.map +1 -1
  15. package/dist/glEffectBlitShader.d.ts +2 -0
  16. package/dist/glEffectBlitShader.d.ts.map +1 -1
  17. package/dist/glEffectBlitShader.js +27 -0
  18. package/dist/glEffectBlitShader.js.map +1 -1
  19. package/dist/glEffectBoxBlur.d.ts +1 -0
  20. package/dist/glEffectBoxBlur.d.ts.map +1 -1
  21. package/dist/glEffectBoxBlur.js +28 -5
  22. package/dist/glEffectBoxBlur.js.map +1 -1
  23. package/dist/glEffectTintShader.d.ts.map +1 -1
  24. package/dist/glEffectTintShader.js +2 -0
  25. package/dist/glEffectTintShader.js.map +1 -1
  26. package/dist/glGradientBevelEffect.d.ts.map +1 -1
  27. package/dist/glGradientBevelEffect.js +8 -2
  28. package/dist/glGradientBevelEffect.js.map +1 -1
  29. package/dist/glGradientGlowEffect.d.ts.map +1 -1
  30. package/dist/glGradientGlowEffect.js +10 -3
  31. package/dist/glGradientGlowEffect.js.map +1 -1
  32. package/dist/glInnerGlowEffect.d.ts.map +1 -1
  33. package/dist/glInnerGlowEffect.js +24 -5
  34. package/dist/glInnerGlowEffect.js.map +1 -1
  35. package/dist/glInnerShadowEffect.d.ts.map +1 -1
  36. package/dist/glInnerShadowEffect.js +24 -5
  37. package/dist/glInnerShadowEffect.js.map +1 -1
  38. package/dist/glOuterGlowEffect.d.ts.map +1 -1
  39. package/dist/glOuterGlowEffect.js +8 -4
  40. package/dist/glOuterGlowEffect.js.map +1 -1
  41. package/dist/glRenderEffectPipeline.d.ts.map +1 -1
  42. package/dist/glRenderEffectPipeline.js +23 -7
  43. package/dist/glRenderEffectPipeline.js.map +1 -1
  44. package/dist/glRenderEffectRegistrar.d.ts.map +1 -1
  45. package/dist/glRenderEffectRegistrar.js +14 -4
  46. package/dist/glRenderEffectRegistrar.js.map +1 -1
  47. package/dist/index.d.ts +2 -0
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +2 -0
  50. package/dist/index.js.map +1 -1
  51. package/package.json +6 -6
  52. package/src/glBlendEffect.test.ts +111 -0
  53. package/src/glCompositeEffect.test.ts +39 -0
  54. package/src/glDropShadowEffect.test.ts +92 -0
  55. package/src/glEffectBlitShader.test.ts +7 -1
  56. package/src/glEffectBoxBlur.test.ts +50 -0
  57. package/src/glInnerGlowEffect.test.ts +132 -0
  58. package/src/glInnerShadowEffect.test.ts +132 -0
  59. package/src/glOuterGlowEffect.test.ts +91 -0
  60. package/src/glRenderEffectRegistrar.test.ts +2 -1
@@ -1 +1 @@
1
- {"version":3,"file":"glBevelEffect.d.ts","sourceRoot":"","sources":["../src/glBevelEffect.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,WAAW,EAEX,oBAAoB,EACpB,aAAa,EACb,cAAc,EACd,kBAAkB,EACnB,MAAM,iBAAiB,CAAC;AAqBzB,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,aAAa,EACpB,MAAM,EAAE,QAAQ,CAAC,cAAc,CAAC,EAChC,IAAI,EAAE,QAAQ,CAAC,cAAc,CAAC,EAC9B,IAAI,EAAE,kBAAkB,EACxB,MAAM,EAAE,QAAQ,CAAC,WAAW,CAAC,GAC5B,IAAI,CAoDN;AAED,eAAO,MAAM,0BAA0B,EAAE,oBAExC,CAAC"}
1
+ {"version":3,"file":"glBevelEffect.d.ts","sourceRoot":"","sources":["../src/glBevelEffect.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,WAAW,EAEX,oBAAoB,EACpB,aAAa,EACb,cAAc,EACd,kBAAkB,EACnB,MAAM,iBAAiB,CAAC;AAqBzB,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,aAAa,EACpB,MAAM,EAAE,QAAQ,CAAC,cAAc,CAAC,EAChC,IAAI,EAAE,QAAQ,CAAC,cAAc,CAAC,EAC9B,IAAI,EAAE,kBAAkB,EACxB,MAAM,EAAE,QAAQ,CAAC,WAAW,CAAC,GAC5B,IAAI,CAsDN;AAED,eAAO,MAAM,0BAA0B,EAAE,oBAExC,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import { acquireGlRenderTarget, clearGlRenderTarget, compileGlFullscreenProgram, drawGlFullscreenPass, releaseGlRenderTarget, } from '@flighthq/render-gl';
2
- import { applyGlEffectBlitPass } from './glEffectBlitShader';
2
+ import { applyGlEffectBlitPass, applyGlEffectErasePass } from './glEffectBlitShader';
3
3
  import { applyGlEffectBoxBlur } from './glEffectBoxBlur';
4
4
  import { applyGlEffectTintPass } from './glEffectTintShader';
5
5
  // Bevel composite effect: the directional gradient of the blurred silhouette drives a highlight/shadow edge band, clipped by bevelType and composited over the source.
@@ -35,7 +35,7 @@ export function applyBevelEffectToGl(state, source, dest, pool, effect) {
35
35
  const highlightAlpha = effect.highlightAlpha ?? 1;
36
36
  const strength = effect.strength ?? 1;
37
37
  const quality = Math.max(1, Math.round(effect.quality ?? 1));
38
- const knockout = effect.knockout ?? false;
38
+ const sourceMode = effect.sourceMode ?? 'draw';
39
39
  const bevelType = effect.bevelType ?? 'inner';
40
40
  const [tinted, blurred, blurTemp] = [s0, s1, s2];
41
41
  // Blurred alpha field (neutral white tint, strength 1 — strength is the gradient
@@ -47,7 +47,7 @@ export function applyBevelEffectToGl(state, source, dest, pool, effect) {
47
47
  passes: quality,
48
48
  });
49
49
  clearGlRenderTarget(state, dst);
50
- if (!knockout)
50
+ if (sourceMode === 'draw')
51
51
  applyGlEffectBlitPass(state, src, dst);
52
52
  applyGlBevelCompositePass(state, blurred, src, dst, {
53
53
  offsetX: offsetX / src.width,
@@ -60,6 +60,8 @@ export function applyBevelEffectToGl(state, source, dest, pool, effect) {
60
60
  intensity: strength,
61
61
  clipMode: bevelType === 'inner' ? 1 : bevelType === 'outer' ? 2 : 0,
62
62
  });
63
+ if (sourceMode === 'knockout')
64
+ applyGlEffectErasePass(state, src, dst);
63
65
  releaseGlRenderTarget(pool, s0);
64
66
  releaseGlRenderTarget(pool, s1);
65
67
  releaseGlRenderTarget(pool, s2);
@@ -68,7 +70,7 @@ export const defaultGlBevelEffectRunner = (ctx, effect) => {
68
70
  applyBevelEffectToGl(ctx.state, ctx.source, ctx.dest, ctx.pool, effect);
69
71
  };
70
72
  // Reads the blurred alpha field (unit 0) and source (unit 1); writes the tinted, clipped bevel mask,
71
- // premultiplied, blended over `dest` (which already holds the source unless knockout).
73
+ // premultiplied, blended over `dest` (which already holds the source when sourceMode is 'draw').
72
74
  const BEVEL_COMPOSITE_FRAGMENT_SRC = `#version 300 es
73
75
  precision mediump float;
74
76
  in vec2 v_texCoord;
@@ -1 +1 @@
1
- {"version":3,"file":"glBevelEffect.js","sourceRoot":"","sources":["../src/glBevelEffect.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"glBevelEffect.js","sourceRoot":"","sources":["../src/glBevelEffect.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { AdvancedBlendMode, BlendEffect, GlRenderEffectRunner, GlRenderState, GlRenderTarget } from '@flighthq/types';
2
+ export declare function applyBlendEffectToGl(state: GlRenderState, source: Readonly<GlRenderTarget>, dest: Readonly<GlRenderTarget>, effect: Readonly<BlendEffect>): void;
3
+ export declare const defaultGlBlendEffectRunner: GlRenderEffectRunner;
4
+ export declare function getBlendEffectModeIndex(mode: AdvancedBlendMode): number;
5
+ export declare function getGlBlendEffectBackdrop(state: GlRenderState, backdropKey: string | null): WebGLTexture | null;
6
+ export declare function registerGlBlendEffectBackdrop(state: GlRenderState, backdropKey: string, texture: WebGLTexture): void;
7
+ export declare function unregisterGlBlendEffectBackdrop(state: GlRenderState, backdropKey: string): boolean;
8
+ //# sourceMappingURL=glBlendEffect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"glBlendEffect.d.ts","sourceRoot":"","sources":["../src/glBlendEffect.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,iBAAiB,EACjB,WAAW,EACX,oBAAoB,EACpB,aAAa,EACb,cAAc,EACf,MAAM,iBAAiB,CAAC;AAezB,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,aAAa,EACpB,MAAM,EAAE,QAAQ,CAAC,cAAc,CAAC,EAChC,IAAI,EAAE,QAAQ,CAAC,cAAc,CAAC,EAC9B,MAAM,EAAE,QAAQ,CAAC,WAAW,CAAC,GAC5B,IAAI,CAkBN;AAED,eAAO,MAAM,0BAA0B,EAAE,oBAExC,CAAC;AAIF,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,CAEvE;AAID,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,YAAY,GAAG,IAAI,CAG9G;AAKD,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,IAAI,CAOpH;AAID,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAElG"}
@@ -0,0 +1,169 @@
1
+ import { drawGlFullscreenPass } from '@flighthq/render-gl';
2
+ import { AdvancedBlendMode as AdvancedBlendModeValues } from '@flighthq/types';
3
+ import { getGlEffectProgram, getGlEffectUniformLocation } from './glEffectProgramCache';
4
+ // Advanced-blend composite pass: sample the incoming layer (`u_texture0`, the effect's `source`) and a
5
+ // registered backdrop (`u_texture1`), compute the destination-reading / non-separable blend named by the
6
+ // effect's `mode`, composite the blended color over the backdrop (Porter-Duff source-over), and write to
7
+ // `dest`. This is the GL realization of the `BlendEffect` composite recipe — the escape hatch for the
8
+ // AdvancedBlendMode set the fixed-function BlendMode enum cannot express. The GLSL mirrors
9
+ // @flighthq/effects blendModeMath exactly, so the pass is verified against those plain-number tests.
10
+ //
11
+ // The backdrop is looked up by the effect's `backdropKey` in the per-state backdrop registry populated by
12
+ // registerGlBlendEffectBackdrop. An unregistered (or absent) key composites the layer over an implicit
13
+ // transparent backdrop, which reduces to source-over passthrough rather than erroring.
14
+ export function applyBlendEffectToGl(state, source, dest, effect) {
15
+ const backdrop = getGlBlendEffectBackdrop(state, effect.backdropKey ?? null);
16
+ const program = getGlEffectProgram(state, 'blend.advanced', BLEND_FRAGMENT_SRC);
17
+ const modeIndex = getBlendEffectModeIndex(effect.mode);
18
+ const opacity = effect.opacity ?? 1;
19
+ const hasBackdrop = backdrop !== null;
20
+ // Bind the layer to unit 0 and the backdrop (or the layer itself as a harmless stand-in) to unit 1;
21
+ // `u_hasBackdrop` gates whether unit 1 is used, so a missing backdrop is a source-over passthrough.
22
+ const inputs = [source.texture, hasBackdrop ? backdrop : source.texture];
23
+ drawGlFullscreenPass(state, program, inputs, dest, (gl, p) => {
24
+ const modeLoc = getGlEffectUniformLocation(state, p, 'u_mode');
25
+ const opacityLoc = getGlEffectUniformLocation(state, p, 'u_opacity');
26
+ const hasBackdropLoc = getGlEffectUniformLocation(state, p, 'u_hasBackdrop');
27
+ if (modeLoc !== null)
28
+ gl.uniform1i(modeLoc, modeIndex);
29
+ if (opacityLoc !== null)
30
+ gl.uniform1f(opacityLoc, opacity);
31
+ if (hasBackdropLoc !== null)
32
+ gl.uniform1i(hasBackdropLoc, hasBackdrop ? 1 : 0);
33
+ });
34
+ }
35
+ export const defaultGlBlendEffectRunner = (ctx, effect) => {
36
+ applyBlendEffectToGl(ctx.state, ctx.source, ctx.dest, effect);
37
+ };
38
+ // Maps an AdvancedBlendMode string to the integer the fragment shader switches on. Kept in lockstep with
39
+ // the BLEND_FRAGMENT_SRC branch order; an unknown mode maps to -1 (Normal passthrough in the shader).
40
+ export function getBlendEffectModeIndex(mode) {
41
+ return BLEND_MODE_INDEX[mode] ?? -1;
42
+ }
43
+ // Returns the backdrop texture registered under `backdropKey` for this state, or null when the key is
44
+ // null/absent or nothing is registered. Doubles as the introspection query for the passthrough fallback.
45
+ export function getGlBlendEffectBackdrop(state, backdropKey) {
46
+ if (backdropKey === null)
47
+ return null;
48
+ return _backdrops.get(state)?.get(backdropKey) ?? null;
49
+ }
50
+ // Registers a backdrop texture under `backdropKey` for this state, so a BlendEffect naming that key
51
+ // blends its layer over the texture. Last write wins. Pass a texture produced by the caller (e.g. a
52
+ // prior render target's `.texture`); the registry holds the handle only and never owns/frees it.
53
+ export function registerGlBlendEffectBackdrop(state, backdropKey, texture) {
54
+ let registry = _backdrops.get(state);
55
+ if (registry === undefined) {
56
+ registry = new Map();
57
+ _backdrops.set(state, registry);
58
+ }
59
+ registry.set(backdropKey, texture);
60
+ }
61
+ // Removes the backdrop registered under `backdropKey` for this state, returning true if one was present.
62
+ // The texture itself is the caller's to free; this only drops the registry reference.
63
+ export function unregisterGlBlendEffectBackdrop(state, backdropKey) {
64
+ return _backdrops.get(state)?.delete(backdropKey) ?? false;
65
+ }
66
+ // AdvancedBlendMode → shader branch index. Alphabetical by value; kept in lockstep with the switch in
67
+ // BLEND_FRAGMENT_SRC. The four HSL modes (Color/Hue/Luminosity/Saturation) take indices 7..10.
68
+ const BLEND_MODE_INDEX = {
69
+ [AdvancedBlendModeValues.Overlay]: 0,
70
+ [AdvancedBlendModeValues.HardLight]: 1,
71
+ [AdvancedBlendModeValues.SoftLight]: 2,
72
+ [AdvancedBlendModeValues.Difference]: 3,
73
+ [AdvancedBlendModeValues.Exclusion]: 4,
74
+ [AdvancedBlendModeValues.ColorDodge]: 5,
75
+ [AdvancedBlendModeValues.ColorBurn]: 6,
76
+ [AdvancedBlendModeValues.Hue]: 7,
77
+ [AdvancedBlendModeValues.Saturation]: 8,
78
+ [AdvancedBlendModeValues.Color]: 9,
79
+ [AdvancedBlendModeValues.Luminosity]: 10,
80
+ };
81
+ // Per-state backdrop registry. Off the render-state runtime type, freed with the state. Holds texture
82
+ // handles only — never owns or frees them.
83
+ const _backdrops = new WeakMap();
84
+ // The advanced-blend fragment shader. Layer = u_texture0 (premultiplied), backdrop = u_texture1. Both are
85
+ // un-premultiplied to straight RGB for the blend math, blended via the mode's B(cb, cs), then the blended
86
+ // color is composited over the backdrop with W3C mixing (cs' = (1 - ab)*cs + ab*B) and Porter-Duff
87
+ // source-over, re-premultiplied on output. The separable/HSL formulas mirror effects/blendModeMath.ts.
88
+ const BLEND_FRAGMENT_SRC = `#version 300 es
89
+ precision highp float;
90
+ in vec2 v_texCoord;
91
+ uniform sampler2D u_texture0;
92
+ uniform sampler2D u_texture1;
93
+ uniform int u_mode;
94
+ uniform float u_opacity;
95
+ uniform int u_hasBackdrop;
96
+ out vec4 o_color;
97
+
98
+ float lum(vec3 c) { return 0.3 * c.r + 0.59 * c.g + 0.11 * c.b; }
99
+ float sat(vec3 c) { return max(max(c.r, c.g), c.b) - min(min(c.r, c.g), c.b); }
100
+
101
+ vec3 clipColor(vec3 c) {
102
+ float l = lum(c);
103
+ float mn = min(min(c.r, c.g), c.b);
104
+ float mx = max(max(c.r, c.g), c.b);
105
+ if (mn < 0.0) c = l + (c - l) * l / (l - mn);
106
+ if (mx > 1.0) c = l + (c - l) * (1.0 - l) / (mx - l);
107
+ return c;
108
+ }
109
+ vec3 setLum(vec3 c, float l) { return clipColor(c + (l - lum(c))); }
110
+
111
+ vec3 setSat(vec3 c, float s) {
112
+ // Resolve min/mid/max channels, rescale mid+max to s, pin min to 0. Branchy but only three channels.
113
+ float mn = min(min(c.r, c.g), c.b);
114
+ float mx = max(max(c.r, c.g), c.b);
115
+ float md = (c.r + c.g + c.b) - mn - mx;
116
+ vec3 o;
117
+ float rmid = (mx > mn) ? (md - mn) * s / (mx - mn) : 0.0;
118
+ float rmax = (mx > mn) ? s : 0.0;
119
+ o.r = (c.r == mx) ? rmax : ((c.r == mn) ? 0.0 : rmid);
120
+ o.g = (c.g == mx) ? rmax : ((c.g == mn) ? 0.0 : rmid);
121
+ o.b = (c.b == mx) ? rmax : ((c.b == mn) ? 0.0 : rmid);
122
+ return o;
123
+ }
124
+
125
+ float sepChannel(int mode, float cb, float cs) {
126
+ if (mode == 0) return cb <= 0.5 ? 2.0 * cb * cs : 1.0 - 2.0 * (1.0 - cb) * (1.0 - cs); // Overlay
127
+ if (mode == 1) return cs <= 0.5 ? 2.0 * cb * cs : 1.0 - 2.0 * (1.0 - cb) * (1.0 - cs); // HardLight
128
+ if (mode == 2) { // SoftLight
129
+ float d = cb <= 0.25 ? ((16.0 * cb - 12.0) * cb + 4.0) * cb : sqrt(cb);
130
+ return cs <= 0.5 ? cb - (1.0 - 2.0 * cs) * cb * (1.0 - cb) : cb + (2.0 * cs - 1.0) * (d - cb);
131
+ }
132
+ if (mode == 3) return abs(cb - cs); // Difference
133
+ if (mode == 4) return cb + cs - 2.0 * cb * cs; // Exclusion
134
+ if (mode == 5) return cb <= 0.0 ? 0.0 : (cs >= 1.0 ? 1.0 : min(1.0, cb / (1.0 - cs))); // ColorDodge
135
+ if (mode == 6) return cb >= 1.0 ? 1.0 : (cs <= 0.0 ? 0.0 : 1.0 - min(1.0, (1.0 - cb) / cs)); // ColorBurn
136
+ return cs; // Normal
137
+ }
138
+
139
+ vec3 blendRgb(int mode, vec3 cb, vec3 cs) {
140
+ if (mode == 7) return setLum(setSat(cs, sat(cb)), lum(cb)); // Hue
141
+ if (mode == 8) return setLum(setSat(cb, sat(cs)), lum(cb)); // Saturation
142
+ if (mode == 9) return setLum(cs, lum(cb)); // Color
143
+ if (mode == 10) return setLum(cb, lum(cs)); // Luminosity
144
+ return vec3(sepChannel(mode, cb.r, cs.r), sepChannel(mode, cb.g, cs.g), sepChannel(mode, cb.b, cs.b));
145
+ }
146
+
147
+ void main() {
148
+ vec4 layer = texture(u_texture0, v_texCoord);
149
+ // No backdrop registered: the blend has nothing to read, so pass the layer through unchanged.
150
+ if (u_hasBackdrop == 0) { o_color = layer; return; }
151
+ vec4 back = texture(u_texture1, v_texCoord);
152
+
153
+ // Un-premultiply to straight RGB for the blend math.
154
+ vec3 cs = layer.a > 0.0 ? layer.rgb / layer.a : vec3(0.0);
155
+ vec3 cb = back.a > 0.0 ? back.rgb / back.a : vec3(0.0);
156
+ float as = layer.a * u_opacity;
157
+ float ab = back.a;
158
+
159
+ // W3C blend mixing: the blended color contributes only where the backdrop is opaque; elsewhere the
160
+ // straight source shows through. cs' = (1 - ab) * cs + ab * B(cb, cs).
161
+ vec3 blended = blendRgb(u_mode, cb, cs);
162
+ vec3 mixed = (1.0 - ab) * cs + ab * blended;
163
+
164
+ // Porter-Duff source-over of the (mixed) layer onto the backdrop, output premultiplied.
165
+ float outA = as + ab * (1.0 - as);
166
+ vec3 outRgb = mixed * as + cb * ab * (1.0 - as);
167
+ o_color = vec4(outRgb, outA);
168
+ }`;
169
+ //# sourceMappingURL=glBlendEffect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"glBlendEffect.js","sourceRoot":"","sources":["../src/glBlendEffect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAQ3D,OAAO,EAAE,iBAAiB,IAAI,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAE/E,OAAO,EAAE,kBAAkB,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AAExF,uGAAuG;AACvG,yGAAyG;AACzG,yGAAyG;AACzG,sGAAsG;AACtG,2FAA2F;AAC3F,qGAAqG;AACrG,EAAE;AACF,0GAA0G;AAC1G,uGAAuG;AACvG,uFAAuF;AACvF,MAAM,UAAU,oBAAoB,CAClC,KAAoB,EACpB,MAAgC,EAChC,IAA8B,EAC9B,MAA6B;IAE7B,MAAM,QAAQ,GAAG,wBAAwB,CAAC,KAAK,EAAE,MAAM,CAAC,WAAW,IAAI,IAAI,CAAC,CAAC;IAC7E,MAAM,OAAO,GAAG,kBAAkB,CAAC,KAAK,EAAE,gBAAgB,EAAE,kBAAkB,CAAC,CAAC;IAChF,MAAM,SAAS,GAAG,uBAAuB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACvD,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,IAAI,CAAC,CAAC;IACpC,MAAM,WAAW,GAAG,QAAQ,KAAK,IAAI,CAAC;IAEtC,oGAAoG;IACpG,oGAAoG;IACpG,MAAM,MAAM,GAAG,CAAC,MAAM,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC,CAAE,QAAyB,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC3F,oBAAoB,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE;QAC3D,MAAM,OAAO,GAAG,0BAA0B,CAAC,KAAK,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC;QAC/D,MAAM,UAAU,GAAG,0BAA0B,CAAC,KAAK,EAAE,CAAC,EAAE,WAAW,CAAC,CAAC;QACrE,MAAM,cAAc,GAAG,0BAA0B,CAAC,KAAK,EAAE,CAAC,EAAE,eAAe,CAAC,CAAC;QAC7E,IAAI,OAAO,KAAK,IAAI;YAAE,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QACvD,IAAI,UAAU,KAAK,IAAI;YAAE,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAC3D,IAAI,cAAc,KAAK,IAAI;YAAE,EAAE,CAAC,SAAS,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACjF,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,MAAM,0BAA0B,GAAyB,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE;IAC9E,oBAAoB,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI,EAAE,MAAqB,CAAC,CAAC;AAC/E,CAAC,CAAC;AAEF,yGAAyG;AACzG,sGAAsG;AACtG,MAAM,UAAU,uBAAuB,CAAC,IAAuB;IAC7D,OAAO,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AACtC,CAAC;AAED,sGAAsG;AACtG,yGAAyG;AACzG,MAAM,UAAU,wBAAwB,CAAC,KAAoB,EAAE,WAA0B;IACvF,IAAI,WAAW,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACtC,OAAO,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC;AACzD,CAAC;AAED,oGAAoG;AACpG,oGAAoG;AACpG,iGAAiG;AACjG,MAAM,UAAU,6BAA6B,CAAC,KAAoB,EAAE,WAAmB,EAAE,OAAqB;IAC5G,IAAI,QAAQ,GAAG,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACrC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,QAAQ,GAAG,IAAI,GAAG,EAAE,CAAC;QACrB,UAAU,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IAClC,CAAC;IACD,QAAQ,CAAC,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;AACrC,CAAC;AAED,yGAAyG;AACzG,sFAAsF;AACtF,MAAM,UAAU,+BAA+B,CAAC,KAAoB,EAAE,WAAmB;IACvF,OAAO,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,WAAW,CAAC,IAAI,KAAK,CAAC;AAC7D,CAAC;AAED,sGAAsG;AACtG,+FAA+F;AAC/F,MAAM,gBAAgB,GAAqC;IACzD,CAAC,uBAAuB,CAAC,OAAO,CAAC,EAAE,CAAC;IACpC,CAAC,uBAAuB,CAAC,SAAS,CAAC,EAAE,CAAC;IACtC,CAAC,uBAAuB,CAAC,SAAS,CAAC,EAAE,CAAC;IACtC,CAAC,uBAAuB,CAAC,UAAU,CAAC,EAAE,CAAC;IACvC,CAAC,uBAAuB,CAAC,SAAS,CAAC,EAAE,CAAC;IACtC,CAAC,uBAAuB,CAAC,UAAU,CAAC,EAAE,CAAC;IACvC,CAAC,uBAAuB,CAAC,SAAS,CAAC,EAAE,CAAC;IACtC,CAAC,uBAAuB,CAAC,GAAG,CAAC,EAAE,CAAC;IAChC,CAAC,uBAAuB,CAAC,UAAU,CAAC,EAAE,CAAC;IACvC,CAAC,uBAAuB,CAAC,KAAK,CAAC,EAAE,CAAC;IAClC,CAAC,uBAAuB,CAAC,UAAU,CAAC,EAAE,EAAE;CACzC,CAAC;AAEF,sGAAsG;AACtG,2CAA2C;AAC3C,MAAM,UAAU,GAAG,IAAI,OAAO,EAA4C,CAAC;AAE3E,0GAA0G;AAC1G,0GAA0G;AAC1G,mGAAmG;AACnG,uGAAuG;AACvG,MAAM,kBAAkB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgFzB,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { CompositeEffect, CompositeOperator, GlRenderEffectRunner, GlRenderState, GlRenderTarget } from '@flighthq/types';
2
+ export declare function applyCompositeEffectToGl(state: GlRenderState, source: Readonly<GlRenderTarget>, dest: Readonly<GlRenderTarget>, effect: Readonly<CompositeEffect>): void;
3
+ export declare const defaultGlCompositeEffectRunner: GlRenderEffectRunner;
4
+ export declare function getCompositeEffectOperatorIndex(operator: CompositeOperator): number;
5
+ //# sourceMappingURL=glCompositeEffect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"glCompositeEffect.d.ts","sourceRoot":"","sources":["../src/glCompositeEffect.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,eAAe,EACf,iBAAiB,EACjB,oBAAoB,EACpB,aAAa,EACb,cAAc,EACf,MAAM,iBAAiB,CAAC;AAiBzB,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,aAAa,EACpB,MAAM,EAAE,QAAQ,CAAC,cAAc,CAAC,EAChC,IAAI,EAAE,QAAQ,CAAC,cAAc,CAAC,EAC9B,MAAM,EAAE,QAAQ,CAAC,eAAe,CAAC,GAChC,IAAI,CAeN;AAED,eAAO,MAAM,8BAA8B,EAAE,oBAE5C,CAAC;AAIF,wBAAgB,+BAA+B,CAAC,QAAQ,EAAE,iBAAiB,GAAG,MAAM,CAEnF"}
@@ -0,0 +1,90 @@
1
+ import { drawGlFullscreenPass } from '@flighthq/render-gl';
2
+ import { CompositeOperator as CompositeOperatorValues } from '@flighthq/types';
3
+ import { getGlBlendEffectBackdrop } from './glBlendEffect';
4
+ import { getGlEffectProgram, getGlEffectUniformLocation } from './glEffectProgramCache';
5
+ // Porter-Duff composite pass: sample the incoming layer (`u_texture0`, the effect's `source`) and a
6
+ // registered backdrop (`u_texture1`), combine them with the coverage factors of the effect's `operator`
7
+ // (`Fa*layer + Fb*backdrop` on premultiplied color), and write to `dest`. This is the GL realization of
8
+ // the CompositeEffect — the fixed-function-cost sibling of the shader-based BlendEffect. The GLSL factor
9
+ // formulas mirror @flighthq/effects compositeOperatorMath exactly, so the pass is verified against those
10
+ // plain-number tests.
11
+ //
12
+ // The backdrop is shared with BlendEffect: looked up by the effect's `backdropKey` in the per-state
13
+ // registry populated by registerGlBlendEffectBackdrop. A null/unregistered key composites over an implicit
14
+ // transparent backdrop (source-over reduces to passthrough; erase/mask reduce to clear) rather than
15
+ // erroring.
16
+ export function applyCompositeEffectToGl(state, source, dest, effect) {
17
+ const backdrop = getGlBlendEffectBackdrop(state, effect.backdropKey ?? null);
18
+ const program = getGlEffectProgram(state, 'composite.porterduff', COMPOSITE_FRAGMENT_SRC);
19
+ const operatorIndex = getCompositeEffectOperatorIndex(effect.operator);
20
+ const hasBackdrop = backdrop !== null;
21
+ // Bind the layer to unit 0 and the backdrop (or the layer itself as a harmless stand-in) to unit 1;
22
+ // `u_hasBackdrop` gates whether unit 1 is read, so a missing backdrop composites over transparent.
23
+ const inputs = [source.texture, hasBackdrop ? backdrop : source.texture];
24
+ drawGlFullscreenPass(state, program, inputs, dest, (gl, p) => {
25
+ const operatorLoc = getGlEffectUniformLocation(state, p, 'u_operator');
26
+ const hasBackdropLoc = getGlEffectUniformLocation(state, p, 'u_hasBackdrop');
27
+ if (operatorLoc !== null)
28
+ gl.uniform1i(operatorLoc, operatorIndex);
29
+ if (hasBackdropLoc !== null)
30
+ gl.uniform1i(hasBackdropLoc, hasBackdrop ? 1 : 0);
31
+ });
32
+ }
33
+ export const defaultGlCompositeEffectRunner = (ctx, effect) => {
34
+ applyCompositeEffectToGl(ctx.state, ctx.source, ctx.dest, effect);
35
+ };
36
+ // Maps a CompositeOperator string to the integer the fragment shader switches on. Kept in lockstep with
37
+ // the COMPOSITE_FRAGMENT_SRC branch order; an unknown (vendor) operator maps to 0 (SourceOver).
38
+ export function getCompositeEffectOperatorIndex(operator) {
39
+ return COMPOSITE_OPERATOR_INDEX[operator] ?? 0;
40
+ }
41
+ // CompositeOperator → shader branch index. Kept in lockstep with the if-chain in COMPOSITE_FRAGMENT_SRC
42
+ // and with the factor formulas in @flighthq/effects compositeOperatorMath.
43
+ const COMPOSITE_OPERATOR_INDEX = {
44
+ [CompositeOperatorValues.SourceOver]: 0,
45
+ [CompositeOperatorValues.DestinationOver]: 1,
46
+ [CompositeOperatorValues.SourceIn]: 2,
47
+ [CompositeOperatorValues.DestinationIn]: 3,
48
+ [CompositeOperatorValues.SourceOut]: 4,
49
+ [CompositeOperatorValues.DestinationOut]: 5,
50
+ [CompositeOperatorValues.SourceAtop]: 6,
51
+ [CompositeOperatorValues.DestinationAtop]: 7,
52
+ [CompositeOperatorValues.Xor]: 8,
53
+ [CompositeOperatorValues.Copy]: 9,
54
+ [CompositeOperatorValues.Clear]: 10,
55
+ };
56
+ // Premultiplied Porter-Duff fragment shader. Layer = u_texture0, backdrop = u_texture1, both premultiplied.
57
+ // The composited pixel is `Fa*layer + Fb*backdrop`, where Fa/Fb depend on the operator and the coverage
58
+ // alphas (as = layer.a, ab = backdrop.a) — the same factors as compositeOperatorMath. Premultiplication is
59
+ // what lets one factor pair drive rgb and a alike, so no un-premultiply is needed (unlike BlendEffect).
60
+ const COMPOSITE_FRAGMENT_SRC = `#version 300 es
61
+ precision highp float;
62
+ in vec2 v_texCoord;
63
+ uniform sampler2D u_texture0;
64
+ uniform sampler2D u_texture1;
65
+ uniform int u_operator;
66
+ uniform int u_hasBackdrop;
67
+ out vec4 o_color;
68
+
69
+ void main() {
70
+ vec4 layer = texture(u_texture0, v_texCoord);
71
+ vec4 back = u_hasBackdrop == 1 ? texture(u_texture1, v_texCoord) : vec4(0.0);
72
+ float as = layer.a;
73
+ float ab = back.a;
74
+
75
+ float fa = 1.0;
76
+ float fb = 1.0 - as; // SourceOver (0, default)
77
+ if (u_operator == 1) { fa = 1.0 - ab; fb = 1.0; } // DestinationOver
78
+ else if (u_operator == 2) { fa = ab; fb = 0.0; } // SourceIn
79
+ else if (u_operator == 3) { fa = 0.0; fb = as; } // DestinationIn
80
+ else if (u_operator == 4) { fa = 1.0 - ab; fb = 0.0; } // SourceOut
81
+ else if (u_operator == 5) { fa = 0.0; fb = 1.0 - as; } // DestinationOut
82
+ else if (u_operator == 6) { fa = ab; fb = 1.0 - as; } // SourceAtop
83
+ else if (u_operator == 7) { fa = 1.0 - ab; fb = as; } // DestinationAtop
84
+ else if (u_operator == 8) { fa = 1.0 - ab; fb = 1.0 - as; } // Xor
85
+ else if (u_operator == 9) { fa = 1.0; fb = 0.0; } // Copy
86
+ else if (u_operator == 10) { fa = 0.0; fb = 0.0; } // Clear
87
+
88
+ o_color = fa * layer + fb * back;
89
+ }`;
90
+ //# sourceMappingURL=glCompositeEffect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"glCompositeEffect.js","sourceRoot":"","sources":["../src/glCompositeEffect.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"glDropShadowEffect.d.ts","sourceRoot":"","sources":["../src/glDropShadowEffect.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,gBAAgB,EAChB,oBAAoB,EACpB,aAAa,EACb,cAAc,EACd,kBAAkB,EACnB,MAAM,iBAAiB,CAAC;AAYzB,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,aAAa,EACpB,MAAM,EAAE,QAAQ,CAAC,cAAc,CAAC,EAChC,IAAI,EAAE,QAAQ,CAAC,cAAc,CAAC,EAC9B,IAAI,EAAE,kBAAkB,EACxB,MAAM,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GACjC,IAAI,CA4CN;AAED,eAAO,MAAM,+BAA+B,EAAE,oBAE7C,CAAC"}
1
+ {"version":3,"file":"glDropShadowEffect.d.ts","sourceRoot":"","sources":["../src/glDropShadowEffect.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,gBAAgB,EAChB,oBAAoB,EACpB,aAAa,EACb,cAAc,EACd,kBAAkB,EACnB,MAAM,iBAAiB,CAAC;AAYzB,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,aAAa,EACpB,MAAM,EAAE,QAAQ,CAAC,cAAc,CAAC,EAChC,IAAI,EAAE,QAAQ,CAAC,cAAc,CAAC,EAC9B,IAAI,EAAE,kBAAkB,EACxB,MAAM,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GACjC,IAAI,CA6CN;AAED,eAAO,MAAM,+BAA+B,EAAE,oBAE7C,CAAC"}
@@ -1,13 +1,13 @@
1
1
  import { acquireGlRenderTarget, clearGlRenderTarget, releaseGlRenderTarget } from '@flighthq/render-gl';
2
- import { applyGlEffectBlitOffsetPass, applyGlEffectBlitPass } from './glEffectBlitShader';
2
+ import { applyGlEffectBlitOffsetPass, applyGlEffectBlitPass, applyGlEffectErasePass } from './glEffectBlitShader';
3
3
  import { applyGlEffectBoxBlur } from './glEffectBoxBlur';
4
4
  import { applyGlEffectTintPass } from './glEffectTintShader';
5
5
  // Drop-shadow composite effect: tint the scene silhouette, blur it, offset it by angle/distance, then composite the source over the shadow.
6
6
  // Full-frame realization: acquires the recipe's three scratch targets from the effect pool, runs the
7
7
  // inlined multi-pass recipe, then releases them.
8
8
  //
9
- // Compositing order: shadow at offset → source (unless `hideObject` is true).
10
- // `knockout` and `hideObject` both composite the shadow alone, omitting the source object.
9
+ // Compositing order depends on `sourceMode`: 'draw' composites shadow → source, 'hide' composites
10
+ // shadow only, and 'knockout' composites shadow then erases the un-offset source silhouette.
11
11
  export function applyDropShadowEffectToGl(state, source, dest, pool, effect) {
12
12
  const descriptor = { width: source.width, height: source.height, format: source.format };
13
13
  const s0 = acquireGlRenderTarget(state, pool, descriptor);
@@ -23,8 +23,7 @@ export function applyDropShadowEffectToGl(state, source, dest, pool, effect) {
23
23
  const alpha = effect.alpha ?? 1;
24
24
  const strength = effect.strength ?? 1;
25
25
  const quality = Math.max(1, Math.round(effect.quality ?? 1));
26
- const hideObject = effect.hideObject ?? false;
27
- const knockout = effect.knockout ?? false;
26
+ const sourceMode = effect.sourceMode ?? 'draw';
28
27
  const tintStrength = Math.min(1, strength);
29
28
  const shadowPasses = Math.max(1, Math.floor(strength));
30
29
  const [mask, blurred, blurTemp] = [s0, s1, s2];
@@ -38,7 +37,10 @@ export function applyDropShadowEffectToGl(state, source, dest, pool, effect) {
38
37
  for (let i = 0; i < shadowPasses; i++) {
39
38
  applyGlEffectBlitOffsetPass(state, blurred, dst, dx, dy);
40
39
  }
41
- if (!hideObject && !knockout) {
40
+ if (sourceMode === 'knockout') {
41
+ applyGlEffectErasePass(state, src, dst);
42
+ }
43
+ else if (sourceMode === 'draw') {
42
44
  applyGlEffectBlitPass(state, src, dst);
43
45
  }
44
46
  releaseGlRenderTarget(pool, s0);
@@ -1 +1 @@
1
- {"version":3,"file":"glDropShadowEffect.js","sourceRoot":"","sources":["../src/glDropShadowEffect.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"glDropShadowEffect.js","sourceRoot":"","sources":["../src/glDropShadowEffect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AASxG,OAAO,EAAE,2BAA2B,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAClH,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,4IAA4I;AAC5I,qGAAqG;AACrG,iDAAiD;AACjD,EAAE;AACF,kGAAkG;AAClG,6FAA6F;AAC7F,MAAM,UAAU,yBAAyB,CACvC,KAAoB,EACpB,MAAgC,EAChC,IAA8B,EAC9B,IAAwB,EACxB,MAAkC;IAElC,MAAM,UAAU,GAAG,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC;IACzF,MAAM,EAAE,GAAG,qBAAqB,CAAC,KAAK,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;IAC1D,MAAM,EAAE,GAAG,qBAAqB,CAAC,KAAK,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;IAC1D,MAAM,EAAE,GAAG,qBAAqB,CAAC,KAAK,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;IAE1D,MAAM,GAAG,GAAG,MAAwB,CAAC;IACrC,MAAM,GAAG,GAAG,IAAsB,CAAC;IAEnC,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC;IACrD,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC;IACtC,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,QAAQ,CAAC;IACtC,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,QAAQ,CAAC;IACtC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,CAAC,CAAC;IAChC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,CAAC,CAAC;IAChC,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC;IACtC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC;IAC7D,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC;IAE/C,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;IAC3C,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEvD,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IAE/C,qBAAqB,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC;IACpE,oBAAoB,CAAC,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE;QACnD,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,CAAC;QACxB,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,CAAC;QACxB,MAAM,EAAE,OAAO;KAChB,CAAC,CAAC;IAEH,mBAAmB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAChC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,2BAA2B,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IAC3D,CAAC;IAED,IAAI,UAAU,KAAK,UAAU,EAAE,CAAC;QAC9B,sBAAsB,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IAC1C,CAAC;SAAM,IAAI,UAAU,KAAK,MAAM,EAAE,CAAC;QACjC,qBAAqB,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IACzC,CAAC;IAED,qBAAqB,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAChC,qBAAqB,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IAChC,qBAAqB,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;AAClC,CAAC;AAED,MAAM,CAAC,MAAM,+BAA+B,GAAyB,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE;IACnF,yBAAyB,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,MAA0B,CAAC,CAAC;AACnG,CAAC,CAAC"}
@@ -7,4 +7,6 @@ import type { GlRenderState } from '@flighthq/types';
7
7
  export declare function applyGlEffectBlitOffsetPass(state: GlRenderState, source: GlRenderTarget, dest: GlRenderTarget, dx: number, dy: number): void;
8
8
  /** Blits source directly into dest without modification. */
9
9
  export declare function applyGlEffectBlitPass(state: GlRenderState, source: GlRenderTarget, dest: GlRenderTarget): void;
10
+ /** Erases dest by the source alpha mask, equivalent to destination-out compositing. */
11
+ export declare function applyGlEffectErasePass(state: GlRenderState, source: GlRenderTarget, dest: GlRenderTarget): void;
10
12
  //# sourceMappingURL=glEffectBlitShader.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"glEffectBlitShader.d.ts","sourceRoot":"","sources":["../src/glEffectBlitShader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAuB,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAmC1E;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,aAAa,EACpB,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,cAAc,EACpB,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,GACT,IAAI,CAKN;AAED,4DAA4D;AAC5D,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE,cAAc,GAAG,IAAI,CAG9G"}
1
+ {"version":3,"file":"glEffectBlitShader.d.ts","sourceRoot":"","sources":["../src/glEffectBlitShader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAuB,aAAa,EAAE,MAAM,iBAAiB,CAAC;AA+C1E;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,aAAa,EACpB,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,cAAc,EACpB,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,GACT,IAAI,CAKN;AAED,4DAA4D;AAC5D,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE,cAAc,GAAG,IAAI,CAG9G;AAED,uFAAuF;AACvF,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE,cAAc,GAAG,IAAI,CAK/G"}
@@ -23,8 +23,19 @@ out vec4 fragColor;
23
23
  void main() {
24
24
  fragColor = texture(u_texture, v_texCoord);
25
25
  }`;
26
+ // Emits source alpha for a destination-out erase pass; blend state supplies the coverage operator.
27
+ const ERASE_FRAGMENT_SRC = `#version 300 es
28
+ precision mediump float;
29
+ in vec2 v_texCoord;
30
+ uniform sampler2D u_texture;
31
+ out vec4 fragColor;
32
+ void main() {
33
+ float a = texture(u_texture, v_texCoord).a;
34
+ fragColor = vec4(0.0, 0.0, 0.0, a);
35
+ }`;
26
36
  const blitOffsetShaders = new WeakMap();
27
37
  const blitShaders = new WeakMap();
38
+ const eraseShaders = new WeakMap();
28
39
  /**
29
40
  * Blits source into dest at a pixel offset (dx, dy in screen-space Y-down).
30
41
  * Pixels sampling outside the source bounds produce transparent output.
@@ -40,6 +51,13 @@ export function applyGlEffectBlitPass(state, source, dest) {
40
51
  const loc = getGlBlitShader(state);
41
52
  drawGlFullscreenPass(state, loc, [source.texture], dest, () => { });
42
53
  }
54
+ /** Erases dest by the source alpha mask, equivalent to destination-out compositing. */
55
+ export function applyGlEffectErasePass(state, source, dest) {
56
+ const loc = getGlEraseShader(state);
57
+ drawGlFullscreenPass(state, loc, [source.texture], dest, (gl) => {
58
+ gl.blendFunc(gl.ZERO, gl.ONE_MINUS_SRC_ALPHA);
59
+ });
60
+ }
43
61
  function getGlBlitOffsetShader(state) {
44
62
  let loc = blitOffsetShaders.get(state);
45
63
  if (loc === undefined) {
@@ -59,4 +77,13 @@ function getGlBlitShader(state) {
59
77
  }
60
78
  return loc;
61
79
  }
80
+ function getGlEraseShader(state) {
81
+ let loc = eraseShaders.get(state);
82
+ if (loc === undefined) {
83
+ const gl = state.gl;
84
+ loc = compileGlFullscreenProgram(gl, ERASE_FRAGMENT_SRC);
85
+ eraseShaders.set(state, loc);
86
+ }
87
+ return loc;
88
+ }
62
89
  //# sourceMappingURL=glEffectBlitShader.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"glEffectBlitShader.js","sourceRoot":"","sources":["../src/glEffectBlitShader.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,0BAA0B,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAGvF,2FAA2F;AAC3F,MAAM,wBAAwB,GAAG;;;;;;;;;;;;;EAa/B,CAAC;AAEH,qBAAqB;AACrB,MAAM,iBAAiB,GAAG;;;;;;;EAOxB,CAAC;AAMH,MAAM,iBAAiB,GAAG,IAAI,OAAO,EAA4C,CAAC;AAClF,MAAM,WAAW,GAAG,IAAI,OAAO,EAAsC,CAAC;AAEtE;;;GAGG;AACH,MAAM,UAAU,2BAA2B,CACzC,KAAoB,EACpB,MAAsB,EACtB,IAAoB,EACpB,EAAU,EACV,EAAU;IAEV,MAAM,GAAG,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;IACzC,oBAAoB,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE;QAC9D,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,EAAE,GAAG,MAAM,CAAC,KAAK,EAAE,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IACtE,CAAC,CAAC,CAAC;AACL,CAAC;AAED,4DAA4D;AAC5D,MAAM,UAAU,qBAAqB,CAAC,KAAoB,EAAE,MAAsB,EAAE,IAAoB;IACtG,MAAM,GAAG,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;IACnC,oBAAoB,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;AACrE,CAAC;AAED,SAAS,qBAAqB,CAAC,KAAoB;IACjD,IAAI,GAAG,GAAG,iBAAiB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACvC,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtB,MAAM,EAAE,GAAG,KAAK,CAAC,EAAE,CAAC;QACpB,MAAM,IAAI,GAAG,0BAA0B,CAAC,EAAE,EAAE,wBAAwB,CAAC,CAAC;QACtE,GAAG,GAAG,EAAE,GAAG,IAAI,EAAE,SAAS,EAAE,EAAE,CAAC,kBAAkB,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAE,EAAE,CAAC;QAC/E,iBAAiB,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACpC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,eAAe,CAAC,KAAoB;IAC3C,IAAI,GAAG,GAAG,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACjC,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtB,MAAM,EAAE,GAAG,KAAK,CAAC,EAAE,CAAC;QACpB,GAAG,GAAG,0BAA0B,CAAC,EAAE,EAAE,iBAAiB,CAAC,CAAC;QACxD,WAAW,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC9B,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
1
+ {"version":3,"file":"glEffectBlitShader.js","sourceRoot":"","sources":["../src/glEffectBlitShader.ts"],"names":[],"mappings":"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"}
@@ -11,5 +11,6 @@ export declare function applyGlEffectBoxBlur(state: GlRenderState, source: GlRen
11
11
  blurX?: number;
12
12
  blurY?: number;
13
13
  passes?: number;
14
+ edgeColor?: readonly [number, number, number, number];
14
15
  }>): void;
15
16
  //# sourceMappingURL=glEffectBoxBlur.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"glEffectBoxBlur.d.ts","sourceRoot":"","sources":["../src/glEffectBoxBlur.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAuB,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAgC1E;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,aAAa,EACpB,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,cAAc,EACpB,IAAI,EAAE,cAAc,EACpB,OAAO,EAAE,QAAQ,CAAC;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,GACrE,IAAI,CA6BN"}
1
+ {"version":3,"file":"glEffectBoxBlur.d.ts","sourceRoot":"","sources":["../src/glEffectBoxBlur.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE1D,OAAO,KAAK,EAAuB,aAAa,EAAE,MAAM,iBAAiB,CAAC;AA4C1E;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,aAAa,EACpB,MAAM,EAAE,cAAc,EACtB,IAAI,EAAE,cAAc,EACpB,IAAI,EAAE,cAAc,EACpB,OAAO,EAAE,QAAQ,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;CACvD,CAAC,GACD,IAAI,CA8BN"}
@@ -7,17 +7,25 @@ uniform sampler2D u_texture;
7
7
  uniform vec2 u_texelSize;
8
8
  uniform float u_radius;
9
9
  uniform vec2 u_direction;
10
+ uniform vec4 u_edgeColor;
11
+ uniform float u_useEdgeColor;
10
12
  out vec4 fragColor;
13
+ vec4 sampleBlur(vec2 uv) {
14
+ if (u_useEdgeColor > 0.5 && (uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0)) {
15
+ return u_edgeColor;
16
+ }
17
+ return texture(u_texture, uv);
18
+ }
11
19
  void main() {
12
20
  int r = max(0, int(u_radius));
13
21
  if (r == 0) {
14
- fragColor = texture(u_texture, v_texCoord);
22
+ fragColor = sampleBlur(v_texCoord);
15
23
  return;
16
24
  }
17
25
  vec4 sum = vec4(0.0);
18
26
  int count = 2 * r + 1;
19
27
  for (int i = -r; i <= r; i++) {
20
- sum += texture(u_texture, v_texCoord + float(i) * u_texelSize * u_direction);
28
+ sum += sampleBlur(v_texCoord + float(i) * u_texelSize * u_direction);
21
29
  }
22
30
  fragColor = sum / float(count);
23
31
  }`;
@@ -33,6 +41,7 @@ export function applyGlEffectBoxBlur(state, source, dest, temp, options) {
33
41
  const passes = Math.max(1, Math.round(options.passes ?? 1));
34
42
  const blurX = options.blurX ?? 4;
35
43
  const blurY = options.blurY ?? 4;
44
+ const edgeColor = options.edgeColor;
36
45
  const loc = getBoxBlurShader(state);
37
46
  let read = source;
38
47
  let write = temp;
@@ -41,13 +50,13 @@ export function applyGlEffectBoxBlur(state, source, dest, temp, options) {
41
50
  for (let pass = 0; pass < passes; pass++) {
42
51
  const radiusX = computeBoxBlurPassRadius(blurX, passes, pass);
43
52
  if (radiusX > 0) {
44
- applyBoxBlurPass(state, read, write, loc, radiusX, 1, 0);
53
+ applyBoxBlurPass(state, read, write, loc, radiusX, 1, 0, edgeColor);
45
54
  read = write;
46
55
  write = write === temp ? dest : temp;
47
56
  }
48
57
  const radiusY = computeBoxBlurPassRadius(blurY, passes, pass);
49
58
  if (radiusY > 0) {
50
- applyBoxBlurPass(state, read, write, loc, radiusY, 0, 1);
59
+ applyBoxBlurPass(state, read, write, loc, radiusY, 0, 1, edgeColor);
51
60
  read = write;
52
61
  write = write === temp ? dest : temp;
53
62
  }
@@ -62,13 +71,25 @@ function applyBlurBlit(state, source, dest) {
62
71
  gl.uniform2f(loc.locTexelSize, 0, 0);
63
72
  gl.uniform1f(loc.locRadius, 0);
64
73
  gl.uniform2f(loc.locDirection, 0, 0);
74
+ gl.uniform4f(loc.locEdgeColor, 0, 0, 0, 0);
75
+ gl.uniform1f(loc.locUseEdgeColor, 0);
76
+ gl.blendFunc(gl.ONE, gl.ZERO);
65
77
  });
66
78
  }
67
- function applyBoxBlurPass(state, source, dest, loc, radius, dirX, dirY) {
79
+ function applyBoxBlurPass(state, source, dest, loc, radius, dirX, dirY, edgeColor) {
68
80
  drawGlFullscreenPass(state, loc, [source.texture], dest, (gl) => {
69
81
  gl.uniform2f(loc.locTexelSize, 1 / source.width, 1 / source.height);
70
82
  gl.uniform1f(loc.locRadius, radius);
71
83
  gl.uniform2f(loc.locDirection, dirX, dirY);
84
+ if (edgeColor === undefined) {
85
+ gl.uniform4f(loc.locEdgeColor, 0, 0, 0, 0);
86
+ gl.uniform1f(loc.locUseEdgeColor, 0);
87
+ }
88
+ else {
89
+ gl.uniform4f(loc.locEdgeColor, edgeColor[0], edgeColor[1], edgeColor[2], edgeColor[3]);
90
+ gl.uniform1f(loc.locUseEdgeColor, 1);
91
+ }
92
+ gl.blendFunc(gl.ONE, gl.ZERO);
72
93
  });
73
94
  }
74
95
  function getBoxBlurShader(state) {
@@ -81,6 +102,8 @@ function getBoxBlurShader(state) {
81
102
  locTexelSize: gl.getUniformLocation(base.program, 'u_texelSize'),
82
103
  locRadius: gl.getUniformLocation(base.program, 'u_radius'),
83
104
  locDirection: gl.getUniformLocation(base.program, 'u_direction'),
105
+ locEdgeColor: gl.getUniformLocation(base.program, 'u_edgeColor'),
106
+ locUseEdgeColor: gl.getUniformLocation(base.program, 'u_useEdgeColor'),
84
107
  };
85
108
  boxBlurShaders.set(state, loc);
86
109
  }