{
	"$schema": "https://ui.shadcn.com/schema/registry-item.json",
	"name": "PlasmaWave-TS-TW",
	"title": "PlasmaWave",
	"description": "Raymarched plasma waves with dual-wave interference and OGL.",
	"type": "registry:component",
	"files": [
		{
			"type": "registry:component",
			"path": "PlasmaWave/PlasmaWave.tsx",
			"content": "import { useRef, useEffect } from 'react';\nimport { Renderer, Camera, Transform, Program, Mesh, Geometry } from 'ogl';\n\nfunction hexToRgb(hex: string): [number, number, number] {\n  const r = parseInt(hex.slice(1, 3), 16) / 255;\n  const g = parseInt(hex.slice(3, 5), 16) / 255;\n  const b = parseInt(hex.slice(5, 7), 16) / 255;\n  return [r, g, b];\n}\n\nconst VERT = /* glsl */ `\nattribute vec2 position;\nvoid main() {\n  gl_Position = vec4(position, 0.0, 1.0);\n}\n`;\n\nconst FRAG = /* glsl */ `\nprecision highp float;\nuniform float iTime;\nuniform vec2  iResolution;\nuniform vec2  uOffset;\nuniform float uRotation;\nuniform float uFocalLength;\nuniform float uSpeed1;\nuniform float uSpeed2;\nuniform float uDir2;\nuniform float uBend1;\nuniform float uBend2;\nuniform vec3  uColor1;\nuniform vec3  uColor2;\nuniform float uLightMode;\n\nconst float lt   = 0.3;\nconst float pi   = 3.14159;\nconst float pi2  = 6.28318;\nconst float pi_2 = 1.5708;\n#define MAX_STEPS 14\n\nvoid mainImage(out vec4 C, in vec2 U) {\n  float t = iTime * pi;\n  float s = 1.0;\n  float d = 0.0;\n  vec2  R = iResolution;\n\n  vec3 o = vec3(0.0, 0.0, -7.0);\n  vec3 u = normalize(vec3((U - 0.5 * R) / R.y, uFocalLength));\n  vec2 k = vec2(0.0);\n  vec3 p;\n\n  float t1 = t * 0.7;\n  float t2 = t * 0.9;\n  float tSpeed1 = t * uSpeed1;\n  float tSpeed2 = t * uSpeed2 * uDir2;\n\n  for (int i = 0; i < MAX_STEPS; ++i) {\n    p = o + u * d;\n    p.x -= 15.0;\n\n    float px = p.x;\n    float wob1 = uBend1 + sin(t1 + px * 0.8) * 0.1;\n    float wob2 = uBend2 + cos(t2 + px * 1.1) * 0.1;\n\n    float px2 = px + pi_2;\n    vec2 sinOffset = sin(vec2(px, px2) + tSpeed1) * wob1;\n    vec2 cosOffset = cos(vec2(px, px2) + tSpeed2) * wob2;\n\n    vec2 yz = p.yz;\n    float pxLt = px + lt;\n    k.x = max(pxLt, length(yz - sinOffset) - lt);\n    k.y = max(pxLt, length(yz - cosOffset) - lt);\n\n    float current = min(k.x, k.y);\n    s = min(s, current);\n    if (s < 0.001 || d > 300.0) break;\n    d += s * 0.7;\n  }\n\n  float sqrtD = sqrt(d);\n  vec3 raw = max(cos(d * pi2) - s * sqrtD - vec3(k, 0.0), 0.0);\n  float field = max(raw.r, max(raw.g, raw.b));\n  float outerMask = smoothstep(0.0, 0.055, field);\n  float glowMask = smoothstep(0.012, 0.13, field);\n  float coreMask = smoothstep(0.075, 0.27, field);\n  if (uLightMode < 0.5 && field < 0.15) discard;\n  raw.gb += uLightMode > 0.5 ? 0.1 * glowMask : 0.1;\n  raw = raw * 0.4 + raw.brg * 0.6 + raw * raw;\n  float lum = dot(raw, vec3(0.299, 0.587, 0.114));\n  float w1 = max(0.0, 1.0 - k.x * 2.0);\n  float w2 = max(0.0, 1.0 - k.y * 2.0);\n  float wt = w1 + w2 + 0.001;\n  vec3 baseColor = (uColor1 * w1 + uColor2 * w2) / wt;\n  vec3 c = baseColor * lum * 3.5;\n  if (uLightMode > 0.5) {\n    float lightW1 = exp(-max(k.x, 0.0) * 4.0);\n    float lightW2 = exp(-max(k.y, 0.0) * 4.0);\n    vec3 lightBase = (uColor1 * lightW1 + uColor2 * lightW2) / (lightW1 + lightW2 + 0.001);\n    float lightLuma = dot(lightBase, vec3(0.299, 0.587, 0.114));\n    vec3 vividColor = clamp(pow(max(mix(vec3(lightLuma), lightBase, 1.35), 0.0), vec3(0.64)) * 1.14, 0.0, 1.0);\n    float colorPresence = clamp(outerMask * 0.34 + glowMask * 1.08 + coreMask * 0.22, 0.0, 1.0);\n    vec3 lightColor = mix(vec3(1.0), vividColor, colorPresence);\n    lightColor = mix(lightColor, vec3(1.0), coreMask * smoothstep(0.16, 0.95, lum) * 0.1);\n    C = vec4(lightColor, 1.0);\n  } else {\n    C = vec4(c, 1.0);\n  }\n}\n\nvoid main() {\n  vec2 coord = gl_FragCoord.xy + uOffset;\n  coord -= 0.5 * iResolution;\n  float c = cos(uRotation), s = sin(uRotation);\n  coord = mat2(c, -s, s, c) * coord;\n  coord += 0.5 * iResolution;\n\n  vec4 color;\n  mainImage(color, coord);\n  gl_FragColor = color;\n}\n`;\n\ninterface PlasmaWaveProps {\n  xOffset?: number;\n  yOffset?: number;\n  rotationDeg?: number;\n  focalLength?: number;\n  speed1?: number;\n  speed2?: number;\n  dir2?: number;\n  bend1?: number;\n  bend2?: number;\n  colors?: [string, string];\n  lightMode?: boolean;\n}\n\nexport default function PlasmaWave(props: PlasmaWaveProps) {\n  const {\n    xOffset = 0,\n    yOffset = 0,\n    rotationDeg = 0,\n    focalLength = 0.8,\n    speed1 = 0.05,\n    speed2 = 0.05,\n    dir2 = 1.0,\n    bend1 = 1,\n    bend2 = 0.5,\n    colors = ['#A855F7', '#06B6D4'],\n    lightMode = false\n  } = props;\n\n  const propsRef = useRef<PlasmaWaveProps>(props);\n  propsRef.current = props;\n\n  const containerRef = useRef<HTMLDivElement>(null);\n\n  useEffect(() => {\n    const ctn = containerRef.current;\n    if (!ctn) return;\n\n    const renderer = new Renderer({\n      alpha: true,\n      dpr: Math.min(window.devicePixelRatio, 1.5),\n      antialias: true,\n      depth: false,\n      stencil: false,\n      premultipliedAlpha: false,\n      preserveDrawingBuffer: false,\n      powerPreference: 'high-performance'\n    });\n\n    const gl = renderer.gl;\n    gl.clearColor(0, 0, 0, 0);\n    ctn.appendChild(gl.canvas);\n\n    const camera = new Camera(gl);\n    const scene = new Transform();\n\n    const geometry = new Geometry(gl, {\n      position: { size: 2, data: new Float32Array([-1, -1, 3, -1, -1, 3]) }\n    });\n\n    const uniformOffset = new Float32Array([xOffset, yOffset]);\n    const uniformResolution = new Float32Array([1, 1]);\n    const c1 = hexToRgb(colors[0]);\n    const c2 = hexToRgb(colors[1]);\n\n    const program = new Program(gl, {\n      vertex: VERT,\n      fragment: FRAG,\n      uniforms: {\n        iTime: { value: 0 },\n        iResolution: { value: uniformResolution },\n        uOffset: { value: uniformOffset },\n        uRotation: { value: (rotationDeg * Math.PI) / 180 },\n        uFocalLength: { value: focalLength },\n        uSpeed1: { value: speed1 },\n        uSpeed2: { value: speed2 },\n        uDir2: { value: dir2 },\n        uBend1: { value: bend1 },\n        uBend2: { value: bend2 },\n        uColor1: { value: c1 },\n        uColor2: { value: c2 },\n        uLightMode: { value: lightMode ? 1 : 0 }\n      }\n    });\n\n    new Mesh(gl, { geometry, program }).setParent(scene);\n\n    function resize() {\n      if (!ctn) return;\n      const { width, height } = ctn.getBoundingClientRect();\n      renderer.setSize(width, height);\n      uniformResolution[0] = width * renderer.dpr;\n      uniformResolution[1] = height * renderer.dpr;\n      gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);\n    }\n\n    const ro = new ResizeObserver(resize);\n    ro.observe(ctn);\n    resize();\n\n    const startTime = performance.now();\n    let animateId: number;\n\n    const update = (now: number) => {\n      const {\n        xOffset: xOff = 0,\n        yOffset: yOff = 0,\n        rotationDeg: rot = 0,\n        focalLength: fLen = 0.8,\n        speed1: s1 = 0.05,\n        speed2: s2 = 0.05,\n        dir2: d2 = 1.0,\n        bend1: b1 = 1,\n        bend2: b2 = 0.5,\n        colors: cols = ['#A855F7', '#06B6D4'],\n        lightMode: isLight = false\n      } = propsRef.current;\n\n      uniformOffset[0] = xOff;\n      uniformOffset[1] = yOff;\n      program.uniforms.iTime.value = (now - startTime) * 0.001;\n      program.uniforms.uRotation.value = (rot * Math.PI) / 180;\n      program.uniforms.uFocalLength.value = fLen;\n      program.uniforms.uSpeed1.value = s1;\n      program.uniforms.uSpeed2.value = s2;\n      program.uniforms.uDir2.value = d2;\n      program.uniforms.uBend1.value = b1;\n      program.uniforms.uBend2.value = b2;\n      program.uniforms.uColor1.value = hexToRgb(cols[0]);\n      program.uniforms.uColor2.value = hexToRgb(cols[1]);\n      program.uniforms.uLightMode.value = isLight ? 1 : 0;\n\n      renderer.render({ scene, camera });\n      animateId = requestAnimationFrame(update);\n    };\n\n    animateId = requestAnimationFrame(update);\n\n    return () => {\n      cancelAnimationFrame(animateId);\n      ro.disconnect();\n      if (ctn && gl.canvas.parentNode === ctn) {\n        ctn.removeChild(gl.canvas);\n      }\n      gl.getExtension('WEBGL_lose_context')?.loseContext();\n    };\n  }, []);\n\n  return <div ref={containerRef} className=\"w-full h-full\" />;\n}\n"
		}
	],
	"registryDependencies": [],
	"dependencies": [
		"ogl@^1.0.11"
	]
}