BufferAttribute type / precision conversion API#32614
BufferAttribute type / precision conversion API#32614FrostKiwi wants to merge 4 commits intomrdoob:devfrom
BufferAttribute type / precision conversion API#32614Conversation
… with new BufferAttribute Type / Precision conversion
📦 Bundle sizeFull ESM build, minified and gzipped.
🌳 Bundle size after tree-shakingMinimal build including a renderer, camera, empty scene, and dependencies.
|
|
In e272553 Fixed GitHub Actions Linter complaint https://github.com/mrdoob/three.js/actions/runs/20463774152/job/58802394771?pr=32614 Also here is a playground for the different Precisions. Just saw the GitHack demo on #32613 and first time hearing about it, thought it was neat way to showcase the precision api. In a different branch, modified the existing grounded Skybox example to have precision select boxes. Kinda funny how dropping down to 8bit ints for position shows up as squares and how making the positions any unsigned int makes the skybox all mush into one Quadrant, as there are no more negative coordinates possible. |

BufferAttribute.convert()e0ae5b1 introduces a
.convert()function inBufferAttributeto allow for precision conversion and buffer quantization of attributes likeposition,uvetc.This allows one to drop any BufferAttribute to a lower precision like
HalfFloatorInt8to save on VRAM (and RAM).Thanks to already existing data conversion like
three.js/src/extras/DataUtils.js
Line 150 in 69a97bf
three.js/src/core/BufferAttribute.js
Line 876 in 69a97bf
ThreeJS already has the ability to convert to and from various types for values, but not for buffers as a whole yet. This commit creates a conversion function which makes use of these preexisting data conversions to do exactly that.
The idea is to allow all the various Geometry generation functions like SphereGeometry.js to output with lower precision, without introducing a bunch of per-geometry generator custom code.
I see some potentially strong VRAM savings for this like dynamically imported 3D Satellite maps.
SphereGeometry( ... , precision = { ... } )To showcase this, in dd01e63 I extended SphereGeometry.js to (optionally) allow to set precisions for each
BufferAttributeor entirely remove said attribute. It also clarifies which precisions were used previously by default, which wasFloat32. Default case remains as is, nothing changes here, no API break.E.g. this allows the creation of a sphere with no normals, Half-Float Positions and 8-bit UVs.:
Motivation and VRAM savings in
GroundedSkyboxCommit 0ecfbb9 uses these new parameters to get a 50% VRAM and RAM size reduction of
GroundedSkyboxgeometry on default settings with no visual impact.In #27422 & #27448 @elalish changed the previous shader based
GroundProjectedSkyboxto the new geometryGroundedSkybox. To get the newly introduced rounded curve from floor to dome,GroundedSkyboxgenerates 65,024 triangles on defaultresolutionand deforms it, with full precision BufferAttributes and unused normals.GroundedSkyboxwith defaultresolutionGroundedSkyboxwith defaultresolutionDue to how SphereGeometry.js works, it produces very dense mesh on the flat floor. The 65,024 triangles default chosen by @elalish is the only way to get enough geometry and avoid distortions of the spherical texture on the curved transition.
The VRAM and RAM usage of the default
GroundedSkyboxis as follows:0ecfbb9 now requests a Sphere with the following
precisionproperties:This results in no visual change and the following RAM and VRAM usage:
The 50%
GroundedSkyboxVRAM savings aren't that important in the grand scheme of things, but this shows how I think a Three.JS user might want use such a attribute precision api to get VRAM savings on dynamically generated geometry and avoid hard crashes due to strict VRAM limits that some iPhones impose in WebGL.0ecfbb9 also adds a material name in

GroundedSkybox, so it doesn't show up as blank in Debuggers like https://github.com/utsuboco/r3f-perfStuff to decide
If we wanna merge this, I'll properly write the docs and stuff, but some things need to be clarified first:
precision = { ... }to all the geometry constructors in src/geometries or this this out of scope? Rename it toattributes = { ... }?fromArraycreate all the types yet, so this leads to the bit awkward expression ofthis.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ).convert( precision.position ) );which creates a Float32 Buffer to immediately convert it. Is this fine or do we need to do something about this?toJSON()stuff, something I ignored so far in this PR. So we would need to switch outTHREE.Float16BufferAttributefor constant likefloat16. But the already existing constants likeHalfFloatTypeare texture related and there is no 8bit vs 16bit int constant in the first place, so what to do? Create a new set of Geometry constants and correctBufferAttribute.gpuTypewhich has been using Texture constants for Geometry Attributes?