Wonderland Engine's Optimizations
To allow more complex applications and scenes in your WebXR app, Wonderland Engine implements various optimizations. Find a non-exhaustive list below:
Optimizations that target faster frame rendering.
Dual Quaternion Scene Graph
While conventional scene graphs are implemented using matrices, Wonderland Engine’s scene graph uses dual quaternions.
Dual quaternions require only half the amount of memory of a 4x4 matrix and require less operations to concatenate.
As dual quaternions only represent rotation and translation, we augment them with a separate scaling vector.
For skinning, dual quaternions are especially advantageous, as they preserve volume better than other methods. With the scene graph, this integrates nicely.
Wonderland Engine joins meshes together at runtime to allow multiple meshes to be drawn with a single draw call. As each mesh usually uses different materials, we have special shaders that are able to use a list of materials to draw parts of the batch in different ways.
Textures need to be batched aswell. This process is called “texture atlassing”.
This optimization heavily reduces draw calls, as e.g. 512 draw calls can be merged into a single one as long as they all share the same shader.
Using compressed GPU formats, the GPU storage can be used more efficiently. This way the same amount of GPU memory can hold more textures and texture resolution in the scene can be higher.
SIMD instructions in WebAssembly allow processing multiple pioeces of data in a single instruction. This can especially speed up vector math.
While WebAssembly SIMD is not yet generally supported in Browsers yet (most require setting a flag to enable support), Wonderland Engine is ready for it.
Data Oriented Design
Wonderland Engine’s scene graph and component system, awell as other parts of the code base, are designed through Data Oriented Design. DOD is a way to write code such that data is processed more efficiently by the CPU by improving cache usage and helping predicitive code execution.
Optimizations that target faster loading.
Binary scene format
As parsing text (e.g. from
obj files) into binary for WebGL is already done in the editor,
the data is passed to the runtime in a binary format directly.
This binary data is layed out in a way such that minimal effort is required by the runtime to use it for rendering.
It also allows us to do Quantization on e.g. the mesh data: some mesh properties can be stored with less bits per vertex, if their value range is known.
Basis Universal image compression
Compressed Texture format support is different per device. With Basis Universal, we can compress images to a single format that can then be converted (“transcribed”) into device specific compressed GPU texture formats.
We use Quantization and remove redundant keyframes to reduce size of animations.
We pay special attention to keep our WebAssembly binary size small and keep the amount of dependencies low, as the runtime is one of the first things to be downloaded.
Our WebAssembly runtime is currently around 1.3 MB and will even be reduced further eventually.