A simple and not very optimized Gaussian splat renderer.

Developed in the early days of a university project, in order to help me understand how Gaussian splats work.
Notes
Below, I’ve included the notes I took on the math behind 3DGS. They’re not very fleshed out, but I may as well just put them here so they don’t sit alone in some private git repo :D
Step 1: Reading the Data
The center of each Gaussian is given as 3D coordinates :
The point_cloud.ply files store scale and rotation as a vector and
quaternion, respectively:
From these, we can obtain scale and rotation matrices, and respectively. For splatting, we are interested in the covariance matrix , which describes how the Gaussian distribution falls off from the center outwards – this is kinda like a three-dimensional version of what the variance is for a 1D Gaussian distribution.
The covariance can be obtained as the result of applying both the rotation and scaling :
Note that since is the result of a multiplication of a matrix with its transpose , it is symmetric, i.e. of some form
Color is stored using spherical harmonics – this is what makes color view-angle-dependent.
However, the first harmonic does not depend on the angles and , hence can be used to obtain a view-independent “base” color that, for a simple Gaussian renderer will look okay enough.
The point_cloud.ply files store the
coefficients as the properties f_dc_0 through f_dc_2. The colors can
be obtained as such:
The opacity value is stored as the opacity property, where we obtain
like:
Note that this way, the values are between and .
Step 2: Rendering the Thing
The overall approach is this: Given our 3D covariance matrix , as well as the view matrix and the projection transform, find the 2D covariance matrix that approximates the projection of the 3D Gaussian onto the screen as a 2D Gaussian.
Typically, we’re given a model-view matrix . To work with the matrix , we’ll take the upper left corner of to get a matrix , thereby disregarding translation.
We’ll also want to perform projection, for which we have the projection matrix . This transformation is, however, not affine, i.e. we can’t just take the upper left corner here. Instead, the non-affine projection is approximated as follows:
This is using the first two terms of the Taylor expansion, and akin to the 1D case of approximating some function near a point as . Here, we’re approximating near the Gaussian’s center . The center, projected into view space is , equivalent to the term. For what would be the derivative in the 1D case, we’re using the Jacobian .
For projecting, we have the following transformation of a point onto the near plane at :
The Jacobian of the function is defined as
This yields:
The covariance matrix in camera space is obtained by calculating
where we discard the third row and column.
We can then get the eigenvalues and eigenvectors of . The vectors span a screen-space quad corresponding to the projection of the Gaussian.