@ume-group/contracts 0.2.1

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 (57) hide show
  1. package/README.md +37 -0
  2. package/dist/adserving.d.ts +150 -0
  3. package/dist/adserving.d.ts.map +1 -0
  4. package/dist/adserving.js +8 -0
  5. package/dist/campaigns.d.ts +37 -0
  6. package/dist/campaigns.d.ts.map +1 -0
  7. package/dist/campaigns.js +8 -0
  8. package/dist/gausst.d.ts +236 -0
  9. package/dist/gausst.d.ts.map +1 -0
  10. package/dist/gausst.js +307 -0
  11. package/dist/gausst.test.d.ts +2 -0
  12. package/dist/gausst.test.d.ts.map +1 -0
  13. package/dist/gausst.test.js +71 -0
  14. package/dist/index.d.ts +1531 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +1112 -0
  17. package/dist/layer2/index.d.ts +9 -0
  18. package/dist/layer2/index.d.ts.map +1 -0
  19. package/dist/layer2/index.js +10 -0
  20. package/dist/layer2/shaders.d.ts +185 -0
  21. package/dist/layer2/shaders.d.ts.map +1 -0
  22. package/dist/layer2/shaders.js +604 -0
  23. package/dist/layer2/webcam-utils.d.ts +113 -0
  24. package/dist/layer2/webcam-utils.d.ts.map +1 -0
  25. package/dist/layer2/webcam-utils.js +147 -0
  26. package/dist/layer2/webcam-utils.test.d.ts +2 -0
  27. package/dist/layer2/webcam-utils.test.d.ts.map +1 -0
  28. package/dist/layer2/webcam-utils.test.js +18 -0
  29. package/dist/layer2.d.ts +558 -0
  30. package/dist/layer2.d.ts.map +1 -0
  31. package/dist/layer2.js +376 -0
  32. package/dist/layer2.test.d.ts +2 -0
  33. package/dist/layer2.test.d.ts.map +1 -0
  34. package/dist/layer2.test.js +65 -0
  35. package/dist/perspective.d.ts +28 -0
  36. package/dist/perspective.d.ts.map +1 -0
  37. package/dist/perspective.js +157 -0
  38. package/dist/segmentation/MediaPipeSegmenter.d.ts +201 -0
  39. package/dist/segmentation/MediaPipeSegmenter.d.ts.map +1 -0
  40. package/dist/segmentation/MediaPipeSegmenter.js +434 -0
  41. package/dist/segmentation/index.d.ts +5 -0
  42. package/dist/segmentation/index.d.ts.map +1 -0
  43. package/dist/segmentation/index.js +4 -0
  44. package/dist/webcam/GarbageMatteDragManager.d.ts +63 -0
  45. package/dist/webcam/GarbageMatteDragManager.d.ts.map +1 -0
  46. package/dist/webcam/GarbageMatteDragManager.js +183 -0
  47. package/dist/webcam/WebcamStreamManager.d.ts +103 -0
  48. package/dist/webcam/WebcamStreamManager.d.ts.map +1 -0
  49. package/dist/webcam/WebcamStreamManager.js +356 -0
  50. package/dist/webcam/index.d.ts +5 -0
  51. package/dist/webcam/index.d.ts.map +1 -0
  52. package/dist/webcam/index.js +2 -0
  53. package/openapi/admetise.yaml +632 -0
  54. package/openapi/includu.yaml +621 -0
  55. package/openapi/integration.yaml +372 -0
  56. package/openapi/shared/schemas.yaml +227 -0
  57. package/package.json +53 -0
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Layer 2 (WebGL/3D) module exports
3
+ *
4
+ * This module contains shared components for webcam compositing
5
+ * used by both editor and player applications.
6
+ */
7
+ export { webcamVertexShader, webcamFragmentShader, getDefaultPlayerUniforms, getDefaultEditorUniforms, type WebcamShaderUniforms } from './shaders';
8
+ export { WEBCAM_BASE_HEIGHT_METERS, SILHOUETTE_HEIGHT_RATIO, getWebcamBaseDimensions, getWebcamMeshYOffset, getObjectEuler, getCameraEuler, GAM_PIXELS_TO_METERS, AD_TEMPLATE_DIMENSIONS, getAdDimensions, CHROMA_KEY_COLORS, getChromaKeyColorHex, featherToUV, featherEdgesToUV } from './webcam-utils';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/layer2/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EACN,kBAAkB,EAClB,oBAAoB,EACpB,wBAAwB,EACxB,wBAAwB,EACxB,KAAK,oBAAoB,EACzB,MAAM,WAAW,CAAC;AAGnB,OAAO,EACN,yBAAyB,EACzB,uBAAuB,EACvB,uBAAuB,EACvB,oBAAoB,EACpB,cAAc,EACd,cAAc,EACd,oBAAoB,EACpB,sBAAsB,EACtB,eAAe,EACf,iBAAiB,EACjB,oBAAoB,EACpB,WAAW,EACX,gBAAgB,EAChB,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Layer 2 (WebGL/3D) module exports
3
+ *
4
+ * This module contains shared components for webcam compositing
5
+ * used by both editor and player applications.
6
+ */
7
+ // Shader exports
8
+ export { webcamVertexShader, webcamFragmentShader, getDefaultPlayerUniforms, getDefaultEditorUniforms } from './shaders';
9
+ // Webcam utility exports
10
+ export { WEBCAM_BASE_HEIGHT_METERS, SILHOUETTE_HEIGHT_RATIO, getWebcamBaseDimensions, getWebcamMeshYOffset, getObjectEuler, getCameraEuler, GAM_PIXELS_TO_METERS, AD_TEMPLATE_DIMENSIONS, getAdDimensions, CHROMA_KEY_COLORS, getChromaKeyColorHex, featherToUV, featherEdgesToUV } from './webcam-utils';
@@ -0,0 +1,185 @@
1
+ /**
2
+ * Shared WebGL shaders for Layer 2 webcam compositing
3
+ *
4
+ * These shaders are used by both editor and player for consistent rendering.
5
+ * The fragment shader supports multiple modes:
6
+ * - AI segmentation (MediaPipe)
7
+ * - Chroma key (green/blue/custom with HSV window option)
8
+ * - Procedural silhouette (fallback/placeholder)
9
+ * - Full view mode (no masking)
10
+ *
11
+ * ArchiMate: Application Component (Shared Rendering Logic)
12
+ */
13
+ /**
14
+ * Simple vertex shader for webcam plane rendering
15
+ */
16
+ export declare const webcamVertexShader = "\n\tvarying vec2 vUv;\n\tvoid main() {\n\t\tvUv = uv;\n\t\tgl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n\t}\n";
17
+ /**
18
+ * Fragment shader for webcam compositing with background removal
19
+ *
20
+ * Supports:
21
+ * - AI segmentation mask
22
+ * - Chroma key with HSV or YCbCr algorithms
23
+ * - Garbage matte (rectangle crop with feathering)
24
+ * - Color correction (brightness, contrast, saturation, temperature)
25
+ * - Pre-multiplied alpha for correct edge blending
26
+ *
27
+ * Uniforms:
28
+ * - webcamTexture: The live webcam VideoTexture
29
+ * - segmentationMask: AI-generated mask (white = person)
30
+ * - hasTexture: Whether webcam texture is available
31
+ * - useAIMask: Enable AI segmentation mode
32
+ * - maskThreshold: AI mask threshold (0.0 - 1.0)
33
+ * - aspectRatio: Plane aspect ratio for silhouette proportions (always >= 1.0)
34
+ * - videoAspectRatio: Actual video W/H (may be < 1.0 for portrait), used for cover-crop UV
35
+ * - useChromaKey: Enable chroma key mode
36
+ * - chromaKeyColor: Key color in RGB (0.0 - 1.0)
37
+ * - chromaKeyTolerance: Color tolerance (0.0 - 1.0)
38
+ * - chromaKeySpill: Spill suppression amount (0.0 - 1.0)
39
+ * - chromaKeyEdge: Edge softness (0.0 - 1.0)
40
+ * - setupMode: Show silhouette overlay for positioning (editor only)
41
+ * - useHsvWindow: Enable HSV window mode for advanced keying
42
+ * - hsvMinHue/hsvMaxHue: Hue range (0-360)
43
+ * - hsvMinSat/hsvMaxSat: Saturation range (0-1)
44
+ * - hsvMinVal/hsvMaxVal: Value range (0-1)
45
+ * - useGarbageMatte: Enable garbage matte cropping
46
+ * - garbageMatteIsRect: True = rectangle, false = polygon texture
47
+ * - garbageMatteRect: Rectangle bounds (x1, y1, x2, y2)
48
+ * - garbageMatteInvert: Invert mask
49
+ * - garbageMatteFeather: Edge softness in UV units
50
+ * - garbageMatteFeatherEdges: Per-edge feather (top, right, bottom, left)
51
+ * - usePerEdgeFeather: Enable per-edge feathering
52
+ * - ccBrightness/ccContrast/ccSaturation/ccTemperature: Color correction
53
+ * - fullViewMode: Show entire webcam without masking
54
+ * - darkOpacity: Opacity for areas outside silhouette (editor preview)
55
+ * - placeholderColor/placeholderOpacity: Editor placeholder when no webcam
56
+ */
57
+ export declare const webcamFragmentShader = "\n\tuniform sampler2D webcamTexture;\n\tuniform sampler2D segmentationMask;\n\tuniform float darkOpacity;\n\tuniform bool hasTexture;\n\tuniform bool useAIMask;\n\tuniform float maskThreshold;\n\tuniform vec3 placeholderColor;\n\tuniform float placeholderOpacity;\n\tuniform float aspectRatio;\n\tuniform float videoAspectRatio;\n\t// Chroma key uniforms\n\tuniform bool useChromaKey;\n\tuniform vec3 chromaKeyColor;\n\tuniform float chromaKeyTolerance;\n\tuniform float chromaKeySpill;\n\tuniform float chromaKeyEdge;\n\tuniform bool setupMode;\n\t// HSV window uniforms\n\tuniform bool useHsvWindow;\n\tuniform float hsvMinHue;\n\tuniform float hsvMaxHue;\n\tuniform float hsvMinSat;\n\tuniform float hsvMaxSat;\n\tuniform float hsvMinVal;\n\tuniform float hsvMaxVal;\n\t// Garbage matte uniforms\n\tuniform bool useGarbageMatte;\n\tuniform bool garbageMatteIsRect;\n\tuniform vec4 garbageMatteRect;\n\tuniform sampler2D garbageMatteMask;\n\tuniform bool garbageMatteInvert;\n\tuniform float garbageMatteFeather;\n\tuniform vec4 garbageMatteFeatherEdges;\n\tuniform bool usePerEdgeFeather;\n\t// Color correction uniforms\n\tuniform float ccBrightness;\n\tuniform float ccContrast;\n\tuniform float ccSaturation;\n\tuniform float ccTemperature;\n\t// Full view mode\n\tuniform bool fullViewMode;\n\t// Debug: visualize the AI mask as a color overlay\n\tuniform bool debugShowMask;\n\t// Silhouette scale for generous capture (participantHeight / captureHeight)\n\tuniform float silhouetteScale;\n\n\tvarying vec2 vUv;\n\n\t// Check if point is inside an ellipse (for head)\n\tbool inEllipse(vec2 p, vec2 center, vec2 radius) {\n\t\tvec2 d = (p - center) / radius;\n\t\treturn dot(d, d) <= 1.0;\n\t}\n\n\t// Check if point is inside a rectangle\n\tbool inRect(vec2 p, vec2 center, vec2 halfSize) {\n\t\tvec2 d = abs(p - center);\n\t\treturn d.x <= halfSize.x && d.y <= halfSize.y;\n\t}\n\n\t// Convert RGB to HSV (Hue 0-6, Saturation 0-1, Value 0-1)\n\t// Based on legacy Gausst chroma key implementation\n\tvec3 rgb2hsv(vec3 c) {\n\t\tfloat minVal = min(min(c.r, c.g), c.b);\n\t\tfloat maxVal = max(max(c.r, c.g), c.b);\n\t\tfloat delta = maxVal - minVal;\n\n\t\tfloat h = 0.0;\n\t\tfloat s = (maxVal > 0.0) ? delta / maxVal : 0.0;\n\t\tfloat v = maxVal;\n\n\t\tif (delta > 0.001) {\n\t\t\tif (c.r == maxVal) {\n\t\t\t\tif (minVal == c.g) {\n\t\t\t\t\th = 5.0 + (1.0 - c.b / c.r);\n\t\t\t\t} else {\n\t\t\t\t\th = c.g / c.r;\n\t\t\t\t}\n\t\t\t} else if (c.g == maxVal) {\n\t\t\t\tif (minVal == c.r) {\n\t\t\t\t\th = 2.0 + (1.0 - c.b / c.g);\n\t\t\t\t} else {\n\t\t\t\t\th = 1.0 + c.r / c.g;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (minVal == c.r) {\n\t\t\t\t\th = 3.0 + (1.0 - c.g / c.b);\n\t\t\t\t} else {\n\t\t\t\t\th = 4.0 + c.r / c.b;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn vec3(h, s, v);\n\t}\n\n\t// Convert RGB to HSV with 0-360 degree hue for Gausst window mode\n\tvec3 rgb2hsv360(vec3 c) {\n\t\tvec3 hsv = rgb2hsv(c);\n\t\thsv.x = hsv.x * 60.0;\n\t\treturn hsv;\n\t}\n\n\t// Garbage matte mask function\n\t// Returns 1.0 = keep pixel, 0.0 = discard pixel\n\tfloat getGarbageMatteMask(vec2 uv) {\n\t\tif (!useGarbageMatte) return 1.0;\n\n\t\tfloat mask;\n\t\tif (garbageMatteIsRect) {\n\t\t\tfloat x1 = garbageMatteRect.x;\n\t\t\tfloat y1 = garbageMatteRect.y;\n\t\t\tfloat x2 = garbageMatteRect.z;\n\t\t\tfloat y2 = garbageMatteRect.w;\n\n\t\t\tbool isFullFrame = x1 < 0.01 && y1 < 0.01 && x2 > 0.99 && y2 > 0.99;\n\n\t\t\tbool hasFeather = usePerEdgeFeather\n\t\t\t\t? (garbageMatteFeatherEdges.x > 0.0 || garbageMatteFeatherEdges.y > 0.0 ||\n\t\t\t\t garbageMatteFeatherEdges.z > 0.0 || garbageMatteFeatherEdges.w > 0.0)\n\t\t\t\t: (garbageMatteFeather > 0.0);\n\n\t\t\tif (hasFeather && !isFullFrame) {\n\t\t\t\tfloat dLeft = x1 - uv.x;\n\t\t\t\tfloat dRight = uv.x - x2;\n\t\t\t\tfloat dTop = y1 - uv.y;\n\t\t\t\tfloat dBottom = uv.y - y2;\n\n\t\t\t\tfloat featherTop = usePerEdgeFeather ? garbageMatteFeatherEdges.x : garbageMatteFeather;\n\t\t\t\tfloat featherRight = usePerEdgeFeather ? garbageMatteFeatherEdges.y : garbageMatteFeather;\n\t\t\t\tfloat featherBottom = usePerEdgeFeather ? garbageMatteFeatherEdges.z : garbageMatteFeather;\n\t\t\t\tfloat featherLeft = usePerEdgeFeather ? garbageMatteFeatherEdges.w : garbageMatteFeather;\n\n\t\t\t\tfloat maskTop = featherTop > 0.0 ? 1.0 - smoothstep(-featherTop, featherTop, dTop) : (dTop < 0.0 ? 1.0 : 0.0);\n\t\t\t\tfloat maskRight = featherRight > 0.0 ? 1.0 - smoothstep(-featherRight, featherRight, dRight) : (dRight < 0.0 ? 1.0 : 0.0);\n\t\t\t\tfloat maskBottom = featherBottom > 0.0 ? 1.0 - smoothstep(-featherBottom, featherBottom, dBottom) : (dBottom < 0.0 ? 1.0 : 0.0);\n\t\t\t\tfloat maskLeft = featherLeft > 0.0 ? 1.0 - smoothstep(-featherLeft, featherLeft, dLeft) : (dLeft < 0.0 ? 1.0 : 0.0);\n\n\t\t\t\t// Use min() to keep edge feathering independent without corner rounding\n\t\t\t\t// (multiplication would cause 0.5 * 0.5 = 0.25 at corners, creating rounded effect)\n\t\t\t\tmask = min(min(maskTop, maskBottom), min(maskLeft, maskRight));\n\t\t\t} else {\n\t\t\t\tbool inside = uv.x >= x1 && uv.x <= x2 && uv.y >= y1 && uv.y <= y2;\n\t\t\t\tmask = inside ? 1.0 : 0.0;\n\t\t\t}\n\t\t} else {\n\t\t\tmask = texture2D(garbageMatteMask, uv).r;\n\t\t}\n\n\t\treturn garbageMatteInvert ? 1.0 - mask : mask;\n\t}\n\n\t// HSV window-based chroma key (Gausst algorithm)\n\tfloat hsvWindowMask(vec3 color, float minH, float maxH, float minS, float maxS, float minV, float maxV, float edgeSoftness) {\n\t\tvec3 hsv = rgb2hsv360(color);\n\n\t\tbool hueInRange;\n\t\tif (minH <= maxH) {\n\t\t\thueInRange = hsv.x >= minH && hsv.x <= maxH;\n\t\t} else {\n\t\t\thueInRange = hsv.x >= minH || hsv.x <= maxH;\n\t\t}\n\n\t\tbool satInRange = hsv.y >= minS && hsv.y <= maxS;\n\t\tbool valInRange = hsv.z >= minV && hsv.z <= maxV;\n\n\t\tif (hueInRange && satInRange && valInRange) {\n\t\t\tfloat hueCenter = (minH + maxH) / 2.0;\n\t\t\tfloat hueDist = abs(hsv.x - hueCenter) / ((maxH - minH) / 2.0 + 0.001);\n\t\t\tfloat satCenter = (minS + maxS) / 2.0;\n\t\t\tfloat satDist = abs(hsv.y - satCenter) / ((maxS - minS) / 2.0 + 0.001);\n\t\t\tfloat valCenter = (minV + maxV) / 2.0;\n\t\t\tfloat valDist = abs(hsv.z - valCenter) / ((maxV - minV) / 2.0 + 0.001);\n\n\t\t\tfloat dist = max(max(hueDist, satDist), valDist);\n\t\t\treturn smoothstep(1.0 - edgeSoftness * 2.0, 1.0, dist);\n\t\t} else {\n\t\t\treturn 1.0;\n\t\t}\n\t}\n\n\t// Chroma key mask calculation\n\t// HSV window acts as an additional refinement filter on top of the normal\n\t// chroma key. With full range (0-360, 0-1, 0-1), result is identical to\n\t// normal chroma key. Narrowing the HSV window restricts which pixels get keyed.\n\tfloat chromaKeyMask(vec3 color, vec3 keyColor, float tolerance, float edgeSoftness) {\n\t\tbool isGreenScreen = keyColor.g > 0.5 && keyColor.g > keyColor.r * 1.5 && keyColor.g > keyColor.b * 1.5;\n\t\tbool isBlueScreen = keyColor.b > 0.5 && keyColor.b > keyColor.r * 1.5 && keyColor.b > keyColor.g * 1.5;\n\n\t\tfloat normalMask;\n\n\t\tif (isGreenScreen || isBlueScreen) {\n\t\t\tfloat Y = 0.299 * color.r + 0.587 * color.g + 0.114 * color.b;\n\t\t\tfloat Cb = 0.564 * (color.b - Y);\n\t\t\tfloat Cr = 0.713 * (color.r - Y);\n\n\t\t\tfloat keyY = 0.299 * keyColor.r + 0.587 * keyColor.g + 0.114 * keyColor.b;\n\t\t\tfloat keyCb = 0.564 * (keyColor.b - keyY);\n\t\t\tfloat keyCr = 0.713 * (keyColor.r - keyY);\n\n\t\t\tfloat dist = distance(vec2(Cb, Cr), vec2(keyCb, keyCr));\n\n\t\t\tfloat scaledTolerance = tolerance * 0.5;\n\t\t\tfloat softRange = edgeSoftness * 0.3;\n\t\t\tnormalMask = smoothstep(scaledTolerance - softRange, scaledTolerance + softRange, dist);\n\t\t} else {\n\t\t\tvec3 colorHSV = rgb2hsv(color);\n\t\t\tvec3 keyHSV = rgb2hsv(keyColor);\n\n\t\t\tfloat hueDiff = abs(colorHSV.x - keyHSV.x);\n\t\t\tif (hueDiff > 3.0) hueDiff = 6.0 - hueDiff;\n\t\t\thueDiff /= 3.0;\n\n\t\t\tfloat satDiff = abs(colorHSV.y - keyHSV.y);\n\t\t\tfloat valDiff = abs(colorHSV.z - keyHSV.z);\n\n\t\t\tfloat dist = hueDiff * 0.7 + satDiff * 0.2 + valDiff * 0.1;\n\n\t\t\tif (colorHSV.y < 0.15 && keyHSV.y < 0.15) {\n\t\t\t\tdist = valDiff * 0.8 + satDiff * 0.2;\n\t\t\t}\n\n\t\t\tfloat scaledTolerance = tolerance * 0.4;\n\t\t\tfloat softRange = edgeSoftness * 0.2;\n\t\t\tnormalMask = smoothstep(scaledTolerance - softRange, scaledTolerance + softRange, dist);\n\t\t}\n\n\t\tif (useHsvWindow) {\n\t\t\t// HSV window restricts keying: pixels outside the window stay opaque\n\t\t\tfloat hsvMask = hsvWindowMask(color, hsvMinHue, hsvMaxHue, hsvMinSat, hsvMaxSat, hsvMinVal, hsvMaxVal, edgeSoftness);\n\t\t\treturn max(normalMask, hsvMask);\n\t\t}\n\n\t\treturn normalMask;\n\t}\n\n\t// Spill suppression - works with any key color\n\tvec3 suppressSpill(vec3 color, vec3 keyColor, float spillAmount) {\n\t\tif (spillAmount <= 0.0) return color;\n\n\t\tfloat keyMax = max(keyColor.r, max(keyColor.g, keyColor.b));\n\t\tif (keyMax < 0.01) return color;\n\n\t\tvec3 keyDir = keyColor / keyMax;\n\t\tfloat colorDot = dot(color, keyDir);\n\t\tfloat keyDot = dot(keyDir, keyDir);\n\t\tvec3 neutral = color - keyDir * max(0.0, (colorDot / keyDot - length(color) * 0.3));\n\t\tfloat keyInfluence = dot(normalize(color + 0.001), normalize(keyColor + 0.001));\n\t\tkeyInfluence = max(0.0, keyInfluence - 0.5) * 2.0;\n\n\t\treturn mix(color, neutral, spillAmount * keyInfluence);\n\t}\n\n\t// Color correction\n\tvec3 applyColorCorrection(vec3 color) {\n\t\tif (ccBrightness == 0.0 && ccContrast == 0.0 && ccSaturation == 0.0 && ccTemperature == 0.0) {\n\t\t\treturn color;\n\t\t}\n\n\t\tvec3 result = color;\n\n\t\t// Brightness\n\t\tresult += ccBrightness * 0.5;\n\n\t\t// Contrast\n\t\tfloat contrastFactor = 1.0 + ccContrast;\n\t\tresult = (result - 0.5) * contrastFactor + 0.5;\n\n\t\t// Saturation\n\t\tfloat luminance = dot(result, vec3(0.299, 0.587, 0.114));\n\t\tvec3 grayscale = vec3(luminance);\n\t\tfloat satFactor = 1.0 + ccSaturation;\n\t\tresult = mix(grayscale, result, satFactor);\n\n\t\t// Temperature\n\t\tif (ccTemperature != 0.0) {\n\t\t\tfloat temp = ccTemperature * 0.2;\n\t\t\tresult.r += temp;\n\t\t\tresult.g += temp * 0.5;\n\t\t\tresult.b -= temp;\n\t\t}\n\n\t\treturn clamp(result, 0.0, 1.0);\n\t}\n\n\t// Procedural silhouette check\n\tbool inSilhouette(vec2 uv, float aspectRatioFactor) {\n\t\tfloat fullPersonHeight = 0.85;\n\t\tfloat personHeight = fullPersonHeight * silhouetteScale;\n\t\tfloat bottomMargin = (1.0 - fullPersonHeight) / 2.0;\n\n\t\tfloat feetY = bottomMargin;\n\t\tfloat legHeight = personHeight * 0.45;\n\t\tfloat hipY = feetY + legHeight;\n\t\tfloat torsoHeight = personHeight * 0.35;\n\t\tfloat shoulderY = hipY + torsoHeight;\n\t\tfloat neckLength = personHeight * 0.03;\n\t\tfloat neckY = shoulderY + neckLength;\n\t\tfloat headRadius = personHeight * 0.09;\n\t\tfloat headY = neckY + headRadius;\n\n\t\tfloat torsoWidth = personHeight * 0.22 * aspectRatioFactor;\n\t\tfloat legWidth = personHeight * 0.08 * aspectRatioFactor;\n\t\tfloat legGap = personHeight * 0.02 * aspectRatioFactor;\n\t\tfloat armWidth = personHeight * 0.05 * aspectRatioFactor;\n\t\tfloat armLength = personHeight * 0.35;\n\n\t\tfloat cx = 0.5;\n\n\t\tfloat headRadiusX = headRadius * aspectRatioFactor;\n\t\tfloat headRadiusY = headRadius;\n\t\tif (inEllipse(uv, vec2(cx, headY), vec2(headRadiusX, headRadiusY))) return true;\n\n\t\tfloat neckWidth = headRadiusX * 0.5;\n\t\tif (inRect(uv, vec2(cx, neckY - neckLength/2.0), vec2(neckWidth, neckLength/2.0))) return true;\n\n\t\tif (inRect(uv, vec2(cx, hipY + torsoHeight/2.0), vec2(torsoWidth/2.0, torsoHeight/2.0))) return true;\n\n\t\tfloat armX = cx - torsoWidth/2.0 - armWidth/2.0;\n\t\tif (inRect(uv, vec2(armX, shoulderY - armLength/2.0), vec2(armWidth/2.0, armLength/2.0))) return true;\n\n\t\tarmX = cx + torsoWidth/2.0 + armWidth/2.0;\n\t\tif (inRect(uv, vec2(armX, shoulderY - armLength/2.0), vec2(armWidth/2.0, armLength/2.0))) return true;\n\n\t\tfloat legX = cx - legGap - legWidth/2.0;\n\t\tif (inRect(uv, vec2(legX, feetY + legHeight/2.0), vec2(legWidth/2.0, legHeight/2.0))) return true;\n\n\t\tlegX = cx + legGap + legWidth/2.0;\n\t\tif (inRect(uv, vec2(legX, feetY + legHeight/2.0), vec2(legWidth/2.0, legHeight/2.0))) return true;\n\n\t\treturn false;\n\t}\n\n\t// Cover-crop UV: maps plane UV to texture UV when video AR differs from plane AR.\n\t// Acts like CSS object-fit:cover \u2014 fills the plane, crops excess, no stretching.\n\t// When video and plane have the same AR, returns uv unchanged.\n\tvec2 getCoverUV(vec2 uv) {\n\t\tfloat planeAR = aspectRatio;\n\t\tfloat vidAR = videoAspectRatio;\n\t\tif (vidAR <= 0.0 || planeAR <= 0.0 || abs(vidAR - planeAR) < 0.01) {\n\t\t\treturn uv;\n\t\t}\n\t\tif (vidAR < planeAR) {\n\t\t\t// Video is narrower/taller than plane \u2014 crop top/bottom\n\t\t\tfloat scale = vidAR / planeAR;\n\t\t\treturn vec2(uv.x, uv.y * scale + (1.0 - scale) * 0.5);\n\t\t} else {\n\t\t\t// Video is wider than plane \u2014 crop sides\n\t\t\tfloat scale = planeAR / vidAR;\n\t\t\treturn vec2(uv.x * scale + (1.0 - scale) * 0.5, uv.y);\n\t\t}\n\t}\n\n\tvoid main() {\n\t\t// Positioning mode: setup modal open AND neither AI nor chroma key active\n\t\t// In this mode, show full silhouette guide WITHOUT garbage matte\n\t\t// setupMode is set by component when webcam setup modal is open\n\t\tbool isPositioningMode = setupMode && !useAIMask && !useChromaKey && !fullViewMode;\n\n\t\t// Get garbage matte mask - skip in positioning mode to show full silhouette\n\t\tfloat garbageMask = isPositioningMode ? 1.0 : getGarbageMatteMask(vUv);\n\n\t\tif (garbageMask < 0.001) {\n\t\t\tdiscard;\n\t\t}\n\n\t\tfloat aspectRatioFactor = 1.0 / aspectRatio;\n\n\t\t// Cover-crop UV for texture sampling when video AR differs from plane AR\n\t\t// (e.g., portrait video on landscape plane). Silhouette/matte use vUv (plane space).\n\t\tvec2 texUV = getCoverUV(vUv);\n\t\tvec4 texColor = texture2D(webcamTexture, texUV);\n\n\t\t// Debug: visualize AI mask as color overlay (red=person, blue=background)\n\t\tif (debugShowMask && useAIMask) {\n\t\t\tfloat maskVal = texture2D(segmentationMask, texUV).r;\n\t\t\tgl_FragColor = vec4(maskVal, 0.0, 1.0 - maskVal, 1.0);\n\t\t\treturn;\n\t\t}\n\n\t\t// Full view mode - MUST be checked FIRST before any processing\n\t\t// Used during eyedropper color picking to show raw webcam\n\t\tif (fullViewMode) {\n\t\t\tfloat fvGarbageMask = getGarbageMatteMask(vUv);\n\t\t\tif (fvGarbageMask < 0.5) {\n\t\t\t\tdiscard;\n\t\t\t}\n\t\t\tif (hasTexture) {\n\t\t\t\tgl_FragColor = vec4(texColor.rgb, 1.0);\n\t\t\t} else {\n\t\t\t\tgl_FragColor = vec4(placeholderColor, placeholderOpacity);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Chroma key mode\n\t\tif (useChromaKey && hasTexture) {\n\t\t\tfloat mask = chromaKeyMask(texColor.rgb, chromaKeyColor, chromaKeyTolerance, chromaKeyEdge);\n\n\t\t\tbool insideSilhouette = inSilhouette(vUv, aspectRatioFactor);\n\n\t\t\tif (setupMode) {\n\t\t\t\t// Setup mode: show silhouette overlay for positioning\n\t\t\t\tvec3 cleanColor = suppressSpill(texColor.rgb, chromaKeyColor, chromaKeySpill);\n\t\t\t\tcleanColor = applyColorCorrection(cleanColor);\n\n\t\t\t\tif (mask < 0.01) {\n\t\t\t\t\tif (insideSilhouette) {\n\t\t\t\t\t\tvec3 cyan = vec3(0.0, 0.8, 0.8);\n\t\t\t\t\t\tgl_FragColor = vec4(cyan * 0.3, 0.3);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tgl_FragColor = vec4(0.0, 0.0, 0.0, 0.4);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (insideSilhouette) {\n\t\t\t\t\t\tgl_FragColor = vec4(cleanColor, 1.0);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvec3 warningTint = mix(cleanColor, vec3(1.0, 0.5, 0.0), 0.2);\n\t\t\t\t\t\tgl_FragColor = vec4(warningTint * mask, mask);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Normal chroma key compositing\n\t\t\tif (mask < 0.01) {\n\t\t\t\tdiscard;\n\t\t\t} else if (mask > 0.99) {\n\t\t\t\tvec3 cleanColor = suppressSpill(texColor.rgb, chromaKeyColor, chromaKeySpill);\n\t\t\t\tcleanColor = applyColorCorrection(cleanColor);\n\t\t\t\tfloat finalAlpha = garbageMask;\n\t\t\t\tgl_FragColor = vec4(cleanColor * finalAlpha, finalAlpha);\n\t\t\t} else {\n\t\t\t\tvec3 cleanColor = suppressSpill(texColor.rgb, chromaKeyColor, chromaKeySpill);\n\t\t\t\tcleanColor = applyColorCorrection(cleanColor);\n\t\t\t\tfloat finalAlpha = mask * garbageMask;\n\t\t\t\tgl_FragColor = vec4(cleanColor * finalAlpha, finalAlpha);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Apply color correction for non-chroma-key modes\n\t\ttexColor.rgb = applyColorCorrection(texColor.rgb);\n\n\t\t// AI mask or silhouette fallback\n\t\tbool inside;\n\n\t\tif (useAIMask && hasTexture) {\n\t\t\tfloat maskValue = texture2D(segmentationMask, texUV).r;\n\n\t\t\tif (useHsvWindow) {\n\t\t\t\t// HSV refines AI mask: background-colored pixels get reduced confidence\n\t\t\t\t// hsvMask: 0 = matches background color, 1 = doesn't match\n\t\t\t\tfloat hsvMask = hsvWindowMask(texColor.rgb, hsvMinHue, hsvMaxHue,\n\t\t\t\t hsvMinSat, hsvMaxSat, hsvMinVal, hsvMaxVal, 0.1);\n\t\t\t\t// Background pixels need ~3.3x higher AI confidence to survive\n\t\t\t\tfloat refinedMask = maskValue * (0.3 + 0.7 * hsvMask);\n\t\t\t\tinside = refinedMask > maskThreshold;\n\t\t\t} else {\n\t\t\t\tinside = maskValue > maskThreshold;\n\t\t\t}\n\t\t} else {\n\t\t\tinside = inSilhouette(vUv, aspectRatioFactor);\n\t\t}\n\n\t\t// isPositioningMode is defined at top of main() - shows full silhouette guide\n\n\t\tif (hasTexture) {\n\t\t\tif (inside) {\n\t\t\t\tgl_FragColor = vec4(texColor.rgb * garbageMask, garbageMask);\n\t\t\t} else {\n\t\t\t\tif (useAIMask) {\n\t\t\t\t\tdiscard;\n\t\t\t\t} else if (isPositioningMode) {\n\t\t\t\t\t// Positioning mode: much darker outside for clear guide visibility\n\t\t\t\t\t// Use 75% opacity dark overlay so silhouette boundary is obvious\n\t\t\t\t\tfloat positioningAlpha = 0.75 * garbageMask;\n\t\t\t\t\tgl_FragColor = vec4(0.0, 0.0, 0.0, positioningAlpha);\n\t\t\t\t} else {\n\t\t\t\t\tfloat finalAlpha = darkOpacity * garbageMask;\n\t\t\t\t\tgl_FragColor = vec4(0.0, 0.0, 0.0, finalAlpha);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tif (inside) {\n\t\t\t\tfloat alpha = (placeholderOpacity + 0.15) * garbageMask;\n\t\t\t\tgl_FragColor = vec4(placeholderColor * alpha, alpha);\n\t\t\t} else {\n\t\t\t\tfloat alpha = placeholderOpacity * garbageMask;\n\t\t\t\tgl_FragColor = vec4(placeholderColor * 0.5 * alpha, alpha);\n\t\t\t}\n\t\t}\n\t}\n";
58
+ /**
59
+ * Default uniform values for webcam shader
60
+ */
61
+ export interface WebcamShaderUniforms {
62
+ webcamTexture: {
63
+ value: unknown;
64
+ };
65
+ segmentationMask: {
66
+ value: unknown;
67
+ };
68
+ hasTexture: {
69
+ value: boolean;
70
+ };
71
+ useAIMask: {
72
+ value: boolean;
73
+ };
74
+ maskThreshold: {
75
+ value: number;
76
+ };
77
+ darkOpacity: {
78
+ value: number;
79
+ };
80
+ placeholderColor: {
81
+ value: unknown;
82
+ };
83
+ placeholderOpacity: {
84
+ value: number;
85
+ };
86
+ aspectRatio: {
87
+ value: number;
88
+ };
89
+ videoAspectRatio: {
90
+ value: number;
91
+ };
92
+ useChromaKey: {
93
+ value: boolean;
94
+ };
95
+ chromaKeyColor: {
96
+ value: unknown;
97
+ };
98
+ chromaKeyTolerance: {
99
+ value: number;
100
+ };
101
+ chromaKeySpill: {
102
+ value: number;
103
+ };
104
+ chromaKeyEdge: {
105
+ value: number;
106
+ };
107
+ setupMode: {
108
+ value: boolean;
109
+ };
110
+ useHsvWindow: {
111
+ value: boolean;
112
+ };
113
+ hsvMinHue: {
114
+ value: number;
115
+ };
116
+ hsvMaxHue: {
117
+ value: number;
118
+ };
119
+ hsvMinSat: {
120
+ value: number;
121
+ };
122
+ hsvMaxSat: {
123
+ value: number;
124
+ };
125
+ hsvMinVal: {
126
+ value: number;
127
+ };
128
+ hsvMaxVal: {
129
+ value: number;
130
+ };
131
+ useGarbageMatte: {
132
+ value: boolean;
133
+ };
134
+ garbageMatteIsRect: {
135
+ value: boolean;
136
+ };
137
+ garbageMatteRect: {
138
+ value: unknown;
139
+ };
140
+ garbageMatteMask: {
141
+ value: unknown;
142
+ };
143
+ garbageMatteInvert: {
144
+ value: boolean;
145
+ };
146
+ garbageMatteFeather: {
147
+ value: number;
148
+ };
149
+ garbageMatteFeatherEdges: {
150
+ value: unknown;
151
+ };
152
+ usePerEdgeFeather: {
153
+ value: boolean;
154
+ };
155
+ ccBrightness: {
156
+ value: number;
157
+ };
158
+ ccContrast: {
159
+ value: number;
160
+ };
161
+ ccSaturation: {
162
+ value: number;
163
+ };
164
+ ccTemperature: {
165
+ value: number;
166
+ };
167
+ fullViewMode: {
168
+ value: boolean;
169
+ };
170
+ debugShowMask: {
171
+ value: boolean;
172
+ };
173
+ silhouetteScale: {
174
+ value: number;
175
+ };
176
+ }
177
+ /**
178
+ * Get default uniform values for player mode (no editor-specific features)
179
+ */
180
+ export declare function getDefaultPlayerUniforms(): Partial<WebcamShaderUniforms>;
181
+ /**
182
+ * Get default uniform values for editor mode (includes editor-specific features)
183
+ */
184
+ export declare function getDefaultEditorUniforms(): Partial<WebcamShaderUniforms>;
185
+ //# sourceMappingURL=shaders.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shaders.d.ts","sourceRoot":"","sources":["../../src/layer2/shaders.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;GAEG;AACH,eAAO,MAAM,kBAAkB,8IAM9B,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,eAAO,MAAM,oBAAoB,y6jBA8ehC,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACpC,aAAa,EAAE;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC;IAClC,gBAAgB,EAAE;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC;IACrC,UAAU,EAAE;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC;IAC/B,SAAS,EAAE;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC;IAC9B,aAAa,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACjC,WAAW,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/B,gBAAgB,EAAE;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC;IACrC,kBAAkB,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACtC,WAAW,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/B,gBAAgB,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACpC,YAAY,EAAE;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC;IACjC,cAAc,EAAE;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC;IACnC,kBAAkB,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACtC,cAAc,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAClC,aAAa,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACjC,SAAS,EAAE;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC;IAC9B,YAAY,EAAE;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC;IACjC,SAAS,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7B,SAAS,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7B,SAAS,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7B,SAAS,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7B,SAAS,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7B,SAAS,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7B,eAAe,EAAE;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC;IACpC,kBAAkB,EAAE;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC;IACvC,gBAAgB,EAAE;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC;IACrC,gBAAgB,EAAE;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC;IACrC,kBAAkB,EAAE;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC;IACvC,mBAAmB,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACvC,wBAAwB,EAAE;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC;IAC7C,iBAAiB,EAAE;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC;IACtC,YAAY,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAChC,UAAU,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9B,YAAY,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAChC,aAAa,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACjC,YAAY,EAAE;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC;IACjC,aAAa,EAAE;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC;IAClC,eAAe,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;CACnC;AAED;;GAEG;AACH,wBAAgB,wBAAwB,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAiCxE;AAED;;GAEG;AACH,wBAAgB,wBAAwB,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAMxE"}