nerfstudio-project / gsplat

CUDA accelerated rasterization of gaussian splatting
https://docs.gsplat.studio/
Apache License 2.0
1.99k stars 244 forks source link

[Question] The math for projective transformation in 2D Gaussian Splatting #417

Open DylanWaken opened 1 week ago

DylanWaken commented 1 week ago

1: in fully_fused_projection_2dgs_fwd.cu, why is the point in the uv-space of primitives represented as [u,v,-1] instead of [u,v,1]. Since we should add "the gaussian position in camera space i.e. mean_c " for properly transforming from uv to camera space, but we are actually subtracting it. Is this a convention thing?

2: The projection math here from fully_fused_projection_2dgs_fwd.cu:

    const vec3<T> temp_point = vec3<T>(1.0f, 1.0f, -1.0f);
    const T distance = sum(temp_point * M2 * M2);

    if (distance == 0.0f)
        return;

    const vec3<T> f = (1 / distance) * temp_point;
    const vec2<T> mean2d = vec2<T>(sum(f * M0 * M2), sum(f * M1 * M2));

    const vec2<T> temp = {sum(f * M0 * M0), sum(f * M1 * M1)};
    const vec2<T> half_extend = mean2d * mean2d - temp;

This is code-wise equivalent to the following trivial implementation (but faster by few percent)

    const vec3<T> mean_ray = glm::transpose(M) * vec3<T>(0.0f, 0.0f, -1.0f);
    const vec3<T> temp_point_ray = glm::transpose(M) * temp_point;
    const vec2<T> mean2d = vec2<T>(mean_ray.x / mean_ray.z, mean_ray.y / mean_ray.z);
    const vec2<T> half_extend_p = vec2<T>(temp_point_ray.x / temp_point_ray.z, temp_point_ray.y / temp_point_ray.z) - mean2d;
    const vec2<T> half_extend = vec2<T>(half_extend_p.x * half_extend_p.x, half_extend_p.y * half_extend_p.y);

Why this implementation works? tried to derive it manually but failed in proofs.

Then why this still works?

FantasticOven2 commented 2 days ago

Hey! Thanks for your question and sorry for the late reply. You can refer to the math derivation here by Binbin.