Full Code of ektogamat/r3f-webgpu-starter for AI

main c87883c66090 cached
24 files
34.7 KB
10.6k tokens
12 symbols
1 requests
Download .txt
Repository: ektogamat/r3f-webgpu-starter
Branch: main
Commit: c87883c66090
Files: 24
Total size: 34.7 KB

Directory structure:
gitextract_zhgr58d5/

├── .gitignore
├── README.md
├── package.json
├── public/
│   ├── darth-transformed.glb
│   ├── favicon/
│   │   ├── about.txt
│   │   └── site.webmanifest
│   ├── hall-transformed.glb
│   ├── index.html
│   ├── naboo_royal_starship-transformed.glb
│   └── probe-transformed.glb
└── src/
    ├── App.js
    ├── components/
    │   ├── Darth.js
    │   ├── Hall.js
    │   ├── JetEngineMaterial.js
    │   ├── Light_Environment.js
    │   ├── ManciniCanvas.js
    │   ├── Overlay.js
    │   ├── Probe.js
    │   ├── ResizeHandler.js
    │   ├── Royal.js
    │   ├── VaderScene.js
    │   └── WebGPUPostProcessing.js
    ├── index.js
    └── styles.css

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*

# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage
*.lcov

# nyc test coverage
.nyc_output

# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# Snowpack dependency directory (https://snowpack.dev/)
web_modules/

# TypeScript cache
*.tsbuildinfo

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional stylelint cache
.stylelintcache

# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local

# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache

# Next.js build output
.next
out

# Nuxt.js build / generate output
.nuxt
dist

# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public

# vuepress build output
.vuepress/dist

# vuepress v2.x temp and cache directory
.temp
.cache

# Docusaurus cache and generated files
.docusaurus

# Serverless directories
.serverless/

# FuseBox cache
.fusebox/

# DynamoDB Local files
.dynamodb/

# TernJS port file
.tern-port

# Stores VSCode versions used for testing VSCode extensions
.vscode-test

# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
.vercel


================================================
FILE: README.md
================================================
# React Three Fiber WebGPU Post Processing

<h4>by Anderson Mancini</h4>

[![screenshot](https://r3f-webgpu-post-processing.vercel.app/social.jpg)](https://r3f-webgpu-post-processing.vercel.app/)

A very simple scene to demonstrate how to integrate Threejs WebGPU with React Three Fiber using Post Processing effects.
[See the demo here](https://r3f-webgpu-post-processing.vercel.app/)

### Getting Started using this demo project

Download and install Node.js on your computer (https://nodejs.org/en/download/).

Then, open VSCODE, drag the project folder to it. Open VSCODE terminal and install dependencies (you need to do this only in the first time)

```shell
npm install
```

Run this command in your terminal to open a local server at localhost:3000

```shell
npm run start
```

### Can you leave a star please?

I genuinely appreciate your support! If you're willing to show your appreciation, you can <strong>give me a star on GitHub 🎉 </strong>or consider buying a coffee to support my development at https://www.buymeacoffee.com/andersonmancini. The funds received will be utilized to create more valuable content about Three.js and invest in acquiring new courses. Thank you for your consideration!


================================================
FILE: package.json
================================================
{
  "name": "basic-demo",
  "version": "1.0.0",
  "description": "Shows how to form self-contained components with their own state and user interaction.",
  "keywords": [
    "interaction",
    "pointer-events"
  ],
  "main": "src/index.js",
  "dependencies": {
    "@react-three/drei": "^9.99.0",
    "@react-three/fiber": "^8.15.0",
    "@types/three": "^0.177.0",
    "maath": "0.10.8",
    "react": "18.2.0",
    "react-dom": "18.2.0",
    "react-scripts": "5.0.1",
    "three": "^0.177.0",
    "three-mesh-bvh": "^0.8.0"
  },
  "scripts": {
    "start": "set HOST=0.0.0.0 && react-scripts start",
    "build": "GENERATE_SOURCEMAP=false react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject",
    "deploy": "vercel --prod"
  },
  "browserslist": [
    ">1%",
    "not dead",
    "not ie <= 11",
    "not op_mini all"
  ]
}


================================================
FILE: public/favicon/about.txt
================================================
This favicon was generated using the following graphics from Twitter Twemoji:

- Graphics Title: 1f441-200d-1f5e8.svg
- Graphics Author: Copyright 2020 Twitter, Inc and other contributors (https://github.com/twitter/twemoji)
- Graphics Source: https://github.com/twitter/twemoji/blob/master/assets/svg/1f441-200d-1f5e8.svg
- Graphics License: CC-BY 4.0 (https://creativecommons.org/licenses/by/4.0/)


================================================
FILE: public/favicon/site.webmanifest
================================================
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}

================================================
FILE: public/index.html
================================================
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1, shrink-to-fit=no"
    />
    <title>WebGPU Post Processing Example - By Anderson Mancini</title>
    <meta
      name="description"
      content="This is a demo of React Three Fiber using post processing with threejs and WebGPU, featuring Screen Space Reflections."
    />

    <meta
      property="og:url"
      content="https://r3f-webgpu-post-processing.vercel.app"
    />
    <meta property="og:type" content="website" />
    <meta
      property="og:title"
      content="This is a demo of React Three Fiber using post processing with threejs and WebGPU, featuring Screen Space Reflections."
    />
    <meta
      property="og:description"
      content="This is a demo of React Three Fiber using post processing with threejs and WebGPU, featuring Screen Space Reflections."
    />
    <meta
      property="og:image"
      content="https://r3f-webgpu-post-processing.vercel.app/social.jpg"
    />

    <meta name="twitter:card" content="summary_large_image" />
    <meta
      property="twitter:domain"
      content="r3f-webgpu-post-processing.vercel.app"
    />
    <meta
      property="twitter:url"
      content="https://r3f-webgpu-post-processing.vercel.app"
    />
    <meta
      name="twitter:title"
      content="This is a demo of React Three Fiber using post processing with threejs and WebGPU, featuring Screen Space Reflections."
    />
    <meta
      name="twitter:description"
      content="This is a demo of React Three Fiber using post processing with threejs and WebGPU, featuring Screen Space Reflections."
    />
    <meta
      name="twitter:image"
      content="https://r3f-webgpu-post-processing.vercel.app/social.jpg"
    />

    <meta
      name="keywords"
      content="react three fiber, webgpu, post processing, threejs, HTML, CSS, JavaScript"
    />
    <meta name="author" content="Anderson Mancini.dev" />
    <meta name="msapplication-TileColor" content="#000000" />
    <meta name="theme-color" content="#000000" />

    <link
      rel="apple-touch-icon"
      sizes="180x180"
      href="favicon/apple-touch-icon.png"
    />
    <link
      rel="icon"
      type="image/png"
      sizes="32x32"
      href="favicon/favicon-32x32.png"
    />
    <link
      rel="icon"
      type="image/png"
      sizes="16x16"
      href="favicon/favicon-16x16.png"
    />
    <link rel="manifest" href="favicon/site.webmanifest" />
  </head>

  <body>
    <noscript> You need to enable JavaScript to run this app. </noscript>
    <div id="root"></div>
  </body>
</html>


================================================
FILE: src/App.js
================================================
import { useState } from "react";
import { Loader } from "@react-three/drei";
import { WebGPUPostProcessing } from "./components/WebGPUPostProcessing";
import { Hall } from "./components/Hall";
import { Overlay } from "./components/Overlay";
import RoyalNaboo from "./components/Royal";
import { Light_Environment } from "./components/Light_Environment";
import { VaderScene } from "./components/VaderScene";
import { ManciniCanvas } from "./components/ManciniCanvas";

export default function App() {
  const [currentScene, setCurrentScene] = useState("vader");
  const [quality, setQuality] = useState("default");
  const [isPostProcessingEnabled, setIsPostProcessingEnabled] = useState(true);
  // Disable frameloop by default, waiting for WebGPU to be ready

  return (
    <>
      <Overlay
        isPostProcessingEnabled={isPostProcessingEnabled}
        setIsPostProcessingEnabled={setIsPostProcessingEnabled}
        setCurrentScene={setCurrentScene}
        currentScene={currentScene}
        setQuality={setQuality}
        quality={quality}
      />

      <Loader />

      <ManciniCanvas quality={quality}>
        <color attach="background" args={["black"]} />

        {isPostProcessingEnabled && (
          <WebGPUPostProcessing
            strength={0.25}
            radius={0.1}
            quality={quality}
          />
        )}

        <Light_Environment />

        <group position={[-1, 0, 0]}>
          <Hall position={[16.3, 0, -0.15]} scale={[1, 1, 1.3]} />

          <group
            visible={currentScene === "vader"}
            scale={[0.8, 0.8, 0.8]}
            position={[0, -0.25, 0]}
          >
            <VaderScene />
          </group>

          <RoyalNaboo
            visible={currentScene === "royal"}
            position={[3, -0.5, -2.2]}
            scale={0.35}
            rotation={[0, 0, 0]}
          />
        </group>
      </ManciniCanvas>
    </>
  );
}


================================================
FILE: src/components/Darth.js
================================================
/*
Auto-generated by: https://github.com/pmndrs/gltfjsx
Author: AFTONBLADET (https://sketchfab.com/wallander)
License: CC-BY-4.0 (http://creativecommons.org/licenses/by/4.0/)
Source: https://sketchfab.com/3d-models/darth-vader-by-makeamo-5b3371f4789c41eeaa691c9a3dfe1a96
Title: Darth Vader by Makeamo
*/

import React, { useRef } from "react";
import { useGLTF } from "@react-three/drei";

export function Darth(props) {
  const { nodes, materials } = useGLTF("/darth-transformed.glb");

  materials.Sabel_svart.emissiveIntensity = 20;
  materials.darthvader_VaderConsolesFlickermat.roughness = 0.2;
  materials.darthvader_VaderCapemat.roughness = 0.2;
  materials.darthvader_VaderCapemat.metalness = 0.7;
  materials.darthvader_VaderHelmetRimmat.roughness = 0.3;
  materials.darthvader_VaderHelmetRimmat.metalness = 0.6;
  materials.darthvader_VaderBodyArmourmat.roughness = 0.2;
  materials.darthvader_VaderBodyArmourmat.metalness = 0.9;

  return (
    <group {...props} dispose={null}>
      <mesh
        castShadow
        receiveShadow
        geometry={nodes.DARTH_Sabel_vit_0.geometry}
        material={materials.Sabel_vit}
      />
      <mesh
        castShadow
        receiveShadow
        geometry={nodes.DARTH_darthvader_VaderConsolesFlickermat_0.geometry}
        material={materials.darthvader_VaderConsolesFlickermat}
      />
      <mesh
        castShadow
        receiveShadow
        geometry={nodes.DARTH_darthvader_VaderCapemat_0.geometry}
        material={materials.darthvader_VaderCapemat}
      />
      <mesh
        castShadow
        receiveShadow
        geometry={nodes.DARTH_darthvader_VaderHelmetRimmat_0.geometry}
        material={materials.darthvader_VaderHelmetRimmat}
      />
      <mesh
        castShadow
        receiveShadow
        geometry={nodes.DARTH_darthvader_VaderBodyArmourmat_0.geometry}
        material={materials.darthvader_VaderBodyArmourmat}
      />
      <mesh
        castShadow
        receiveShadow
        geometry={nodes.DARTH_Laser_0.geometry}
        material={materials.Laser}
      />
      <mesh
        castShadow
        receiveShadow
        geometry={nodes.DARTH_Sabel_svart_0.geometry}
        material={materials.Sabel_svart}
      />
    </group>
  );
}

useGLTF.preload("/darth-transformed.glb");


================================================
FILE: src/components/Hall.js
================================================
/*
Auto-generated by: https://github.com/pmndrs/gltfjsx
*/

import React, { useRef } from "react";
import { useGLTF } from "@react-three/drei";
import { FrontSide } from "three";
export function Hall(props) {
  const { nodes, materials } = useGLTF("/hall-transformed.glb");

  materials.VenatorV3_SmallDoor_WallLight.emissiveIntensity = 2.6;
  materials.Venator_Floor.color.set("black");
  materials.Venator_Floor.roughness = 0.95;
  materials.Venator_Floor.normalMap = null;

  //   materials.Venator_Floor.roughnessMap = null;
  //   materials.Venator_Floor.roughnessMap = null;
  //   materials.Venator_Floor.metalnessMap = null;
  //   materials.Venator_Floor.emissiveIntensity = 0;

  materials.Venator_Floor.metalness = 1;
  materials.Venator_Floor.metalnessMap = null;
  materials.VenatorV3_WallPanels.color.set("grey");
  materials.VenatorV3_WallPanels.roughness = 0.8;
  materials.VenatorV3_WallPanels.metalness = 0.5;
  materials.VenatorV3_WallPanels.side = FrontSide;
  materials.VenatorV3_LargeDoor.side = FrontSide;
  materials.VenatorV3_SmallDoor_WallLight.side = FrontSide;

  return (
    <group {...props} dispose={null}>
      <group rotation={[-Math.PI / 2, 0, 0]} scale={0.012}>
        <group rotation={[Math.PI / 2, 0, 0]}>
          <group position={[-1448.93, -5.342, -159.366]} scale={6.463}>
            <mesh
              receiveShadow
              geometry={nodes.WallPanel21_VenatorV3_WallPanels_0001.geometry}
              material={materials.VenatorV3_WallPanels}
            />
            <mesh
              receiveShadow
              geometry={nodes.WallPanel21_VenatorV3_WallPanels_0001_1.geometry}
              material={materials.VenatorV3_LargeDoor}
            />
            <mesh
              receiveShadow
              geometry={nodes.WallPanel21_VenatorV3_WallPanels_0001_2.geometry}
              material={materials.Venator_Floor}
            >
              {/* <meshPhysicalMaterial
                color="black"
                metalness={0.8}
                roughness={0.7}
              /> */}
            </mesh>
            <mesh
              receiveShadow
              geometry={nodes.WallPanel21_VenatorV3_WallPanels_0001_3.geometry}
              material={materials.VenatorV3_SmallDoor_WallLight}
            />
          </group>
        </group>
      </group>
    </group>
  );
}

useGLTF.preload("/hall-transformed.glb");


================================================
FILE: src/components/JetEngineMaterial.js
================================================
import { useFrame } from "@react-three/fiber";
import {
  uniform,
  float,
  vec2,
  sin,
  cos,
  uv,
  mod,
  div,
  sub,
  length,
  pow,
  abs,
  vec3,
  add,
  mul,
} from "three/tsl";

export function useJetEngineMaterial() {
  // Create uniform and shader calculations
  const uTime = uniform(float(0.0));
  const TAU = float(6.28318530718);
  const MAX_ITER = float(8);
  const inten = float(0.007);

  // Get UV coordinates and time
  const currentUV = uv();
  const currentTime = mul(uTime, float(2.5));

  // Rotate UV coordinates
  const angle = float(3.147);
  const s = sin(angle);
  const c = cos(angle);

  // Create rotation matrix manually
  const rotatedX = add(mul(currentUV.x, c), mul(currentUV.y, s));
  const rotatedY = sub(mul(currentUV.x, s), mul(currentUV.y, c));
  const uvRotated = add(vec2(rotatedX, rotatedY), mul(uTime, float(2.4)));

  // Calculate base coordinates
  const p = sub(mod(mul(uvRotated, TAU), TAU), float(256.0));

  // Initialize accumulator
  let accumulator = float(0.9);

  // Unroll the loop
  for (let i = 0; i < 8; i++) {
    const t = mul(currentTime, sub(float(1.0), div(float(3.5), float(i + 1))));

    const px = add(cos(sub(t, p.x)), sin(add(t, p.y)));
    const py = add(sin(sub(t, p.y)), cos(add(t, p.x)));

    const iVec = add(p, vec2(px, py));

    const lenVec = vec2(
      div(p.x, div(sin(add(iVec.x, t)), inten)),
      div(p.y, div(cos(add(iVec.y, t)), inten))
    );

    accumulator = add(accumulator, div(float(1.1), length(lenVec)));
  }

  // Final color calculations
  accumulator = div(accumulator, float(MAX_ITER));
  accumulator = sub(float(1.1), pow(accumulator, float(1.5)));

  const engineColor = pow(abs(accumulator), float(30.0));
  const finalColor = add(
    vec3(engineColor).mul(vec3(0, 0.5, 1.0)),
    vec3(0.0, 0.0, 0.0)
  ).mul(float(25.0));

  // Update time in animation frame
  useFrame((state, delta) => {
    uTime.value += delta * 0.5;
  });

  return {
    key: uTime.id,
    colorNode: finalColor,
  };
}


================================================
FILE: src/components/Light_Environment.js
================================================
import { Environment } from "@react-three/drei";
import { OrbitControls } from "@react-three/drei";

export function Light_Environment() {
  return (
    <>
      <directionalLight
        position={[-0.7, 1.8, 0.1]}
        intensity={6}
        castShadow
        shadow-mapSize={[128, 128]}
        shadow-camera-near={2}
        shadow-camera-far={100}
        shadow-camera-top={3}
        shadow-camera-right={3}
        shadow-camera-bottom={-3}
        shadow-camera-left={-3}
        shadow-bias={-0.002}
      />
      <OrbitControls
        target={[2, -0.6, 0]}
        // zoomSpeed={0.8}
        screenSpacePanning={false}
        dampingFactor={0.08}
        maxPolarAngle={Math.PI / 1.75}
        minPolarAngle={Math.PI / 2.7}
        maxDistance={2.4}
        minDistance={1}
        minZoom={0.5}
        maxZoom={1}
      />
      <Environment
        preset="warehouse"
        environmentIntensity={0.2}
        environmentRotation={[0.4, 0, 1.4]}
      />
    </>
  );
}


================================================
FILE: src/components/ManciniCanvas.js
================================================
import { Canvas, extend } from "@react-three/fiber";
import { useRef, useState } from "react";
import * as THREE from "three/webgpu";
import { ResizeHandler } from "./ResizeHandler";

extend(THREE);

export function ManciniCanvas({ quality, children }) {
  const rendererRef = useRef();
  const [frameloop, setFrameloop] = useState("never");
  return (
    <Canvas
      onCreated={(state) => {
        state.setSize(window.innerWidth, window.innerHeight);
      }}
      frameloop={frameloop}
      dpr={quality === "default" ? 1 : [1, 1.5]}
      camera={{
        position: [18.6, -0.6, 0],
        near: 0.1,
        far: 50,
        fov: 65,
        // zoom: 1,
      }}
      shadows={"variance"}
      gl={(canvas) => {
        const renderer = new THREE.WebGPURenderer({
          canvas,
          powerPreference: "high-performance",
          antialias: false,
          alpha: false,
          stencil: false,
        });

        // Initialize WebGPU and store renderer reference
        renderer.init().then(() => setFrameloop("always"));
        rendererRef.current = renderer;
        return renderer;
      }}
    >
      {children}
      <ResizeHandler quality={quality} rendererRef={rendererRef} />
    </Canvas>
  );
}


================================================
FILE: src/components/Overlay.js
================================================
export function Overlay({
  isPostProcessingEnabled,
  setIsPostProcessingEnabled,
  currentScene,
  setCurrentScene,
  quality,
  setQuality,
}) {
  return (
    <div className="overlay">
      <header>
        <h1>
          R3F <span>WebGPU</span>
        </h1>
        <p>
          This is a demo of React Three Fiber using post processing with threejs
          and WebGPU, featuring Screen Space Reflections.
        </p>
      </header>
      <footer>
        <p className="footer-text">
          Created by <a href="https://andersonmancini.dev">Anderson Mancini</a>
        </p>
        <div className="footer-buttons">
          <button
            onClick={() => setIsPostProcessingEnabled(!isPostProcessingEnabled)}
          >
            {isPostProcessingEnabled ? "Disable" : "Enable"} Post Processing
          </button>
          <button
            className="toggle"
            onClick={() =>
              setCurrentScene(currentScene === "vader" ? "royal" : "vader")
            }
          >
            Toggle Scene
          </button>
          <button
            onClick={() =>
              setQuality(quality === "default" ? "high" : "default")
            }
            className="toggle-quality"
          >
            {quality === "default" ? "Higher Quality" : "Performance Mode"}
          </button>
        </div>
        <a
          href="https://github.com/ektogamat/r3f-webgpu-starter"
          download
          className="download-button"
        >
          <SvgIcon />
        </a>
      </footer>
    </div>
  );
}

const SvgIcon = (props) => (
  <svg
    xmlns="http://www.w3.org/2000/svg"
    width="24"
    height="24"
    viewBox="0 0 24 24"
    fill="white"
  >
    <path
      d="m20.59 12-3.3-3.3a1 1 0 1 1 1.42-1.4l4 4a1 1 0 0 1 0 1.4l-4 4a1 1 0 0 1-1.42-1.4zM3.4 12l3.3 3.3a1 1 0 0 1-1.42 1.4l-4-4a1 1 0 0 1 0-1.4l4-4A1 1 0 0 1 6.7 8.7zm7.56 8.24a1 1 0 0 1-1.94-.48l4-16a1 1 0 1 1 1.94.48z"
      className="heroicon-ui"
    ></path>
  </svg>
);


================================================
FILE: src/components/Probe.js
================================================
import React, { useRef } from "react";
import { useGLTF } from "@react-three/drei";

export function Probe(props) {
  const { nodes, materials } = useGLTF("/probe-transformed.glb");
  const lightMaterial = materials.light.clone();
  lightMaterial.emissiveIntensity = 10;
  lightMaterial.emissive.set(props.color);

  return (
    <group {...props} dispose={null}>
      <group position={[-0.423, 0.036, -0.084]} rotation={[-Math.PI / 2, 0, 0]}>
        <mesh
          castShadow
          receiveShadow
          geometry={nodes["cam_low_Material_#26_0_1"].geometry}
          material={materials.Material_26}
        />
        <mesh
          castShadow
          receiveShadow
          geometry={nodes["cam_low_Material_#26_0_2"].geometry}
          material={lightMaterial}
        />
      </group>
      <mesh
        castShadow
        receiveShadow
        geometry={nodes["ball_low_Material_#26_0"].geometry}
        material={materials.Material_26}
        position={[-0.423, 0.036, -0.084]}
        rotation={[-Math.PI / 2, 0, 0]}
      />
      <mesh
        castShadow
        receiveShadow
        geometry={nodes["d_low_Material_#26_0"].geometry}
        material={materials.Material_26}
        position={[-0.423, 0.036, -0.084]}
        rotation={[-Math.PI / 2, 0, 0]}
      />
      <mesh
        castShadow
        receiveShadow
        geometry={nodes["inner_low_Material_#26_0"].geometry}
        material={materials.Material_26}
        position={[-0.211, -0.033, 7.813]}
        rotation={[-Math.PI / 2, 0, 0]}
      />
      <mesh
        castShadow
        receiveShadow
        geometry={nodes["Object018_Material_#26_0"].geometry}
        material={lightMaterial}
        position={[-0.423, 0.036, -0.084]}
        rotation={[-Math.PI / 2, 0, 0]}
      />
      <mesh
        castShadow
        receiveShadow
        geometry={nodes["shell_low_Material_#26_0"].geometry}
        position={[-0.423, 0.036, -0.084]}
        rotation={[-Math.PI / 2, 0, 0]}
      >
        <meshPhysicalMaterial
          color="white"
          roughness={0.35}
          metalness={1}
          clearcoat={1}
        />
      </mesh>
    </group>
  );
}

useGLTF.preload("/probe-transformed.glb");


================================================
FILE: src/components/ResizeHandler.js
================================================
import { useEffect } from "react";

export function ResizeHandler({ quality, rendererRef }) {
  useEffect(() => {
    const handleResize = () => {
      if (rendererRef.current) {
        rendererRef.current.setSize(window.innerWidth, window.innerHeight);
      }
    };

    window.addEventListener("resize", handleResize);

    // Cleanup
    return () => window.removeEventListener("resize", handleResize);
  }, [quality]);

  return null;
}


================================================
FILE: src/components/Royal.js
================================================
/*
Auto-generated by: https://github.com/pmndrs/gltfjsx
Command: npx gltfjsx@6.1.4 naboo_royal_starship.glb --transform --simplify
Author: hobbit84 (https://sketchfab.com/hobbit84)
License: CC-BY-NC-4.0 (http://creativecommons.org/licenses/by-nc/4.0/)
Source: https://sketchfab.com/3d-models/naboo-royal-starship-j-type-327-nubian-f631077977754b5591298ecfa201380b
Title: Naboo Royal Starship (J-type 327 Nubian)
*/

import React from "react";
import { Float, useGLTF } from "@react-three/drei";
import { AdditiveBlending, DoubleSide } from "three";
import { useJetEngineMaterial } from "./JetEngineMaterial";

export default function RoyalNaboo(props) {
  const { nodes, materials } = useGLTF("/naboo_royal_starship-transformed.glb");
  const { key, colorNode } = useJetEngineMaterial();

  materials["blinn1.002"].roughness = 0.15;
  materials["blinn1.002"].metalness = 1;
  materials["blinn1.002"].roughnessMap = null;

  return (
    <Float speed={2} floatIntensity={0.2} rotationIntensity={0.3}>
      <group {...props} dispose={null}>
        <group position={[-0.01, 0, 6.5]} rotation={[-Math.PI / 2, 0, Math.PI]}>
          <mesh
            castShadow
            receiveShadow
            geometry={nodes.Object_2.geometry}
            material={materials["Material.002"]}
          />
          <mesh
            castShadow
            receiveShadow
            geometry={nodes.Object_3.geometry}
            material={materials["aiwindow.002"]}
          />
          <mesh
            castShadow
            receiveShadow
            geometry={nodes.Object_4.geometry}
            material={materials["blinn1.002"]}
          />
          <mesh
            castShadow
            receiveShadow
            geometry={nodes.Object_5.geometry}
            material={materials["blinn1.002"]}
          />
          <mesh
            castShadow
            receiveShadow
            geometry={nodes.Object_6.geometry}
            material={materials["blinn1.002"]}
          />
          <mesh position={[-1.48, -4.1, -0.36]}>
            <cylinderGeometry args={[0.2, 0.01, 2.9, 16, 8, true]} />
            <meshStandardNodeMaterial
              key={key}
              colorNode={colorNode}
              transparent
              blending={AdditiveBlending}
              side={DoubleSide}
              emissiveNode={colorNode}
            />
          </mesh>
          <mesh position={[1.48, -4.1, -0.36]}>
            <cylinderGeometry args={[0.2, 0.01, 2.9, 16, 8, true]} />
            <meshStandardNodeMaterial
              key={key}
              colorNode={colorNode}
              transparent
              blending={AdditiveBlending}
              side={DoubleSide}
              emissiveNode={colorNode}
            />
          </mesh>
          <mesh
            rotation={[Math.PI / 2, 0, 0]}
            position={[1.51, -2.68, -0.37]}
            renderOrder={-1}
          >
            <torusGeometry args={[0.2, 0.03, 24, 24]} />
            <meshStandardNodeMaterial
              color="red"
              transparent
              emissive="cyan"
              emissiveIntensity={10}
            />
          </mesh>
          <mesh
            rotation={[Math.PI / 2, 0, 0]}
            position={[-1.5, -2.68, -0.36]}
            renderOrder={-1}
          >
            <torusGeometry args={[0.2, 0.03, 24, 24]} />
            <meshStandardNodeMaterial
              color="cyan"
              transparent
              emissive="cyan"
              emissiveIntensity={10}
            />
          </mesh>
        </group>
      </group>
    </Float>
  );
}

useGLTF.preload("/naboo_royal_starship-transformed.glb");


================================================
FILE: src/components/VaderScene.js
================================================
import { Float } from "@react-three/drei";
import { Probe } from "./Probe";
import { Darth } from "./Darth";

export function VaderScene() {
  return (
    <>
      <Float speed={3.5} floatIntensity={0.2} rotationIntensity={0.3}>
        <Probe
          position={[3, 0, 1.2]}
          scale={0.05}
          rotation={[0, Math.PI / 2, 0]}
          color="red"
        />
      </Float>
      <Float speed={6.5} floatIntensity={0.4} rotationIntensity={0.5}>
        <Probe
          position={[-1.5, 0, -1.5]}
          scale={0.1}
          rotation={[0, Math.PI / 2, 0]}
          color="cyan"
        />
      </Float>
      <Float speed={3.5} floatIntensity={0.2} rotationIntensity={0.3}>
        <Probe
          position={[3.5, -0.8, -1.2]}
          scale={0.05}
          rotation={[0, Math.PI / 2, 0]}
          color="red"
        />
      </Float>
      <Float speed={3.5} floatIntensity={1.5} rotationIntensity={0.4}>
        <Probe
          position={[3, 0.2, -2.8]}
          scale={0.05}
          rotation={[0, Math.PI / 2 - 0.2, 0.1]}
          color="cyan"
        />
      </Float>
      <Float speed={3.5} floatIntensity={1.5} rotationIntensity={0.4}>
        <Probe
          position={[2.6, 0.2, 2.8]}
          scale={0.05}
          rotation={[0, Math.PI / 2 + 0.5, 0.1]}
          color="cyan"
        />
      </Float>
      <Darth
        scale={0.008}
        position={[3.5, -1.325, 0.4]}
        rotation={[0, Math.PI / 2, 0]}
      />
    </>
  );
}


================================================
FILE: src/components/WebGPUPostProcessing.js
================================================
import * as THREE from "three/webgpu";
import {
  pass,
  mrt,
  output,
  transformedNormalView,
  metalness,
  blendColor,
  depth,
  emissive,
} from "three/tsl";
import { bloom } from "three/addons/tsl/display/BloomNode.js";
import { ssr } from "three/addons/tsl/display/SSRNode.js";
import { smaa } from "three/addons/tsl/display/SMAANode.js";
import { useThree, useFrame } from "@react-three/fiber";
import { useEffect, useRef } from "react";

export function WebGPUPostProcessing({
  strength = 2.5,
  radius = 0.5,
  quality = "default",
}) {
  const { gl: renderer, scene, camera, size } = useThree();
  const postProcessingRef = useRef(null);

  useEffect(() => {
    if (!renderer || !scene || !camera) return;

    // Create post-processing setup with specific filters
    const scenePass = pass(scene, camera, {
      minFilter: THREE.LinearFilter,
      magFilter: THREE.LinearFilter,
    });

    // Setup Multiple Render Targets (MRT)
    scenePass.setMRT(
      mrt({
        output: output,
        normal: transformedNormalView,
        metalness: metalness,
        emissive: emissive,
      })
    );

    // Get texture nodes
    const scenePassColor = scenePass.getTextureNode("output");
    const scenePassNormal = scenePass.getTextureNode("normal");
    const scenePassDepth = scenePass.getTextureNode("depth");
    const scenePassMetalness = scenePass.getTextureNode("metalness");
    const scenePassEmissive = scenePass.getTextureNode("emissive");

    // Create SSR pass
    const ssrPass = ssr(
      scenePassColor,
      scenePassDepth,
      scenePassNormal,
      scenePassMetalness,
      camera
    );
    ssrPass.resolutionScale = 0.65;
    ssrPass.maxDistance.value = 0.65;
    ssrPass.opacity.value = 0.85;
    ssrPass.thickness.value = 0.015;

    // Create bloom pass
    const bloomPass = bloom(scenePassEmissive, strength, radius, 0.6);

    // Blend SSR over beauty with SMAA
    const outputNode = smaa(blendColor(scenePassColor.add(bloomPass), ssrPass));

    // Setup post-processing
    const postProcessing = new THREE.PostProcessing(renderer);
    postProcessing.outputNode = outputNode;
    postProcessingRef.current = postProcessing;

    // Handle window resize

    if (postProcessingRef.current.setSize) {
      postProcessingRef.current.setSize(size.width, size.height);
      postProcessingRef.current.needsUpdate = true;
    }

    return () => {
      postProcessingRef.current = null;
    };
  }, [renderer, scene, camera, size, strength, radius, quality]);

  useFrame(({ gl, scene, camera }) => {
    if (postProcessingRef.current) {
      gl.clear();
      postProcessingRef.current.render();
    }
  }, 1);

  return null;
}


================================================
FILE: src/index.js
================================================
import { createRoot } from 'react-dom/client'
import './styles.css'
import App from './App'

createRoot(window.root).render(<App />)


================================================
FILE: src/styles.css
================================================
@import url("https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap");

:root {
  --bg-background: #111827;
  --clr-card: #1f2937;
  --clr-1: #6420aa;
  --clr-2: #ff3ea5;
  --clr-3: #ff7ed4;
}

* {
  box-sizing: border-box;
}

html,
body,
canvas {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  font-family: "Inter", sans-serif;
  overflow: hidden;
  touch-action: none;
}

body {
  background: #020202;
}

.overlay {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 1000;
  pointer-events: none;
  display: flex;
  justify-content: center;
  align-items: flex-start;
}

header {
  background-image: linear-gradient(
    to bottom,
    #020202,
    rgba(0, 0, 0, 0.775),
    #02020200
  );
  width: 100%;
  height: 170px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

header h1 {
  margin: 0;
  padding: 0;
  color: white;
  font-size: 3rem;
  font-weight: 300;
  letter-spacing: -0.04em;
  text-transform: uppercase;
  text-align: center;
}

header h1 span {
  font-weight: 900;
}

header p {
  color: white;
  font-size: 0.8rem;
  font-weight: 200;
  letter-spacing: -0.04em;
  text-align: center;
  margin-top: 0.5rem;
  padding: 0;
  max-width: 500px;
}

footer {
  width: 100%;
  height: 110px;
  display: flex;
  justify-content: center;
  align-items: center;
  position: absolute;
  bottom: 0;
}

.footer-buttons {
  display: flex;
  gap: 2rem;
}

@property --gradient-angle {
  syntax: "<angle>";
  initial-value: 90deg;
  inherits: false;
}

footer button {
  color: white;
  padding: 1rem 1.3rem;
  border-radius: 0.5rem;
  box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
  font-size: 0.45rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: 300;
  pointer-events: all;
  cursor: pointer;
  position: relative;
  cursor: pointer;
  border: none;
  border-radius: 50px;
  background-color: var(--clr-card);
  transition: all 0.3s ease;
}

footer button:hover {
  background: rgb(65, 60, 79);
  color: white;
}

footer button:hover:after {
  transform: scale(1.5);
  filter: blur(2rem);
  transition: all 0.3s ease;
}

footer button::after,
footer button::before {
  content: " ";
  position: absolute;
  z-index: -1;
  inset: -0.06rem;
  background: conic-gradient(
    from var(--gradient-angle),
    var(--clr-card),
    var(--clr-1),
    var(--clr-2),
    var(--clr-3),
    var(--clr-2),
    var(--clr-1),
    var(--clr-card)
  );
  border-radius: inherit;
  animation: rotate 2.5s ease-in-out infinite;
  transition: all 0.3s ease;
}

footer button.toggle::before {
  content: " ";
  position: absolute;
  z-index: -1;
  inset: -0.06rem;
  background: conic-gradient(
    from var(--gradient-angle),
    var(--clr-card),
    var(--clr-1),
    var(--clr-2),
    var(--clr-3),
    var(--clr-2),
    var(--clr-1),
    var(--clr-card)
  );
  border-radius: inherit;
  animation: rotate2 3.5s ease-in-out infinite;
  transition: all 0.3s ease;
}

footer button::after {
  filter: blur(3rem);
}

@keyframes rotate {
  0% {
    --gradient-angle: 0deg;
  }
  100% {
    --gradient-angle: 360deg;
  }
}

@keyframes rotate2 {
  0% {
    --gradient-angle: 0deg;
  }
  50% {
    --gradient-angle: 120deg;
  }
  100% {
    --gradient-angle: 360deg;
  }
}

.footer-text {
  color: white;
  font-size: 0.8rem;
  font-weight: 200;
  letter-spacing: -0.04em;
  text-align: center;
  padding: 0;
  position: absolute;
  bottom: 20px;
  left: 20px;
  width: max-content;
  opacity: 0.3;
}

.footer-text a {
  color: white;
  font-weight: 400;
  text-decoration: none;
  pointer-events: all;
}

.download-button {
  position: fixed;
  bottom: 20px;
  right: 20px;
  background-color: transparent;
  border: 1px solid white;
  border-radius: 50px;
  padding: 10px 10px;
  text-align: center;
  cursor: pointer;
  z-index: 1000;
  pointer-events: all;
  display: flex;
  opacity: 0.3;
}

.download-button img {
  width: 20px;
  height: 20px;
  vertical-align: middle;
}

.download-button:hover {
  background-color: #ffffff7b;
}

/* Mobile */
@media (max-width: 768px) {
  header h1 {
    font-size: 2.5rem;
  }

  header p {
    font-size: 0.9rem;
    max-width: 300px;
  }
  .download-button {
    display: none;
  }

  .footer-buttons {
    gap: 0.5rem;
  }
  footer {
    height: 150px;
  }

  footer button {
    padding: 0.9rem 1.3rem;
    font-size: 0.5rem;
  }

  footer button.toggle-quality {
    display: none;
  }

  .footer-text {
    font-size: 0.6rem;
    bottom: 10px;
    left: 50%;
    transform: translateX(-50%);
  }
}
Download .txt
gitextract_zhgr58d5/

├── .gitignore
├── README.md
├── package.json
├── public/
│   ├── darth-transformed.glb
│   ├── favicon/
│   │   ├── about.txt
│   │   └── site.webmanifest
│   ├── hall-transformed.glb
│   ├── index.html
│   ├── naboo_royal_starship-transformed.glb
│   └── probe-transformed.glb
└── src/
    ├── App.js
    ├── components/
    │   ├── Darth.js
    │   ├── Hall.js
    │   ├── JetEngineMaterial.js
    │   ├── Light_Environment.js
    │   ├── ManciniCanvas.js
    │   ├── Overlay.js
    │   ├── Probe.js
    │   ├── ResizeHandler.js
    │   ├── Royal.js
    │   ├── VaderScene.js
    │   └── WebGPUPostProcessing.js
    ├── index.js
    └── styles.css
Download .txt
SYMBOL INDEX (12 symbols across 12 files)

FILE: src/App.js
  function App (line 11) | function App() {

FILE: src/components/Darth.js
  function Darth (line 12) | function Darth(props) {

FILE: src/components/Hall.js
  function Hall (line 8) | function Hall(props) {

FILE: src/components/JetEngineMaterial.js
  function useJetEngineMaterial (line 20) | function useJetEngineMaterial() {

FILE: src/components/Light_Environment.js
  function Light_Environment (line 4) | function Light_Environment() {

FILE: src/components/ManciniCanvas.js
  function ManciniCanvas (line 8) | function ManciniCanvas({ quality, children }) {

FILE: src/components/Overlay.js
  function Overlay (line 1) | function Overlay({

FILE: src/components/Probe.js
  function Probe (line 4) | function Probe(props) {

FILE: src/components/ResizeHandler.js
  function ResizeHandler (line 3) | function ResizeHandler({ quality, rendererRef }) {

FILE: src/components/Royal.js
  function RoyalNaboo (line 15) | function RoyalNaboo(props) {

FILE: src/components/VaderScene.js
  function VaderScene (line 5) | function VaderScene() {

FILE: src/components/WebGPUPostProcessing.js
  function WebGPUPostProcessing (line 18) | function WebGPUPostProcessing({
Condensed preview — 24 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (38K chars).
[
  {
    "path": ".gitignore",
    "chars": 2055,
    "preview": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\nlerna-debug.log*\n.pnpm-debug.log*\n\n# Diagnostic reports"
  },
  {
    "path": "README.md",
    "chars": 1211,
    "preview": "# React Three Fiber WebGPU Post Processing\n\n<h4>by Anderson Mancini</h4>\n\n[![screenshot](https://r3f-webgpu-post-process"
  },
  {
    "path": "package.json",
    "chars": 875,
    "preview": "{\n  \"name\": \"basic-demo\",\n  \"version\": \"1.0.0\",\n  \"description\": \"Shows how to form self-contained components with their"
  },
  {
    "path": "public/favicon/about.txt",
    "chars": 400,
    "preview": "This favicon was generated using the following graphics from Twitter Twemoji:\n\n- Graphics Title: 1f441-200d-1f5e8.svg\n- "
  },
  {
    "path": "public/favicon/site.webmanifest",
    "chars": 263,
    "preview": "{\"name\":\"\",\"short_name\":\"\",\"icons\":[{\"src\":\"/android-chrome-192x192.png\",\"sizes\":\"192x192\",\"type\":\"image/png\"},{\"src\":\"/"
  },
  {
    "path": "public/index.html",
    "chars": 2659,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <meta\n      name=\"viewport\"\n      content=\"wi"
  },
  {
    "path": "src/App.js",
    "chars": 1923,
    "preview": "import { useState } from \"react\";\nimport { Loader } from \"@react-three/drei\";\nimport { WebGPUPostProcessing } from \"./co"
  },
  {
    "path": "src/components/Darth.js",
    "chars": 2277,
    "preview": "/*\nAuto-generated by: https://github.com/pmndrs/gltfjsx\nAuthor: AFTONBLADET (https://sketchfab.com/wallander)\nLicense: C"
  },
  {
    "path": "src/components/Hall.js",
    "chars": 2393,
    "preview": "/*\nAuto-generated by: https://github.com/pmndrs/gltfjsx\n*/\n\nimport React, { useRef } from \"react\";\nimport { useGLTF } fr"
  },
  {
    "path": "src/components/JetEngineMaterial.js",
    "chars": 2006,
    "preview": "import { useFrame } from \"@react-three/fiber\";\nimport {\n  uniform,\n  float,\n  vec2,\n  sin,\n  cos,\n  uv,\n  mod,\n  div,\n  "
  },
  {
    "path": "src/components/Light_Environment.js",
    "chars": 992,
    "preview": "import { Environment } from \"@react-three/drei\";\nimport { OrbitControls } from \"@react-three/drei\";\n\nexport function Lig"
  },
  {
    "path": "src/components/ManciniCanvas.js",
    "chars": 1239,
    "preview": "import { Canvas, extend } from \"@react-three/fiber\";\nimport { useRef, useState } from \"react\";\nimport * as THREE from \"t"
  },
  {
    "path": "src/components/Overlay.js",
    "chars": 2003,
    "preview": "export function Overlay({\n  isPostProcessingEnabled,\n  setIsPostProcessingEnabled,\n  currentScene,\n  setCurrentScene,\n  "
  },
  {
    "path": "src/components/Probe.js",
    "chars": 2209,
    "preview": "import React, { useRef } from \"react\";\nimport { useGLTF } from \"@react-three/drei\";\n\nexport function Probe(props) {\n  co"
  },
  {
    "path": "src/components/ResizeHandler.js",
    "chars": 445,
    "preview": "import { useEffect } from \"react\";\n\nexport function ResizeHandler({ quality, rendererRef }) {\n  useEffect(() => {\n    co"
  },
  {
    "path": "src/components/Royal.js",
    "chars": 3656,
    "preview": "/*\nAuto-generated by: https://github.com/pmndrs/gltfjsx\nCommand: npx gltfjsx@6.1.4 naboo_royal_starship.glb --transform "
  },
  {
    "path": "src/components/VaderScene.js",
    "chars": 1485,
    "preview": "import { Float } from \"@react-three/drei\";\nimport { Probe } from \"./Probe\";\nimport { Darth } from \"./Darth\";\n\nexport fun"
  },
  {
    "path": "src/components/WebGPUPostProcessing.js",
    "chars": 2688,
    "preview": "import * as THREE from \"three/webgpu\";\nimport {\n  pass,\n  mrt,\n  output,\n  transformedNormalView,\n  metalness,\n  blendCo"
  },
  {
    "path": "src/index.js",
    "chars": 133,
    "preview": "import { createRoot } from 'react-dom/client'\nimport './styles.css'\nimport App from './App'\n\ncreateRoot(window.root).ren"
  },
  {
    "path": "src/styles.css",
    "chars": 4600,
    "preview": "@import url(\"https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=s"
  }
]

// ... and 4 more files (download for full content)

About this extraction

This page contains the full source code of the ektogamat/r3f-webgpu-starter GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 24 files (34.7 KB), approximately 10.6k tokens, and a symbol index with 12 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!