{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "pixel-planet",
  "description": "A collection of 3D pixel planets built with React Three Fiber.",
  "dependencies": ["three", "@react-three/fiber", "@react-three/drei"],
  "files": [
    {
      "path": "src/registry/new-york/items/pixel-planet/components/pixel-planet.tsx",
      "content": "\"use client\"\n\nimport { Canvas, useFrame } from \"@react-three/fiber\"\nimport { Stars } from \"@react-three/drei\"\nimport { useEffect, useMemo, useRef, useState } from \"react\"\nimport { generatePlanetByType, type PlanetOptions } from \"../lib/utils\"\nimport { Timer } from \"three\"\n\nexport interface PixelPlanetProps {\n  type:\n    | \"ice\"\n    | \"gas_giant_1\"\n    | \"gas_giant_2\"\n    | \"asteroid\"\n    | \"star\"\n    | \"lava\"\n    | \"dry\"\n    | \"earth\"\n    | \"no_atmosphere\"\n  seed: number\n\n  cameraZ?: number\n  /**\n   * advanced customization options for the planet.\n   */\n  advanced?: PlanetOptions\n  className?: string\n  stars?: boolean\n  orbitControls?: boolean\n  orbitControlsSensitivity?: number\n}\n\nconst mapTypeToLabel: Record<PixelPlanetProps[\"type\"], string> = {\n  ice: \"Ice Planet\",\n  gas_giant_1: \"Gas giant 1\",\n  gas_giant_2: \"Gas giant 2\",\n  asteroid: \"Asteroid\",\n  star: \"Star\",\n  lava: \"Lava Planet\",\n  dry: \"Dry Planet\",\n  earth: \"Earth Planet\",\n  no_atmosphere: \"No atmosphere\",\n}\n\nfunction CameraUpdater({ cameraZ }: { cameraZ: number }) {\n  useFrame(({ camera }) => {\n    if (camera.position.z !== cameraZ) {\n      camera.position.set(0, 0, cameraZ)\n      camera.lookAt(0, 0, 0)\n    }\n  })\n  return null\n}\n\nfunction PlanetContent({\n  type,\n  seed,\n  advanced: options,\n  rotationOffset = 0,\n}: PixelPlanetProps & { rotationOffset?: number }) {\n  const planetLabel = mapTypeToLabel[type]\n\n  // Generate planet group when type changes\n  const planet = useMemo(() => {\n    return generatePlanetByType(planetLabel, options)\n  }, [planetLabel, options])\n\n  // Update seed when it changes\n  useEffect(() => {\n    if (!planet) return\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    planet.children.forEach((layer: any) => {\n      if (layer.material && layer.material.uniforms) {\n        if (layer.material.uniforms[\"seed\"]) {\n          layer.material.uniforms[\"seed\"].value = seed\n        }\n      }\n    })\n  }, [planet, seed])\n\n  const timer = useMemo(() => new Timer(), [])\n\n  // Animation loop - update time and manual offset for texture scrolling\n  useFrame(() => {\n    if (!planet) return\n\n    timer.update()\n\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    planet.children.forEach((layer: any) => {\n      if (layer.material && layer.material.uniforms) {\n        if (layer.material.uniforms[\"time\"]) {\n          layer.material.uniforms[\"time\"].value =\n            timer.getElapsed() + rotationOffset\n        }\n      }\n    })\n  })\n\n  if (!planet) return null\n\n  return <primitive object={planet} />\n}\n\nexport function PixelPlanet({\n  className,\n  stars,\n  orbitControls,\n  orbitControlsSensitivity,\n  ...props\n}: PixelPlanetProps & React.ComponentProps<typeof Canvas>) {\n  const [isDragging, setIsDragging] = useState(false)\n  const [rotationOffset, setRotationOffset] = useState(0)\n  const [velocity, setVelocity] = useState(0)\n  const dragStartXRef = useRef<number>(0)\n  const rotationAtDragStartRef = useRef<number>(0)\n  const lastDragTimeRef = useRef<number>(0)\n  const lastDragXRef = useRef<number>(0)\n\n  const orbitControlsEnabled =\n    orbitControls ?? orbitControlsSensitivity !== undefined\n  const sensitivity = orbitControlsSensitivity ?? -0.005 // Default sensitivity\n  const friction = 0.95 // Friction coefficient (lower = more friction)\n\n  const defaultCameraZ = props.type === \"gas_giant_2\" ? 1.5 : 1.0\n  const cameraZ =\n    props.cameraZ ?? props.advanced?.cameraDistance ?? defaultCameraZ\n\n  // Apply velocity and friction when not dragging\n  useEffect(() => {\n    if (isDragging || !orbitControlsEnabled) return\n\n    let animationFrame: number\n\n    const applyMomentum = () => {\n      setVelocity(v => {\n        const newVelocity = v * friction\n        // Stop when velocity is very small\n        if (Math.abs(newVelocity) < 0.0001) {\n          return 0\n        }\n        return newVelocity\n      })\n\n      setRotationOffset(offset => offset + velocity)\n\n      // Continue animation loop if there's still velocity\n      if (Math.abs(velocity) > 0.0001) {\n        animationFrame = requestAnimationFrame(applyMomentum)\n      }\n    }\n\n    if (Math.abs(velocity) > 0.0001) {\n      animationFrame = requestAnimationFrame(applyMomentum)\n    }\n\n    return () => {\n      if (animationFrame) {\n        cancelAnimationFrame(animationFrame)\n      }\n    }\n  }, [isDragging, velocity, orbitControlsEnabled, friction])\n\n  const handlePointerDown = (e: React.PointerEvent<HTMLDivElement>) => {\n    if (!orbitControlsEnabled) return\n    setIsDragging(true)\n    setVelocity(0) // Stop any existing momentum\n    dragStartXRef.current = e.clientX\n    lastDragXRef.current = e.clientX\n    lastDragTimeRef.current = Date.now()\n    rotationAtDragStartRef.current = rotationOffset\n    ;(e.target as HTMLElement).setPointerCapture(e.pointerId)\n  }\n\n  const handlePointerMove = (e: React.PointerEvent<HTMLDivElement>) => {\n    if (!orbitControlsEnabled || !isDragging) return\n\n    const currentTime = Date.now()\n    const deltaX = e.clientX - dragStartXRef.current\n    const deltaTime = currentTime - lastDragTimeRef.current\n\n    // Update rotation\n    const newOffset = rotationAtDragStartRef.current + deltaX * sensitivity\n    setRotationOffset(newOffset)\n\n    // Calculate velocity based on movement since last frame\n    if (deltaTime > 0) {\n      const movementDelta = e.clientX - lastDragXRef.current\n      const instantVelocity =\n        ((movementDelta * sensitivity) / Math.max(deltaTime, 16)) * 16\n      setVelocity(instantVelocity)\n    }\n\n    lastDragXRef.current = e.clientX\n    lastDragTimeRef.current = currentTime\n  }\n\n  const handlePointerUp = (e: React.PointerEvent<HTMLDivElement>) => {\n    if (!orbitControlsEnabled) return\n    setIsDragging(false)\n    ;(e.target as HTMLElement).releasePointerCapture(e.pointerId)\n    // Velocity is already set from last move event, momentum will take over\n  }\n\n  const cursorStyle = orbitControlsEnabled\n    ? isDragging\n      ? \"grabbing\"\n      : \"grab\"\n    : \"inherit\"\n\n  const canvasRef = useRef<HTMLDivElement>(null)\n\n  // Apply cursor style directly to ensure it overrides any CSS\n  useEffect(() => {\n    if (canvasRef.current) {\n      const canvas = canvasRef.current.querySelector(\"canvas\")\n      if (canvas && orbitControlsEnabled) {\n        canvas.style.cursor = cursorStyle\n      }\n    }\n  }, [cursorStyle, orbitControlsEnabled])\n\n  return (\n    <div\n      ref={canvasRef}\n      className={className}\n      style={{\n        ...props.style,\n        touchAction: \"none\",\n        userSelect: \"none\",\n      }}\n      onPointerDown={handlePointerDown}\n      onPointerMove={handlePointerMove}\n      onPointerUp={handlePointerUp}\n      onPointerLeave={handlePointerUp}\n    >\n      <Canvas\n        camera={{ position: [0, 0, cameraZ] }}\n        style={{\n          cursor: cursorStyle,\n          touchAction: \"none\",\n        }}\n        {...props}\n      >\n        <ambientLight intensity={0.5} />\n        <pointLight position={[10, 10, 10]} intensity={1} />\n\n        {stars && (\n          <Stars\n            radius={300}\n            depth={50}\n            count={5000}\n            factor={4}\n            saturation={0}\n            fade\n            speed={1}\n          />\n        )}\n\n        <PlanetContent {...props} rotationOffset={rotationOffset} />\n\n        <CameraUpdater cameraZ={cameraZ} />\n\n        {/* <OrbitControls enablePan={false} /> */}\n      </Canvas>\n    </div>\n  )\n}\n",
      "type": "registry:ui",
      "target": "components/ui/pixel-planet.tsx"
    },
    {
      "path": "src/registry/new-york/items/pixel-planet/lib/utils.ts",
      "content": "import { createAsteroid } from \"./Planets/asteroid\"\nimport { createDryPlanet } from \"./Planets/dryPlanet\"\nimport { createEarthPlanet } from \"./Planets/earthPlanet\"\nimport { createGasGiant } from \"./Planets/gasGiant\"\nimport { createGasGiantRing } from \"./Planets/gasGiantRing\"\nimport { createIcePlanet } from \"./Planets/icePlanet\"\nimport { createLavaPlanet } from \"./Planets/lavaPlanet\"\nimport { createNoAtmospherePlanet } from \"./Planets/noAtmospherePlanet\"\nimport { createStarPlanet } from \"./Planets/starPlanet\"\nimport { Group } from \"three\"\n\nexport function rand(min: number, max: number): number {\n  return Math.floor(Math.random() * (max - min + 1) + min)\n}\n\nexport function flip(): boolean {\n  return Math.random() > 0.5\n}\n\nexport function randomPointOnSphere(): { x: number; y: number; z: number } {\n  const u = Math.random()\n  const v = Math.random()\n  const theta = 2 * Math.PI * u\n  const phi = Math.acos(2 * v - 1)\n  const x = 0 + 1 * Math.sin(phi) * Math.cos(theta)\n  const y = 0 + 1 * Math.sin(phi) * Math.sin(theta)\n  const z = 0 + 1 * Math.cos(phi)\n  return { x: x, y: y, z: z }\n}\n\nexport interface PlanetOptions {\n  lightPosition?: [number, number]\n  rotation?: number\n  rotationSpeed?: number\n  pixelSize?: number\n  waterLevel?: number // for lakes/rivers\n  cloudCover?: number\n  cameraDistance?: number // for manual zoom control\n  orbitControls?: boolean // Enable drag-to-rotate interaction\n  orbitControlsSensitivity?: number // Custom sensitivity for drag-to-rotate\n  colors?: {\n    base?: [number, number, number, number][]\n    craters?: [number, number, number, number][]\n    rivers?: [number, number, number, number][]\n    clouds?: [number, number, number, number][]\n  }\n}\n\nexport function generatePlanetByType(\n  type: string,\n  options?: PlanetOptions,\n): Group | undefined {\n  switch (type) {\n    case \"No atmosphere\":\n      return createNoAtmospherePlanet(options)\n    case \"Ice Planet\":\n      return createIcePlanet(options)\n    case \"Gas giant 1\":\n      return createGasGiant(options)\n    case \"Gas giant 2\":\n      return createGasGiantRing(options)\n    case \"Asteroid\":\n      return createAsteroid(options)\n    case \"Star\":\n      return createStarPlanet(options)\n    case \"Lava Planet\":\n      return createLavaPlanet(options)\n    case \"Dry Planet\":\n      return createDryPlanet(options)\n    case \"Earth Planet\":\n      return createEarthPlanet(options)\n  }\n}\n",
      "type": "registry:lib"
    },
    {
      "path": "src/registry/new-york/items/pixel-planet/lib/seed-utils.ts",
      "content": "export function getSeedFromId(id: string): number {\n  let hash = 0\n  for (let i = 0; i < id.length; i++) {\n    const char = id.charCodeAt(i)\n    hash = (hash << 5) - hash + char\n    hash = hash & hash\n  }\n\n  // Generate a 5-digit seed (range: 10000 to 99999)\n  // 5 digits provides 100k unique variations while staying within\n  // GLSL float precision limits (32-bit floats have ~7 decimal digits of precision)\n  const min5Digit = 10000\n  const max5Digit = 99999\n  const range = max5Digit - min5Digit + 1\n\n  return min5Digit + (Math.abs(hash) % range)\n}\n",
      "type": "registry:lib"
    },
    {
      "path": "src/registry/new-york/items/pixel-planet/lib/Three.ts",
      "content": "import { Clock, Group, Scene, WebGLRenderer } from \"three\"\n\nexport function createScene(): Scene {\n  return new Scene()\n}\n\nexport function createClock(): Clock {\n  return new Clock()\n}\n\nexport function createWebGlRenderer(): WebGLRenderer {\n  return new WebGLRenderer()\n}\n\nexport function createGroup(): Group {\n  return new Group()\n}\n",
      "type": "registry:lib"
    },
    {
      "path": "src/registry/new-york/items/pixel-planet/lib/camera.ts",
      "content": "import { PerspectiveCamera } from \"three\"\n\nexport const createCamera = (\n  fov: number,\n  aspect: number,\n  near: number,\n  far: number,\n): PerspectiveCamera => {\n  return new PerspectiveCamera(fov, aspect, near, far)\n}\n",
      "type": "registry:lib"
    },
    {
      "path": "src/registry/new-york/items/pixel-planet/lib/Planets/asteroid.ts",
      "content": "import {\n  Group,\n  Mesh,\n  PlaneGeometry,\n  ShaderMaterial,\n  Vector2,\n  Vector4,\n} from \"three\"\nimport { flip } from \"../utils\"\n\nconst vertexShader = (): string => {\n  return `\n    varying vec3 vUv; \n\n    void main() {\n      vUv = position; \n\n      vec4 modelViewPosition = modelViewMatrix * vec4(position, 1.0);\n      gl_Position = projectionMatrix * modelViewPosition; \n    }\n  `\n}\n\nconst fragmentShaderPlanet = (): string => {\n  return `\n        varying vec3 vUv;\n        uniform float pixels;\n        uniform float rotation;\n        uniform vec2 light_origin;\n        uniform vec4 color1;\n        uniform vec4 color2;\n        uniform vec4 color3;\n        uniform float size;\n        int OCTAVES = 4;\n        uniform float seed;\n        uniform float time;\n        bool should_dither = true;\n\n        float rand(vec2 coord) {\n            return fract(sin(dot(coord.xy ,vec2(12.9898,78.233))) * 15.5453 * seed);\n        }\n        \n        float noise(vec2 coord){\n            vec2 i = floor(coord);\n            vec2 f = fract(coord);\n            \n            float a = rand(i);\n            float b = rand(i + vec2(1.0, 0.0));\n            float c = rand(i + vec2(0.0, 1.0));\n            float d = rand(i + vec2(1.0, 1.0));\n        \n            vec2 cubic = f * f * (3.0 - 2.0 * f);\n        \n            return mix(a, b, cubic.x) + (c - a) * cubic.y * (1.0 - cubic.x) + (d - b) * cubic.x * cubic.y;\n        }\n        \n        float fbm(vec2 coord){\n            float value = 0.0;\n            float scale = 0.5;\n        \n            for(int i = 0; i < OCTAVES ; i++){\n                value += noise(coord) * scale;\n                coord *= 2.0;\n                scale *= 0.5;\n            }\n            return value;\n        }\n        \n        bool dither(vec2 uv1, vec2 uv2) {\n            return mod(uv1.x+uv2.y,2.0/pixels) <= 1.0 / pixels;\n        }\n        \n        vec2 rotate(vec2 coord, float angle){\n            coord -= 0.5;\n            coord *= mat2(vec2(cos(angle),-sin(angle)),vec2(sin(angle),cos(angle)));\n            return coord + 0.5;\n        }\n        \n        // by Leukbaars from https://www.shadertoy.com/view/4tK3zR\n        float circleNoise(vec2 uv) {\n            float uv_y = floor(uv.y);\n            uv.x += uv_y*.31;\n            vec2 f = fract(uv);\n            float h = rand(vec2(floor(uv.x),floor(uv_y)));\n            float m = (length(f-0.25-(h*0.5)));\n            float r = h*0.25;\n            return m = smoothstep(r-.10*r,r,m);\n        }\n        \n        float crater(vec2 uv) {\n            float c = 1.0;\n            for (int i = 0; i < 2; i++) {\n                c *= circleNoise((uv * size) + (float(i+1)+10.));\n            }\n            return 1.0 - c;\n        }\n\n        void main() {\n            vec2 uv = (floor(vUv.xy*pixels)/pixels) + 0.5;\n\t\n            // we use this val later to interpolate between shades\n            bool dith = dither(uv, vUv.xy);\n            \n            // distance from center\n            float d = distance(uv, vec2(0.5));\n            \n            // optional rotation, do this after the dither or the dither will look very messed up\n            uv = rotate(uv, time*0.1);\n            \n            // two noise values with one slightly offset according to light source, to create shadows later\n            float n = fbm(uv * size);\n            float n2 = fbm(uv * size + (rotate(light_origin, rotation)-0.5) * 0.5);\n            \n            // step noise values to determine where the edge of the asteroid is\n            // step cutoff value depends on distance from center\n            float n_step = step(0.2, n - d);\n            float n2_step = step(0.2, n2 - d);\n            \n            // with this val we can determine where the shadows should be\n            float noise_rel = (n2_step + n2) - (n_step + n);\n            \n            // two crater values, again one extra for the shadows\n            float c1 = crater(uv );\n            float c2 = crater(uv + (light_origin-0.5)*0.03);\n        \n            // now we just assign colors depending on noise values and crater values\n            // base\n            vec4 col = color2;\n            \n            // noise\n            if (noise_rel < -0.06 || (noise_rel < -0.04 && (dith || !should_dither))) {\n                col = color1;\n            }\n            if (noise_rel > 0.05 || (noise_rel > 0.03 && (dith || !should_dither))) {\n                col = color3;\n            }\n            \n            // crater\n            if (c1 > 0.4)  {\n                col = color2;\n            }\n            if (c2<c1) {\n                col = color3;\n            }\n            \n            gl_FragColor = vec4(col.rgb, n_step * col.a);\n            if (gl_FragColor.a < 0.01) discard;\n        }\n    `\n}\n\nimport { type PlanetOptions } from \"../utils\"\n\nexport const createAsteroid = (options?: PlanetOptions): Group => {\n  const lightPos = options?.lightPosition\n    ? new Vector2(options.lightPosition[0], options.lightPosition[1])\n    : new Vector2(0.39, 0.7)\n  const colors = options?.colors?.base\n    ? options.colors.base.map(c => new Vector4(c[0], c[1], c[2], c[3]))\n    : null\n  const rotation = options?.rotation ?? 0.0\n\n  const colorPalette = colors\n    ? colors\n    : [\n        new Vector4(155 / 255, 158 / 255, 184 / 255, 1),\n        new Vector4(71 / 255, 97 / 255, 124 / 255, 1),\n        new Vector4(53 / 255, 57 / 255, 85 / 255, 1),\n      ]\n  const planetGeometry = new PlaneGeometry(1.5, 1.5)\n  const planetMaterial = new ShaderMaterial({\n    uniforms: {\n      pixels: { value: 100.0 },\n      color1: { value: colorPalette[0] },\n      size: { value: Math.random() * 10 },\n      color2: { value: colorPalette[1] },\n      color3: { value: colorPalette[2] },\n      light_origin: { value: lightPos },\n      rotation: { value: rotation },\n      seed: { value: flip() ? Math.random() * 10 : Math.random() * 100 },\n      time: { value: 0.0 },\n    },\n    vertexShader: vertexShader(),\n    fragmentShader: fragmentShaderPlanet(),\n    transparent: true,\n  })\n\n  const asteroid = new Mesh(planetGeometry, planetMaterial)\n\n  return new Group().add(asteroid)\n}\n",
      "type": "registry:lib"
    },
    {
      "path": "src/registry/new-york/items/pixel-planet/lib/Planets/dryPlanet.ts",
      "content": "import {\n  Group,\n  Mesh,\n  NearestFilter,\n  PlaneGeometry,\n  ShaderMaterial,\n  TextureLoader,\n  Vector2,\n} from \"three\"\nimport { flip } from \"../utils\"\n\nconst vertexShader = (): string => {\n  return `\n    varying vec3 vUv; \n\n    void main() {\n      vUv = position; \n\n      vec4 modelViewPosition = modelViewMatrix * vec4(position, 1.0);\n      gl_Position = projectionMatrix * modelViewPosition; \n    }\n  `\n}\n\nconst fragmentShader = (): string => {\n  return `\n        varying vec3 vUv;\n        uniform float pixels;\n        uniform float rotation;\n        uniform vec2 light_origin;\n        float light_distance1 = 0.362;\n        float light_distance2 = 0.525;\n        uniform float time_speed;\n        uniform sampler2D colors;\n        float size = 10.0;\n        int OCTAVES = 4;\n        uniform float seed;\n        uniform float time;\n        bool should_dither = true;\n\n        float rand(vec2 coord) {\n            coord = mod(coord, vec2(1.0,1.0)*floor(size+0.5));\n            return fract(sin(dot(coord.xy ,vec2(12.9898,78.233))) * 15.5453 * seed);\n        }\n        \n        float noise(vec2 coord){\n            vec2 i = floor(coord);\n            vec2 f = fract(coord);\n            \n            float a = rand(i);\n            float b = rand(i + vec2(1.0, 0.0));\n            float c = rand(i + vec2(0.0, 1.0));\n            float d = rand(i + vec2(1.0, 1.0));\n        \n            vec2 cubic = f * f * (3.0 - 2.0 * f);\n        \n            return mix(a, b, cubic.x) + (c - a) * cubic.y * (1.0 - cubic.x) + (d - b) * cubic.x * cubic.y;\n        }\n        \n        float fbm(vec2 coord){\n            float value = 0.0;\n            float scale = 0.5;\n        \n            for(int i = 0; i < OCTAVES ; i++){\n                value += noise(coord) * scale;\n                coord *= 2.0;\n                scale *= 0.5;\n            }\n            return value;\n        }\n        \n        bool dither(vec2 uv1, vec2 uv2) {\n            return mod(uv1.x+uv2.y,2.0/pixels) <= 1.0 / pixels;\n        }\n        \n        vec2 rotate(vec2 coord, float angle){\n            coord -= 0.5;\n            coord *= mat2(vec2(cos(angle),-sin(angle)),vec2(sin(angle),cos(angle)));\n            return coord + 0.5;\n        }\n        \n        vec2 spherify(vec2 uv) {\n            vec2 centered= uv *2.0-1.0;\n            float z = sqrt(1.0 - dot(centered.xy, centered.xy));\n            vec2 sphere = centered/(z + 1.0);\n            return sphere * 0.5+0.5;\n        }\n        \n        \n        void main() {\n            //pixelize uv\n            vec2 uv = (floor(vUv.xy*pixels)/pixels) + 0.5;\n            bool dith = dither(uv, vUv.xy);\n            \n            // cut out a circle\n            float d_circle = distance(uv, vec2(0.5));\n            float a = step(d_circle, 0.49999);\n            \n            uv = spherify(uv);\n            \n            // check distance distance to light\n            float d_light = distance(uv , vec2(light_origin));\n            \n            uv = rotate(uv, rotation);\n            \n            // noise\n            float f = fbm(uv*size+vec2(time*time_speed, 0.0));\n            \n            // remap light\n            d_light = smoothstep(-0.3, 1.2, d_light);\n            \n            if (d_light < light_distance1) {\n                d_light *= 0.9;\n            }\n            if (d_light < light_distance2) {\n                d_light *= 0.9;\n            }\n            \n            \n            float c = d_light*pow(f,0.8)*3.5; // change the magic nums here for different light strengths\n            \n            // apply dithering\n            if (dith || !should_dither) {\n                c += 0.02;\n                c *= 1.05;\n            }\n            \n            // now we can assign colors based on distance to light origin\n            float posterize = floor(c*4.0)/4.0;\n            vec4 col = texture(colors, vec2(posterize, 0.0));\n            \n            gl_FragColor = vec4(col.rgb, a * col.a);\n\n        }\n    `\n}\n\nimport { type PlanetOptions } from \"../utils\"\n\nexport function createDryPlanet(options?: PlanetOptions): Group {\n  const {\n    lightPosition,\n    colors,\n    rotationSpeed = 0.1,\n    rotation = 0.0,\n  } = options ?? {}\n\n  const lightPos = lightPosition\n    ? new Vector2(lightPosition[0], lightPosition[1])\n    : new Vector2(0.39, 0.7)\n\n  const colorSchemeTexture = new TextureLoader().load(\n    typeof colors === \"string\"\n      ? colors\n      : \"/pixel-planet/colorScheme/colorScheme2.png\",\n  )\n  colorSchemeTexture.magFilter = NearestFilter\n  colorSchemeTexture.minFilter = NearestFilter\n\n  const planetGeometry = new PlaneGeometry(1, 1)\n  const planetMaterial = new ShaderMaterial({\n    uniforms: {\n      pixels: { value: 100.0 },\n      colors: { value: colorSchemeTexture },\n      light_origin: { value: lightPos },\n      time_speed: { value: rotationSpeed },\n      rotation: { value: rotation },\n      seed: { value: flip() ? Math.random() * 10 : Math.random() * 100 },\n      time: { value: 0.0 },\n    },\n    vertexShader: vertexShader(),\n    fragmentShader: fragmentShader(),\n    transparent: true,\n  })\n\n  const basePlanet = new Mesh(planetGeometry, planetMaterial)\n  return new Group().add(basePlanet)\n}\n",
      "type": "registry:lib"
    },
    {
      "path": "src/registry/new-york/items/pixel-planet/lib/Planets/earthPlanet.ts",
      "content": "import { Group, Vector2, Vector4 } from \"three\"\nimport { createAtmosphereLayer } from \"../Layers/atmosphereLayer\"\nimport { createBasePlanet } from \"../Layers/basePlanet\"\nimport { createCloudLayer } from \"../Layers/cloudLayer\"\nimport { createlandMassLayer } from \"../Layers/landMass\"\nimport { type PlanetOptions } from \"../utils\"\n\nexport const createEarthPlanet = (options?: PlanetOptions): Group => {\n  const earth = new Group()\n\n  const lightPos = options?.lightPosition\n    ? new Vector2(options.lightPosition[0], options.lightPosition[1])\n    : undefined\n\n  const rotation = options?.rotation ?? 0.0\n  const rotationSpeed = options?.rotationSpeed\n\n  const baseColors = options?.colors?.base\n    ? options.colors.base.map(c => new Vector4(c[0], c[1], c[2], c[3]))\n    : [\n        new Vector4(102 / 255, 176 / 255, 199 / 255, 1),\n        new Vector4(102 / 255, 176 / 255, 199 / 255, 1),\n        new Vector4(52 / 255, 65 / 255, 157 / 255, 1),\n      ]\n\n  const cloudColors = options?.colors?.clouds\n    ? options.colors.clouds.map(c => new Vector4(c[0], c[1], c[2], c[3]))\n    : undefined\n\n  const basePlanet = createBasePlanet({\n    lightPos,\n    colors: baseColors,\n    rotationSpeed,\n    rotation,\n  })\n  const landmass = createlandMassLayer({\n    lightPos,\n    rotationSpeed,\n    rotation,\n    land: 0.5,\n  })\n  const clouds = createCloudLayer({\n    colors: cloudColors,\n    lightPos,\n    rotationSpeed,\n    rotation,\n    cloudCover: options?.cloudCover,\n  })\n  const atmosphere = createAtmosphereLayer()\n\n  earth.add(basePlanet, landmass, clouds, atmosphere)\n  return earth\n}\n",
      "type": "registry:lib"
    },
    {
      "path": "src/registry/new-york/items/pixel-planet/lib/Planets/gasGiant.ts",
      "content": "import { Group, Vector2, Vector4 } from \"three\"\nimport { createBaseGasPlanet } from \"../Layers/baseGasPlanet\"\nimport { createGasPLayer } from \"../Layers/gasLayer\"\nimport { type PlanetOptions } from \"../utils\"\n\nexport const createGasGiant = (options?: PlanetOptions): Group => {\n  const gasGiantGroup = new Group()\n\n  const lightPos = options?.lightPosition\n    ? new Vector2(options.lightPosition[0], options.lightPosition[1])\n    : undefined\n\n  const rotation = options?.rotation ?? 0.0\n  const rotationSpeed = options?.rotationSpeed\n\n  const baseColors = options?.colors?.base\n    ? options.colors.base.map(c => new Vector4(c[0], c[1], c[2], c[3]))\n    : undefined\n\n  const cloudColors = options?.colors?.clouds\n    ? options.colors.clouds.map(c => new Vector4(c[0], c[1], c[2], c[3]))\n    : undefined\n\n  const basePlanet = createBaseGasPlanet({\n    lightPos,\n    cloudCover: options?.cloudCover,\n    colors: baseColors,\n    rotationSpeed,\n    rotation,\n  })\n  const gasLayer = createGasPLayer({\n    lightPos,\n    cloudCover: options?.cloudCover,\n    colors: cloudColors,\n    rotationSpeed,\n    rotation,\n  })\n  gasLayer.position.z = 0.01\n  gasGiantGroup.add(basePlanet)\n  gasGiantGroup.add(gasLayer)\n\n  return gasGiantGroup\n}\n",
      "type": "registry:lib"
    },
    {
      "path": "src/registry/new-york/items/pixel-planet/lib/Planets/gasGiantRing.ts",
      "content": "import { Group, Vector2 } from \"three\"\nimport { createDenseGasPlanet } from \"../Layers/denseGasLayer\"\nimport { createRingLayer } from \"../Layers/ringLayer\"\nimport { type PlanetOptions } from \"../utils\"\n\nexport const createGasGiantRing = (options?: PlanetOptions): Group => {\n  const gasGiantGroup = new Group()\n\n  const lightPos = options?.lightPosition\n    ? new Vector2(options.lightPosition[0], options.lightPosition[1])\n    : undefined\n\n  const rotationSpeed = options?.rotationSpeed\n\n  const ring = createRingLayer({\n    lightPos,\n    rotationSpeed,\n    rotation: options?.rotation,\n  })\n  const gasPlanet = createDenseGasPlanet({\n    lightPos,\n    rotationSpeed,\n    rotation: options?.rotation,\n  })\n  ring.position.z = 0.01\n  ring.scale.set(2.0, 2.0, 1.0)\n  gasGiantGroup.add(gasPlanet)\n  gasGiantGroup.add(ring)\n\n  return gasGiantGroup\n}\n",
      "type": "registry:lib"
    },
    {
      "path": "src/registry/new-york/items/pixel-planet/lib/Planets/icePlanet.ts",
      "content": "import { Group, Vector2, Vector4 } from \"three\"\nimport { createBasePlanet } from \"../Layers/basePlanet\"\nimport { createCloudLayer } from \"../Layers/cloudLayer\"\nimport { createLakeLayer } from \"../Layers/lakeLayer\"\nimport { type PlanetOptions } from \"../utils\"\n\nexport const createIcePlanet = (options?: PlanetOptions): Group => {\n  const icePlanet = new Group()\n\n  const lightPos = options?.lightPosition\n    ? new Vector2(options.lightPosition[0], options.lightPosition[1])\n    : undefined\n\n  const rotation = options?.rotation ?? 0.0\n  const rotationSpeed = options?.rotationSpeed\n\n  const baseColors = options?.colors?.base\n    ? options.colors.base.map(c => new Vector4(c[0], c[1], c[2], c[3]))\n    : [\n        new Vector4(250 / 255, 255 / 255, 255 / 255, 1),\n        new Vector4(199 / 255, 212 / 255, 255 / 255, 1),\n        new Vector4(146 / 255, 143 / 255, 184 / 255, 1),\n      ]\n\n  const lakeColors = options?.colors?.rivers\n    ? options.colors.rivers.map(c => new Vector4(c[0], c[1], c[2], c[3]))\n    : undefined\n\n  const cloudColors = options?.colors?.clouds\n    ? options.colors.clouds.map(c => new Vector4(c[0], c[1], c[2], c[3]))\n    : undefined\n\n  const basePlanet = createBasePlanet({\n    lightPos,\n    colors: baseColors,\n    rotationSpeed,\n    rotation,\n  })\n  const lakeLayer = createLakeLayer({\n    lightPos,\n    rotationSpeed,\n    waterLevel: options?.waterLevel,\n    colors: lakeColors,\n    rotation,\n  })\n  const cloudLayer = createCloudLayer({\n    colors: cloudColors,\n    lightPos,\n    rotationSpeed,\n    rotation,\n    cloudCover: options?.cloudCover,\n  })\n  icePlanet.add(basePlanet)\n  icePlanet.add(lakeLayer)\n  icePlanet.add(cloudLayer)\n\n  return icePlanet\n}\n",
      "type": "registry:lib"
    },
    {
      "path": "src/registry/new-york/items/pixel-planet/lib/Planets/lavaPlanet.ts",
      "content": "import { Group, Vector2, Vector4 } from \"three\"\nimport { createBasePlanet } from \"../Layers/basePlanet\"\nimport { createCraterLayer } from \"../Layers/craterLayer\"\nimport { createRiverLayer } from \"../Layers/riversLayer\"\nimport { createGroup } from \"../Three\"\nimport { type PlanetOptions } from \"../utils\"\n\nexport const createLavaPlanet = (options?: PlanetOptions): Group => {\n  const lightPos = options?.lightPosition\n    ? new Vector2(options.lightPosition[0], options.lightPosition[1])\n    : undefined\n\n  const rotation = options?.rotation ?? 0.0\n  const rotationSpeed = options?.rotationSpeed\n\n  const baseColors = options?.colors?.base\n    ? options.colors.base.map(c => new Vector4(c[0], c[1], c[2], c[3]))\n    : [\n        new Vector4(0.560784, 0.301961, 0.341176, 1),\n        new Vector4(0.321569, 0.2, 0.247059, 1),\n        new Vector4(0.239216, 0.160784, 0.211765, 1),\n      ]\n\n  const craterColors = options?.colors?.craters\n    ? options.colors.craters.map(c => new Vector4(c[0], c[1], c[2], c[3]))\n    : [\n        new Vector4(0.321569, 0.2, 0.247059, 1),\n        new Vector4(0.239216, 0.160784, 0.211765, 1),\n      ]\n\n  const riverColors = options?.colors?.rivers\n    ? options.colors.rivers.map(c => new Vector4(c[0], c[1], c[2], c[3]))\n    : [\n        new Vector4(1, 0.537255, 0.2, 1),\n        new Vector4(0.901961, 0.270588, 0.223529, 1),\n        new Vector4(0.678431, 0.184314, 0.270588, 1),\n      ]\n\n  const planetGroup = createGroup()\n\n  const basePlanet = createBasePlanet({\n    lightPos,\n    colors: baseColors,\n    rotationSpeed,\n    rotation,\n  })\n  const craterLayer = createCraterLayer({\n    lightPos,\n    rotationSpeed,\n    colors: craterColors,\n    rotation,\n  })\n  const riverLayer = createRiverLayer({\n    lightPos,\n    rotationSpeed,\n    rivers: options?.waterLevel,\n    colors: riverColors,\n    rotation,\n  })\n  planetGroup.add(basePlanet)\n  planetGroup.add(craterLayer)\n  planetGroup.add(riverLayer)\n  return planetGroup\n}\n",
      "type": "registry:lib"
    },
    {
      "path": "src/registry/new-york/items/pixel-planet/lib/Planets/noAtmospherePlanet.ts",
      "content": "import { Group } from \"three\"\nimport { createBasePlanet } from \"../Layers/basePlanet\"\nimport { createCraterLayer } from \"../Layers/craterLayer\"\n\nimport { type PlanetOptions } from \"../utils\"\nimport { Vector2, Vector4 } from \"three\"\n\nexport const createNoAtmospherePlanet = (options?: PlanetOptions): Group => {\n  const noAtmospherePlanet = new Group()\n\n  const lightPos = options?.lightPosition\n    ? new Vector2(options.lightPosition[0], options.lightPosition[1])\n    : undefined\n  const rotationSpeed = options?.rotationSpeed\n  const rotation = options?.rotation\n\n  const basePlanet = createBasePlanet({\n    lightPos,\n    colors: options?.colors?.base\n      ? options.colors.base.map(c => new Vector4(c[0], c[1], c[2], c[3]))\n      : undefined,\n    rotationSpeed,\n    rotation,\n  })\n  const craterLayer = createCraterLayer({\n    lightPos,\n    rotationSpeed,\n    colors: options?.colors?.craters\n      ? options.colors.craters.map(c => new Vector4(c[0], c[1], c[2], c[3]))\n      : undefined,\n    rotation,\n  })\n\n  noAtmospherePlanet.add(basePlanet)\n  noAtmospherePlanet.add(craterLayer)\n\n  return noAtmospherePlanet\n}\n",
      "type": "registry:lib"
    },
    {
      "path": "src/registry/new-york/items/pixel-planet/lib/Planets/starPlanet.ts",
      "content": "import { Group, Vector2 } from \"three\"\nimport { createStar } from \"../Layers/star\"\nimport { createStarBlobLayer } from \"../Layers/starBlobLayer\"\nimport { createStarFlareLayer } from \"../Layers/starFlareLayer\"\nimport { type PlanetOptions } from \"../utils\"\n\nexport const createStarPlanet = (options?: PlanetOptions): Group => {\n  const StarPlanet = new Group()\n\n  const lightPos = options?.lightPosition\n    ? new Vector2(options.lightPosition[0], options.lightPosition[1])\n    : undefined\n\n  const rotation = options?.rotation ?? 0.0\n  const rotationSpeed = options?.rotationSpeed\n\n  const basePlanet = createStar({\n    lightPos,\n    rotationSpeed,\n    rotation,\n  })\n  const starFlareLayer = createStarFlareLayer({\n    rotationSpeed,\n    rotation: options?.rotation,\n  })\n  const blobLayer = createStarBlobLayer({\n    rotationSpeed,\n    rotation: options?.rotation,\n  })\n\n  starFlareLayer.position.z = 0.01\n  starFlareLayer.scale.set(1.2, 1.2, 1.0)\n  blobLayer.position.z = -0.01\n  blobLayer.scale.set(1.9, 1.9, 1.0)\n\n  StarPlanet.add(basePlanet)\n  StarPlanet.add(starFlareLayer)\n  StarPlanet.add(blobLayer)\n\n  return StarPlanet\n}\n",
      "type": "registry:lib"
    },
    {
      "path": "src/registry/new-york/items/pixel-planet/lib/Layers/atmosphereLayer.ts",
      "content": "import { Mesh, PlaneGeometry, ShaderMaterial, Vector4 } from \"three\"\n\nconst vertexShader = (): string => {\n  return `\n    varying vec3 vUv; \n\n    void main() {\n      vUv = position; \n\n      vec4 modelViewPosition = modelViewMatrix * vec4(position, 1.0);\n      gl_Position = projectionMatrix * modelViewPosition; \n    }\n  `\n}\n\nconst fragmentShader = (): string => {\n  return `\n        varying vec3 vUv;\n        uniform vec4 color;\n        uniform vec4 color2;\n        uniform vec4 color3;\n        float pixels = 100.0;\n        \n        float dist(vec2 p0, vec2 pf){\n            return sqrt((pf.x-p0.x)*(pf.x-p0.x)+(pf.y-p0.y)*(pf.y-p0.y));\n        }\n       \n        void main() {\n            vec2 uv = (floor(vUv.xy*pixels)/pixels) + 0.5;   \n            vec2 pos_ndc = 2.0 * uv.xy  - 1.0;\n            float dist = length(pos_ndc);\n            \n            float step0 = 0.65;\n            float step1 = 0.87;\n            float step2 = 0.97;\n            float step3 = 1.04;\n            float step4 = 1.04;\n        \n            vec4 color = mix(vec4(0,0,0,0), color, smoothstep(step0, step1, dist));\n            color = mix(color, color2, smoothstep(step1, step2, dist));\n            color = mix(color, color3, smoothstep(step2, step3, dist));\n            color = mix(color, vec4(0,0,0,0), smoothstep(step3, step4, dist));\n        \n            gl_FragColor = color;\n            if (gl_FragColor.a < 0.01) discard;\n        }\n    `\n}\n\nexport const createAtmosphereLayer = (): Mesh => {\n  const atmopshereGeometry = new PlaneGeometry(1.02, 1.02)\n  const atmopshereMaterial = new ShaderMaterial({\n    uniforms: {\n      color: { value: new Vector4(173 / 255, 216 / 255, 230 / 255, 0.25) },\n      color2: { value: new Vector4(0 / 255, 127 / 255, 255 / 255, 0.35) },\n      color3: { value: new Vector4(0 / 255, 0 / 255, 128 / 255, 0.45) },\n    },\n    vertexShader: vertexShader(),\n    fragmentShader: fragmentShader(),\n    transparent: true,\n  })\n\n  const atmosphereLayer = new Mesh(atmopshereGeometry, atmopshereMaterial)\n\n  return atmosphereLayer\n}\n",
      "type": "registry:lib"
    },
    {
      "path": "src/registry/new-york/items/pixel-planet/lib/Layers/background.ts",
      "content": "import {\n  Mesh,\n  NearestFilter,\n  PlaneGeometry,\n  ShaderMaterial,\n  TextureLoader,\n} from \"three\"\nimport { flip } from \"../utils\"\n\nconst fragmentShaderDust = (): string => {\n  return `\n    varying vec3 vUv;\n    float size = 10.0;\n    int OCTAVES = 12;\n    uniform float seed;\n    float pixels = 100.0;\n    bool should_tile = false;\n    bool reduce_background = false;\n    uniform sampler2D colorscheme;\n    vec2 uv_correct = vec2(1.0);\n\n    \n    float rand(vec2 coord, float tilesize) {\n        if (should_tile) {\n            coord = mod(coord / uv_correct, tilesize );\n        }\n\n        return fract(sin(dot(coord.xy ,vec2(12.9898,78.233))) * (15.5453 + seed));\n    }\n\n    float noise(vec2 coord, float tilesize){\n        vec2 i = floor(coord);\n        vec2 f = fract(coord);\n            \n        float a = rand(i, tilesize);\n        float b = rand(i + vec2(1.0, 0.0), tilesize);\n        float c = rand(i + vec2(0.0, 1.0), tilesize);\n        float d = rand(i + vec2(1.0, 1.0), tilesize);\n    \n        vec2 cubic = f * f * (3.0 - 2.0 * f);\n    \n        return mix(a, b, cubic.x) + (c - a) * cubic.y * (1.0 - cubic.x) + (d - b) * cubic.x * cubic.y;\n    }\n\n    float fbm(vec2 coord, float tilesize){\n        float value = 0.0;\n        float scale = 0.5;\n    \n        for(int i = 0; i < OCTAVES ; i++){\n            value += noise(coord, tilesize ) * scale;\n            coord *= 2.0;\n            scale *= 0.5;\n        }\n        return value;\n    }\n\n    bool dither(vec2 uv1, vec2 uv2) {\n        return mod(uv1.y+uv2.x,2.0/pixels) <= 1.0 / pixels;\n    }\n\n    float circleNoise(vec2 uv, float tilesize) {\n        if (should_tile) {\n            uv = mod(uv, tilesize);\n        }\n        \n        float uv_y = floor(uv.y);\n        uv.x += uv_y*.31;\n        vec2 f = fract(uv);\n        float h = rand(vec2(floor(uv.x),floor(uv_y)), tilesize);\n        float m = (length(f-0.25-(h*0.5)));\n        float r = h*0.25;\n        return smoothstep(0.0, r, m*0.75);\n    }\n\n    float cloud_alpha(vec2 uv, float tilesize) {\n        float c_noise = 0.0;\n        \n        // more iterations for more turbulence\n        int iters = 2;\n        for (int i = 0; i < iters; i++) {\n            c_noise += circleNoise(uv * 0.5 + (float(i+1)) + vec2(-0.3, 0.0), ceil(tilesize * 0.5));\n        }\n        float fbm = fbm(uv+c_noise, tilesize);\n        \n        return fbm;\n    }\n\n    void main() {\n        // pixelizing and dithering\n        vec2 uv = floor((vUv.xy) * pixels) / pixels * uv_correct;\n        bool dith = dither(uv, vUv.xy);\n        \n        // noise for the dust\n        // the + vec2(x,y) is to create an offset in noise values\n        float n_alpha = fbm(uv * ceil(size * 0.5) +vec2(2,2), ceil(size * 0.5));\n        float n_dust = cloud_alpha(uv * size, size);\n        float n_dust2 = fbm(uv * ceil(size * 0.2)  -vec2(2,2),ceil(size * 0.2));\n        float n_dust_lerp = n_dust2 * n_dust;\n    \n        // apply dithering\n        if (dith) {\n            n_dust_lerp *= 0.95;\n        }\n    \n        // choose alpha value\n        float a_dust = step(n_alpha , n_dust_lerp * 1.8);\n        n_dust_lerp = pow(n_dust_lerp, 3.2) * 56.0;\n        if (dith) {\n            n_dust_lerp *= 1.1;\n        }\n        \n        // choose & apply colors\n        if (reduce_background) {\n            n_dust_lerp = pow(n_dust_lerp, 0.8) * 0.7;\n        }\n        \n        float col_value = floor(n_dust_lerp) / 7.0;\n        vec3 col = texture(colorscheme, vec2(col_value, 0.0)).rgb;\n        \n        \n        gl_FragColor = vec4(col, a_dust);\n\n    }\n    `\n}\n\nconst fragmentShaderNebula = (): string => {\n  return `\n        varying vec3 vUv;\n        float size = 5.0;\n        int OCTAVES = 8;\n        uniform float seed;\n        float pixels = 100.0;\n        uniform sampler2D colorscheme;\n        vec4 background_color = vec4(0,0,0,0);\n        bool should_tile = false;\n        bool reduce_background = false;\n        vec2 uv_correct = vec2(1.0);\n\n        float rand(vec2 coord, float tilesize) {\n            if (should_tile) {\n                coord = mod(coord / uv_correct, tilesize);\n            }\n        \n            return fract(sin(dot(coord.xy ,vec2(12.9898,78.233))) * (15.5453 + seed));\n        }\n\n        float noise(vec2 coord, float tilesize){\n            vec2 i = floor(coord);\n            vec2 f = fract(coord);\n                \n            float a = rand(i, tilesize);\n            float b = rand(i + vec2(1.0, 0.0), tilesize);\n            float c = rand(i + vec2(0.0, 1.0), tilesize);\n            float d = rand(i + vec2(1.0, 1.0), tilesize);\n        \n            vec2 cubic = f * f * (3.0 - 2.0 * f);\n        \n            return mix(a, b, cubic.x) + (c - a) * cubic.y * (1.0 - cubic.x) + (d - b) * cubic.x * cubic.y;\n        }\n\n        float fbm(vec2 coord, float tilesize){\n            float value = 0.0;\n            float scale = 0.5;\n        \n            for(int i = 0; i < OCTAVES ; i++){\n                value += noise(coord, tilesize ) * scale;\n                coord *= 2.0;\n                scale *= 0.5;\n            }\n            return value;\n        }\n        \n        bool dither(vec2 uv1, vec2 uv2) {\n            return mod(uv1.y+uv2.x,2.0/pixels) <= 1.0 / pixels;\n        }\n\n        float circleNoise(vec2 uv, float tilesize) {\n            if (should_tile) {\n                uv = mod(uv, tilesize / uv_correct);\n            }\n            \n            float uv_y = floor(uv.y);\n            uv.x += uv_y*.31;\n            vec2 f = fract(uv);\n            float h = rand(vec2(floor(uv.x),floor(uv_y)), tilesize);\n            float m = (length(f-0.25-(h*0.5)));\n            float r = h*0.25;\n            return smoothstep(0.0, r, m*0.75);\n        }\n\n        float cloud_alpha(vec2 uv, float tilesize) {\n            float c_noise = 0.0;\n            \n            // more iterations for more turbulence\n            int iters = 4;\n            for (int i = 0; i < iters; i++) {\n                c_noise += circleNoise(uv * 0.5 + (float(i+1)) + vec2(-0.3, 0.0), ceil(tilesize * 0.5));\n            }\n            float fbm = fbm(uv+c_noise, tilesize);\n            \n            return fbm;\n        }\n\n        void main() {\n            // pixelizing and dithering\n            vec2 uv = (floor(vUv.xy*pixels)/pixels) + 0.5; \n  \n            // distance from center\n            float d =  distance(uv, vec2(0.5)) * 0.4;\n            \n            uv *= uv_correct;\n            bool dith = dither(uv, vUv.xy);\n            \n            // noise for the inside of the nebulae\n            float n = cloud_alpha(uv * size, size);\n            float n2 = fbm(uv * size + vec2(1, 1), size);\n            float n_lerp = n2 * n;\n            float n_dust = cloud_alpha(uv * size, size);\n            float n_dust_lerp = n_dust * n_lerp;\n        \n            // apply dithering\n            if (dith) {\n                n_dust_lerp *= 0.95;\n                n_lerp *= 0.95;\n                d*= 0.98;\n            }\n        \n            // slightly offset alpha values to create thin bands around the nebulae\n            float a = step(n2, 0.1 + d);\n            float a2 = step(n2, 0.115 + d);\n            if (should_tile) {\n                a = step(n2, 0.3);\n                a2 = step(n2, 0.315);\n            }\n        \n            // choose colors\n            if (reduce_background) {\n                n_dust_lerp = pow(n_dust_lerp, 1.2) * 0.7;\n            }\n            float col_value = 0.0;\n            if (a2 > a) {\n                col_value = floor(n_dust_lerp * 35.0) / 7.0;\n            } else {\n                col_value = floor(n_dust_lerp * 14.0) / 7.0;\n            }\n            \n            // apply colors\n            vec3 col = texture(colorscheme, vec2(col_value, 0.0)).rgb;\n            if (col_value < 0.1) {\n                col = background_color.rgb;\n            }\n            gl_FragColor = vec4(col, a2);\n\n        }\n    `\n}\n\nconst vertexShader = (): string => {\n  return `\n      varying vec3 vUv; \n  \n      void main() {\n        vUv = position; \n  \n        vec4 modelViewPosition = modelViewMatrix * vec4(position, 1.0);\n        gl_Position = projectionMatrix * modelViewPosition; \n      }\n    `\n}\n\nexport function createDustLayer(): Mesh {\n  const backgroundGeometry = new PlaneGeometry(3, 3)\n  const colorSchemeTexture = new TextureLoader().load(\n    \"/pixel-planet/colorScheme/colorScheme1.png\",\n  )\n  colorSchemeTexture.magFilter = NearestFilter\n  colorSchemeTexture.minFilter = NearestFilter\n  const backgroundMaterial = new ShaderMaterial({\n    uniforms: {\n      colorscheme: { value: colorSchemeTexture },\n      seed: { value: 0.0 },\n    },\n    vertexShader: vertexShader(),\n    fragmentShader: fragmentShaderDust(),\n    transparent: true,\n  })\n  const plane = new Mesh(backgroundGeometry, backgroundMaterial)\n  plane.receiveShadow = false\n  plane.position.z = -1\n  return plane\n}\n\nexport function createNebulaLayer(): Mesh {\n  const backgroundGeometry = new PlaneGeometry(3, 3)\n  const colorSchemeTexture = new TextureLoader().load(\n    \"/pixel-planet/colorScheme/colorScheme1.png\",\n  )\n  colorSchemeTexture.magFilter = NearestFilter\n  colorSchemeTexture.minFilter = NearestFilter\n  const backgroundMaterial = new ShaderMaterial({\n    uniforms: {\n      colorscheme: { value: colorSchemeTexture },\n      seed: { value: flip() ? Math.random() * 10 : Math.random() * 100 },\n    },\n    vertexShader: vertexShader(),\n    fragmentShader: fragmentShaderNebula(),\n    transparent: true,\n  })\n  const plane = new Mesh(backgroundGeometry, backgroundMaterial)\n  plane.position.z = -0.9\n  plane.receiveShadow = false\n\n  return plane\n}\n",
      "type": "registry:lib"
    },
    {
      "path": "src/registry/new-york/items/pixel-planet/lib/Layers/baseGasPlanet.ts",
      "content": "import { Mesh, PlaneGeometry, ShaderMaterial, Vector2, Vector4 } from \"three\"\nimport { flip } from \"../utils\"\nimport type { BaseGasLayerOptions } from \"./types\"\n\nconst vertexShader = (): string => {\n  return `\n    varying vec3 vUv; \n\n    void main() {\n      vUv = position; \n\n      vec4 modelViewPosition = modelViewMatrix * vec4(position, 1.0);\n      gl_Position = projectionMatrix * modelViewPosition; \n    }\n  `\n}\n\nconst fragmentShader = (): string => {\n  return `\n        varying vec3 vUv;\n        float pixels = 100.0;\n        uniform float cloud_cover;\n        uniform vec2 light_origin;\n        uniform float time_speed;\n        uniform float stretch;\n        uniform float cloud_curve;\n        float light_border_1 = 0.4;\n        float light_border_2 = 0.6;\n        uniform float rotation;\n\n        uniform vec4 base_color;\n        uniform vec4 outline_color;\n        uniform vec4 shadow_base_color;\n        uniform vec4 shadow_outline_color;\n\n        float size = 9.0;\n        int OCTAVES = 5;\n        uniform float seed;\n        uniform float time;\n\n\n        float rand(vec2 coord) {\n            coord = mod(coord, vec2(1.0,1.0)*floor(size+0.5));\n            return fract(sin(dot(coord.xy ,vec2(12.9898,78.233))) * 15.5453 * seed);\n        }\n\n        float noise(vec2 coord){\n            vec2 i = floor(coord);\n            vec2 f = fract(coord);\n            \n            float a = rand(i);\n            float b = rand(i + vec2(1.0, 0.0));\n            float c = rand(i + vec2(0.0, 1.0));\n            float d = rand(i + vec2(1.0, 1.0));\n        \n            vec2 cubic = f * f * (3.0 - 2.0 * f);\n        \n            return mix(a, b, cubic.x) + (c - a) * cubic.y * (1.0 - cubic.x) + (d - b) * cubic.x * cubic.y;\n        }\n\n        float circleNoise(vec2 uv) {\n            float uv_y = floor(uv.y);\n            uv.x += uv_y*.31;\n            vec2 f = fract(uv);\n            float h = rand(vec2(floor(uv.x),floor(uv_y)));\n            float m = (length(f-0.25-(h*0.5)));\n            float r = h*0.25;\n            return smoothstep(0.0, r, m*0.75);\n        }\n\n        float fbm(vec2 coord){\n            float value = 0.0;\n            float scale = 0.5;\n        \n            for(int i = 0; i < OCTAVES ; i++){\n                value += noise(coord) * scale;\n                coord *= 2.0;\n                scale *= 0.5;\n            }\n            return value;\n        }\n\n        float cloud_alpha(vec2 uv) {\n            float c_noise = 0.0;\n            \n            // more iterations for more turbulence\n            for (int i = 0; i < 9; i++) {\n                c_noise += circleNoise((uv * size * 0.3) + (float(i+1)+10.) + (vec2(time*time_speed, 0.0)));\n            }\n            float fbm = fbm(uv*size+c_noise + vec2(time*time_speed, 0.0));\n            \n            return fbm;\n        }\n        \n        vec2 spherify(vec2 uv) {\n            vec2 centered= uv *2.0-1.0;\n            float z = sqrt(1.0 - dot(centered.xy, centered.xy));\n            vec2 sphere = centered/(z + 1.0);\n            return sphere * 0.5+0.5;\n        }\n        \n        vec2 rotate(vec2 coord, float angle){\n            coord -= 0.5;\n            coord *= mat2(vec2(cos(angle),-sin(angle)),vec2(sin(angle),cos(angle)));\n            return coord + 0.5;\n        }\n\n        void main() {\n            // pixelize uv\n            vec2 uv = (floor(vUv.xy*pixels)/pixels) + 0.5;\n            \n            // distance to light source\n            float d_light = distance(uv , light_origin);\n            \n            // cut out a circle\n            float d_circle = distance(uv, vec2(0.5));\n            // stepping over 0.5 instead of 0.49999 makes some pixels a little buggy\n            float a = step(d_circle, 0.49999);\n            \n            uv = rotate(uv, rotation);\n            \n            // map to sphere\n            uv = spherify(uv);\n            \n            // slightly make uv go down on the right, and up in the left\n            uv.y += smoothstep(0.0, cloud_curve, abs(uv.x-0.4));\n            \n            float c = cloud_alpha(uv*vec2(1.0, stretch));\n            \n            // assign some colors based on cloud depth & distance from light\n            vec4 col = base_color;\n            if (c < cloud_cover + 0.03) {\n                col = outline_color;\n            }\n            if (d_light + c*0.2 > light_border_1) {\n                col = shadow_base_color;\n        \n            }\n            if (d_light + c*0.2 > light_border_2) {\n                col = shadow_outline_color;\n            }\n            gl_FragColor = vec4(col.rgb, step(cloud_cover, c) * a * col.a);\n            if (gl_FragColor.a < 0.01) discard;\n        }\n    `\n}\n\nexport function createBaseGasPlanet(options: BaseGasLayerOptions = {}): Mesh {\n  const {\n    lightPos = new Vector2(0.39, 0.7),\n    colors,\n    stretch = 1.0,\n    rotationSpeed = 0.1,\n    rotation = 0.0,\n  } = options\n  const colorPalette = colors\n    ? colors\n    : [\n        new Vector4(0.941176, 0.709804, 0.254902, 1),\n        new Vector4(0.811765, 0.458824, 0.168627, 1),\n        new Vector4(0.670588, 0.317647, 0.188235, 1),\n        new Vector4(0.490196, 0.219608, 0.2, 1),\n      ]\n\n  const planetGeometryBase = new PlaneGeometry(1, 1)\n  const planetMaterialBase = new ShaderMaterial({\n    uniforms: {\n      base_color: { value: colorPalette[0] },\n      outline_color: { value: colorPalette[1] },\n      shadow_base_color: { value: colorPalette[2] },\n      shadow_outline_color: { value: colorPalette[3] },\n      cloud_cover: { value: 0.0 },\n      stretch: { value: stretch },\n      cloud_curve: { value: 0.0 },\n      time_speed: { value: rotationSpeed },\n      rotation: { value: rotation },\n      light_origin: { value: lightPos },\n      seed: { value: flip() ? Math.random() * 10 : Math.random() * 100 },\n      time: { value: 0.0 },\n    },\n    vertexShader: vertexShader(),\n    fragmentShader: fragmentShader(),\n    transparent: true,\n  })\n\n  const gasGiantBase = new Mesh(planetGeometryBase, planetMaterialBase)\n\n  return gasGiantBase\n}\n",
      "type": "registry:lib"
    },
    {
      "path": "src/registry/new-york/items/pixel-planet/lib/Layers/basePlanet.ts",
      "content": "import { Mesh, PlaneGeometry, ShaderMaterial, Vector2, Vector4 } from \"three\"\nimport { flip } from \"../utils\"\nimport type { BasePlanetLayerOptions } from \"./types\"\n\nconst vertexShader = (): string => {\n  return `\n    varying vec3 vUv; \n\n    void main() {\n      vUv = position; \n\n      vec4 modelViewPosition = modelViewMatrix * vec4(position, 1.0);\n      gl_Position = projectionMatrix * modelViewPosition; \n    }\n  `\n}\n\nconst fragmentShaderPlanet = (): string => {\n  return `\n        varying vec3 vUv;\n        uniform float lightIntensity;\n        uniform float pixels;\n        uniform float rotation;\n        uniform vec2 light_origin;\n        uniform float time_speed;\n        uniform float manual_offset;\n        float dither_size = 2.0;\n        float light_border_1 = 0.4;\n        float light_border_2 = 0.6;\n        uniform vec4 color1;\n        uniform vec4 color2;\n        uniform vec4 color3;\n        float size = 10.0;\n        int OCTAVES = 20;\n        uniform float seed;\n        uniform float time;\n        bool should_dither = true;\n\n        float rand(vec2 coord) {\n            coord = mod(coord, vec2(1.0,1.0)*floor(size+0.5));\n            return fract(sin(dot(coord.xy ,vec2(12.9898,78.233))) * 15.5453 * seed);\n        }\n\n        float noise(vec2 coord){\n            vec2 i = floor(coord);\n            vec2 f = fract(coord);\n            \n            float a = rand(i);\n            float b = rand(i + vec2(1.0, 0.0));\n            float c = rand(i + vec2(0.0, 1.0));\n            float d = rand(i + vec2(1.0, 1.0));\n        \n            vec2 cubic = f * f * (3.0 - 2.0 * f);\n        \n            return mix(a, b, cubic.x) + (c - a) * cubic.y * (1.0 - cubic.x) + (d - b) * cubic.x * cubic.y;\n        }\n\n        float fbm(vec2 coord){\n            float value = 0.0;\n            float scale = 0.5;\n        \n            for(int i = 0; i < OCTAVES ; i++){\n                value += noise(coord) * scale;\n                coord *= 2.0;\n                scale *= 0.5;\n            }\n            return value;\n        }\n        \n        bool dither(vec2 uv1, vec2 uv2) {\n            return mod(uv1.x+uv2.y,2.0/pixels) <= 1.0 / pixels;\n        }\n        \n        vec2 rotate(vec2 coord, float angle){\n            coord -= 0.5;\n            coord *= mat2(vec2(cos(angle),-sin(angle)),vec2(sin(angle),cos(angle)));\n            return coord + 0.5;\n        }\n\n        void main() {\n            vec2 uv = (floor(vUv.xy*pixels)/pixels) + 0.5;\n\t\n            // check distance from center & distance to light\n            float d_circle = distance(uv, vec2(0.5));\n            float d_light = distance(uv , vec2(light_origin));\n            // cut out a circle\n            // stepping over 0.5 instead of 0.49999 makes some pixels a little buggy\n            float a = step(d_circle, 0.49999);\n            \n            bool dith = dither(uv ,vUv.xy);\n            uv = rotate(uv, rotation);\n\n            // get a noise value with light distance added\n            // this creates a moving dynamic shape\n            float fbm1 = fbm(uv);\n            d_light += fbm(uv*size+fbm1+vec2(time*0.1+time_speed+manual_offset, 0.0))*lightIntensity;\n            \n            // size of edge in which colors should be dithered\n            float dither_border = (1.0/pixels)*dither_size;\n\n            // now we can assign colors based on distance to light origin\n            vec4 col = color1;\n            if (d_light > light_border_1) {\n                col = color2;\n                if (d_light < light_border_1 + dither_border && (dith || !should_dither)) {\n                    col = color1;\n                }\n            }\n            if (d_light > light_border_2) {\n                col = color3;\n                if (d_light < light_border_2 + dither_border && (dith || !should_dither)) {\n                    col = color2;\n                }\n            }\n            \n            gl_FragColor = vec4(col.rgb, a * col.a);\n            if (gl_FragColor.a < 0.01) discard;\n        }\n    `\n}\n\nexport function createBasePlanet(options: BasePlanetLayerOptions = {}): Mesh {\n  const {\n    lightPos = new Vector2(0.39, 0.7),\n    lightIntensity = 0.1,\n    colors = null,\n    rotationSpeed = 0.1,\n    rotation = 0.0,\n    manualOffset = 0.0,\n  } = options\n  const colorPalette = colors\n    ? colors\n    : [\n        new Vector4(155 / 255, 158 / 255, 184 / 255, 1),\n        new Vector4(71 / 255, 97 / 255, 124 / 255, 1),\n        new Vector4(53 / 255, 57 / 255, 85 / 255, 1),\n      ]\n  const planetGeometry = new PlaneGeometry(1, 1)\n  const planetMaterial = new ShaderMaterial({\n    uniforms: {\n      pixels: { value: 100.0 },\n      color1: { value: colorPalette[0] },\n      color2: { value: colorPalette[1] },\n      color3: { value: colorPalette[2] },\n      lightIntensity: { value: lightIntensity },\n      light_origin: { value: lightPos },\n      time_speed: { value: rotationSpeed },\n      rotation: { value: rotation },\n      seed: { value: flip() ? Math.random() * 10 : Math.random() * 100 },\n      time: { value: 0.0 },\n      manual_offset: { value: manualOffset },\n    },\n    vertexShader: vertexShader(),\n    fragmentShader: fragmentShaderPlanet(),\n    transparent: true,\n  })\n\n  const basePlanet = new Mesh(planetGeometry, planetMaterial)\n\n  return basePlanet\n}\n",
      "type": "registry:lib"
    },
    {
      "path": "src/registry/new-york/items/pixel-planet/lib/Layers/cloudLayer.ts",
      "content": "import { Mesh, PlaneGeometry, ShaderMaterial, Vector2, Vector4 } from \"three\"\nimport { flip } from \"../utils\"\nimport type { CloudLayerOptions } from \"./types\"\n\nconst vertexShader = (): string => {\n  return `\n    varying vec3 vUv; \n\n    void main() {\n      vUv = position; \n\n      vec4 modelViewPosition = modelViewMatrix * vec4(position, 1.0);\n      gl_Position = projectionMatrix * modelViewPosition; \n    }\n  `\n}\n\nconst fragmentShaderClouds = (): string => {\n  return `\n        varying vec3 vUv;\n        uniform float pixels;\n        uniform float rotation;\n        uniform float cloud_cover;\n        uniform vec2 light_origin;\n        uniform float time_speed;\n        uniform float manual_offset;\n        uniform float stretch;\n        float cloud_curve = 1.3;\n        float light_border_1 = 0.4;\n        float light_border_2 = 0.6;\n        \n        uniform vec4 base_color;\n        uniform vec4 outline_color;\n        uniform vec4 shadow_base_color;\n        uniform vec4 shadow_outline_color;\n        \n        float size = 4.0;\n        int OCTAVES = 4;\n        uniform float seed;\n        \n        uniform float time;\n        \n        float rand(vec2 coord) {\n            coord = mod(coord, vec2(1.0,1.0)*floor(size+0.5));\n            return fract(sin(dot(coord.xy ,vec2(12.9898,78.233))) * 15.5453 * seed);\n        }\n        \n        float noise(vec2 coord){\n            vec2 i = floor(coord);\n            vec2 f = fract(coord);\n            \n            float a = rand(i);\n            float b = rand(i + vec2(1.0, 0.0));\n            float c = rand(i + vec2(0.0, 1.0));\n            float d = rand(i + vec2(1.0, 1.0));\n        \n            vec2 cubic = f * f * (3.0 - 2.0 * f);\n        \n            return mix(a, b, cubic.x) + (c - a) * cubic.y * (1.0 - cubic.x) + (d - b) * cubic.x * cubic.y;\n        }\n        \n        float fbm(vec2 coord){\n            float value = 0.0;\n            float scale = 0.5;\n        \n            for(int i = 0; i < OCTAVES ; i++){\n                value += noise(coord) * scale;\n                coord *= 2.0;\n                scale *= 0.5;\n            }\n            return value;\n        }\n        \n        float circleNoise(vec2 uv) {\n            float uv_y = floor(uv.y);\n            uv.x += uv_y*.31;\n            vec2 f = fract(uv);\n            float h = rand(vec2(floor(uv.x),floor(uv_y)));\n            float m = (length(f-0.25-(h*0.5)));\n            float r = h*0.25;\n            return smoothstep(0.0, r, m*0.75);\n        }\n        \n        float cloud_alpha(vec2 uv) {\n            float c_noise = 0.0;\n            \n            // more iterations for more turbulence\n            for (int i = 0; i < 9; i++) {\n                c_noise += circleNoise((uv * size * 0.3) + (float(i+1)+10.) + (vec2(time*time_speed+manual_offset, 0.0)));\n            }\n            float fbm = fbm(uv*size+c_noise + vec2(time*time_speed+manual_offset, 0.0));\n            \n            return fbm;//step(a_cutoff, fbm);\n        }\n        \n        bool dither(vec2 uv_pixel, vec2 uv_real) {\n            return mod(uv_pixel.x+uv_real.y,2.0/pixels) <= 1.0 / pixels;\n        }\n        \n        vec2 spherify(vec2 uv) {\n            vec2 centered= uv *2.0-1.0;\n            float z = sqrt(1.0 - dot(centered.xy, centered.xy));\n            vec2 sphere = centered/(z + 1.0);\n            return sphere * 0.5+0.5;\n        }\n        \n        vec2 rotate(vec2 coord, float angle){\n            coord -= 0.5;\n            coord *= mat2(vec2(cos(angle),-sin(angle)),vec2(sin(angle),cos(angle)));\n            return coord + 0.5;\n        }\n        \n        void main() {\n            // pixelize uv\n            vec2 uv = (floor(vUv.xy*pixels)/pixels) + 0.5;\n            \n            // distance to light source\n            float d_light = distance(uv , light_origin);\n            \n            // cut out a circle\n            float d_circle = distance(uv, vec2(0.5));\n            float a = step(d_circle, 0.5);\n            \n            float d_to_center = distance(uv, vec2(0.5));\n            \n            uv = rotate(uv, rotation);\n            \n            // map to sphere\n            uv = spherify(uv);\n            // slightly make uv go down on the right, and up in the left\n            uv.y += smoothstep(0.0, cloud_curve, abs(uv.x-0.4));\n            \n            \n            float c = cloud_alpha(uv*vec2(1.0, stretch));\n            \n            // assign some colors based on cloud depth & distance from light\n            vec4 col = base_color;\n            if (c < cloud_cover + 0.03) {\n                col = outline_color;\n            }\n            if (d_light + c*0.2 > light_border_1) {\n                col = shadow_base_color;\n        \n            }\n            if (d_light + c*0.2 > light_border_2) {\n                col = shadow_outline_color;\n            }\n            \n            c *= step(d_to_center, 0.5);\n            gl_FragColor = vec4(col.rgb, step(cloud_cover, c) * a * col.a);\n            if (gl_FragColor.a < 0.01) discard;\n        }\n    `\n}\n\nexport function createCloudLayer(options: CloudLayerOptions = {}): Mesh {\n  const {\n    colors,\n    lightPos = new Vector2(0.39, 0.7),\n    rotationSpeed = 0.1,\n    rotation = 0.0,\n    cloudCover = 0.546,\n    stretch = 2.5,\n    manualOffset = 0.0,\n  } = options\n  const colorPalette = colors\n    ? colors\n    : [\n        new Vector4(0.882353, 0.94902, 1, 1),\n        new Vector4(0.752941, 0.890196, 1, 1),\n        new Vector4(0.368627, 0.439216, 0.647059, 1),\n        new Vector4(0.25098, 0.286275, 0.45098, 1),\n      ]\n  const planetGeometryClouds = new PlaneGeometry(1, 1)\n  const planetMaterialClouds = new ShaderMaterial({\n    uniforms: {\n      light_origin: { value: lightPos },\n      pixels: { value: 100.0 },\n      seed: { value: flip() ? Math.random() * 10 : Math.random() * 100 },\n      time_speed: { value: rotationSpeed },\n      manual_offset: { value: manualOffset },\n      base_color: { value: colorPalette[0] },\n      outline_color: { value: colorPalette[1] },\n      shadow_base_color: { value: colorPalette[2] },\n      shadow_outline_color: { value: colorPalette[3] },\n      cloud_cover: { value: cloudCover },\n      rotation: { value: rotation },\n      stretch: { value: stretch },\n      time: { value: 0.0 },\n    },\n    vertexShader: vertexShader(),\n    fragmentShader: fragmentShaderClouds(),\n    transparent: true,\n  })\n\n  const cloudLayer = new Mesh(planetGeometryClouds, planetMaterialClouds)\n\n  return cloudLayer\n}\n",
      "type": "registry:lib"
    },
    {
      "path": "src/registry/new-york/items/pixel-planet/lib/Layers/craterLayer.ts",
      "content": "import { Mesh, PlaneGeometry, ShaderMaterial, Vector2, Vector4 } from \"three\"\nimport { flip } from \"../utils\"\nimport type { CraterLayerOptions } from \"./types\"\n\nconst vertexShader = (): string => {\n  return `\n    varying vec3 vUv; \n\n    void main() {\n      vUv = position; \n\n      vec4 modelViewPosition = modelViewMatrix * vec4(position, 1.0);\n      gl_Position = projectionMatrix * modelViewPosition; \n    }\n  `\n}\n\nconst fragmentShaderCrater = (): string => {\n  return `\n        varying vec3 vUv;\n        float pixels = 100.0;\n        uniform float rotation;\n        uniform vec2 light_origin;\n        uniform float time_speed;\n        float dither_size = 2.0;\n        float light_border = 0.4;\n        uniform vec4 color1;\n        uniform vec4 color2;\n        float size = 5.0;\n        int OCTAVES = 20;\n        uniform float seed;\n        uniform float time;\n        bool should_dither = true;\n\n        float rand(vec2 coord) {\n            coord = mod(coord, vec2(1.0,1.0)*floor(size+0.5));\n            return fract(sin(dot(coord.xy ,vec2(12.9898,78.233))) * 15.5453 * seed);\n        }\n\n        float circleNoise(vec2 uv) {\n            float uv_y = floor(uv.y);\n            uv.x += uv_y*.31;\n            vec2 f = fract(uv);\n            float h = rand(vec2(floor(uv.x),floor(uv_y)));\n            float m = (length(f-0.25-(h*0.5)));\n            float r = h*0.25;\n            return m = smoothstep(r-.10*r,r,m);\n        }\n\n        float crater(vec2 uv) {\n            float c = 1.0;\n            for (int i = 0; i < 2; i++) {\n                c *= circleNoise((uv * size) + (float(i+1)+10.) + vec2((time*0.1)+time_speed,0.0));\n            }\n            return 1.0 - c;\n        }\n        \n        vec2 spherify(vec2 uv) {\n            vec2 centered= uv *2.0-1.0;\n            float z = sqrt(1.0 - dot(centered.xy, centered.xy));\n            vec2 sphere = centered/(z + 1.0);\n            return sphere * 0.5+0.5;\n        }\n        \n        vec2 rotate(vec2 coord, float angle){\n            coord -= 0.5;\n            coord *= mat2(vec2(cos(angle),-sin(angle)),vec2(sin(angle),cos(angle)));\n            return coord + 0.5;\n        }\n\n        void main() {\n            vec2 uv = (floor(vUv.xy*pixels)/pixels) + 0.5;\n\t\n            // check distance from center & distance to light\n            float d_circle = distance(uv, vec2(0.5));\n            float d_light = distance(uv , vec2(light_origin));\n            // cut out a circle\n            // stepping over 0.5 instead of 0.49999 makes some pixels a little buggy\n            float a = step(d_circle, 0.49999);\n            \n            uv = rotate(uv, rotation);\n            uv = spherify(uv);\n                \n            float c1 = crater(uv );\n            float c2 = crater(uv +(light_origin-0.5)*0.04);\n            vec4 col = color1;\n            \n            a *= step(0.5, c1);\n            if (c2<c1-(0.5-d_light)*2.0) {\n                col = color2;\n            }\n            if (d_light > light_border) {\n                col = color2;\n            } \n        \n            // cut out a circle\n            a*= step(d_circle, 0.5);\n            \n            gl_FragColor = vec4(col.rgb, a * col.a);\n            if (gl_FragColor.a < 0.01) discard;\n        }\n    `\n}\n\nexport function createCraterLayer(options: CraterLayerOptions = {}): Mesh {\n  const {\n    lightPos = new Vector2(0.39, 0.7),\n    rotationSpeed = 0.1,\n    colors = null,\n    rotation = 0.0,\n  } = options\n  const colorPalette = colors\n    ? colors\n    : [\n        new Vector4(71 / 255, 97 / 255, 124 / 255, 1),\n        new Vector4(53 / 255, 57 / 255, 85 / 255, 1),\n      ]\n  const craterGeometry = new PlaneGeometry(1, 1)\n  const craterMaterial = new ShaderMaterial({\n    uniforms: {\n      color1: { value: colorPalette[0] },\n      color2: { value: colorPalette[1] },\n      light_origin: { value: lightPos },\n      time_speed: { value: rotationSpeed },\n      rotation: { value: rotation },\n      seed: { value: flip() ? Math.random() * 10 : Math.random() * 100 },\n      time: { value: 0.0 },\n    },\n    vertexShader: vertexShader(),\n    fragmentShader: fragmentShaderCrater(),\n    depthTest: true,\n    transparent: true,\n  })\n\n  const craterLayer = new Mesh(craterGeometry, craterMaterial)\n\n  return craterLayer\n}\n",
      "type": "registry:lib"
    },
    {
      "path": "src/registry/new-york/items/pixel-planet/lib/Layers/denseGasLayer.ts",
      "content": "import {\n  Mesh,\n  NearestFilter,\n  PlaneGeometry,\n  ShaderMaterial,\n  TextureLoader,\n  Vector2,\n} from \"three\"\nimport { flip } from \"../utils\"\nimport type { DenseGasLayerOptions } from \"./types\"\n\nconst vertexShader = (): string => {\n  return `\n    varying vec3 vUv; \n\n    void main() {\n      vUv = position; \n\n      vec4 modelViewPosition = modelViewMatrix * vec4(position, 1.0);\n      gl_Position = projectionMatrix * modelViewPosition; \n    }\n  `\n}\n\nconst fragmentShader = (): string => {\n  return `\n        varying vec3 vUv;\n        uniform float pixels;\n        uniform float rotation;\n        uniform vec2 light_origin;\n        uniform float time_speed;\n        uniform float cloud_cover;\n        float stretch = 2.0;\n        float cloud_curve = 1.3;\n        float light_border_1 = 0.4;\n        float light_border_2 = 0.6;\n        float bands = 1.0;\n        bool should_dither = true;\n        \n        uniform sampler2D colorscheme;\n        uniform sampler2D dark_colorscheme;\n        \n        float size = 15.0;\n        int OCTAVES = 6;\n        uniform float seed;\n        uniform float time;\n\n        float rand(vec2 coord) {\n            coord = mod(coord, vec2(2.0,1.0)*floor(size+0.5));\n            return fract(sin(dot(coord.xy ,vec2(12.9898,78.233))) * 15.5453 * seed);\n        }\n        \n        float noise(vec2 coord){\n            vec2 i = floor(coord);\n            vec2 f = fract(coord);\n            \n            float a = rand(i);\n            float b = rand(i + vec2(1.0, 0.0));\n            float c = rand(i + vec2(0.0, 1.0));\n            float d = rand(i + vec2(1.0, 1.0));\n        \n            vec2 cubic = f * f * (3.0 - 2.0 * f);\n        \n            return mix(a, b, cubic.x) + (c - a) * cubic.y * (1.0 - cubic.x) + (d - b) * cubic.x * cubic.y;\n        }\n        \n        float fbm(vec2 coord){\n            float value = 0.0;\n            float scale = 0.5;\n        \n            for(int i = 0; i < OCTAVES ; i++){\n                value += noise(coord) * scale;\n                coord *= 2.0;\n                scale *= 0.5;\n            }\n            return value;\n        }\n        \n        float circleNoise(vec2 uv) {\n            float uv_y = floor(uv.y);\n            uv.x += uv_y*.31;\n            vec2 f = fract(uv);\n            float h = rand(vec2(floor(uv.x),floor(uv_y)));\n            float m = (length(f-0.25-(h*0.5)));\n            float r = h*0.25;\n            return smoothstep(0.0, r, m*0.75);\n        }\n        \n        float turbulence(vec2 uv) {\n            float c_noise = 0.0;\n            \n            \n            // more iterations for more turbulence\n            for (int i = 0; i < 10; i++) {\n                c_noise += circleNoise((uv * size *0.3) + (float(i+1)+10.) + (vec2(time * time_speed, 0.0)));\n            }\n            return c_noise;\n        }\n        \n        bool dither(vec2 uv_pixel, vec2 uv_real) {\n            return mod(uv_pixel.x+uv_real.y,2.0/pixels) <= 1.0 / pixels;\n        }\n        \n        vec2 spherify(vec2 uv) {\n            vec2 centered= uv *2.0-1.0;\n            float z = sqrt(1.0 - dot(centered.xy, centered.xy));\n            vec2 sphere = centered/(z + 1.0);\n            return sphere * 0.5+0.5;\n        }\n        \n        vec2 rotate(vec2 coord, float angle){\n            coord -= 0.5;\n            coord *= mat2(vec2(cos(angle),-sin(angle)),vec2(sin(angle),cos(angle)));\n            return coord + 0.5;\n        }\n        \n        void main() {\n            // pixelize uv\n            vec2 uv = (floor(vUv.xy*pixels)/pixels) + 0.5;\n            \n            float light_d = distance(uv, light_origin);\n\t\n            // we use this value later to dither between colors\n            bool dith = dither(uv, vUv.xy);\n            \n            // stepping over 0.5 instead of 0.49999 makes some pixels a little buggy\n            float a = step(length(uv-vec2(0.5)), 0.49999);\n            \n            // rotate planet\n            uv = rotate(uv, rotation);\n            \n            // map to sphere\n            uv = spherify(uv);\n        \n            // a band is just one dimensional noise\n            float band = fbm(vec2(0.0, uv.y*size*bands));\n            \n            // turbulence value is circles on top of each other\n            float turb = turbulence(uv);\n        \n            // by layering multiple noise values & combining with turbulence and bands\n            // we get some dynamic looking shape\t\n            float fbm1 = fbm(uv*size);\n            float fbm2 = fbm(uv*vec2(1.0, 2.0)*size+fbm1+vec2(-time*time_speed,0.0)+turb);\n            \n            // all of this is just increasing some contrast & applying light\n            fbm2 *= pow(band,2.0)*7.0;\n            float light = fbm2 + light_d*1.8;\n            fbm2 += pow(light_d, 1.0)-0.3;\n            fbm2 = smoothstep(-0.2, 4.0-fbm2, light);\n            \n            // apply the dither value\n            if (dith && should_dither) {\n                fbm2 *= 1.1;\n            }\n            \n            // finally add colors\n            float posterized = floor(fbm2*4.0)/2.0;\n            vec4 col;\n            if (fbm2 < 0.625) {\n                col = texture(colorscheme, vec2(posterized, uv.y));\n            } else {\n                col = texture(dark_colorscheme, vec2(posterized-1.0, uv.y));\n            }\n\n            gl_FragColor = vec4(col.rgb, a * col.a);\n            if (gl_FragColor.a < 0.01) discard;\n        }\n    `\n}\n\nexport function createDenseGasPlanet(options: DenseGasLayerOptions = {}): Mesh {\n  const {\n    lightPos = new Vector2(0.39, 0.7),\n    rotationSpeed = 0.1,\n    rotation = 0.0,\n  } = options\n  const colorSchemeTexture1 = new TextureLoader().load(\n    \"/pixel-planet/colorScheme/colorScheme1.png\",\n  )\n  colorSchemeTexture1.magFilter = NearestFilter\n  colorSchemeTexture1.minFilter = NearestFilter\n\n  const colorSchemeTexture2 = new TextureLoader().load(\n    \"/pixel-planet/colorScheme/colorScheme2.png\",\n  )\n  colorSchemeTexture2.magFilter = NearestFilter\n  colorSchemeTexture2.minFilter = NearestFilter\n\n  const ringGeometry = new PlaneGeometry(1, 1)\n  const ringMaterial = new ShaderMaterial({\n    uniforms: {\n      colorscheme: { value: colorSchemeTexture1 },\n      dark_colorscheme: { value: colorSchemeTexture2 },\n      pixels: { value: 150.0 },\n      light_origin: { value: lightPos },\n      time_speed: { value: rotationSpeed },\n      rotation: { value: rotation },\n      seed: { value: flip() ? Math.random() * 10 : Math.random() * 100 },\n      time: { value: 0.0 },\n    },\n    vertexShader: vertexShader(),\n    fragmentShader: fragmentShader(),\n    transparent: true,\n  })\n\n  const ringLayer = new Mesh(ringGeometry, ringMaterial)\n\n  return ringLayer\n}\n",
      "type": "registry:lib"
    },
    {
      "path": "src/registry/new-york/items/pixel-planet/lib/Layers/gasLayer.ts",
      "content": "import { Mesh, PlaneGeometry, ShaderMaterial, Vector2, Vector4 } from \"three\"\nimport { flip } from \"../utils\"\nimport type { GasLayerOptions } from \"./types\"\n\nconst vertexShader = (): string => {\n  return `\n    varying vec3 vUv; \n\n    void main() {\n      vUv = position; \n\n      vec4 modelViewPosition = modelViewMatrix * vec4(position, 1.0);\n      gl_Position = projectionMatrix * modelViewPosition; \n    }\n  `\n}\n\nconst fragmentShader = (): string => {\n  return `\n        varying vec3 vUv;\n        float pixels = 100.0;\n        uniform float cloud_cover;\n        uniform vec2 light_origin;\n        uniform float time_speed;\n        uniform float stretch;\n        uniform float cloud_curve;\n        float light_border_1 = 0.4;\n        float light_border_2 = 0.6;\n        uniform float rotation;\n\n        uniform vec4 base_color;\n        uniform vec4 outline_color;\n        uniform vec4 shadow_base_color;\n        uniform vec4 shadow_outline_color;\n\n        float size = 9.0;\n        int OCTAVES = 5;\n        uniform float seed;\n        uniform float time;\n\n\n        float rand(vec2 coord) {\n            coord = mod(coord, vec2(1.0,1.0)*floor(size+0.5));\n            return fract(sin(dot(coord.xy ,vec2(12.9898,78.233))) * 15.5453 * seed);\n        }\n\n        float noise(vec2 coord){\n            vec2 i = floor(coord);\n            vec2 f = fract(coord);\n            \n            float a = rand(i);\n            float b = rand(i + vec2(1.0, 0.0));\n            float c = rand(i + vec2(0.0, 1.0));\n            float d = rand(i + vec2(1.0, 1.0));\n        \n            vec2 cubic = f * f * (3.0 - 2.0 * f);\n        \n            return mix(a, b, cubic.x) + (c - a) * cubic.y * (1.0 - cubic.x) + (d - b) * cubic.x * cubic.y;\n        }\n\n        float circleNoise(vec2 uv) {\n            float uv_y = floor(uv.y);\n            uv.x += uv_y*.31;\n            vec2 f = fract(uv);\n            float h = rand(vec2(floor(uv.x),floor(uv_y)));\n            float m = (length(f-0.25-(h*0.5)));\n            float r = h*0.25;\n            return smoothstep(0.0, r, m*0.75);\n        }\n\n        float fbm(vec2 coord){\n            float value = 0.0;\n            float scale = 0.5;\n        \n            for(int i = 0; i < OCTAVES ; i++){\n                value += noise(coord) * scale;\n                coord *= 2.0;\n                scale *= 0.5;\n            }\n            return value;\n        }\n\n        float cloud_alpha(vec2 uv) {\n            float c_noise = 0.0;\n            \n            // more iterations for more turbulence\n            for (int i = 0; i < 9; i++) {\n                c_noise += circleNoise((uv * size * 0.3) + (float(i+1)+10.) + (vec2(time*time_speed, 0.0)));\n            }\n            float fbm = fbm(uv*size+c_noise + vec2(time*time_speed, 0.0));\n            \n            return fbm;\n        }\n        \n        vec2 spherify(vec2 uv) {\n            vec2 centered= uv *2.0-1.0;\n            float z = sqrt(1.0 - dot(centered.xy, centered.xy));\n            vec2 sphere = centered/(z + 1.0);\n            return sphere * 0.5+0.5;\n        }\n        \n        vec2 rotate(vec2 coord, float angle){\n            coord -= 0.5;\n            coord *= mat2(vec2(cos(angle),-sin(angle)),vec2(sin(angle),cos(angle)));\n            return coord + 0.5;\n        }\n\n        void main() {\n            // pixelize uv\n            vec2 uv = (floor(vUv.xy*pixels)/pixels) + 0.5;\n            \n            // distance to light source\n            float d_light = distance(uv , light_origin);\n            \n            // cut out a circle\n            float d_circle = distance(uv, vec2(0.5));\n            // stepping over 0.5 instead of 0.49999 makes some pixels a little buggy\n            float a = step(d_circle, 0.49999);\n            \n            uv = rotate(uv, rotation);\n            \n            // map to sphere\n            uv = spherify(uv);\n            \n            // slightly make uv go down on the right, and up in the left\n            uv.y += smoothstep(0.0, cloud_curve, abs(uv.x-0.4));\n            \n            float c = cloud_alpha(uv*vec2(1.0, stretch));\n            \n            // assign some colors based on cloud depth & distance from light\n            vec4 col = base_color;\n            if (c < cloud_cover + 0.03) {\n                col = outline_color;\n            }\n            if (d_light + c*0.2 > light_border_1) {\n                col = shadow_base_color;\n        \n            }\n            if (d_light + c*0.2 > light_border_2) {\n                col = shadow_outline_color;\n            }\n            gl_FragColor = vec4(col.rgb, step(cloud_cover, c) * a * col.a);\n            if (gl_FragColor.a < 0.01) discard;\n        }\n    `\n}\n\nexport function createGasPLayer(options: GasLayerOptions = {}): Mesh {\n  const {\n    lightPos = new Vector2(0.39, 0.7),\n    cloudCover = 0.538,\n    colors = null,\n    stretch = 1.0,\n    rotationSpeed = 0.1,\n    rotation = 0.0,\n    cloudCurve = 1.3,\n  } = options\n  const colorPalette = colors\n    ? colors\n    : [\n        new Vector4(0.231373, 0.12549, 0.152941, 1),\n        new Vector4(0.231373, 0.12549, 0.152941, 1),\n        new Vector4(0.129412, 0.0941176, 0.105882, 1),\n        new Vector4(0.129412, 0.0941176, 0.105882, 1),\n      ]\n  const planetGeometryGas = new PlaneGeometry(1, 1)\n  const planetMaterialGas = new ShaderMaterial({\n    uniforms: {\n      base_color: { value: colorPalette[0] },\n      outline_color: { value: colorPalette[1] },\n      shadow_base_color: { value: colorPalette[2] },\n      shadow_outline_color: { value: colorPalette[3] },\n      cloud_cover: { value: cloudCover },\n      stretch: { value: stretch },\n      cloud_curve: { value: cloudCurve },\n      time_speed: { value: rotationSpeed },\n      rotation: { value: rotation },\n      light_origin: { value: lightPos },\n      seed: { value: flip() ? Math.random() * 10 : Math.random() * 100 },\n      time: { value: 0.0 },\n    },\n    vertexShader: vertexShader(),\n    fragmentShader: fragmentShader(),\n    transparent: true,\n  })\n\n  const gasGiantGas = new Mesh(planetGeometryGas, planetMaterialGas)\n\n  return gasGiantGas\n}\n",
      "type": "registry:lib"
    },
    {
      "path": "src/registry/new-york/items/pixel-planet/lib/Layers/highlightBorder.ts",
      "content": "import {\n  Mesh,\n  MeshBasicMaterial,\n  NearestFilter,\n  PlaneGeometry,\n  TextureLoader,\n} from \"three\"\n\nexport const Border = (): Mesh => {\n  const texture = new TextureLoader().load(\"/pixel-planet/Images/highlight.png\")\n  texture.magFilter = NearestFilter\n  texture.minFilter = NearestFilter\n  const planetGeometry = new PlaneGeometry(1, 1)\n  const material = new MeshBasicMaterial({\n    map: texture,\n    transparent: true,\n  })\n  const mesh = new Mesh(planetGeometry, material)\n  return mesh\n}\n",
      "type": "registry:lib"
    },
    {
      "path": "src/registry/new-york/items/pixel-planet/lib/Layers/lakeLayer.ts",
      "content": "import { Mesh, PlaneGeometry, ShaderMaterial, Vector2, Vector4 } from \"three\"\nimport { flip } from \"../utils\"\nimport type { LakeLayerOptions } from \"./types\"\n\nconst vertexShader = (): string => {\n  return `\n    varying vec3 vUv; \n\n    void main() {\n      vUv = position; \n\n      vec4 modelViewPosition = modelViewMatrix * vec4(position, 1.0);\n      gl_Position = projectionMatrix * modelViewPosition; \n    }\n  `\n}\n\nconst fragmentShaderLakes = (): string => {\n  return `\n        varying vec3 vUv;\n        uniform float lightIntensity;\n        uniform float pixels;\n        uniform float rotation;\n        uniform vec2 light_origin;\n        uniform float time_speed;\n        float light_border_1 = 0.4;\n        float light_border_2 = 0.6;\n        uniform float lake_cutoff;\n        \n        uniform vec4 color1;\n        uniform vec4 color2;\n        uniform vec4 color3;\n        \n        float size = 10.0;\n        int OCTAVES = 4;\n        uniform float seed;\n        uniform float time;\n        \n        float rand(vec2 coord) {\n            coord = mod(coord, vec2(2.0,1.0)*floor(size+0.5));\n            return fract(sin(dot(coord.xy ,vec2(12.9898,78.233))) * 15.5453 * seed);\n        }\n        \n        float noise(vec2 coord){\n            vec2 i = floor(coord);\n            vec2 f = fract(coord);\n                \n            float a = rand(i);\n            float b = rand(i + vec2(1.0, 0.0));\n            float c = rand(i + vec2(0.0, 1.0));\n            float d = rand(i + vec2(1.0, 1.0));\n        \n            vec2 cubic = f * f * (3.0 - 2.0 * f);\n        \n            return mix(a, b, cubic.x) + (c - a) * cubic.y * (1.0 - cubic.x) + (d - b) * cubic.x * cubic.y;\n        }\n        \n        float fbm(vec2 coord){\n            float value = 0.0;\n            float scale = 0.5;\n        \n            for(int i = 0; i < OCTAVES ; i++){\n                value += noise(coord) * scale;\n                coord *= 2.0;\n                scale *= 0.5;\n            }\n            return value;\n        }\n        \n        bool dither(vec2 uv1, vec2 uv2) {\n            return mod(uv1.x+uv2.y,2.0/pixels) <= 1.0 / pixels;\n        }\n        \n        vec2 rotate(vec2 coord, float angle){\n            coord -= 0.5;\n            coord *= mat2(vec2(cos(angle),-sin(angle)),vec2(sin(angle),cos(angle)));\n            return coord + 0.5;\n        }\n        \n        vec2 spherify(vec2 uv) {\n            vec2 centered= uv *2.0-1.0;\n            float z = sqrt(1.0 - dot(centered.xy, centered.xy));\n            vec2 sphere = centered/(z + 1.0);\n            return sphere * 0.5+0.5;\n        }\n        \n                void main() {\n            // pixelize uv\n            vec2 uv = (floor(vUv.xy*pixels)/pixels) + 0.5;\n            \n            float d_light = distance(uv , vec2(light_origin));\n            \n            // give planet a tilt\n            uv = rotate(uv, rotation);\n        \n            // map to sphere\n            uv = spherify(uv);\n            \n            // some scrolling noise for landmasses\n            float lake = fbm(uv*size+vec2(time*time_speed,0.0));\n        \n            vec4 col = color1;\n            if (d_light > light_border_1) {\n                col = color2;\n            }\n            if (d_light > light_border_2) {\n                col = color3;\n            }\n            \n            float a = step(lake_cutoff, lake);\n            a *= step(distance(vec2(0.5), uv), 0.5);\n            gl_FragColor = vec4(col.rgb, a * col.a);\n            if (gl_FragColor.a < 0.01) discard;\n        }\n    `\n}\n\nexport function createLakeLayer(options: LakeLayerOptions = {}): Mesh {\n  const {\n    lightPos = new Vector2(0.39, 0.7),\n    rotationSpeed = 0.1,\n    waterLevel = 0.6,\n    colors = null,\n    rotation = 0.0,\n  } = options\n  const colorPalette = colors\n    ? colors\n    : [\n        new Vector4(79 / 255, 164 / 255, 184 / 255, 1),\n        new Vector4(76 / 255, 104 / 255, 133 / 255, 1),\n        new Vector4(58 / 255, 63 / 255, 94 / 255, 1),\n      ]\n  const planetGeometryLakes = new PlaneGeometry(1, 1)\n  const planetMaterialLakes = new ShaderMaterial({\n    uniforms: {\n      pixels: { value: 100.0 },\n      light_origin: { value: lightPos },\n      seed: { value: flip() ? Math.random() * 10 : Math.random() * 100 },\n      time_speed: { value: rotationSpeed },\n      lake_cutoff: { value: waterLevel },\n      rotation: { value: rotation },\n      color1: { value: colorPalette[0] },\n      color2: { value: colorPalette[1] },\n      color3: { value: colorPalette[2] },\n      time: { value: 0.0 },\n    },\n    vertexShader: vertexShader(),\n    fragmentShader: fragmentShaderLakes(),\n    transparent: true,\n  })\n\n  const lakeLayer = new Mesh(planetGeometryLakes, planetMaterialLakes)\n\n  return lakeLayer\n}\n",
      "type": "registry:lib"
    },
    {
      "path": "src/registry/new-york/items/pixel-planet/lib/Layers/landMass.ts",
      "content": "import { Mesh, PlaneGeometry, ShaderMaterial, Vector2, Vector4 } from \"three\"\nimport { flip } from \"../utils\"\nimport type { LandMassLayerOptions } from \"./types\"\n\nconst vertexShader = (): string => {\n  return `\n    varying vec3 vUv; \n\n    void main() {\n      vUv = position; \n\n      vec4 modelViewPosition = modelViewMatrix * vec4(position, 1.0);\n      gl_Position = projectionMatrix * modelViewPosition; \n    }\n  `\n}\n\nconst fragmentShaderPlanet = (): string => {\n  return `\n        varying vec3 vUv;\n        uniform float lightIntensity;\n        uniform float pixels;\n        uniform float rotation;\n        uniform vec2 light_origin;\n        uniform float time_speed;\n        uniform float manual_offset;\n        uniform float land_cutoff;\n        float dither_size = 2.0;\n        float light_border_1 = 0.4;\n        float light_border_2 = 0.6;\n        uniform vec4 col1;\n        uniform vec4 col2;\n        uniform vec4 col3;\n        uniform vec4 col4;\n        float size = 10.0;\n        int OCTAVES = 6;\n        uniform float seed;\n        uniform float time;\n\n        float rand(vec2 coord) {\n            coord = mod(coord, vec2(1.0,1.0)*floor(size+0.5));\n            return fract(sin(dot(coord.xy ,vec2(12.9898,78.233))) * 15.5453 * seed);\n        }\n\n        float noise(vec2 coord){\n            vec2 i = floor(coord);\n            vec2 f = fract(coord);\n            \n            float a = rand(i);\n            float b = rand(i + vec2(1.0, 0.0));\n            float c = rand(i + vec2(0.0, 1.0));\n            float d = rand(i + vec2(1.0, 1.0));\n        \n            vec2 cubic = f * f * (3.0 - 2.0 * f);\n        \n            return mix(a, b, cubic.x) + (c - a) * cubic.y * (1.0 - cubic.x) + (d - b) * cubic.x * cubic.y;\n        }\n\n        float fbm(vec2 coord){\n            float value = 0.0;\n            float scale = 0.5;\n        \n            for(int i = 0; i < OCTAVES ; i++){\n                value += noise(coord) * scale;\n                coord *= 2.0;\n                scale *= 0.5;\n            }\n            return value;\n        }\n\n        vec2 spherify(vec2 uv) {\n            vec2 centered= uv *2.0-1.0;\n            float z = sqrt(1.0 - dot(centered.xy, centered.xy));\n            vec2 sphere = centered/(z + 1.0);\n            return sphere * 0.5+0.5;\n        }\n        \n        vec2 rotate(vec2 coord, float angle){\n            coord -= 0.5;\n            coord *= mat2(vec2(cos(angle),-sin(angle)),vec2(sin(angle),cos(angle)));\n            return coord + 0.5;\n        }\n\n        void main() {\n            vec2 uv = (floor(vUv.xy*pixels)/pixels) + 0.5;\n\t\n            float d_light = distance(uv , light_origin);\n            // cut out a circle\n            float d_circle = distance(uv, vec2(0.5));\n            // stepping over 0.5 instead of 0.49999 makes some pixels a little buggy\n            float a = step(d_circle, 0.49999);\n            \n            // give planet a tilt\n            uv = rotate(uv, rotation);\n            \n            // map to sphere\n            uv = spherify(uv);\n            \n            // some scrolling noise for landmasses\n            vec2 base_fbm_uv = (uv)*size+vec2(time*time_speed+manual_offset,0.0);\n            \n            // use multiple fbm's at different places so we can determine what color land gets\n            float fbm1 = fbm(base_fbm_uv);\n            float fbm2 = fbm(base_fbm_uv - light_origin*fbm1);\n            float fbm3 = fbm(base_fbm_uv - light_origin*1.5*fbm1);\n            float fbm4 = fbm(base_fbm_uv - light_origin*2.0*fbm1);\n            \n            // lots of magic numbers here\n            // you can mess with them, it changes the color distribution\n            if (d_light < light_border_1) {\n                fbm4 *= 0.9;\n            }\n            if (d_light > light_border_1) {\n                fbm2 *= 1.05;\n                fbm3 *= 1.05;\n                fbm4 *= 1.05;\n            } \n            if (d_light > light_border_2) {\n                fbm2 *= 1.3;\n                fbm3 *= 1.4;\n                fbm4 *= 1.8;\n            } \n            \n            // increase contrast on d_light\n            d_light = pow(d_light, 2.0)*0.1;\n            vec4 col = col4;\n            // assign colors based on if there is noise to the top-left of noise\n            // and also based on how far noise is from light\n            if (fbm4 + d_light < fbm1) {\n                col = col3;\n            }\n            if (fbm3 + d_light < fbm1) {\n                col = col2;\n            }\n            if (fbm2 + d_light < fbm1) {\n                col = col1;\n            }\n            \n            gl_FragColor = vec4(col.rgb, step(land_cutoff, fbm1) * a * col.a);\n            if (gl_FragColor.a < 0.01) discard;\n        }\n    `\n}\n\nexport function createlandMassLayer(options: LandMassLayerOptions = {}): Mesh {\n  const {\n    lightPos = new Vector2(0.39, 0.7),\n    lightIntensity = 0.1,\n    colors = null,\n    rotationSpeed = 0.1,\n    rotation = 0.0,\n    land = 0.6,\n    manualOffset = 0.0,\n  } = options\n  const colorPalette = colors\n    ? colors\n    : [\n        new Vector4(0.784314, 0.831373, 0.364706, 1),\n        new Vector4(0.388235, 0.670588, 0.247059, 1),\n        new Vector4(0.184314, 0.341176, 0.32549, 1),\n        new Vector4(0.156863, 0.207843, 0.25098, 1),\n      ]\n  const planetGeometry = new PlaneGeometry(1, 1)\n  const planetMaterial = new ShaderMaterial({\n    uniforms: {\n      pixels: { value: 100.0 },\n      land_cutoff: { value: land },\n      col1: { value: colorPalette[0] },\n      col2: { value: colorPalette[1] },\n      col3: { value: colorPalette[2] },\n      col4: { value: colorPalette[3] },\n      lightIntensity: { value: lightIntensity },\n      light_origin: { value: lightPos },\n      time_speed: { value: rotationSpeed },\n      manual_offset: { value: manualOffset },\n      rotation: { value: rotation },\n      seed: { value: flip() ? Math.random() * 10 : Math.random() * 100 },\n      time: { value: 0.0 },\n    },\n    vertexShader: vertexShader(),\n    fragmentShader: fragmentShaderPlanet(),\n    transparent: true,\n  })\n\n  const landMassLayer = new Mesh(planetGeometry, planetMaterial)\n\n  return landMassLayer\n}\n",
      "type": "registry:lib"
    },
    {
      "path": "src/registry/new-york/items/pixel-planet/lib/Layers/ringLayer.ts",
      "content": "import {\n  Mesh,\n  NearestFilter,\n  PlaneGeometry,\n  ShaderMaterial,\n  TextureLoader,\n  Vector2,\n} from \"three\"\nimport { flip } from \"../utils\"\nimport type { RingLayerOptions } from \"./types\"\n\nconst vertexShader = (): string => {\n  return `\n    varying vec3 vUv; \n\n    void main() {\n      vUv = position; \n\n      vec4 modelViewPosition = modelViewMatrix * vec4(position, 1.0);\n      gl_Position = projectionMatrix * modelViewPosition; \n    }\n  `\n}\n\nconst fragmentShader = (): string => {\n  return `\n        varying vec3 vUv;\n        uniform float pixels;\n        uniform float rotation;\n        uniform vec2 light_origin;\n        uniform float time_speed;\n        float light_border_1 = 0.4;\n        float light_border_2 = 0.6;\n        uniform float ring_width;\n        uniform float ring_perspective;\n        uniform float scale_rel_to_planet;\n        \n        uniform sampler2D colorscheme;\n        uniform sampler2D dark_colorscheme;\n        \n        float size = 25.0;\n        int OCTAVES = 8;\n        uniform float seed;\n        uniform float time;\n\n        float rand(vec2 coord) {\n            coord = mod(coord, vec2(2.0,1.0)*floor(size+0.5));\n            return fract(sin(dot(coord.xy ,vec2(12.9898,78.233))) * 15.5453 * seed);\n        }\n        \n        float noise(vec2 coord){\n            vec2 i = floor(coord);\n            vec2 f = fract(coord);\n            \n            float a = rand(i);\n            float b = rand(i + vec2(1.0, 0.0));\n            float c = rand(i + vec2(0.0, 1.0));\n            float d = rand(i + vec2(1.0, 1.0));\n        \n            vec2 cubic = f * f * (3.0 - 2.0 * f);\n        \n            return mix(a, b, cubic.x) + (c - a) * cubic.y * (1.0 - cubic.x) + (d - b) * cubic.x * cubic.y;\n        }\n        \n        float fbm(vec2 coord){\n            float value = 0.0;\n            float scale = 0.5;\n        \n            for(int i = 0; i < OCTAVES ; i++){\n                value += noise(coord) * scale;\n                coord *= 2.0;\n                scale *= 0.5;\n            }\n            return value;\n        }\n        \n        float circleNoise(vec2 uv) {\n            float uv_y = floor(uv.y);\n            uv.x += uv_y*.31;\n            vec2 f = fract(uv);\n            float h = rand(vec2(floor(uv.x),floor(uv_y)));\n            float m = (length(f-0.25-(h*0.5)));\n            float r = h*0.25;\n            return smoothstep(0.0, r, m*0.75);\n        }\n        \n        vec2 spherify(vec2 uv) {\n            vec2 centered= uv *2.0-1.0;\n            float z = sqrt(1.0 - dot(centered.xy, centered.xy));\n            vec2 sphere = centered/(z + 1.0);\n            return sphere * 0.5+0.5;\n        }\n        \n        vec2 rotate(vec2 coord, float angle){\n            coord -= 0.5;\n            coord *= mat2(vec2(cos(angle),-sin(angle)),vec2(sin(angle),cos(angle)));\n            return coord + 0.5;\n        }\n\n        void main() {\n            // pixelize uv\n            vec2 uv = (floor(vUv.xy*pixels)/pixels) + 0.5;\n            \n            float light_d = distance(uv, light_origin);\n            uv = rotate(uv, rotation);\n            \n            // center is used to determine ring position\n            vec2 uv_center = uv - vec2(0.0, 0.5);\n            \n            // tilt ring\n            uv_center *= vec2(1.0, ring_perspective);\n            float center_d = distance(uv_center,vec2(0.5, 0.0));\n            \n            \n            // cut out 2 circles of different sizes and only intersection of the 2.\n            float ring = smoothstep(0.5-ring_width*2.0, 0.5-ring_width, center_d);\n            ring *= smoothstep(center_d-ring_width, center_d, 0.4);\n            \n            // pretend like the ring goes behind the planet by removing it if it's in the upper half.\n            if (uv.y < 0.5) {\n                ring *= step(1.0/scale_rel_to_planet, distance(uv,vec2(0.5)));\n            }\n            \n            // rotate material in the ring\n            uv_center = rotate(uv_center+vec2(0, 0.5), time*time_speed);\n            // some noise\n            ring *= fbm(uv_center*size);\n            \n            // apply some colors based on final value\n            float posterized = floor((ring+pow(light_d, 2.0)*2.0)*4.0)/4.0;\n            vec4 col;\n            if (posterized <= 1.0) {\n                col = texture(colorscheme, vec2(posterized, uv.y));\n            } else {\n                col = texture(dark_colorscheme, vec2(posterized-1.0, uv.y));\n            }\n            float ring_a = step(0.28, ring);\n\n            gl_FragColor = vec4(col.rgb, ring_a * col.a);\n            if (gl_FragColor.a < 0.01) discard;\n        }\n    `\n}\n\nexport function createRingLayer(options: RingLayerOptions = {}): Mesh {\n  const {\n    lightPos = new Vector2(0.39, 0.7),\n    rotationSpeed = 0.1,\n    ringWidth = 0.143,\n    perspective = 6.0,\n    scalePlanet = 4.0,\n  } = options\n  const colorSchemeTexture1 = new TextureLoader().load(\n    \"/pixel-planet/colorScheme/colorScheme1.png\",\n  )\n  colorSchemeTexture1.magFilter = NearestFilter\n  colorSchemeTexture1.minFilter = NearestFilter\n\n  const colorSchemeTexture2 = new TextureLoader().load(\n    \"/pixel-planet/colorScheme/colorScheme2.png\",\n  )\n  colorSchemeTexture2.magFilter = NearestFilter\n  colorSchemeTexture2.minFilter = NearestFilter\n\n  const ringGeometry = new PlaneGeometry(1, 1)\n  const ringMaterial = new ShaderMaterial({\n    uniforms: {\n      colorscheme: { value: colorSchemeTexture1 },\n      dark_colorscheme: { value: colorSchemeTexture2 },\n      ring_width: { value: ringWidth },\n      ring_perspective: { value: perspective },\n      scale_rel_to_planet: { value: scalePlanet },\n      pixels: { value: 250.0 },\n      light_origin: { value: lightPos },\n      time_speed: { value: rotationSpeed },\n      rotation: { value: Math.random() },\n      seed: { value: flip() ? Math.random() * 10 : Math.random() * 100 },\n      time: { value: 0.0 },\n    },\n    vertexShader: vertexShader(),\n    fragmentShader: fragmentShader(),\n    transparent: true,\n  })\n\n  const ringLayer = new Mesh(ringGeometry, ringMaterial)\n\n  return ringLayer\n}\n",
      "type": "registry:lib"
    },
    {
      "path": "src/registry/new-york/items/pixel-planet/lib/Layers/riversLayer.ts",
      "content": "import { Mesh, PlaneGeometry, ShaderMaterial, Vector2, Vector4 } from \"three\"\nimport { flip } from \"../utils\"\nimport type { RiverLayerOptions } from \"./types\"\n\nconst vertexShader = (): string => {\n  return `\n    varying vec3 vUv; \n\n    void main() {\n      vUv = position; \n\n      vec4 modelViewPosition = modelViewMatrix * vec4(position, 1.0);\n      gl_Position = projectionMatrix * modelViewPosition; \n    }\n  `\n}\n\nconst fragmentShaderRivers = (): string => {\n  return `\n        varying vec3 vUv;\n        float pixels = 100.0;\n        uniform float rotation;\n        uniform vec2 light_origin;\n        uniform float time_speed;\n        float light_border_1 = 0.4;\n        float light_border_2 = 0.6;\n        uniform float river_cutoff;\n        \n        uniform vec4 color1;\n        uniform vec4 color2;\n        uniform vec4 color3;\n        \n        float size = 10.0;\n        int OCTAVES = 5;\n        uniform float seed;\n        uniform float time;\n        \n        float rand(vec2 coord) {\n            coord = mod(coord, vec2(2.0,1.0)*floor(size+0.5));\n            return fract(sin(dot(coord.xy ,vec2(12.9898,78.233))) * 15.5453 * seed);\n        }\n        \n        float noise(vec2 coord){\n            vec2 i = floor(coord);\n            vec2 f = fract(coord);\n                \n            float a = rand(i);\n            float b = rand(i + vec2(1.0, 0.0));\n            float c = rand(i + vec2(0.0, 1.0));\n            float d = rand(i + vec2(1.0, 1.0));\n        \n            vec2 cubic = f * f * (3.0 - 2.0 * f);\n        \n            return mix(a, b, cubic.x) + (c - a) * cubic.y * (1.0 - cubic.x) + (d - b) * cubic.x * cubic.y;\n        }\n        \n        float fbm(vec2 coord){\n            float value = 0.0;\n            float scale = 0.5;\n        \n            for(int i = 0; i < OCTAVES ; i++){\n                value += noise(coord) * scale;\n                coord *= 2.0;\n                scale *= 0.5;\n            }\n            return value;\n        }\n\n        vec2 rotate(vec2 coord, float angle){\n            coord -= 0.5;\n            coord *= mat2(vec2(cos(angle),-sin(angle)),vec2(sin(angle),cos(angle)));\n            return coord + 0.5;\n        }\n        \n        vec2 spherify(vec2 uv) {\n            vec2 centered= uv *2.0-1.0;\n            float z = sqrt(1.0 - dot(centered.xy, centered.xy));\n            vec2 sphere = centered/(z + 1.0);\n            return sphere * 0.5+0.5;\n        }\n\n        void main() {\n            // pixelize uv\n            vec2 uv = (floor(vUv.xy*pixels)/pixels) + 0.5;\n            \n            float d_light = distance(uv , light_origin);\n            \n            // cut out a circle\n            float d_circle = distance(uv, vec2(0.5));\n            // stepping over 0.5 instead of 0.49999 makes some pixels a little buggy\n            float a = step(d_circle, 0.49999);\n            \n            // give planet a tilt\n            uv = rotate(uv, rotation);\n            \n            // map to sphere\n            uv = spherify(uv);\n            \n            // some scrolling noise for landmasses\n            float fbm1 = fbm(uv*size+vec2(time*time_speed,0.0));\n            float river_fbm = fbm(uv + fbm1*2.5);\n            \n            river_fbm = step(river_cutoff, river_fbm);\n            \n            // apply colors\n            vec4 col = color1;\n            if (d_light > light_border_1) {\n                col = color2;\n            }\n            if (d_light > light_border_2) {\n                col = color3;\n            }\n            \n            a *= step(river_cutoff, river_fbm);\n            gl_FragColor = vec4(col.rgb, a * col.a);\n            if (gl_FragColor.a < 0.01) discard;\n        }\n    `\n}\n\nexport function createRiverLayer(options: RiverLayerOptions = {}): Mesh {\n  const {\n    lightPos = new Vector2(0.39, 0.7),\n    rotationSpeed = 0.1,\n    rivers = 0.6,\n    colors,\n    rotation = 0.0,\n  } = options\n  const colorPalette = colors\n    ? colors\n    : [\n        new Vector4(79 / 255, 164 / 255, 184 / 255, 1),\n        new Vector4(76 / 255, 104 / 255, 133 / 255, 1),\n        new Vector4(58 / 255, 63 / 255, 94 / 255, 1),\n      ]\n  const planetGeometryRivers = new PlaneGeometry(1, 1)\n  const planetMaterialRivers = new ShaderMaterial({\n    uniforms: {\n      light_origin: { value: lightPos },\n      seed: { value: flip() ? Math.random() * 10 : Math.random() * 100 },\n      time_speed: { value: rotationSpeed },\n      river_cutoff: { value: rivers },\n      rotation: { value: rotation },\n      color1: { value: colorPalette[0] },\n      color2: { value: colorPalette[1] },\n      color3: { value: colorPalette[2] },\n      time: { value: 0.0 },\n    },\n    vertexShader: vertexShader(),\n    fragmentShader: fragmentShaderRivers(),\n    transparent: true,\n  })\n\n  const riverLayer = new Mesh(planetGeometryRivers, planetMaterialRivers)\n\n  return riverLayer\n}\n",
      "type": "registry:lib"
    },
    {
      "path": "src/registry/new-york/items/pixel-planet/lib/Layers/star.ts",
      "content": "import {\n  Mesh,\n  NearestFilter,\n  PlaneGeometry,\n  ShaderMaterial,\n  TextureLoader,\n  Vector2,\n} from \"three\"\nimport { flip } from \"../utils\"\nimport type { StarLayerOptions } from \"./types\"\n\nconst vertexShader = (): string => {\n  return `\n    varying vec3 vUv; \n\n    void main() {\n      vUv = position; \n\n      vec4 modelViewPosition = modelViewMatrix * vec4(position, 1.0);\n      gl_Position = projectionMatrix * modelViewPosition; \n    }\n  `\n}\n\nconst fragmentShaderPlanet = (): string => {\n  return `\n        varying vec3 vUv;\n        uniform float pixels;\n        uniform float time_speed;\n        uniform float time;\n        uniform float rotation;\n        uniform sampler2D colorramp;\n        bool should_dither = true;\n\n        uniform float seed;\n        float size = 15.0;\n        int OCTAVES = 5;\n        float TILES = 2.0;\n\n\n        float rand(vec2 co) {\n            co = mod(co, vec2(1.0,1.0)*floor(size+0.5));\n            return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 15.5453 * seed);\n        }\n        \n        vec2 rotate(vec2 vec, float angle) {\n            vec -=vec2(0.5);\n            vec *= mat2(vec2(cos(angle),-sin(angle)), vec2(sin(angle),cos(angle)));\n            vec += vec2(0.5);\n            return vec;\n        }\n        \n        float noise(vec2 coord){\n            vec2 i = floor(coord);\n            vec2 f = fract(coord);\n                \n            float a = rand(i);\n            float b = rand(i + vec2(1.0, 0.0));\n            float c = rand(i + vec2(0.0, 1.0));\n            float d = rand(i + vec2(1.0, 1.0));\n        \n            vec2 cubic = f * f * (3.0 - 2.0 * f);\n        \n            return mix(a, b, cubic.x) + (c - a) * cubic.y * (1.0 - cubic.x) + (d - b) * cubic.x * cubic.y;\n        }\n        \n        vec2 Hash2(vec2 p) {\n            float r = 523.0*sin(dot(p, vec2(53.3158, 43.6143)));\n            return vec2(fract(15.32354 * r), fract(17.25865 * r));\n            \n        }\n        \n        float cells(in vec2 p, in float numCells) {\n            p *= numCells;\n            float d = 1.0e10;\n            for (int xo = -1; xo <= 1; xo++)\n            {\n                for (int yo = -1; yo <= 1; yo++)\n                {\n                    vec2 tp = floor(p) + vec2(float(xo), float(yo));\n                    tp = p - tp - Hash2(mod(tp, numCells / TILES));\n                    d = min(d, dot(tp, tp));\n                }\n            }\n            return sqrt(d);\n        }\n        \n        bool dither(vec2 uv1, vec2 uv2) {\n            return mod(uv1.x+uv2.y,2.0/pixels) <= 1.0 / pixels;\n        }\n        \n        vec2 spherify(vec2 uv) {\n            vec2 centered= uv *2.0-1.0;\n            float z = sqrt(1.0 - dot(centered.xy, centered.xy));\n            vec2 sphere = centered/(z + 1.0);\n            return sphere * 0.5+0.5;\n        }\n        \n\n        void main() {\n            vec2 pixelized = (floor(vUv.xy*pixels)/pixels) + 0.5;\n\t\n            // cut out a circle\n            // stepping over 0.5 instead of 0.49999 makes some pixels a little buggy\n            float a = step(distance(pixelized, vec2(0.5)), .49999);\n            \n            // use dither val later to mix between colors\n            bool dith = dither(vUv.xy, pixelized);\n            \n            pixelized = rotate(pixelized, rotation);\n            \n            // spherify has to go after dither\n            pixelized = spherify(pixelized);\n            \n            // use two different sized cells for some variation\n            float n = cells(pixelized - vec2(time * time_speed * 2.0, 0), 10.0);\n            n *= cells(pixelized - vec2(time * time_speed * 1.0, 0), 20.0);\n        \n            \n            // adjust cell value to get better looking stuff\n            n*= 2.;\n            n = clamp(n, 0.0, 1.0);\n            if (dith || !should_dither) { // here we dither\n                n *= 1.3;\n            }\n            \n            // constrain values 4 possibilities and then choose color based on those\n            float interpolate = floor(n * 3.0) / 3.0;\n            vec4 col = texture(colorramp, vec2(interpolate, 0.0));\n            \n            gl_FragColor = vec4(col.rgb, a * col.a);\n            if (gl_FragColor.a < 0.01) discard;\n        }\n    `\n}\n\nexport function createStar(options: StarLayerOptions = {}): Mesh {\n  const {\n    lightPos = new Vector2(0.39, 0.7),\n    lightIntensity = 0.1,\n    rotationSpeed = 0.01,\n    rotation = 0.0,\n    color = null,\n  } = options\n  const palette = color\n    ? `/pixel-planet/colorScheme/starPalette/${color}Palette.png`\n    : \"/pixel-planet/colorScheme/starPalette/orangePalette.png\"\n  const colorSchemeTexture = new TextureLoader().load(palette)\n  colorSchemeTexture.magFilter = NearestFilter\n  colorSchemeTexture.minFilter = NearestFilter\n\n  const planetGeometry = new PlaneGeometry(1, 1)\n  const planetMaterial = new ShaderMaterial({\n    uniforms: {\n      pixels: { value: 100.0 },\n      colorramp: { value: colorSchemeTexture },\n      lightIntensity: { value: lightIntensity },\n      light_origin: { value: lightPos },\n      time_speed: { value: rotationSpeed },\n      rotation: { value: rotation },\n      seed: { value: flip() ? Math.random() * 10 : Math.random() * 100 },\n      time: { value: 0.0 },\n    },\n    vertexShader: vertexShader(),\n    fragmentShader: fragmentShaderPlanet(),\n    transparent: true,\n  })\n\n  const basePlanet = new Mesh(planetGeometry, planetMaterial)\n\n  return basePlanet\n}\n",
      "type": "registry:lib"
    },
    {
      "path": "src/registry/new-york/items/pixel-planet/lib/Layers/starBlobLayer.ts",
      "content": "import { Mesh, PlaneGeometry, ShaderMaterial, Vector4 } from \"three\"\nimport { flip } from \"../utils\"\nimport type { StarBlobLayerOptions } from \"./types\"\n\nconst vertexShader = (): string => {\n  return `\n    varying vec3 vUv; \n\n    void main() {\n      vUv = position; \n\n      vec4 modelViewPosition = modelViewMatrix * vec4(position, 1.0);\n      gl_Position = projectionMatrix * modelViewPosition; \n    }\n  `\n}\n\nconst fragmentShader = (): string => {\n  return `\n        varying vec3 vUv;\n        uniform float pixels;\n        uniform float time_speed;\n        uniform float time;\n        uniform float rotation;\n        uniform vec4 color;\n        bool should_dither = true;\n\n        uniform float circle_amount;\n        uniform float circle_size;\n        uniform float scale;\n\n        uniform float seed;\n        float size = 4.0;\n        int OCTAVES = 4;\n        float TILES = 1.0;\n\n\n        float rand(vec2 co){\n            co = mod(co, vec2(1.0,1.0)*floor(size+0.5));\n            return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 15.5453 * seed);\n        }\n        \n        \n        vec2 rotate(vec2 vec, float angle) {\n            vec -=vec2(0.5);\n            vec *= mat2(vec2(cos(angle),-sin(angle)), vec2(sin(angle),cos(angle)));\n            vec += vec2(0.5);\n            return vec;\n        }\n        \n        float circle(vec2 uv) {\n            float invert = 1.0 / circle_amount;\n            \n            if (mod(uv.y, invert*2.0) < invert) {\n                uv.x += invert*0.5;\n            }\n            vec2 rand_co = floor(uv*circle_amount)/circle_amount;\n            uv = mod(uv, invert)*circle_amount;\n            \n            float r = rand(rand_co);\n            r = clamp(r, invert, 1.0 - invert);\n            float circle = distance(uv, vec2(r));\n            return smoothstep(circle, circle+0.5, invert * circle_size * rand(rand_co*1.5));\n        }\n        \n        \n        float noise(vec2 coord){\n            vec2 i = floor(coord);\n            vec2 f = fract(coord);\n                \n            float a = rand(i);\n            float b = rand(i + vec2(1.0, 0.0));\n            float c = rand(i + vec2(0.0, 1.0));\n            float d = rand(i + vec2(1.0, 1.0));\n        \n            vec2 cubic = f * f * (3.0 - 2.0 * f);\n        \n            return mix(a, b, cubic.x) + (c - a) * cubic.y * (1.0 - cubic.x) + (d - b) * cubic.x * cubic.y;\n        }\n        \n        float fbm(vec2 coord){\n            float value = 0.0;\n            float scl = 0.5;\n        \n            for(int i = 0; i < OCTAVES ; i++){\n                value += noise(coord) * scl;\n                coord *= 2.0;\n                scl *= 0.5;\n            }\n            return value;\n        }\n        \n        vec2 spherify(vec2 uv) {\n            vec2 centered= uv *2.0-1.0;\n            float z = sqrt(1.0 - dot(centered.xy, centered.xy));\n            vec2 sphere = centered/(z + 1.0);\n            return sphere * 0.5+0.5;\n        }\n        \n\n        void main() {\n            vec2 pixelized = (floor(vUv.xy*pixels)/pixels) + 0.5;\n\t\n            vec2 uv = rotate(pixelized, rotation);\n\n            // angle from centered uv's\n            float angle = atan(uv.x - 0.5, uv.y - 0.5);\n            float d = distance(pixelized, vec2(0.5));\n            \n            \n            float c = 0.0;\n            for(int i = 0; i < 15; i++) {\n                float r = rand(vec2(float(i)));\n                vec2 circleUV = vec2(d, angle);\n                c += circle(circleUV*size -time * time_speed - (1.0/d) * 0.1 + r);\n            }\n            \n            c *= 0.37 - d;\n            c = step(0.07, c - d);\n            \n            gl_FragColor = vec4(color.rgb, c * color.a);\n            if (gl_FragColor.a < 0.01) discard;\n        }\n    `\n}\n\nexport function createStarBlobLayer(options: StarBlobLayerOptions = {}): Mesh {\n  const { rotationSpeed = 0.1, blobColor = null } = options\n  const color = blobColor\n    ? blobColor\n    : new Vector4(255 / 255, 165 / 255, 0 / 255, 1)\n\n  const planetGeometry = new PlaneGeometry(1.3, 1.3)\n  const planetMaterial = new ShaderMaterial({\n    uniforms: {\n      pixels: { value: 200.0 },\n      color: { value: color },\n      time_speed: { value: rotationSpeed },\n      rotation: { value: options.rotation ?? Math.random() },\n      seed: { value: flip() ? Math.random() * 10 : Math.random() * 100 },\n      time: { value: 0.0 },\n      circle_amount: { value: 3.0 },\n      circle_size: { value: 1.5 },\n      scale: { value: 1.0 },\n    },\n    vertexShader: vertexShader(),\n    fragmentShader: fragmentShader(),\n    transparent: true,\n  })\n\n  const basePlanet = new Mesh(planetGeometry, planetMaterial)\n\n  return basePlanet\n}\n",
      "type": "registry:lib"
    },
    {
      "path": "src/registry/new-york/items/pixel-planet/lib/Layers/starFlareLayer.ts",
      "content": "import {\n  Mesh,\n  NearestFilter,\n  PlaneGeometry,\n  ShaderMaterial,\n  TextureLoader,\n} from \"three\"\nimport { flip } from \"../utils\"\nimport type { StarFlareLayerOptions } from \"./types\"\n\nconst vertexShader = (): string => {\n  return `\n    varying vec3 vUv; \n\n    void main() {\n      vUv = position; \n\n      vec4 modelViewPosition = modelViewMatrix * vec4(position, 1.0);\n      gl_Position = projectionMatrix * modelViewPosition; \n    }\n  `\n}\n\nconst fragmentShader = (): string => {\n  return `\n        varying vec3 vUv;\n        uniform float pixels;\n        uniform float time_speed;\n        uniform float time;\n        uniform float rotation;\n        uniform sampler2D colorramp;\n        bool should_dither = true;\n\n        uniform float storm_width;\n        uniform float storm_dither_width;\n        uniform float circle_amount;\n        uniform float circle_scale;\n        uniform float scale;\n\n        uniform float seed;\n        float size = 2.0;\n        int OCTAVES = 4;\n        float TILES = 1.0;\n\n\n        float rand(vec2 co){\n            co = mod(co, vec2(1.0,1.0)*floor(size+0.5));\n            return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 15.5453 * seed);\n        }\n        \n        \n        vec2 rotate(vec2 vec, float angle) {\n            vec -=vec2(0.5);\n            vec *= mat2(vec2(cos(angle),-sin(angle)), vec2(sin(angle),cos(angle)));\n            vec += vec2(0.5);\n            return vec;\n        }\n        \n        float circle(vec2 uv) {\n            float invert = 1.0 / circle_amount;\n            \n            if (mod(uv.y, invert*2.0) < invert) {\n                uv.x += invert*0.5;\n            }\n            vec2 rand_co = floor(uv*circle_amount)/circle_amount;\n            uv = mod(uv, invert)*circle_amount;\n            \n            float r = rand(rand_co);\n            r = clamp(r, invert, 1.0 - invert);\n            float circle = distance(uv, vec2(r));\n            return smoothstep(circle, circle+0.5, invert * circle_scale * rand(rand_co*1.5));\n        }\n        \n        \n        float noise(vec2 coord){\n            vec2 i = floor(coord);\n            vec2 f = fract(coord);\n                \n            float a = rand(i);\n            float b = rand(i + vec2(1.0, 0.0));\n            float c = rand(i + vec2(0.0, 1.0));\n            float d = rand(i + vec2(1.0, 1.0));\n        \n            vec2 cubic = f * f * (3.0 - 2.0 * f);\n        \n            return mix(a, b, cubic.x) + (c - a) * cubic.y * (1.0 - cubic.x) + (d - b) * cubic.x * cubic.y;\n        }\n        \n        float fbm(vec2 coord){\n            float value = 0.0;\n            float scl = 0.5;\n        \n            for(int i = 0; i < OCTAVES ; i++){\n                value += noise(coord) * scl;\n                coord *= 2.0;\n                scl *= 0.5;\n            }\n            return value;\n        }\n        \n        bool dither(vec2 uv1, vec2 uv2) {\n            return mod(uv1.x+uv2.y,2.0/pixels) <= 1.0 / pixels;\n        }\n        \n        vec2 spherify(vec2 uv) {\n            vec2 centered= uv *2.0-1.0;\n            float z = sqrt(1.0 - dot(centered.xy, centered.xy));\n            vec2 sphere = centered/(z + 1.0);\n            return sphere * 0.5+0.5;\n        }\n        \n\n        void main() {\n            vec2 pixelized = (floor(vUv.xy*pixels)/pixels) + 0.5;\n\t\n            bool dith = dither(vUv.xy, pixelized);\n\t\n            pixelized = rotate(pixelized, rotation);\n            \n            // counter rotation against rotation caused by the way uv's are made later\n            vec2 uv = pixelized;//rotate(pixelized, -time  * time_speed);\n            \n            // angle from centered uv's\n            float angle = atan(uv.x - 0.5, uv.y - 0.5) * 0.4;\n            // distance from center\n            float d = distance(pixelized, vec2(0.5));\n            \n            // we make uv circular here to have eternally outward moving stuff\n            vec2 circleUV = vec2(d, angle);\n            \n            // two types of noise values\n            float n = fbm(circleUV*size -time * time_speed);\n            float nc = circle(circleUV*scale -time * time_speed + n);\n            \n            nc *= 1.5;\n            float n2 = fbm(circleUV*size -time + vec2(100, 100));\n            nc -= n2 * 0.1;\n            \n            // our alpha, default 0\n            float a = 0.0;\n            if (1.0 - d > nc) {\n                // now we generate very thin strips of positive alpha if our noise has certain values and is close enough to center\n                if (nc > storm_width - storm_dither_width + d && (dith || !should_dither)) {\n                    a = 1.0;\n                } else if (nc > storm_width + d) { // could use an or statement instead, but this looks more clear to me\n                    a = 1.0;\n                }\n            }\n            \n            // use our two noise values to assign colors\n            float interpolate = floor(n2 + nc);\n            vec4 col = texture(colorramp, vec2(interpolate, 0.0));\n            \n            // final step to not have everything appear from the center\n            a *= step(n2 * 0.25, d);\n            \n            gl_FragColor = vec4(col.rgb, a * col.a);\n            if (gl_FragColor.a < 0.01) discard;\n        }\n    `\n}\n\nexport function createStarFlareLayer(\n  options: StarFlareLayerOptions = {},\n): Mesh {\n  const {\n    rotationSpeed = 0.05,\n    stormWidth = 0.2,\n    stormDitherWidth = 0.07,\n    color = null,\n  } = options\n  const palette = color\n    ? `/pixel-planet/colorScheme/starPalette/${color}Palette.png`\n    : \"/pixel-planet/colorScheme/starPalette/orangePalette.png\"\n  const colorSchemeTexture = new TextureLoader().load(palette)\n  colorSchemeTexture.magFilter = NearestFilter\n  colorSchemeTexture.minFilter = NearestFilter\n\n  const planetGeometry = new PlaneGeometry(1.5, 1.5)\n  const planetMaterial = new ShaderMaterial({\n    uniforms: {\n      pixels: { value: 200.0 },\n      colorramp: { value: colorSchemeTexture },\n      time_speed: { value: rotationSpeed },\n      rotation: { value: options.rotation ?? Math.random() },\n      seed: { value: flip() ? Math.random() * 10 : Math.random() * 100 },\n      time: { value: 0.0 },\n      storm_width: { value: stormWidth },\n      storm_dither_width: { value: stormDitherWidth },\n      circle_amount: { value: 2.0 },\n      circle_scale: { value: 1.0 },\n      scale: { value: 1.0 },\n    },\n    vertexShader: vertexShader(),\n    fragmentShader: fragmentShader(),\n    transparent: true,\n  })\n\n  const basePlanet = new Mesh(planetGeometry, planetMaterial)\n\n  return basePlanet\n}\n",
      "type": "registry:lib"
    },
    {
      "path": "src/registry/new-york/items/pixel-planet/lib/Layers/stars.ts",
      "content": "import {\n  Group,\n  NearestFilter,\n  Sprite,\n  SpriteMaterial,\n  TextureLoader,\n} from \"three\"\nimport { flip, rand, randomPointOnSphere } from \"../utils\"\n\nexport function createStars(count: number): Group {\n  const starGroup = new Group()\n\n  for (let i = 0; i < count; i++) {\n    const isSpecial = flip()\n    let texture\n    if (isSpecial) {\n      texture = new TextureLoader().load(\n        \"/pixel-planet/stars/stars-special.png\",\n      )\n\n      texture.magFilter = NearestFilter\n      texture.minFilter = NearestFilter\n\n      texture.repeat.x = 1 / 6\n      texture.offset.x = (Math.floor(rand(1, 6) % 6) * 25) / 150\n\n      const mat = new SpriteMaterial({\n        map: texture,\n        color: flip() ? \"#ffef9e\" : \"#ffffff\",\n        transparent: true,\n        opacity: rand(0.1, 1),\n      })\n\n      const starObj = new Sprite(mat)\n      starObj.scale.set(0.05, 0.05, 1.0)\n      const position = randomPointOnSphere()\n      starObj.position.z = position.z\n      starObj.position.y = position.y\n      starObj.position.x = position.x\n      starGroup.add(starObj)\n    } else {\n      texture = new TextureLoader().load(\"/pixel-planet/stars/stars.png\")\n\n      texture.magFilter = NearestFilter\n      texture.minFilter = NearestFilter\n\n      texture.repeat.x = 1 / 17\n      texture.offset.x = (Math.floor(rand(1, 17) % 9) * 9) / 144\n\n      const mat = new SpriteMaterial({\n        map: texture,\n        color: flip() ? \"#ffef9e\" : \"#ffffff\",\n        transparent: true,\n        opacity: rand(0.1, 1),\n      })\n\n      const starObj = new Sprite(mat)\n      starObj.scale.set(0.03, 0.03, 1.0)\n      const position = randomPointOnSphere()\n      starObj.position.z = position.z\n      starObj.position.y = position.y\n      starObj.position.x = position.x\n      starGroup.add(starObj)\n    }\n  }\n  return starGroup\n}\n",
      "type": "registry:lib"
    }
  ],
  "type": "registry:component"
}
