DQLin / RealTimeStochasticLightcuts

Repository of the source code and demo of I3D 2020 paper Real-Time Stochastic Lightcuts
Other
121 stars 13 forks source link

Explanation of HLSL geometry term bound calculation #4

Open Cascades opened 3 years ago

Cascades commented 3 years ago

Hi, thanks for the exciting paper! I was wondering if you could explain, or point me in the direction of how you arrived at the following code snippet? It was my understanding that the geometry term for point lights was:

image

but you mention cosine on the CPU-side version, and this GPU version looks like it does a lot more work than that!

I am most confused by how MaxDistAlong works, and what exactly it's meant to calculate. I presume it's the distance along dir, from p, to the furthest away point on the AABB? If so, I'm confused at how the component-wise multiplication of dir with everything helps, and what the final summation of max functions is meant to represent geometrically.

float MaxDistAlong(float3 p, float3 dir, float3 boundMin, float3 boundMax)
{
    float3 dir_p = dir * p;
    float3 mx0 = dir * boundMin - dir_p;
    float3 mx1 = dir * boundMax - dir_p;
    return max(mx0[0], mx1[0]) + max(mx0[1], mx1[1]) + max(mx0[2], mx1[2]);
}

float GeomTermBound(float3 p, float3 N, float3 boundMin, float3 boundMax)
{
    float nrm_max = MaxDistAlong(p, N, boundMin, boundMax);
    if (nrm_max <= 0) return 0.0f;
    float3 d = min(max(p, boundMin), boundMax) - p;
    float3 tng = d - dot(d, N) * N;
    float hyp2 = dot(tng, tng) + nrm_max * nrm_max;
    return nrm_max * rsqrt(hyp2);
}

If you could perhaps expend/derive/diagram either of these functions I would be extremely grateful.

Again, I loved this work, thanks.

DQLin commented 3 years ago

Hi Cascades, thank you for your interest in the paper. This MaxDistAlong function is actually an optimized version of the same function in CPULightCuts.h. Basically, it calculates max(p_z) in Figure 4 of Walter's Ligthcuts paper.

The rest of the GeomTermBound calculates the remaining terms of the cosine bound (equation 4 of the Lightcuts paper). "float3 d = min(max(p, boundMin), boundMax) - p" computes the minimum distance from the shading point to the bounding box of the light cluster. As I reexamine the code, I found that it computes an approximation of the min(p_x^2) + min(p_y^2) term which is only accurate when the shading normal is axis-aligned. This approximation saves computation, without noticeably affecting the sampling quality. I just added a faithful version of the Lightcuts equation (4) in my latest commit. And there is a "Use Approx Cosine Bound" option in the UI that compares these two methods.