From 14b14f09e384c667d7bfbd8441177997ba10fc12 Mon Sep 17 00:00:00 2001 From: brookee Date: Mon, 26 Feb 2024 06:52:46 -0500 Subject: [PATCH] gsplat --- content/posts/gsplat.md | 39 +++++++++++++++++++++ static/posts/gsplat/index.js | 39 +++++++++++++++++++++ static/posts/gsplat/style.css | 65 +++++++++++++++++++++++++++++++++++ 3 files changed, 143 insertions(+) create mode 100644 content/posts/gsplat.md create mode 100644 static/posts/gsplat/index.js create mode 100644 static/posts/gsplat/style.css diff --git a/content/posts/gsplat.md b/content/posts/gsplat.md new file mode 100644 index 0000000..bcfad27 --- /dev/null +++ b/content/posts/gsplat.md @@ -0,0 +1,39 @@ ++++ +title = "GSplat Demo" +date = "2024-02-24" +author = "Brooke" +description = "Messing around with gsplat.js from huggingface.co" +TOC = false ++++ + +# What is all of this? + +I've been interested in [photogrammetry](https://en.wikipedia.org/wiki/Photogrammetry) and projection scanning for quite a while, but I've never really had a good way of capturing things a bit more artistically. GSplatting, or [3D Gaussian Splatting](https://repo-sam.inria.fr/fungraph/3d-gaussian-splatting/), is a form of capturing scenes in a way that preserves the visual quality but doesn't provide an actual [polygonal](https://en.wikipedia.org/wiki/Polygonal_modeling) model. + +Unlike photogrammetry, GSplatting provides a fairly realistic gaussian of the captured scene that can be viewed using very little computational resources, this is a big reason why Nvidia is investing time into NeRF (actually something completely different but they're similar in output). + +Anyways, here's a quick demo that allows you to view models in a browser, I may add a few different gaussians that I've been working on, but currently I'm borrowing `bonsai-7k-mini.splat`. You can check out the code [here](https://git.myco.systems/mycosystems/coop.myco.systems/src/branch/main/content/posts/gsplat.md), and [here](https://git.myco.systems/mycosystems/coop.myco.systems/src/branch/main/static/posts/gsplat). + +{{< rawhtml >}} + + + + + +
+
+ +

+ +

+ +
+
+ + +
+ + gsplat.js left click rotate, right click pan + +{{< /rawhtml >}} + diff --git a/static/posts/gsplat/index.js b/static/posts/gsplat/index.js new file mode 100644 index 0000000..71761d4 --- /dev/null +++ b/static/posts/gsplat/index.js @@ -0,0 +1,39 @@ +import * as SPLAT from "https://cdn.jsdelivr.net/npm/gsplat@latest"; + +const canvas = document.getElementById("canvas"); +const progressDialog = document.getElementById("progress-dialog"); +const progressIndicator = document.getElementById("progress-indicator"); +const loadButton = document.querySelector("#load-button"); +const loadingLabel = document.querySelector('#progress-dialog label'); + +const renderer = new SPLAT.WebGLRenderer(canvas); +const scene = new SPLAT.Scene(); +const camera = new SPLAT.Camera(); +const controls = new SPLAT.OrbitControls(camera, canvas); + +loadButton.addEventListener('click', () => { + loadingLabel.textContent = 'Loading...'; + main(); +}); + +async function main() { + const url = "https://huggingface.co/datasets/dylanebert/3dgs/resolve/main/bonsai/bonsai-7k-mini.splat"; + await SPLAT.Loader.LoadAsync(url, scene, (progress) => (progressIndicator.value = progress * 100)); + progressDialog.close(); + + const handleResize = () => { + renderer.setSize(canvas.clientWidth, canvas.clientHeight); + }; + + const frame = () => { + controls.update(); + renderer.render(scene, camera); + + requestAnimationFrame(frame); + }; + + handleResize(); + window.addEventListener("resize", handleResize); + + requestAnimationFrame(frame); +} \ No newline at end of file diff --git a/static/posts/gsplat/style.css b/static/posts/gsplat/style.css new file mode 100644 index 0000000..0254c5a --- /dev/null +++ b/static/posts/gsplat/style.css @@ -0,0 +1,65 @@ +#container { + margin: 0; + padding: 0; + gap: 10px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +} + +.gsplat-js { + font-size: 12px !important; + margin: 0; +} + +#canvas { + width: 100%; + overflow: hidden; + border: 1px solid #EE72F1; + padding: 10px; +} + +#load-button { + width: 100%; + margin-top: 10px; +} + + +dialog { + width: 100%; + text-align: center; + max-width: 20em; + color: white; + background-color: #000; + border: none; + position: relative; + padding-bottom: 50px; + /* transform: translate(-50%, -50%); */ +} + +#progress-container { + position: absolute; + /* top: 50%; + left: 50%; */ +} + +progress { + width: 100%; + height: 1em; + border: none; + background-color: #fff; + color: #eee; +} + +progress::-webkit-progress-bar { + background-color: #333; +} + +progress::-webkit-progress-value { + background-color: #eee; +} + +progress::-moz-progress-bar { + background-color: #eee; +} \ No newline at end of file