[
  {
    "path": ".gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndist-ssr\n*.local\n\n# Editor directories and files\n.vscode/*\n!.vscode/extensions.json\n.idea\n.DS_Store\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n.yarn"
  },
  {
    "path": ".prettierrc",
    "content": "{\n  \"trailingComma\": \"none\",\n  \"tabWidth\": 2,\n  \"semi\": true,\n  \"singleQuote\": false\n}\n"
  },
  {
    "path": ".yarnrc.yml",
    "content": "nodeLinker: node-modules\n"
  },
  {
    "path": "LICENSE.md",
    "content": "MIT License\n\nCopyright (c) 2024 Poimandres\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "<br />\n\n<h1 align=\"center\">react-three-gpu-pathtracer</h1>\n<h3 align=\"center\">⚡️ A React abstraction for the popular <a href=\"https://github.com/gkjohnson/three-gpu-pathtracer\">three-gpu-pathtracer</a></h3>\n\n<br />\n\n<p align=\"center\">\n  <a href=\"https://codesandbox.io/embed/github/pmndrs/react-three-gpu-pathtracer/tree/main/example\" target=\"_blank\"><img  src=\"https://github.com/pmndrs/react-three-gpu-pathtracer/blob/main/assets/hero-screenshot.png?raw=true\"/></a>\n</p>\n<p align=\"middle\">\n  <i>This demo is real, you can click it! It contains full code, too. 📦</i>\n</p>\n<p align=\"middle\">\nGameBoy model by \n<a href=\"https://sketchfab.com/kleingeo\">(@kleingeo)</a>\n<a hef=\"https://sketchfab.com/3d-models/game-boy-classic-0ae80019e6f046168923286d7e628f6f\">\n  on Sketchfab\n</a>\n. GameBoy Cartridge by \n<a href=\"https://sketchfab.com/kleingeo\">(@MeBob)</a>\n<a hef=\"https://sketchfab.com/3d-models/gameboy-cartridge-lowpoly-8b9728eab16c4056ac2636ae7f0f038f\">\n  on Sketchfab\n</a>\n.\n</p>\n\n<br>\n\n<p align=\"center\">\n  <a href=\"https://www.npmjs.com/package/@react-three/gpu-pathtracer\" target=\"_blank\">\n    <img src=\"https://img.shields.io/npm/v/@react-three/gpu-pathtracer.svg?style=flat&colorA=000000&colorB=000000\" />\n  </a>\n  <a href=\"https://www.npmjs.com/package/@react-three/gpu-pathtracer\" target=\"_blank\">\n    <img src=\"https://img.shields.io/npm/dm/@react-three/gpu-pathtracer.svg?style=flat&colorA=000000&colorB=000000\" />\n  </a>\n  <a href=\"https://twitter.com/pmndrs\" target=\"_blank\">\n    <img src=\"https://img.shields.io/twitter/follow/pmndrs?label=%40pmndrs&style=flat&colorA=000000&colorB=000000&logo=twitter&logoColor=000000\" alt=\"Chat on Twitter\">\n  </a>\n  <a href=\"https://discord.gg/ZZjjNvJ\" target=\"_blank\">\n    <img src=\"https://img.shields.io/discord/740090768164651008?style=flat&colorA=000000&colorB=000000&label=discord&logo=discord&logoColor=000000\" alt=\"Chat on Twitter\">\n  </a>\n</p>\n\n<br />\n\n`react-three-gpu-pathtracer` lets you render your `react-three-fiber` scenes using Path Tracing! It is as simple as\n\n```jsx\nimport { Pathtracer } from \"@react-three/gpu-pathtracer\";\n\nfunction GradientSphere() {\n  return (\n    <Canvas>\n      <Pathtracer>{/* Your scene */}</Pathtracer>\n    </Canvas>\n  );\n}\n```\n\nThe `<Pathtracer />` component wraps your scene. The scene is then rendered using Path Tracing.\n\n#### Props\n\n| Prop         | Type                                                                   | Default    | Description                                                                                                          |\n| ------------ | ---------------------------------------------------------------------- | ---------- | -------------------------------------------------------------------------------------------------------------------- |\n| `minSamples` | `number`                                                               | `1`        | Default: 5. Min number of samples before blending the base scene with the pathtraced one.                            |\n| `samples`    | `number`                                                               | `1`        | Max number of samples before the pathtracer stops.                                                                   |\n| `frames`     | `number`                                                               | `Infinity` | Number of frames to path trace. Will pause rendering once this number is reached.                                    |\n| `tiles`      | `[number, number] / THREE.Vector2 / { x: number; y: number } / number` | `2`        | Number of tiles. Can be used to improve the responsiveness of a page while still rendering a high resolution target. |\n| `bounces`    | `number`                                                               | `1`        | The number of ray bounces to test. Higher is better quality but slower performance.                                  |\n| `enabled`    | `boolean`                                                              | `true`     | Wether to enable pathtracing.                                                                                        |\n\n### Env maps\n\nEnv maps can be added using [Drei's `<Environment />`](https://github.com/pmndrs/drei#environment) component just like in a regular scene.\n\n```jsx\n<Pathtracer>\n  <Environment\n    preset=\"...\"\n    background // Optional, set as scene background\n    backgroundBlurriness={0.5}\n    backgroundIntensity={1}\n  />\n</Pathtracer>\n```\n\n### `usePathtracer`\n\nThis hook provides access to useful functions in the internal renderer. Can only be used within the `<Pathtracer />` component.\n\n```ts\nconst { renderer, update, reset } = usePathtracer();\n```\n\n| Return value   | Type              | Description                                                                                 |\n| -------------- | ----------------- | ------------------------------------------------------------------------------------------- |\n| `pathtracer`   | `WebGLPathTracer` | Internal renderer. Can be used to access/edit internal properties                           |\n| ~~`renderer`~~ | `WebGLPathTracer` | DEPRECIATED: use `pathtracer` to not get confused with raster renderer                      |\n| `reset`        | `() => void`      | Flushes the rendered scene and resets the samples count.                                    |\n| `update`       | `() => void`      | Tells the pathtracer that the scene has been updated. Everything is managed internally now. |\n\n### Note on controls\n\nWhen you set controls be sure to use `makeDefault` and it's best to import the `OrbitControls` [from drei](https://drei.docs.pmnd.rs/controls/introduction)\n\n```jsx\n<OrbitControls makeDefault>\n        // ...\n```\n\n### Development\n\n#### Dev\n\n```bash\ncd project-root\nyarn\nyarn dev\n```\n\n#### Build\n\n```bash\nyarn build\n```\n\n#### Publish\n\n```bash\ncd package\nnpm run release\n```\n"
  },
  {
    "path": "example/.codesandbox/tasks.json",
    "content": "{\n  // These tasks will run in order when initializing your CodeSandbox project.\n  \"setupTasks\": [\n    {\n      \"name\": \"Installing Dependencies\",\n      \"command\": \"yarn install\"\n    }\n  ],\n\n  // These tasks can be run from CodeSandbox. Running one will open a log in the app.\n  \"tasks\": {\n    \"dev\": {\n      \"name\": \"dev\",\n      \"command\": \"rm -f vite.config.ts && cp csb.vite.config.js vite.config.ts && yarn add @react-three/gpu-pathtracer && yarn dev\",\n      \"runAtStart\": true,\n      \"preview\": {\n        \"port\": 5173\n      }\n    },\n    \"build\": {\n      \"name\": \"build\",\n      \"command\": \"yarn build\",\n      \"runAtStart\": false\n    },\n    \"preview\": {\n      \"name\": \"preview\",\n      \"command\": \"yarn preview\",\n      \"runAtStart\": false\n    }\n  }\n}\n"
  },
  {
    "path": "example/README.md",
    "content": "<br />\n\n<h3 align=\"center\">react-three-gpu-pathtracer</h3>\n<h3 align=\"center\">⚡️ A React abstraction for the popular <a href=\"https://github.com/gkjohnson/three-gpu-pathtracer\">three-gpu-pathtracer</a></h3>\n\n---\n\n<h3 align=\"center\">Example</h3>\n"
  },
  {
    "path": "example/csb.vite.config.js",
    "content": "import react from '@vitejs/plugin-react'\nimport { defineConfig } from 'vite'\n\n// https://vitejs.dev/config/\nexport default defineConfig({\n  resolve: {\n    plugins: [react()],\n  },\n})\n"
  },
  {
    "path": "example/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link\n      rel=\"icon\"\n      type=\"image/svg+xml\"\n      href=\"data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>⚡️</text></svg>\"\n    />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>@react-three/gpu-pathtracer | Example</title>\n  </head>\n  <body>\n    <div id=\"root\"></div>\n    <script type=\"module\" src=\"/src/main.tsx\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "example/package.json",
    "content": "{\n  \"name\": \"@react-three/gpu-pathtracer-example\",\n  \"private\": true,\n  \"version\": \"0.0.0\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"dev\": \"vite\",\n    \"build\": \"tsc -b && vite build\",\n    \"preview\": \"vite preview\"\n  },\n  \"dependencies\": {\n    \"@pmndrs/branding\": \"^0.0.8\",\n    \"@react-three/drei\": \"^10.3.0\",\n    \"@react-three/fiber\": \"^9.1.2\",\n    \"@react-three/gpu-pathtracer\": \"^0.1.1\",\n    \"leva\": \"^0.9.35\",\n    \"react\": \"^19.1.0\",\n    \"react-dom\": \"^19.1.0\",\n    \"react-icons\": \"^5.3.0\",\n    \"three\": \"^0.169.0\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^22.5.5\",\n    \"@types/react\": \"^18.3.3\",\n    \"@types/react-dom\": \"^18.3.0\",\n    \"@vitejs/plugin-react\": \"^4.3.1\",\n    \"globals\": \"^15.9.0\",\n    \"typescript\": \"^5.5.3\",\n    \"vite\": \"^5.4.1\"\n  }\n}\n"
  },
  {
    "path": "example/src/App.tsx",
    "content": "import {\n  Bounds,\n  Center,\n  Circle,\n  Environment,\n  OrbitControls,\n  PerspectiveCamera,\n  Stats,\n  useTexture\n} from \"@react-three/drei\";\nimport { Canvas, useFrame } from \"@react-three/fiber\";\nimport { Pathtracer, usePathtracer } from \"@react-three/gpu-pathtracer\";\nimport { Leva } from \"leva\";\nimport { useEffect, useRef } from \"react\";\n\nimport Controls from \"./Controls\";\n\nimport { ACESFilmicToneMapping, MathUtils } from \"three\";\nimport Model from \"./Model\";\nimport Tag from \"./Tag\";\n\nconst baseURL = import.meta.env.BASE_URL;\n\nfunction Floor() {\n  const [aoMap, diffMap, norMap, roughMap] = useTexture([\n    baseURL + \"/textures/wood_cabinet_worn_long_ao_2k.jpg\",\n    baseURL + \"/textures/wood_cabinet_worn_long_diff_2k.jpg\",\n    baseURL + \"/textures/wood_cabinet_worn_long_nor_gl_2k.jpg\",\n    baseURL + \"/textures/wood_cabinet_worn_long_rough_2k.jpg\"\n  ]);\n\n  return (\n    <>\n      <Circle args={[4, 128]} position={[0, -1, 0]} rotation-x={-Math.PI / 2}>\n        <meshPhysicalMaterial map={diffMap} aoMap={aoMap} roughness={0.2} />\n      </Circle>\n    </>\n  );\n}\n\nfunction UI({ infoRef }) {\n  const { pathtracer } = usePathtracer();\n  const opts = Controls();\n\n  useFrame(() => {\n    if (pathtracer && infoRef.current) {\n      infoRef.current.children[0].textContent = `Samples: ${Math.ceil(\n        // @ts-ignore\n        pathtracer.samples\n      )}/${opts.Rendering_Samples}`;\n\n      // @ts-ignore\n      infoRef.current.children[1].textContent = pathtracer.isCompiling\n        ? `Initializing...`\n        : \"\";\n    }\n  });\n\n  return null;\n}\n\nfunction Thing() {\n  const { reset, update } = usePathtracer();\n  const opts = Controls();\n\n  // Trigger updates when envmap stuff changes\n  useEffect(() => {\n    update();\n  }, [\n    opts.Environment_Visible,\n    opts.Environment_Preset,\n    opts.Environment_Intensity,\n    opts.Environment_Blur\n  ]);\n\n  return (\n    <>\n      <group rotation-y={MathUtils.degToRad(-180)}>\n        <Bounds fit clip observe margin={1.3}>\n          <Center>\n            <group position={[-1, -1.2, 0]}>\n              <Model rotation-y={Math.PI} position={[-0.3, 0, 0]} scale={15} />\n            </group>\n          </Center>\n        </Bounds>\n        <Floor />\n      </group>\n    </>\n  );\n}\n\nexport default function App() {\n  const infoRef = useRef();\n  const opts = Controls();\n\n  return (\n    <>\n      <Leva\n        collapsed\n        titleBar={{\n          title: \"Options\"\n        }}\n      />\n      <Canvas\n        gl={{\n          toneMapping: ACESFilmicToneMapping\n        }}\n      >\n        <PerspectiveCamera makeDefault position={[4, 2, -1]} fov={40} />\n        <OrbitControls makeDefault />\n\n        <Pathtracer\n          samples={opts.Rendering_Samples}\n          bounces={opts.Rendering_Bounces}\n          resolutionFactor={opts.Rendering_Factor}\n          tiles={[opts.Rendering_Tiles.x, opts.Rendering_Tiles.y]}\n          enabled={opts.Rendering_Enabled}\n        >\n          {opts.Environment_Visible ? (\n            <Environment\n              preset={opts.Environment_Preset as any}\n              // background\n              environmentIntensity={opts.Environment_Intensity}\n              backgroundBlurriness={opts.Environment_Blur}\n            />\n          ) : (\n            <directionalLight intensity={5} position={[5, 5, 5]} />\n          )}\n\n          <Thing />\n          <UI infoRef={infoRef} />\n        </Pathtracer>\n      </Canvas>\n      <Stats />\n      <div className=\"info\" ref={infoRef}>\n        <p>Samples: 0</p>\n        <p>Initializing...</p>\n      </div>\n      <Tag />\n    </>\n  );\n}\n"
  },
  {
    "path": "example/src/Controls.js",
    "content": "import { presetsObj } from \"@react-three/drei/helpers/environment-assets\";\nimport { folder, useControls } from \"leva\";\n\nexport default function Controls() {\n  return useControls({\n    Rendering: folder({\n      Rendering_Factor: {\n        value: 1,\n        max: 1,\n        min: 0,\n        step: 0.01,\n        label: \"Resolution Factor\"\n      },\n      Rendering_Samples: {\n        value: 128,\n        max: 512,\n        min: 1,\n        step: 1,\n        label: \"Samples\"\n      },\n      Rendering_Bounces: {\n        value: 8,\n        max: 20,\n        min: 1,\n        step: 1,\n        label: \"Bounces\"\n      },\n      Rendering_Tiles: {\n        value: {\n          x: 2,\n          y: 2\n        },\n        max: 20,\n        min: 1,\n        step: 1,\n        label: \"Tiles\",\n        joystick: false\n      },\n      Rendering_Enabled: {\n        value: true,\n        label: \"Enabled\"\n      }\n    }),\n    Environment: folder({\n      Environment_Visible: {\n        value: true,\n        label: \"Enabled\"\n      },\n      Environment_Preset: {\n        options: Object.keys(presetsObj),\n        value: \"apartment\",\n        label: \"Preset\"\n      },\n      Environment_Intensity: {\n        value: 1.2,\n        max: 10,\n        min: 0,\n        step: 0.01,\n        label: \"Intensity\"\n      },\n      Environment_Blur: {\n        value: 0.3,\n        max: 1,\n        min: 0,\n        step: 0.01,\n        label: \"Blur\"\n      }\n    })\n  });\n}\n"
  },
  {
    "path": "example/src/Model.jsx",
    "content": "/*\nAuto-generated by: https://github.com/pmndrs/gltfjsx\n*/\n\nimport { useGLTF } from \"@react-three/drei\";\nimport { useLayoutEffect } from \"react\";\nimport { MeshPhysicalMaterial } from \"three\";\n\nexport default function Model(props) {\n  const { scene } = useGLTF(import.meta.env.BASE_URL + \"game_boy_classic.glb\");\n\n  useLayoutEffect(() => {\n    convertOpacityToTransmission(scene);\n  }, []);\n\n  return <primitive {...props} object={scene} />;\n}\n\nfunction convertOpacityToTransmission(model) {\n  model.traverse((c) => {\n    if (c.material) {\n      const material = c.material;\n      if (material.opacity < 0.65 && material.opacity > 0.2) {\n        const newMaterial = new MeshPhysicalMaterial();\n        for (const key in material) {\n          if (key in material) {\n            if (material[key] === null) {\n              continue;\n            }\n\n            if (material[key].isTexture) {\n              newMaterial[key] = material[key];\n            } else if (\n              material[key].copy &&\n              material[key].constructor === newMaterial[key].constructor\n            ) {\n              newMaterial[key].copy(material[key]);\n            } else if (typeof material[key] === \"number\") {\n              newMaterial[key] = material[key];\n            }\n          }\n        }\n\n        newMaterial.opacity = 1.0;\n        newMaterial.transmission = 1.0;\n        c.material = newMaterial;\n      }\n    }\n  });\n}\n"
  },
  {
    "path": "example/src/Tag.jsx",
    "content": "import { Logo } from \"@pmndrs/branding\";\nimport { FaGithub } from \"react-icons/fa\";\n\nexport default function Tag() {\n  return (\n    <div className=\"copy\">\n      <a\n        style={{\n          fontSize: \"1.5rem\",\n          color: \"white\",\n          textDecoration: \"underline\"\n        }}\n        target=\"_blank\"\n        rel=\"noopener\"\n        href=\"https://github.com/pmndrs/react-three-gpu-pathtracer\"\n      >\n        @react-three/gpu-pathtracer\n      </a>{\" \"}\n      <div>\n        <span>\n          <a target=\"_blank\" rel=\"noopener\" href=\"https://github.com/pmndrs\">\n            <Logo />\n          </a>\n        </span>\n\n        <span\n          style={{\n            fontSize: \"0.75rem\"\n          }}\n        >\n          <div\n            style={{\n              display: \"flex\",\n              flexDirection: \"column\",\n              justifyContent: \"center\",\n              alignItems: \"center\",\n              gap: \"1rem\"\n            }}\n          >\n            <span>\n              <a\n                target=\"_blank\"\n                rel=\"noopener\"\n                href=\"https://github.com/pmndrs/react-three-gpu-pathtracer\"\n              >\n                @react-three/gpu-pathtracer\n              </a>{\" \"}\n              is a React port of{\" \"}\n              <a\n                target=\"_blank\"\n                rel=\"noopener\"\n                href=\"https://github.com/gkjohnson/three-gpu-pathtracer\"\n              >\n                three-gpu-pathtracer\n              </a>{\" \"}\n              by{\" \"}\n              <a\n                target=\"_blank\"\n                rel=\"noopener\"\n                href=\"https://twitter.com/garrettkjohnson\"\n              >\n                Garrett Johnson\n              </a>\n            </span>\n            <span>\n              GameBoy model by{\" \"}\n              <a href=\"https://sketchfab.com/kleingeo\">(@kleingeo)</a>{\" \"}\n              <a hef=\"https://sketchfab.com/3d-models/game-boy-classic-0ae80019e6f046168923286d7e628f6f\">\n                on Sketchfab\n              </a>\n              . GameBoy Cartridge by{\" \"}\n              <a href=\"https://sketchfab.com/kleingeo\">(@MeBob)</a>{\" \"}\n              <a hef=\"https://sketchfab.com/3d-models/gameboy-cartridge-lowpoly-8b9728eab16c4056ac2636ae7f0f038f\">\n                on Sketchfab\n              </a>\n              .\n            </span>\n          </div>\n        </span>\n        <span>\n          <a\n            target=\"_blank\"\n            rel=\"noopener\"\n            href=\"https://github.com/pmndrs/react-three-gpu-pathtracer\"\n          >\n            <FaGithub size={40} />\n          </a>\n        </span>\n      </div>\n    </div>\n  );\n}\n"
  },
  {
    "path": "example/src/index.css",
    "content": "body {\n  margin: 0;\n  font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", \"Roboto\", \"Oxygen\",\n    \"Ubuntu\", \"Cantarell\", \"Fira Sans\", \"Droid Sans\", \"Helvetica Neue\",\n    sans-serif;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n}\n\ncode {\n  font-family: source-code-pro, Menlo, Monaco, Consolas, \"Courier New\",\n    monospace;\n}\n\n#root,\nbody,\ncanvas {\n  width: 100vw;\n  height: 100vh;\n  overflow: hidden;\n  margin: 0;\n  background: linear-gradient(180deg, #2a1303 0%, #000000 100%);\n}\n\ncanvas {\n  cursor: grab;\n  cursor: -moz-grab;\n  cursor: -webkit-grab;\n}\n\ncanvas:active {\n  cursor: grabbing;\n  cursor: -moz-grabbing;\n  cursor: -webkit-grabbing;\n}\n\n.copy {\n  position: absolute;\n  bottom: 0;\n  right: 0;\n  width: 100%;\n  box-sizing: border-box;\n  padding: 32px;\n  color: white;\n  text-align: center;\n\n  display: flex;\n  flex-direction: column;\n  justify-content: center;\n  align-items: center;\n  gap: 0.25rem;\n\n  pointer-events: none;\n\n  background: linear-gradient(180deg, rgba(0, 0, 0, 0) 0%, #000000 80%);\n}\n\n.copy > div {\n  width: 100%;\n  display: flex;\n  flex-direction: row;\n  justify-content: space-between;\n  align-items: center;\n  gap: 1rem;\n}\n\n.copy svg {\n  width: 1.5rem;\n  fill: white;\n}\n\na {\n  font-style: italic;\n  color: #ffbe33;\n  font-weight: bold;\n  text-decoration: none;\n  pointer-events: all;\n}\n\n/* .copy span a svg {\n  margin-right: 16px;\n} */\n\n.info {\n  position: absolute;\n  top: 50px;\n  left: 0;\n\n  padding: 0.25rem;\n\n  color: white;\n  font-family: monospace;\n}\n\n.info p {\n  margin: 0;\n}\n"
  },
  {
    "path": "example/src/index.js",
    "content": "import React from \"react\";\nimport ReactDOM from \"react-dom/client\";\nimport \"./index.css\";\nimport App from \"./App\";\n\nconst root = ReactDOM.createRoot(document.getElementById(\"root\"));\nroot.render(\n  <React.StrictMode>\n    <App />\n  </React.StrictMode>\n);\n"
  },
  {
    "path": "example/src/main.tsx",
    "content": "import { StrictMode } from \"react\";\nimport { createRoot } from \"react-dom/client\";\nimport App from \"./App.tsx\";\nimport \"./index.css\";\n\ncreateRoot(document.getElementById(\"root\")!).render(\n  <StrictMode>\n    <App />\n  </StrictMode>\n);\n"
  },
  {
    "path": "example/src/vite-env.d.ts",
    "content": "/// <reference types=\"vite/client\" />\n"
  },
  {
    "path": "example/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"useDefineForClassFields\": true,\n    \"lib\": [\"ES2020\", \"DOM\", \"DOM.Iterable\"],\n    \"module\": \"ESNext\",\n    \"skipLibCheck\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"isolatedModules\": true,\n    \"moduleDetection\": \"force\",\n    \"noEmit\": true,\n    \"jsx\": \"react-jsx\",\n\n    /* Linting */\n    \"strict\": false,\n    \"allowJs\": true,\n\n    \"preserveSymlinks\": true,\n    \"paths\": {\n      \"@react-three/gpu-pathtracer\": [\"../package/src\"]\n    }\n  },\n  \"include\": [\"src\"]\n}\n"
  },
  {
    "path": "example/tsconfig.tsbuildinfo",
    "content": "{\"root\":[\"./src/app.tsx\",\"./src/controls.js\",\"./src/model.jsx\",\"./src/tag.jsx\",\"./src/index.js\",\"./src/main.tsx\",\"./src/vite-env.d.ts\"],\"version\":\"5.6.2\"}"
  },
  {
    "path": "example/vite.config.ts",
    "content": "import react from \"@vitejs/plugin-react\";\nimport path from \"path\";\nimport { defineConfig } from \"vite\";\n\n// https://vitejs.dev/config/\nexport default defineConfig({\n  base: \"/react-three-gpu-pathtracer/\",\n  plugins: [react()],\n  resolve: {\n    alias: {\n      \"@react-three/gpu-pathtracer\": path.resolve(\n        __dirname,\n        \"../package/src/index.ts\"\n      )\n    }\n  }\n});\n"
  },
  {
    "path": "package/package.json",
    "content": "{\n  \"name\": \"@react-three/gpu-pathtracer\",\n  \"version\": \"0.3.2\",\n  \"description\": \"⚡️ A React abstraction for the popular three-gpu-pathtracer.\",\n  \"type\": \"module\",\n  \"files\": [\n    \"./**/*\"\n  ],\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/pmndrs/react-three-gpu-pathtracer\"\n  },\n  \"bugs\": {\n    \"url\": \"https://github.com/pmndrs/react-three-gpu-pathtracer/issues\"\n  },\n  \"author\": \"Faraz Shaikh <farazzshaikh@gmail.com> (https://twitter.com/CantBeFaraz)\",\n  \"contributors\": [\n    \"Dennis Smolek <Dennis@smolek.dev> (https://twitter.com/DennisSmolek)\"\n  ],\n  \"license\": \"MIT\",\n  \"homepage\": \"https://github.com/pmndrs/react-three-gpu-pathtracer\",\n  \"keywords\": [\n    \"react\",\n    \"webgl\",\n    \"three\",\n    \"path\",\n    \"tracing\",\n    \"pathtracing\",\n    \"raytracing\"\n  ],\n  \"main\": \"react-three-gpu-pathtracer.cjs.js\",\n  \"module\": \"react-three-gpu-pathtracer.es.js\",\n  \"types\": \"index.d.ts\",\n  \"scripts\": {\n    \"build\": \"tsc && vite build\",\n    \"release\": \"yarn build && cp ./package.json ./dist/package.json && cd ./dist && npm publish\"\n  },\n  \"devDependencies\": {\n    \"@types/node\": \"^22.7.4\",\n    \"@types/react\": \"^18.3.3\",\n    \"@types/react-dom\": \"^18.3.0\",\n    \"@types/three\": \"^0.177.0\",\n    \"@vitejs/plugin-react\": \"^4.3.1\",\n    \"globals\": \"^15.9.0\",\n    \"rollup-plugin-exclude-dependencies-from-bundle\": \"^1.1.24\",\n    \"typescript\": \"^5.5.3\",\n    \"typescript-eslint\": \"^8.0.1\",\n    \"vite\": \"^5.4.1\",\n    \"vite-plugin-dts\": \"^4.2.1\"\n  },\n  \"peerDependencies\": {\n    \"@react-three/fiber\": \">=8.0\",\n    \"react\": \">=18.0\",\n    \"three\": \">=0.149\"\n  },\n  \"dependencies\": {\n    \"three-gpu-pathtracer\": \"^0.0.23\"\n  }\n}\n"
  },
  {
    "path": "package/src/FogVolumeMaterial.tsx",
    "content": "import { extend, ThreeElement } from \"@react-three/fiber\";\nimport { useEffect } from \"react\";\nimport { FogVolumeMaterial as FogVolumeMaterialImpl } from \"three-gpu-pathtracer\";\nimport { usePathtracer } from \"./Pathtracer\";\n\nexport function FogVolumeMaterial(\n  props: ThreeElement<typeof FogVolumeMaterialImpl>\n) {\n  extend({ FogVolumeMaterial: FogVolumeMaterialImpl });\n  const { pathtracer } = usePathtracer();\n  useEffect(() => void pathtracer.updateMaterials());\n  // @ts-expect-error\n  return <fogVolumeMaterial {...props} />;\n}\n\nexport { FogVolumeMaterialImpl };\n"
  },
  {
    "path": "package/src/Pass.ts",
    "content": "import {\n  Material,\n  Mesh,\n  OrthographicCamera,\n  PlaneGeometry,\n  WebGLRenderer,\n  WebGLRenderTarget\n} from \"three\";\n\nclass Pass {\n  // if set to true, the pass is processed by the composer\n  public enabled = true;\n\n  // if set to true, the pass indicates to swap read and write buffer after rendering\n  public needsSwap = true;\n\n  // if set to true, the pass clears its buffer before rendering\n  public clear = false;\n\n  // if set to true, the result of the pass is rendered to screen. This is set automatically by EffectComposer.\n  public renderToScreen = false;\n\n  public setSize(\n    /* eslint-disable @typescript-eslint/no-unused-vars */\n    /* eslint-disable no-unused-vars */\n    width: number,\n    height: number\n  ): void {}\n\n  public render(\n    /* eslint-disable @typescript-eslint/no-unused-vars */\n    /* eslint-disable no-unused-vars */\n    renderer: WebGLRenderer,\n    writeBuffer: WebGLRenderTarget,\n    readBuffer: WebGLRenderTarget,\n    deltaTime: number,\n    maskActive?: unknown\n  ): void {\n    console.error(\"THREE.Pass: .render() must be implemented in derived pass.\");\n  }\n}\n\n// Helper for passes that need to fill the viewport with a single quad.\nclass FullScreenQuad<TMaterial extends Material = Material> {\n  public camera = new OrthographicCamera(-1, 1, 1, -1, 0, 1);\n  public geometry = new PlaneGeometry(2, 2);\n  private mesh: Mesh<PlaneGeometry, TMaterial>;\n\n  constructor(material: TMaterial) {\n    this.mesh = new Mesh(this.geometry, material);\n  }\n\n  public get material(): TMaterial {\n    return this.mesh.material;\n  }\n\n  public set material(value: TMaterial) {\n    this.mesh.material = value;\n  }\n\n  public dispose(): void {\n    this.mesh.geometry.dispose();\n  }\n\n  public render(renderer: WebGLRenderer): void {\n    renderer.render(this.mesh, this.camera);\n  }\n}\n\nexport { FullScreenQuad, Pass };\n"
  },
  {
    "path": "package/src/Pathtracer.tsx",
    "content": "import {\n  applyProps,\n  ElementProps,\n  useFrame,\n  useThree,\n  Vector2\n} from \"@react-three/fiber\";\nimport React, { useMemo } from \"react\";\nimport * as THREE from \"three\";\nimport { WebGLPathTracer } from \"three-gpu-pathtracer\";\n\ntype PathtracerProps = ElementProps<typeof WebGLPathTracer> & {\n  minSamples?: number;\n  samples?: number;\n  tiles?: Vector2;\n  bounces?: number;\n  enabled?: boolean;\n  resolutionFactor?: number;\n  renderPriority?: number;\n  filteredGlossyFactor?: number;\n};\n\ninterface PathtracerAPI {\n  update: () => void;\n  reset: () => void;\n  renderer: WebGLPathTracer;\n  pathtracer: WebGLPathTracer;\n}\n\nconst context = React.createContext<PathtracerAPI>(null as any);\n\n//* Helper Function to convert TilesType to [number, number]\nfunction fiberVec2ToArr(vec: Vector2): [number, number] {\n  if (Array.isArray(vec)) return vec;\n  if (vec instanceof THREE.Vector2) return [vec.x, vec.y];\n  if (typeof vec === \"number\") return [vec, vec];\n  return [1, 1]; // Default to 1x1 tiles if not specified\n}\n\nexport const Pathtracer = React.forwardRef<\n  InstanceType<typeof WebGLPathTracer>,\n  React.PropsWithChildren<PathtracerProps>\n>(\n  (\n    {\n      children,\n      enabled = true,\n      minSamples = 1,\n      samples = 32,\n      bounces = 4,\n      resolutionFactor = 1,\n      renderPriority = 1,\n      filteredGlossyFactor = 0,\n      renderDelay = 0,\n      fadeDuration = 0,\n      dynamicLowRes = true,\n      lowResScale = 0.25,\n      textureSize = [1024, 1024],\n      rasterizeScene = false,\n      tiles = [3, 3],\n      ...props\n    },\n    ref\n  ) => {\n    // state objects\n    const { gl, camera, scene, controls } = useThree();\n\n    const pathtracer = useMemo(() => {\n      const pt = new WebGLPathTracer(gl);\n      pt.synchronizeRenderSize = true;\n      // This might not be needed as we arent using setSceneAsync\n      //pt.setBVHWorker(new ParallelMeshBVHWorker())\n      return pt;\n    }, [gl]);\n\n    // Expose the pathtracer instance via ref\n    React.useImperativeHandle(ref, () => pathtracer, [pathtracer]);\n\n    //* Single handler for all props\n    React.useLayoutEffect(() => {\n      applyProps(pathtracer, {\n        bounces,\n        filteredGlossyFactor,\n        renderDelay,\n        fadeDuration,\n        minSamples,\n        dynamicLowRes,\n        lowResScale,\n        rasterizeScene,\n        textureSize,\n        tiles\n      });\n      pathtracer.renderScale = resolutionFactor;\n      pathtracer.reset();\n    }, [props, resolutionFactor, bounces, minSamples, pathtracer]);\n\n    React.useEffect(() => {\n      if (enabled) pathtracer.reset();\n    }, [enabled]);\n\n    const api = React.useMemo<PathtracerAPI>(\n      () => ({\n        /**\n         * Update the pathtracer scene. Call this after adding or removing objects from the scene\n         */\n        update: () => {\n          pathtracer.setScene(scene, camera);\n        },\n        /**\n         * Reset the pathtracer. Call this after changing any pathtracing properties\n         */\n        reset: () => {\n          pathtracer.reset();\n        },\n        /**\n         * @deprecated Use `pathtracer` instead\n         */\n        renderer: pathtracer,\n        pathtracer: pathtracer // Use this instead. Keeps base three renderer seperate mentally\n      }),\n      [pathtracer, scene, camera]\n    );\n\n    //* Initialize the pathtracer\n    React.useLayoutEffect(() => {\n      // scene.updateMatrixWorld()\n      pathtracer.setScene(scene, camera);\n    }, [scene, camera]);\n\n    // Bind control listeners\n    React.useLayoutEffect(() => {\n      // setup control listeners\n\n      const controlListener = () => {\n        pathtracer.updateCamera();\n      };\n\n      // @ts-ignore\n      if (controls) controls.addEventListener(\"change\", controlListener);\n\n      return () => {\n        // @ts-ignore\n        if (controls) controls.removeEventListener(\"change\", controlListener);\n      };\n    }, [controls, pathtracer]);\n\n    useFrame(({ camera, gl, scene }) => {\n      if (enabled && pathtracer.samples < (samples ?? Infinity))\n        pathtracer.renderSample();\n      if (!enabled) gl.render(scene, camera);\n    }, 1);\n\n    return <context.Provider value={api}>{children}</context.Provider>;\n  }\n);\n\nexport function usePathtracer() {\n  const ctx = React.useContext(context);\n  if (!ctx) throw new Error(\"usePathtracer must be used within a Pathtracer\");\n\n  return ctx;\n}\n"
  },
  {
    "path": "package/src/PhysicalCamera.tsx",
    "content": "import { extend, ThreeElement, useThree } from \"@react-three/fiber\";\nimport { useLayoutEffect, useEffect, useRef } from \"react\";\nimport { PhysicalCamera as PhysicalCameraImpl } from \"three-gpu-pathtracer\";\nimport { usePathtracer } from \"./Pathtracer\";\n\nexport function PhysicalCamera(\n  props: ThreeElement<typeof PhysicalCameraImpl> & { manual?: boolean }\n) {\n  extend({ PhysicalCamera: PhysicalCameraImpl });\n  const { pathtracer } = usePathtracer();\n\n  const set = useThree(({ set }) => set);\n  const camera = useThree(({ camera }) => camera);\n  const size = useThree(({ size }) => size);\n  const cameraRef = useRef<PhysicalCameraImpl>(null!);\n\n  useLayoutEffect(() => {\n    if (!props.manual) {\n      // Calculate correct aspect ratio\n      cameraRef.current.aspect = size.width / size.height;\n    }\n  }, [size, props]);\n\n  useLayoutEffect(() => {\n    // Update the camera's projection matrix\n    cameraRef.current.updateProjectionMatrix();\n  });\n\n  useLayoutEffect(() => {\n    // Set as the default camera\n    const oldCam = camera;\n    set(() => ({ camera: cameraRef.current }));\n    return () => set(() => ({ camera: oldCam }));\n  }, [cameraRef, set]);\n\n  // Update the pathtracer\n  useEffect(() => void pathtracer.updateCamera());\n\n  // @ts-expect-error\n  return <physicalCamera ref={cameraRef} {...props} />;\n}\n\nexport { PhysicalCameraImpl };\n"
  },
  {
    "path": "package/src/PhysicalSpotLight.tsx",
    "content": "import { extend, ThreeElement } from \"@react-three/fiber\";\nimport { useEffect } from \"react\";\nimport { PhysicalSpotLight as PhysicalSpotLightImpl } from \"three-gpu-pathtracer\";\nimport { usePathtracer } from \"./Pathtracer\";\n\nexport function PhysicalSpotLight(\n  props: ThreeElement<typeof PhysicalSpotLightImpl>\n) {\n  extend({ PhysicalSpotLight: PhysicalSpotLightImpl });\n  const { pathtracer } = usePathtracer();\n  useEffect(() => void pathtracer.updateLights());\n  // @ts-expect-error\n  return <physicalSpotLight {...props} />;\n}\n\nexport { PhysicalSpotLightImpl };\n"
  },
  {
    "path": "package/src/ShapedAreaLight.tsx",
    "content": "import { extend, ThreeElement } from \"@react-three/fiber\";\nimport { useEffect } from \"react\";\nimport { ShapedAreaLight as ShapedAreaLightImpl } from \"three-gpu-pathtracer\";\nimport { usePathtracer } from \"./Pathtracer\";\n\nexport function ShapedAreaLight(\n  props: ThreeElement<typeof ShapedAreaLightImpl>\n) {\n  extend({ ShapedAreaLight: ShapedAreaLightImpl });\n  const { pathtracer } = usePathtracer();\n  useEffect(() => void pathtracer.updateLights());\n  // @ts-expect-error\n  return <shapedAreaLight {...props} />;\n}\n\nexport { ShapedAreaLightImpl };\n"
  },
  {
    "path": "package/src/index.ts",
    "content": "export * from \"./FogVolumeMaterial\";\nexport * from \"./Pathtracer\";\nexport * from \"./PhysicalCamera\";\nexport * from \"./PhysicalSpotLight\";\nexport * from \"./ShapedAreaLight\";\n"
  },
  {
    "path": "package/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"noEmit\": true,\n    \"allowSyntheticDefaultImports\": true,\n    \"jsx\": \"react-jsx\",\n    \"strict\": true,\n    \"moduleResolution\": \"Node\",\n    \"skipLibCheck\": true,\n    \"allowJs\": true,\n    \"lib\": [\"esnext\", \"dom\"]\n  },\n  \"include\": [\"src/**/*\"],\n  \"exclude\": [\"node_modules\", \"dist\"]\n}\n"
  },
  {
    "path": "package/vite.config.ts",
    "content": "import react from \"@vitejs/plugin-react\";\nimport fs from \"fs/promises\";\nimport path from \"path\";\nimport excludeDependenciesFromBundle from \"rollup-plugin-exclude-dependencies-from-bundle\";\nimport { defineConfig } from \"vite\";\nimport dts from \"vite-plugin-dts\";\n\nfunction copyFiles() {\n  return {\n    name: \"copy-license\",\n    closeBundle: async () => {\n      await fs.copyFile(\"../LICENSE.md\", \"./dist/LICENSE.md\");\n      await fs.copyFile(\"../README.md\", \"./dist/README.md\");\n      await fs.copyFile(\"./package.json\", \"./dist/package.json\");\n    }\n  };\n}\n\nexport default defineConfig({\n  build: {\n    outDir: \"dist\",\n    lib: {\n      entry: path.resolve(__dirname, \"src/index.ts\"),\n      name: \"react-three-gpu-pathtracer\",\n      formats: [\"es\", \"cjs\"],\n      fileName: (format) => `react-three-gpu-pathtracer.${format}.js`\n    },\n    rollupOptions: {\n      external: [\"react\", \"three\", \"@react-three/fiber\"],\n      plugins: [\n        // @ts-ignore\n        excludeDependenciesFromBundle({\n          dependencies: true,\n          peerDependencies: true\n        })\n      ]\n    },\n    sourcemap: true,\n    emptyOutDir: true\n  },\n  plugins: [react(), dts(), copyFiles()]\n});\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"@react-three/gpu-pathtracer-monorepo\",\n  \"description\": \"Monorepo for @react-three/gpu-pathtracer-monorepo and its examples\",\n  \"version\": \"1.0.0\",\n  \"private\": true,\n  \"repository\": \"https://github.com/pmndrs/react-three-gpu-pathtracer\",\n  \"author\": \"Faraz Shaikh <farazzshaikh@gmail.com> (https://twitter.com/CantBeFaraz)\",\n  \"contributors\": [\n    \"Dennis Smolek <Dennis@smolek.dev> (https://twitter.com/DennisSmolek)\"\n  ],\n  \"license\": \"MIT\",\n  \"homepage\": \"https://github.com/pmndrs/react-three-gpu-pathtracer\",\n  \"workspaces\": [\n    \"package\",\n    \"example\"\n  ],\n  \"scripts\": {\n    \"build:package\": \"yarn --cwd package build\",\n    \"build\": \"yarn --cwd example build\",\n    \"preview\": \"yarn --cwd example preview\",\n    \"dev\": \"yarn --cwd example dev\",\n    \"release\": \"yarn --cwd package release\"\n  },\n  \"packageManager\": \"yarn@4.9.2\"\n}\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"module\": \"esnext\",\n    \"target\": \"es2018\",\n    \"allowSyntheticDefaultImports\": true,\n    \"jsx\": \"react\",\n    \"strict\": true,\n    \"preserveSymlinks\": true,\n    \"moduleResolution\": \"Node\",\n    \"esModuleInterop\": true,\n    \"declaration\": true,\n    \"skipLibCheck\": true,\n    \"removeComments\": false\n  },\n  \"include\": [\"package/src/**/*\"],\n  \"exclude\": [\"node_modules\", \"package/dist/**/*\"]\n}\n"
  }
]