Thanks to visit codestin.com
Credit goes to Github.com

Skip to content

caseprince/voxel-visualizer

Repository files navigation

Three.js Voxel Visualizer

An experimental particle-based voxel renderer designed to explore optimization strategies for rendering large (1–8 million) particle buffers in Three.js. The test model is a 6cm test sphere generated by a volumetric GLSL shader and stored as a sequence of PNGs or a single "sprite sheet." This voxel shader was used to create larger lamp shades with various Stratasys PolyJet 3D printers. These printers achieve variable-transparency, full-color prints by dithering voxels of CMYKW (cyan, magenta, yellow, black, white) and transparent photopolymer resins, using a sacrificial support material.

View it live here: https://caseprince.github.io/voxel-visualizer

Voxel rendering alongside completed 3D print Left: Screenshot of Voxel Visualizer. Right: Voxel data 3D printed on Stratasys J750.

Optimization Observations

  1. Reading individual pixels from a Canvas context via var pixel = ctx.getImageData(x, y, 1, 1).data is quite slow, even when using a sprite sheet. Setting willReadFrequently appears to have little effect.
  2. Reads are faster if ImageData is first converted into a Uint32Array (e.g., new Uint32Array(myImageData.data.buffer)) — see Faster canvas pixel manipulation with typed arrays.
  3. Array.push() does not seem slower than Float32Array.set() for writing data.
  4. Bypassing the Canvas entirely by loading a PNG as a raw file using XMLHttpRequest, then piping the ArrayBuffer into a Uint8Array and decoding via UPNG seems to be the fastest way to read pixel data; it also supports indexed-color PNG-8s. 8-bit PNGs are more than sufficient for PolyJet voxel printing, since PolyJet printers support a maximum of 7–8 colors/resin types per print.
  5. Not all PNGs are created equal. UPNG and ImageMagick both encode PNGs with 4-bit depth properties (as decoded by UPNG), which corresponds to the bit depth of color indices and makes sense given a small color palette. Photoshop, on the other hand, encodes PNG-8 with 8-bit indices, which makes access via Uint8Array painless and avoids bitwise logic. (JavaScript has no built-in Uint4Array typed array.) Oddly, despite this, Photoshop's PNGs are slightly smaller. This makes me think I don't fully understand the PNG bit depth behavior, or there may be a bug in UPNG. The two formats appear incompatible for reading color indices. This demo uses Photoshop-encoded PNGs for simplicity.
  6. UPNG supports encoding animated PNGs (APNGs), which theoretically should be the most efficient format since frames only encode pixels from regions that are changing. However, initial experimentation encoding APNGs yielded files that are ~15% larger than equivalent 2D sprite sheets. This may warrant further investigation.

Setup

  1. Install Node.js version 22.11.0 (or a compatible LTS release).
  2. Install dependencies
npm install
  1. Start dev server
npm run dev
  1. Visit http://127.0.0.1:8080

Thanks:

TODO

  • Simulate color blending
  • Output sprites directly as animated PNG
  • Add ability to parse indexed-color PNGs with 4bit indices
  • 3D bounding box calculation

About

Visualizer for Voxel Based 3D Printable Models

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published