{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "camera-lens",
  "title": "Camera Lens",
  "description": "Put a scene behind real glass: resolution falls off toward the corners, highlights bloom through the optics, colour fringes at the edges — a screencast that reads as filmed rather than rendered.",
  "dependencies": ["remotion"],
  "registryDependencies": ["@remocn/canvas-presentation"],
  "files": [
    {
      "path": "registry/remocn/camera-lens/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 CameraLensProps = {\n  softness?: number;\n  bloom?: number;\n  aberration?: number;\n  vignette?: number;\n  distortion?: number;\n};\n\nconst DEFAULTS = {\n  softness: 0.5,\n  bloom: 0.5,\n  aberration: 0.5,\n  vignette: 0.5,\n  distortion: 0.05,\n};\n\nconst FRAGMENT_SHADER = `#version 300 es\nprecision highp float;\n\nuniform sampler2D u_scene;\nuniform float u_aspect;\nuniform float u_softness;\nuniform float u_bloom;\nuniform float u_aberration;\nuniform float u_vignette;\nuniform float u_distortion;\n\nin vec2 v_uv;\nout vec4 outColor;\n\nconst int SOFT_TAPS = 6;\nconst int GLARE_TAPS = 8;\nconst float GOLDEN = 2.39996323;\n\nvec2 lensUv(vec2 direction, float distance) {\n  vec2 q = direction * distance;\n  q.x /= u_aspect;\n  return q * 0.5 + 0.5;\n}\n\nvec2 spiral(int index, int count, float radius, float turn) {\n  float angle = float(index) * GOLDEN + turn;\n  float step = sqrt((float(index) + 0.5) / float(count)) * radius;\n  return vec2(cos(angle) * step / u_aspect, sin(angle) * step);\n}\n\nvec4 softSample(vec2 uv, float radius) {\n  vec4 sum = texture(u_scene, uv);\n  if (radius <= 0.00002) {\n    return sum;\n  }\n  for (int i = 0; i < SOFT_TAPS; i++) {\n    sum += texture(u_scene, uv + spiral(i, SOFT_TAPS, radius, 0.0));\n  }\n  return sum / float(SOFT_TAPS + 1);\n}\n\nvoid main() {\n  vec2 p = (v_uv - 0.5) * 2.0;\n  p.x *= u_aspect;\n\n  float span = sqrt(u_aspect * u_aspect + 1.0);\n  float reach = length(p);\n  float radius = reach / span;\n  vec2 direction = reach > 0.0001 ? p / reach : vec2(0.0);\n\n  float bend = 1.0 / (1.0 + clamp(u_distortion, 0.0, 1.0) * radius * radius);\n  float focused = reach * bend;\n  vec2 base = lensUv(direction, focused);\n\n  float soft = u_softness * 0.011 * smoothstep(0.22, 1.0, radius);\n  float split = u_aberration * 0.0035 * radius;\n\n  vec4 mid = softSample(base, soft);\n  float red = softSample(lensUv(direction, focused * (1.0 + split)), soft).r;\n  float blue = softSample(lensUv(direction, focused * (1.0 - split)), soft).b;\n  vec3 color = vec3(red, mid.g, blue);\n\n  vec3 glare = vec3(0.0);\n  for (int i = 0; i < GLARE_TAPS; i++) {\n    vec3 tap =\n      texture(u_scene, base + spiral(i, GLARE_TAPS, u_bloom * 0.026, 0.7)).rgb;\n    glare += max(tap - 0.62, vec3(0.0));\n  }\n  color += (glare / float(GLARE_TAPS)) * u_bloom * 1.4;\n\n  float falloff = pow(cos(min(radius, 1.0) * 0.55), 4.0);\n  color *= mix(1.0, falloff, clamp(u_vignette, 0.0, 1.5));\n\n  outColor = vec4(clamp(color, 0.0, 1.0), mid.a);\n}`;\n\nconst shader = makeFilterShader<CameraLensProps>(\n  FRAGMENT_SHADER,\n  ({ gl, uniform, passedProps }) => {\n    const {\n      softness = DEFAULTS.softness,\n      bloom = DEFAULTS.bloom,\n      aberration = DEFAULTS.aberration,\n      vignette = DEFAULTS.vignette,\n      distortion = DEFAULTS.distortion,\n    } = passedProps;\n    gl.uniform1f(uniform(\"u_softness\"), softness);\n    gl.uniform1f(uniform(\"u_bloom\"), bloom);\n    gl.uniform1f(uniform(\"u_aberration\"), aberration);\n    gl.uniform1f(uniform(\"u_vignette\"), vignette);\n    gl.uniform1f(uniform(\"u_distortion\"), distortion);\n  },\n);\n\nconst CameraLensFallback: React.FC<CameraLensProps & CanvasFilterProps> = ({\n  children,\n  bloom = DEFAULTS.bloom,\n  vignette = DEFAULTS.vignette,\n}) => (\n  <AbsoluteFill>\n    <AbsoluteFill>{children}</AbsoluteFill>\n    <AbsoluteFill\n      style={{\n        filter: `blur(${6 * bloom}px) brightness(1.5) contrast(1.3)`,\n        mixBlendMode: \"screen\",\n        opacity: 0.3 * bloom,\n      }}\n    >\n      {children}\n    </AbsoluteFill>\n    <AbsoluteFill\n      style={{\n        background:\n          \"radial-gradient(ellipse 78% 76% at 50% 50%, transparent 52%, rgba(0, 0, 0, 0.5) 100%)\",\n        opacity: Math.min(vignette, 1),\n      }}\n    />\n  </AbsoluteFill>\n);\n\nexport const CameraLens = makeCanvasFilter<CameraLensProps>({\n  shader,\n  fallback: CameraLensFallback,\n});\n",
      "type": "registry:component",
      "target": "components/remocn/camera-lens.tsx"
    }
  ],
  "type": "registry:component"
}
