{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "hologram",
  "title": "Hologram",
  "description": "Play a scene as a projection: a ghost double shimmers off the image, emission lines structure it, and only what is bright enough carries through the dark volume it hangs in.",
  "dependencies": ["remotion"],
  "registryDependencies": ["@remocn/canvas-presentation"],
  "files": [
    {
      "path": "registry/remocn/hologram/index.tsx",
      "content": "\"use client\";\n\nimport type React from \"react\";\nimport { AbsoluteFill } from \"remotion\";\nimport {\n  type CanvasFilterProps,\n  makeCanvasFilter,\n  makeFilterShader,\n} from \"@/lib/remocn/canvas-presentation\";\n\nexport type HologramProps = {\n  tint?: string;\n  glow?: number;\n  ghost?: number;\n  flicker?: number;\n  intensity?: number;\n};\n\nconst DEFAULTS = {\n  tint: \"#63e8ff\",\n  glow: 1,\n  ghost: 1,\n  flicker: 1,\n  intensity: 1,\n};\n\nconst FRAGMENT_SHADER = `#version 300 es\nprecision highp float;\n\nuniform sampler2D u_scene;\nuniform float u_aspect;\nuniform float u_frame;\nuniform vec3 u_tint;\nuniform float u_glow;\nuniform float u_ghost;\nuniform float u_flicker;\nuniform float u_intensity;\n\nin vec2 v_uv;\nout vec4 outColor;\n\nconst float PI = 3.141592653589793;\nconst float TAU = 6.28318530718;\nconst float GOLDEN = 2.39996323;\nconst int HALO_TAPS = 8;\nconst vec3 LUMA = vec3(0.299, 0.587, 0.114);\n\nfloat hash(vec2 p) {\n  return fract(sin(dot(p, vec2(12.9898, 78.233))) * 43758.5453123);\n}\n\nfloat lumaAt(vec2 uv) {\n  return dot(texture(u_scene, uv).rgb, LUMA);\n}\n\nvoid main() {\n  vec4 src = texture(u_scene, v_uv);\n  float amount = clamp(u_intensity, 0.0, 1.0);\n\n  if (!(amount > 0.001)) {\n    outColor = src;\n    return;\n  }\n\n  float row = floor(v_uv.y * 300.0);\n  float clock = floor(u_frame);\n  float slip =\n    (hash(vec2(row, clock)) - 0.5) * u_ghost * 0.006 * step(0.55, hash(vec2(row, clock + 3.0)));\n  vec2 base = vec2(v_uv.x + slip / u_aspect, v_uv.y);\n\n  vec4 held = texture(u_scene, base);\n  float lit = dot(held.rgb, LUMA);\n\n  vec2 apart = vec2(u_ghost * 0.0045 / u_aspect, u_ghost * 0.0035);\n  vec3 twin = texture(u_scene, base + apart).rgb;\n\n  float step2 = 0.0022;\n  float gx =\n    lumaAt(base + vec2(step2 / u_aspect, 0.0)) -\n    lumaAt(base - vec2(step2 / u_aspect, 0.0));\n  float gy = lumaAt(base + vec2(0.0, step2)) - lumaAt(base - vec2(0.0, step2));\n  float rim = clamp(length(vec2(gx, gy)) * 7.0, 0.0, 1.0);\n\n  vec3 halo = vec3(0.0);\n  for (int i = 0; i < HALO_TAPS; i++) {\n    float angle = float(i) * GOLDEN;\n    float reach = sqrt((float(i) + 0.5) / float(HALO_TAPS)) * u_glow * 0.022;\n    vec2 at = base + vec2(cos(angle) * reach / u_aspect, sin(angle) * reach);\n    halo += max(texture(u_scene, at).rgb - 0.34, vec3(0.0));\n  }\n  halo /= float(HALO_TAPS);\n\n  vec3 core = u_tint * (0.12 + lit * 1.55);\n  core = mix(core, held.rgb * u_tint * 1.9, 0.12);\n  core += u_tint * rim * 1.9 * u_glow;\n  core += halo * u_tint * 2.4 * u_glow;\n  core += twin * u_tint * 0.5 * u_ghost;\n\n  float interlace = mod(row, 2.0) < 1.0 ? 1.0 : 0.58;\n  core *= interlace;\n\n  float blink =\n    1.0 -\n    u_flicker *\n      (0.04 + 0.05 * hash(vec2(clock, 7.0))) *\n      (0.5 + 0.5 * sin(u_frame * TAU / 15.0));\n  core *= blink;\n\n  float presence = clamp(lit * 1.5 + rim * 0.8 + 0.03, 0.0, 1.0);\n  vec3 painted = clamp(u_tint * 0.035 + core * presence, 0.0, 1.0);\n\n  outColor = vec4(mix(src.rgb, painted, amount), src.a);\n}`;\n\nfunction toRgb(hex: string): [number, number, number] {\n  const value = hex.replace(\"#\", \"\");\n  const full =\n    value.length === 3\n      ? value\n          .split(\"\")\n          .map((c) => c + c)\n          .join(\"\")\n      : value;\n  const int = Number.parseInt(full, 16);\n  if (Number.isNaN(int)) return [1, 1, 1];\n  return [\n    ((int >> 16) & 255) / 255,\n    ((int >> 8) & 255) / 255,\n    (int & 255) / 255,\n  ];\n}\n\nconst shader = makeFilterShader<HologramProps>(\n  FRAGMENT_SHADER,\n  ({ gl, uniform, passedProps }) => {\n    const {\n      tint = DEFAULTS.tint,\n      glow = DEFAULTS.glow,\n      ghost = DEFAULTS.ghost,\n      flicker = DEFAULTS.flicker,\n      intensity = DEFAULTS.intensity,\n    } = passedProps;\n    gl.uniform3fv(uniform(\"u_tint\"), toRgb(tint));\n    gl.uniform1f(uniform(\"u_glow\"), glow);\n    gl.uniform1f(uniform(\"u_ghost\"), ghost);\n    gl.uniform1f(uniform(\"u_flicker\"), flicker);\n    gl.uniform1f(uniform(\"u_intensity\"), intensity);\n  },\n);\n\nconst HologramFallback: React.FC<HologramProps & CanvasFilterProps> = ({\n  children,\n  tint = DEFAULTS.tint,\n  intensity = DEFAULTS.intensity,\n}) => (\n  <AbsoluteFill>\n    <AbsoluteFill style={{ filter: `saturate(${1 - 0.5 * intensity})` }}>\n      {children}\n    </AbsoluteFill>\n    <AbsoluteFill\n      style={{\n        background: tint,\n        mixBlendMode: \"color\",\n        opacity: 0.75 * intensity,\n      }}\n    />\n    <AbsoluteFill\n      style={{\n        background:\n          \"repeating-linear-gradient(to bottom, rgba(0, 0, 0, 0.32) 0px, rgba(0, 0, 0, 0.32) 2px, transparent 2px, transparent 4px)\",\n        opacity: intensity,\n      }}\n    />\n  </AbsoluteFill>\n);\n\nexport const Hologram = makeCanvasFilter<HologramProps>({\n  shader,\n  fallback: HologramFallback,\n});\n",
      "type": "registry:component",
      "target": "components/remocn/hologram.tsx"
    }
  ],
  "type": "registry:component"
}
