Gaussian Splatting, React Three Fiber
February 7, 2024
February 7, 2024
A feladat során a React Three Fiber segítségével gaussian splatting-et fogunk megjeleníteni.
POWERSHELLnpm create vite@latest
React + typescript + SWC választása
POWERSHELLnpm install three @types/three @react-three/fiber
A projekt miatt, még szükséges a következők instalálása:
POWERSHELLnpm install @react-three/drei
Ebbe a fejezetbe beállítjuk a környezetet és a dobozokat amibe az objektumokat fogjuk tárolni.
PLAIN TEXT//src/index.css* {box-sizing: border-box;}html,body,#root {width: 100%;height: 100%;margin: 0;padding: 0;}body {overscroll-behavior: none;background: #f0f0f0;font-family: "Inter";}
A Canvas komponens létrehoz egy 3D renderelési teret, amelyen belül a 3D szcénánk fog megjelenni. A camera prop beállításai definiálják a kamera pozícióját, látószögét, és a renderelés mélységét (közeli és távoli klipping síkok). Egyszerű glb fájlok hozzáadása a Canvas-hoz amik a glb és gaussian splatting objektumokat fogják tárolni.
Az Environment komponens egy HDR (High Dynamic Range) képet használ a környezeti fényforrásként, ami realisztikusabb megvilágítást és reflexiókat biztosít. A Lightformer komponensek különböző formájú és intenzitású fényforrásokat adnak a szcénához, tovább növelve a vizuális hatást.
A ContactShadows komponens árnyékokat generál az objektumok alá, ami mélységet és térérzetet ad a szcénának. A CameraControls lehetővé teszi a felhasználó számára, hogy interaktívan mozogjon és zoomoljon a kamerával a 3D térben, növelve ezzel a szcéna interaktivitását.
A Preload komponens előtölti az összes szükséges erőforrást, hogy a felhasználói élmény gördülékeny legyen, és csökkentse a betöltési időt amikor a felhasználó először látogatja meg az oldalt.
TYPESCRIPT//src/App.tsximport { Canvas } from "@react-three/fiber";import {Preload,Lightformer,Environment,CameraControls,ContactShadows,} from "@react-three/drei";import Aquarium from "./components/Aquarium";export default function App() {return (<Canvasdpr={[1.5, 2]}camera={{ position: [50, 5, -10], fov: 45, near: 1, far: 300 }}><Aquarium position={[-0.1, 10.8, 3]} rotation={[Math.PI / 2, 0, 0]}></Aquarium><Aquarium position={[0, 0, 0]} rotation={[0, 0, 0]}></Aquarium><Environmentfiles="https://dl.polyhaven.org/file/ph-assets/HDRIs/hdr/1k/dancing_hall_1k.hdr"resolution={1024}>{/** On top of the HDRI we add some rectangular and circular shapes for nicer reflections */}<group rotation={[-Math.PI / 3, 0, 0]}><Lightformerintensity={4}rotation-x={Math.PI / 2}position={[0, 5, -9]}scale={[10, 10, 1]}/>{[2, 0, 2, 0, 2, 0, 2, 0].map((x, i) => (<Lightformerkey={i}form="circle"intensity={4}rotation={[Math.PI / 2, 0, 0]}position={[x, 4, i * 4]}scale={[4, 1, 1]}/>))}<Lightformerintensity={2}rotation-y={Math.PI / 2}position={[-5, 1, -1]}scale={[50, 2, 1]}/><Lightformerintensity={2}rotation-y={-Math.PI / 2}position={[10, 1, 0]}scale={[50, 2, 1]}/></group></Environment><ContactShadowssmooth={false}scale={100}position={[0, -5.05, 0]}blur={0.5}opacity={0.75}/><CameraControlsmakeDefaultdollyToCursorminPolarAngle={0}maxPolarAngle={Math.PI / 2}/><Preload all /></Canvas>);}
A useRef hook segítségével egy referenciát hoz létre a csoport (group) objektumra, amit a szcénában lévő összes objektum tárolására és manipulálására használ. A useMask hook pedig egy stencil maszkot hoz létre, amit az objektumok anyagának manipulálására használ, hogy speciális renderelési effekteket érjen el, mint például a transzmissziós anyagok megjelenítése.
A useLayoutEffect hook segítségével a komponens beállítja az egyes mesh-ek (hálók) anyagát a maszkkal, amint a DOM felépült, biztosítva, hogy a 3D objektumok a megfelelő anyagbeállításokkal jelenjenek meg. Ez a folyamat dinamikusan módosítja az anyag tulajdonságait, így azok megfelelnek a stencil maszk által meghatározott viselkedésnek.
A MeshTransmissionMaterial egy speciális anyag, amit a @react-three/drei biztosít, és lehetővé teszi a fény áteresztését a 3D objektumon, létrehozva ezzel egy üvegszerű, átlátszó hatást, ami tökéletesen illik egy akvárium vizualizációjához. Ez az anyag számos paraméterrel rendelkezik, mint például a mintavételezés (samples), vastagság (thickness), kromatikus aberráció (chromaticAberration), és több más, ami lehetővé teszi a vizuális effektusok finomhangolását.
TYPESCRIPT//src/components/Aquarium.tsximport { useLayoutEffect, useRef } from "react";import { MeshTransmissionMaterial, useGLTF, useMask } from "@react-three/drei";import { Group, Mesh } from "three";import { GLTF } from "three/examples/jsm/loaders/GLTFLoader.js";type AquariumProps = JSX.IntrinsicElements["group"] & {children: React.ReactNode;};interface GLTFResult extends GLTF {nodes: {[name: string]: THREE.Mesh;};animations: THREE.AnimationClip[];}const Aquarium: React.FC<AquariumProps> = ({ children, ...props }) => {const ref = useRef<Group>(null);const { nodes } = useGLTF("/shapes-transformed.glb") as unknown as GLTFResult;const stencil = useMask(1, false);useLayoutEffect(() => {if (ref.current) {ref.current.traverse((child: THREE.Object3D) => {if ((child as Mesh).isMesh) {// Now TypeScript knows 'child' is a Mesh, so 'child.material' is safe to accessconst mesh = child as Mesh;if (Array.isArray(mesh.material)) {mesh.material.forEach((material) =>Object.assign(material, stencil));} else {Object.assign(mesh.material, stencil);}}});}}, [stencil]);return (<group {...props} dispose={null}><meshcastShadowscale={[0.61 * 6, 0.8 * 6, 1 * 6]}geometry={nodes.Cube.geometry}><MeshTransmissionMaterialbacksidesamples={4}thickness={3}chromaticAberration={0.025}anisotropy={0.1}distortion={0.1}distortionScale={0.1}temporalDistortion={0.2}iridescence={1}iridescenceIOR={1}iridescenceThicknessRange={[0, 1400]}/></mesh><group ref={ref}>{children}</group></group>);};export default Aquarium;
Az Aquarium komponens végül létrehoz egy csoportot, amely tartalmazza a 3D modellt és az opcionálisan hozzáadott gyermek komponenseket, lehetővé téve a felhasználó számára, hogy további elemeket helyezzen el az akváriumban, így növelve a szcéna komplexitását és interaktivitását.
A GlbShoe funkcionális komponens a cipő modelljét és anyagát használja fel a useGLTF hook segítségével betöltött adatok alapján. A modell több különböző geometriai részből áll (például a fűzők, háló, talp stb.), amelyeket külön-külön adják hozzá a szcénához mesh elemekként. Mindegyik mesh elem saját geometriát és anyagot kap, valamint egy egyedi színt (material-color), ami lehetővé teszi a részletek kiemelését és a modell általános vizuális megjelenésének személyre szabását.
A ref hook segítségével egy referencia objektumot hoz létre a csoport (group) számára, ami lehetővé teszi a komponensben lévő összes mesh kezelését egyetlen egységként. A csoport pozícióját, méretarányát és forgatását is beállítja, hogy megfelelően jelenjen meg a szcénában.
TYPESCRIPT//src/components/GlbShoe.tsximport React, { useRef } from "react";import { Float, useGLTF } from "@react-three/drei";import { Group } from "three";import { GLTF } from "three/examples/jsm/loaders/GLTFLoader.js";const App: React.FC = () => {return (<><ambientLight intensity={0.3} /><Float rotationIntensity={2} floatIntensity={10} speed={2}><GlbShoe /></Float></>);};type GLTFResult = GLTF & {nodes: {[name: string]: THREE.Mesh;};materials: {[name: string]: THREE.Material;};};const GlbShoe = () => {const ref = useRef<Group>(null);const { nodes, materials } = useGLTF("/shoe-draco.glb") as unknown as GLTFResult;return (<groupref={ref}scale={3}position={[0, 0, 0]}rotation={[-Math.PI / 2, Math.PI / 2, 0]}><meshreceiveShadowcastShadowgeometry={nodes.shoe.geometry}material={materials.laces}material-color="orange"/><meshreceiveShadowcastShadowgeometry={nodes.shoe_1.geometry}material={materials.mesh}material-color="red"/><meshreceiveShadowcastShadowgeometry={nodes.shoe_2.geometry}material={materials.caps}material-color="red"/><meshreceiveShadowcastShadowgeometry={nodes.shoe_3.geometry}material={materials.inner}material-color="orange"/><meshreceiveShadowcastShadowgeometry={nodes.shoe_4.geometry}material={materials.sole}material-color="white"/><meshreceiveShadowcastShadowgeometry={nodes.shoe_5.geometry}material={materials.stripes}material-color="orange"/><meshreceiveShadowcastShadowgeometry={nodes.shoe_6.geometry}material={materials.band}material-color="orange"/><meshreceiveShadowcastShadowgeometry={nodes.shoe_7.geometry}material={materials.patch}material-color="orange"/></group>);};export default App;
A Float komponens azt a hatást adja, hogy az objektum lágyan lebeg az alkalmazás 3D terében. Ez a viselkedés két paraméterrel szabályozható: a rotationIntensity (forgási intenzitás) és a floatIntensity (lebegési intenzitás) segítségével, valamint a speed (sebesség) paraméterrel, ami a lebegés sebességét állítja be.
A Splat komponens scale, position és rotation prop-okkal rendelkezik, amelyek lehetővé teszik a helyzetének, méretének és forgásának testreszabását a 3D térben. A src prop pedig a textúra URL-jét várja, amit a megjelenítéshez használ. Ebben az esetben a textúra forrása egy "https://huggingface.co/cakewalk/splat-data/resolve/main/nike.splat" URL, ami egy speciális formátumú fájl, ami a "splat" adatokat tartalmazza.
TYPESCRIPT//src/components/GaussianShoe.tsximport React from "react";import { Float, Splat } from "@react-three/drei";const App: React.FC = () => {return (<><ambientLight intensity={0.3} /><Float rotationIntensity={2} floatIntensity={10} speed={2}><Splatscale={2}position={[4, 3, 1]}rotation={[0, Math.PI / 2, 0]}src="https://huggingface.co/cakewalk/splat-data/resolve/main/nike.splat"/></Float></>);};export default App;
Hozzáadjuk a két új fájlt az előzőleg létre hozott akváriumunkhoz
TYPESCRIPT//src/App.tsx...import GaussianShoe from "./components/GaussianShoe";import GlbShoe from "./components/GlbShoe";export default function App() {return (<Canvasdpr={[1.5, 2]}camera={{ position: [50, 5, -10], fov: 45, near: 1, far: 300 }}><Aquarium position={[-0.1, 10.8, 3]} rotation={[Math.PI / 2, 0, 0]}><GlbShoe /></Aquarium><Aquarium position={[0, 0, 0]} rotation={[0, 0, 0]}><GaussianShoe /></Aquarium>...
Az általunk létrehozott két vizuális elem, egyrészt egy GLB formátumban tárolt cipő modell, másrészt egy Gaussian Splatting technikával előállított cipő, tökéletesen demonstrálja a két megközelítés közötti különbségeket és alkalmazási területeket. A GLB fájlból származó cipőmodell részletes és pontos megjelenítést nyújt, amely a digitális modellalkotás magas szintű precizitását tükrözi. Ez a fajta modell ideális választás lehet olyan alkalmazásokban, ahol a részletesség és a vizuális minőség elsődleges szempont, mint például a virtuális valóságban vagy a magas minőségű grafikát igénylő játékokban.
Ezzel szemben a Gaussian Splatting technikával előállított cipőmodell, bár kevésbé részletes, egy gyors és hatékony módszert kínál a 3D objektumok vizualizációjára. Ez a megközelítés különösen hasznos lehet olyan helyzetekben, ahol a sebesség és a hatékonyság fontosabb, mint a részletesség, például prototípusok gyors elkészítésénél.
A GLB modell előállítása általában több időt és erőforrást igényel, mivel részletes modellezési és textúrázási folyamatokon kell átesnie. Ezzel szemben a Gaussian Splatting egy viszonylag egyszerű algoritmussal képes gyorsan létrehozni a 3D elemeket, lehetővé téve az azonnali vizualizációt és iterációt.
A teljes kód megtalálható:
https://github.com/balazsfaragodev/GaussianSplatting-ReactThreeFiber
Oszd meg ezt a cikket
Indítsd a napod a legújabb technológiai áttörésekkel. Csatlakozz most, és merülj el az innovációban!