Skip to content

Commit

Permalink
Fix incorrect meshlight pdf (ref only)
Browse files Browse the repository at this point in the history
  • Loading branch information
sergcpp committed Sep 1, 2024
1 parent 3aabc46 commit 320cf29
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 68 deletions.
122 changes: 61 additions & 61 deletions internal/CoreRef.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1164,67 +1164,6 @@ force_inline float angle_between(const fvec4 &v1, const fvec4 &v2) {
}
}

// "Stratified Sampling of Spherical Triangles" https://www.graphics.cornell.edu/pubs/1995/Arv95c.pdf
// Based on https://www.shadertoy.com/view/4tGGzd
float SampleSphericalTriangle(const fvec4 &P, const fvec4 &p1, const fvec4 &p2, const fvec4 &p3, const fvec2 Xi,
fvec4 *out_dir) {
// Setup spherical triangle
const fvec4 A = normalize(p1 - P), B = normalize(p2 - P), C = normalize(p3 - P);

// calculate internal angles of spherical triangle: alpha, beta and gamma
const fvec4 BA = orthogonalize(A, B - A);
const fvec4 CA = orthogonalize(A, C - A);
const fvec4 AB = orthogonalize(B, A - B);
const fvec4 CB = orthogonalize(B, C - B);
const fvec4 BC = orthogonalize(C, B - C);
const fvec4 AC = orthogonalize(C, A - C);

const float alpha = angle_between(BA, CA);
const float beta = angle_between(AB, CB);
const float gamma = angle_between(BC, AC);

const float area = alpha + beta + gamma - PI;
if (area <= SPHERICAL_AREA_THRESHOLD) {
return 0.0f;
}

if (out_dir) {
// calculate arc lengths for edges of spherical triangle
// const float a = portable_acosf(clamp(dot(B, C), -1.0f, 1.0f));
const float b = portable_acosf(clamp(dot(C, A), -1.0f, 1.0f));
const float c = portable_acosf(clamp(dot(A, B), -1.0f, 1.0f));

// Use one random variable to select the new area
const float area_S = Xi.get<0>() * area;

// Save the sine and cosine of the angle delta
const float p = sinf(area_S - alpha);
const float q = cosf(area_S - alpha);

// Compute the pair(u; v) that determines sin(beta_s) and cos(beta_s)
const float u = q - cosf(alpha);
const float v = p + sinf(alpha) * cosf(c);

// Compute the s coordinate as normalized arc length from A to C_s
const float denom = ((v * p + u * q) * sinf(alpha));
const float s =
(1.0f / b) * portable_acosf(clamp(safe_div(((v * q - u * p) * cosf(alpha) - v), denom), -1.0f, 1.0f));

// Compute the third vertex of the sub - triangle
const fvec4 C_s = slerp(A, C, s);

// Compute the t coordinate using C_s and Xi[1]
const float denom2 = portable_acosf(clamp(dot(C_s, B), -1.0f, 1.0f));
const float t = safe_div(portable_acosf(clamp(1.0f - Xi.get<1>() * (1.0f - dot(C_s, B)), -1.0f, 1.0f)), denom2);

// Construct the corresponding point on the sphere.
(*out_dir) = slerp(B, C_s, t);
}

// return pdf
return (1.0f / area);
}

} // namespace Ref
} // namespace Ray

Expand Down Expand Up @@ -1296,6 +1235,67 @@ float Ray::Ref::SampleSphericalRectangle(const fvec4 &P, const fvec4 &light_pos,
return (1.0f / area);
}

// "Stratified Sampling of Spherical Triangles" https://www.graphics.cornell.edu/pubs/1995/Arv95c.pdf
// Based on https://www.shadertoy.com/view/4tGGzd
float Ray::Ref::SampleSphericalTriangle(const fvec4 &P, const fvec4 &p1, const fvec4 &p2, const fvec4 &p3,
const fvec2 Xi, fvec4 *out_dir) {
// Setup spherical triangle
const fvec4 A = normalize(p1 - P), B = normalize(p2 - P), C = normalize(p3 - P);

// calculate internal angles of spherical triangle: alpha, beta and gamma
const fvec4 BA = orthogonalize(A, B - A);
const fvec4 CA = orthogonalize(A, C - A);
const fvec4 AB = orthogonalize(B, A - B);
const fvec4 CB = orthogonalize(B, C - B);
const fvec4 BC = orthogonalize(C, B - C);
const fvec4 AC = orthogonalize(C, A - C);

const float alpha = angle_between(BA, CA);
const float beta = angle_between(AB, CB);
const float gamma = angle_between(BC, AC);

const float area = alpha + beta + gamma - PI;
if (area <= SPHERICAL_AREA_THRESHOLD) {
return 0.0f;
}

if (out_dir) {
// calculate arc lengths for edges of spherical triangle
// const float a = portable_acosf(clamp(dot(B, C), -1.0f, 1.0f));
const float b = portable_acosf(clamp(dot(C, A), -1.0f, 1.0f));
const float c = portable_acosf(clamp(dot(A, B), -1.0f, 1.0f));

// Use one random variable to select the new area
const float area_S = Xi.get<0>() * area;

// Save the sine and cosine of the angle delta
const float p = sinf(area_S - alpha);
const float q = cosf(area_S - alpha);

// Compute the pair(u; v) that determines sin(beta_s) and cos(beta_s)
const float u = q - cosf(alpha);
const float v = p + sinf(alpha) * cosf(c);

// Compute the s coordinate as normalized arc length from A to C_s
const float denom = ((v * p + u * q) * sinf(alpha));
const float s =
(1.0f / b) * portable_acosf(clamp(safe_div(((v * q - u * p) * cosf(alpha) - v), denom), -1.0f, 1.0f));

// Compute the third vertex of the sub - triangle
const fvec4 C_s = slerp(A, C, s);

// Compute the t coordinate using C_s and Xi[1]
const float denom2 = portable_acosf(clamp(dot(C_s, B), -1.0f, 1.0f));
const float t = safe_div(portable_acosf(clamp(1.0f - Xi.get<1>() * (1.0f - dot(C_s, B)), -1.0f, 1.0f)), denom2);

// Construct the corresponding point on the sphere.
(*out_dir) = slerp(B, C_s, t);
}

// return pdf
return (1.0f / area);
}

Ray::Ref::fvec2 Ray::Ref::get_scrambled_2d_rand(const uint32_t dim, const uint32_t seed, const int sample,
const uint32_t rand_seq[]) {
const uint32_t shuffled_dim = nested_uniform_scramble_base2(dim, seed) & (RAND_DIMS_COUNT - 1);
Expand Down
2 changes: 2 additions & 0 deletions internal/CoreRef.h
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,8 @@ fvec2 get_scrambled_2d_rand(const uint32_t dim, const uint32_t seed, const int s

float SampleSphericalRectangle(const fvec4 &P, const fvec4 &light_pos, const fvec4 &axis_u, const fvec4 &axis_v,
fvec2 Xi, fvec4 *out_p);
float SampleSphericalTriangle(const fvec4 &P, const fvec4 &p1, const fvec4 &p2, const fvec4 &p3, const fvec2 Xi,
fvec4 *out_dir);

// Generation of rays
void GeneratePrimaryRays(const camera_t &cam, const rect_t &r, int w, int h, const uint32_t rand_seq[],
Expand Down
13 changes: 6 additions & 7 deletions internal/ShadeRef.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1504,13 +1504,12 @@ Ray::color_rgba_t Ray::Ref::ShadeSurface(const pass_settings_t &ps, const float

const float cos_theta = fabsf(dot(I, light_forward)); // abs for doublesided light
if (cos_theta > 0.0f) {
float light_pdf;
#if USE_SPHERICAL_AREA_LIGHT_SAMPLING
const fvec4 P = TransformPoint(ro, mi->inv_xform);
light_pdf = SampleSphericalTriangle(P, p1, p2, p3, {}, nullptr) / pdf_factor;
if (light_pdf == 0.0f)
#endif
{
float light_pdf = 0.0f;
if (USE_SPHERICAL_AREA_LIGHT_SAMPLING) {
const fvec4 P = TransformPoint(ro, mi->inv_xform);
light_pdf = SampleSphericalTriangle(P, p1, p2, p3, {}, nullptr) / pdf_factor;
}
if (light_pdf == 0.0f) {
light_pdf = (inter.t * inter.t) / (tri_area * cos_theta * pdf_factor);
}

Expand Down

0 comments on commit 320cf29

Please sign in to comment.