Skip to content

Fix Potential Division-by-Zero Issues #88

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

atakan-topaloglu
Copy link

Summary of Potential Division-by-Zero Fixes

This document explains the root causes of potential division-by-zero errors fixed in the diff_gaussian_rasterization library for improved usability. While the original code functions correctly under typical conditions, certain edge cases (e.g., Gaussians exactly at the camera center, projected Gaussians becoming degenerate) could lead to floating-point exceptions (FPEs) and crashes.

1. View Direction Normalization (Forward & Backward)

  • Location: computeColorFromSH (Forward), dnormvdv helper used in preprocessCUDA (Backward)
  • Cause: The code normalizes the view direction vector calculated as (Gaussian Position - Camera Position). If a Gaussian's 3D position (pos) is exactly identical to the camera position (campos), this vector becomes the zero vector. Attempting to normalize it (dividing by its magnitude) results in division by zero.

2. 2D Covariance Calculation (Forward & Backward)

  • Location: computeCov2D (Forward), computeCov2DCUDA (Backward)
  • Cause: These functions calculate terms for the Jacobian matrix used in projecting the 3D covariance to 2D. These terms involve divisions like 1 / t.z and 1 / (t.z * t.z), where t.z is the Gaussian's depth in view space. If a Gaussian lies exactly on the camera plane (after view transformation), its t.z will be zero, leading to division by zero.

3. 2D Covariance Inversion (Forward)

  • Location: preprocessCUDA kernel (Forward)
  • Cause: The code computes the inverse of the projected 2D covariance matrix. This requires calculating 1 / determinant. If the projected 2D Gaussian is degenerate (e.g., forms a line), its 2D covariance matrix becomes singular, and its determinant (det) is zero, resulting in division by zero.

4. 2D Covariance Inversion Gradient (Backward)

  • Location: computeCov2DCUDA kernel (Backward)
  • Cause: When calculating the gradients with respect to the 2D covariance matrix elements (dL_da, dL_db, dL_dc), the formulas involve dividing by the squared determinant (denom * denom). Similar to the forward pass, if the determinant is zero, this leads to division by zero.

5. Quaternion Normalization Derivative (Backward)

  • Location: computeCov3D calling dnormvdv helper (Backward)
  • Cause: The backward pass calculates gradients with respect to the input rotation quaternion (rot). The helper function dnormvdv implicitly divides by the magnitude of the vector during gradient calculation. If the input rotations tensor contains a zero vector [0, 0, 0, 0], its magnitude is zero, causing division by zero when computing the gradient contribution from the (implicitly handled) normalization.

These fixes primarily focus on usability by adding small epsilon checks before potentially problematic divisions, preventing unexpected crashes for users who might encounter these edge cases inadvertently during experimentation or training. This makes the rasterizer more robust to unusual inputs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant