diff --git a/example/package.json b/example/package.json index b77d097..fa5d780 100644 --- a/example/package.json +++ b/example/package.json @@ -31,6 +31,7 @@ "@types/node": "^22.5.5", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", + "@types/three": "0.168.0", "@vitejs/plugin-react": "^4.3.1", "eslint": "^9.9.0", "eslint-plugin-react-hooks": "^5.1.0-rc.0", @@ -41,4 +42,4 @@ "vite": "^5.4.1", "vite-plugin-svgr": "^4.2.0" } -} +} \ No newline at end of file diff --git a/example/src/App.tsx b/example/src/App.tsx index 13fe710..d1acb88 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -1,3 +1,4 @@ +import * as THREE from "three"; import { AccumulativeShadows, Bounds, @@ -15,6 +16,7 @@ import { useShaderBaker } from "three-shader-baker/react"; +import { ShaderBaker as ShaderBakerImpl } from "three-shader-baker"; import { useEffect, useState } from "react"; import { EffectComposer } from "@react-three/postprocessing"; @@ -24,6 +26,8 @@ import { Clothes } from "./Clothes"; import { N8AO } from "./N8AO"; import { TextureViewer3D } from "./TextureViewer3D"; +const sb = new ShaderBakerImpl(); + function Thing() { const { bake } = useShaderBaker(); const [seed, setSeed] = useState(0); @@ -48,9 +52,49 @@ function Thing() { } export default function App() { + const [scene, setScene] = useState(null); + const [gl, setGl] = useState(null); + + function downloadGLTF() { + const exporter = sb.exportAsBakedGLTF(scene, gl); + exporter({ + onDone: (gltf) => { + const blob = new Blob([JSON.stringify(gltf)], { + type: "application/json" + }); + const url = URL.createObjectURL(blob); + + const link = document.createElement("a"); + link.href = url; + link.download = "scene.gltf"; + link.click(); + + URL.revokeObjectURL(url); + }, + onError: (error) => { + console.log(error); + } + }); + } + return ( <> + { + setScene(scene); + setGl(gl); + }} shadows camera={{ position: [-2, 1, 5] diff --git a/package/src/index.ts b/package/src/index.ts index e0ec177..ee7e0dc 100644 --- a/package/src/index.ts +++ b/package/src/index.ts @@ -1,4 +1,6 @@ import * as THREE from "three"; +import { GLTFExporter } from "three/examples/jsm/exporters/GLTFExporter"; + import { DilationMaterial } from "./DilationMaterial"; import { FullScreenQuad } from "./FullScreenQuad"; @@ -119,6 +121,32 @@ export class ShaderBaker { return targetFbo; } + + exportAsBakedGLTF( + scene: THREE.Scene, + gl: THREE.WebGLRenderer, + options?: BakeOptions + ): ({ + onDone, + onError + }: { + onDone: Parameters["parse"]>[1]; // onDone param + onError: Parameters["parse"]>[2]; // onError param + }) => any { + scene.traverse((object) => { + console.log(object); + if (object instanceof THREE.Mesh) { + const texture = this.bake(gl, object, options).texture; + object.material = new THREE.MeshBasicMaterial({ + ...object.material, + map: texture + }); + } + }); + + return ({ onDone, onError }) => + new GLTFExporter().parse(scene, onDone, onError); + } } export * from "./utils"; diff --git a/yarn.lock b/yarn.lock index 1c79535..58e04e0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1909,26 +1909,26 @@ resolved "https://registry.yarnpkg.com/@types/stats.js/-/stats.js-0.17.3.tgz#705446e12ce0fad618557dd88236f51148b7a935" integrity sha512-pXNfAD3KHOdif9EQXZ9deK82HVNaXP5ZIF5RP2QG6OQFNTaY2YIetfrE9t528vEreGQvEPRDDc8muaoYeK0SxQ== -"@types/three@^0.163.0": - version "0.163.0" - resolved "https://registry.yarnpkg.com/@types/three/-/three-0.163.0.tgz#96f5440fcd39452d2c84dfe0c9b7a9cf0247b9e6" - integrity sha512-uIdDhsXRpQiBUkflBS/i1l3JX14fW6Ot9csed60nfbZNXHDTRsnV2xnTVwXcgbvTiboAR4IW+t+lTL5f1rqIqA== +"@types/three@0.168.0", "@types/three@^0.168.0": + version "0.168.0" + resolved "https://registry.yarnpkg.com/@types/three/-/three-0.168.0.tgz#510420c4bbee7937bbbcdfbc5dc31160771eaef8" + integrity sha512-qAGLGzbaYgkkonOBfwOr+TZpOskPfFjrDAj801WQSVkUz0/D9zwir4vhruJ/CC/GteywzR9pqeVVfs5th/2oKw== dependencies: - "@tweenjs/tween.js" "~23.1.1" + "@tweenjs/tween.js" "~23.1.3" "@types/stats.js" "*" "@types/webxr" "*" + "@webgpu/types" "*" fflate "~0.8.2" meshoptimizer "~0.18.1" -"@types/three@^0.168.0": - version "0.168.0" - resolved "https://registry.yarnpkg.com/@types/three/-/three-0.168.0.tgz#510420c4bbee7937bbbcdfbc5dc31160771eaef8" - integrity sha512-qAGLGzbaYgkkonOBfwOr+TZpOskPfFjrDAj801WQSVkUz0/D9zwir4vhruJ/CC/GteywzR9pqeVVfs5th/2oKw== +"@types/three@^0.163.0": + version "0.163.0" + resolved "https://registry.yarnpkg.com/@types/three/-/three-0.163.0.tgz#96f5440fcd39452d2c84dfe0c9b7a9cf0247b9e6" + integrity sha512-uIdDhsXRpQiBUkflBS/i1l3JX14fW6Ot9csed60nfbZNXHDTRsnV2xnTVwXcgbvTiboAR4IW+t+lTL5f1rqIqA== dependencies: - "@tweenjs/tween.js" "~23.1.3" + "@tweenjs/tween.js" "~23.1.1" "@types/stats.js" "*" "@types/webxr" "*" - "@webgpu/types" "*" fflate "~0.8.2" meshoptimizer "~0.18.1"