A common practice in computer graphics is to pack and compress vertex attributes. It reduces the memory footprint, time to transfer data across the bus from the CPU to the GPU, and GPU memory bandwidth at the cost of extra instructions in the vertex shader. Another benefit may be that there are more attributes than the maximum number of vertex attributes supported.
One way to reduce the number of vertex attributes is to make all attributes a four-component vector and make sure all of the components are used. For example, instead of
we could use one vec4 attribute:
We can take it a step further by packing multiple attributes into a single floating-point number. For example, why store a boolean attribute in an unsigned byte when it only needs one bit? I expect there to be GLSL bitwise operators in WebGL 2.0, but, until then, we can use multiplication and division by powers of two to shift bits.
A 32-bit floating-point number has 24 bits of precision so we can pack 24 bits into a single floating-point value. As an example, we will walk through one packed component of a compressed
We simply reverse these operations in GLSL to extract the values. See BillboardCollectionVS.glsl.
For more information on vertex compression, see the references.
Cartesian3 to an oct encoded
Encoding three unit vectors into two floating-point numbers is only useful for unrelated unit vectors. For example, tangent space vectors only needs two vectors to be encoded. The third vector can be computed using the cross product of the other two.
Texture Coordinate Compression
For geometry generated by Cesium and billboards, the full 24-bit precision of floating-point numbers is not needed for texture coordinates. We only use 12 bits of precision for each texture coordinate. The texture wrap mode must not be needed and each coordinate must be strictly in the zero to one range. See AttributeCompression.compressTextureCoordinates which will compress the texture coordinates into a single floating-point number.
In Cesium, we use this for generated geometry where we know the texture coordinates will be in the zero-to-one range and we do not make use of the texture wrap mode. Similarly, we use this compression for billboards. It may cause artifacts for billboards if the texture atlas gets large enough, but we haven’t seen any artifacts in practice.
Vertex Compression in Cesium
The BillboardCollection and LabelCollection have a total of 18 attributes per vertex, each with various types and number of components. After packing and compression, the number is down to eight four-component floating-point attributes per vertex. For more details, see the BillboardCollection or its vertex shader.
[Calver02] Dean Calver. Vertex Decompression in a Shader. In Direct3D ShaderX: Vertex and Pixel Shader Tips and Tricks. Edited by Wolfgang F. Engel. 2002.
[Cigolle14] Cigolle, Donow, Evangelakos, Mara, McGuire, Meyer, A Survey of Efficient Representations for Independent Unit Vectors, Journal of Computer Graphics Techniques (JCGT), vol. 3, no. 2, 1-30, 2014.
[Persson12] Emil Persson. Creating Vast Game Worlds. 2012.
[Pranckevičius09] Aras Pranckevičius. Compact Normal Storage for Small G-Buffers. 2009.