Add VAT character crowd rendering scripts and example - #9123
Merged
Conversation
Bakes skinned animation into a texture so a crowd renders as one instanced draw call, with no skeletons or per character animation evaluation. Adds a script library under scripts/esm/vat (runtime script, glb converter, generic shader chunks usable by StandardMaterial as well as a custom ShaderMaterial, and a simple shader material), plus an animation/vat-characters example with single and crowd modes and an in-browser glb converter. No engine changes - only new files and four symbol registrations in the scripts TypeDoc config.
Build size reportThis PR does not change the size of the minified bundles.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds vertex animation texture (VAT) support as a set of reusable ESM scripts plus an example.
Skinned animation is baked ahead of time into a texture, so a whole crowd renders as one
instanced draw call with no skeletons, bone matrices or per character animation evaluation.
There are no changes to the engine itself — only new files under
scripts/esm/vat, a newexample, and four symbol registrations in the scripts TypeDoc config.
Changes:
scripts/esm/vatscript library: a runtime script, a glb converter, generic shaderchunks and a simple shader material
transformCoreVS/normalCoreVS, so they work with aStandardMaterialas well as with a customShaderMaterialanimation/vat-charactersexample with single character and crowd modes, a materialswitch, and an in-browser glb converter behind a file picker
examples/assets/vatfolder holding the converted lumberjack, its source glb and creditsContainerResource,Scene,VertexBufferandScene.ambientLightintypedoc.scripts.config.mjsso the new JSDoc links resolveAPI Changes:
New, all additive —
playcanvas/scripts/esm/vat/:vat-characters.mjs—VatCharactersscript. Attributes:url,useStandardMaterial,castShadows,light,ambientSky,ambientGround. Properties:capacity,count,animations,characterBounds,ready. Methods:load,setData,getAnimationIndex,setAnimation,setSpeed,setLoop,setTime,getTime,setPosition,setRotation,setEulerAngles,setScale,setTransformvat-converter.mjs—convertToVat,saveVat,VAT_MAX_TEXELSvat-data.mjs—parseVat,VatData,createVatTexture,createVatMesh,createVatAlbedoTexture,createWhiteTexture,octDecode,vatTextureSize,VAT_VERSION,VAT_MAGIC,VAT_TEXTURE_LIMITvat-chunks.mjs—vatChunks,setupVatMaterial,VAT_FRAME_SEMANTIC,VAT_TRANSFORM_SEMANTICSvat-material.mjs—createVatShaderMaterialFile format:
The converter emits a glb-style binary container (12 byte header with a magic number and a
version, then a JSON chunk and a BIN chunk). Like a glb it is stored uncompressed and leaves
compression to the transport — brotli over the raw payload is around 40% smaller than gzip
baked into the file, and pre-compressing would leave the transport nothing to work with.
The texture is RGBA16U, one texel per vertex per sampled frame: position quantized to 16 bits
per axis over the bounds of the animation in xyz, and an octahedrally encoded normal packed
into w. One fetch therefore supplies a whole vertex. Quantizing over the bounds is also more
accurate than a half float where it matters — near the top of a character fp16 has a step of
about 1.8 mm at human scale, against 28 µm for 16 bit.
Texels are addressed by the flat index
vertex * frameCount + frame, wrapped at the power oftwo texture width. This decouples the vertex count from a texture dimension: the limit is the
total texel count of a 4096x4096 texture, so roughly 218k vertices at 77 frames rather than
4096. 4096 is used because every WebGL 2 and WebGPU device supports at least that, so data
loads regardless of the machine it was authored on.
Examples:
animation/vat-characters— crowd of up to 10,000 walking characters by default, with asingle character mode with an animation drop down, a Shader/Standard material switch, a
shadow toggle, and a Convert GLB panel that converts and previews any skinned glb in browser
Performance:
characters (about 31M vertices per frame), CPU 2.1 ms
frame index. The fourth row is always (0,0,0,1) and the shader appends it
the CPU
crowd.mov