Skip to content
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

Fixed ray differentials for analytical sphere #764

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions src/shapes/sphere.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -525,12 +525,11 @@ class Sphere final : public Shape<Float, Spectrum> {

if (likely(need_uv)) {
Float rd_2 = dr::sqr(local.x()) + dr::sqr(local.y()),
theta = unit_angle_z(local),
phi = dr::atan2(local.y(), local.x());

dr::masked(phi, phi < 0.f) += 2.f * dr::Pi<Float>;

si.uv = Point2f(phi * dr::InvTwoPi<Float>, theta * dr::InvPi<Float>);
si.uv = Point2f(phi * dr::InvTwoPi<Float>, dr::fnmadd(0.5f, local.z(), 0.5f));
if (likely(need_dp_duv)) {
si.dp_du = Vector3f(-local.y(), local.x(), 0.f);

Expand All @@ -539,16 +538,16 @@ class Sphere final : public Shape<Float, Spectrum> {
cos_phi = local.x() * inv_rd,
sin_phi = local.y() * inv_rd;

si.dp_dv = Vector3f(local.z() * cos_phi,
local.z() * sin_phi,
-rd);
si.dp_dv = Vector3f(local.z() * cos_phi * inv_rd,
local.z() * sin_phi * inv_rd,
-1.f);

Mask singularity_mask = active && dr::eq(rd, 0.f);
if (unlikely(dr::any_or<true>(singularity_mask)))
si.dp_dv[singularity_mask] = Vector3f(1.f, 0.f, 0.f);

si.dp_du = to_world * si.dp_du * (2.f * dr::Pi<Float>);
si.dp_dv = to_world * si.dp_dv * dr::Pi<Float>;
si.dp_dv = to_world * si.dp_dv * 2.f;
}
}

Expand Down
14 changes: 7 additions & 7 deletions src/shapes/tests/test_sphere.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,17 +74,17 @@ def test03_ray_intersect_transform(variant_scalar_rgb):
si = s.ray_intersect(ray)
ray_u = mi.Ray3f(ray)
ray_v = mi.Ray3f(ray)
eps = 1e-4
eps = 1e-5
ray_u.o += si.dp_du * eps
ray_v.o += si.dp_dv * eps
si_u = s.ray_intersect(ray_u)
si_v = s.ray_intersect(ray_v)
if si_u.is_valid():
du = (si_u.uv - si.uv) / eps
assert dr.allclose(du, [1, 0], atol=2e-2)
assert dr.allclose(du, [1, 0], atol=6e-2)
if si_v.is_valid():
dv = (si_v.uv - si.uv) / eps
assert dr.allclose(dv, [0, 1], atol=2e-2)
assert dr.allclose(dv, [0, 1], atol=6e-2)


def test04_ray_intersect_vec(variant_scalar_rgb):
Expand Down Expand Up @@ -180,7 +180,7 @@ def test06_differentiable_surface_interaction_ray_forward(variants_all_ad_rgb):
si = shape.ray_intersect(ray)
si.uv *= 1.0
dr.forward(ray.o.z)
assert dr.allclose(dr.grad(si.uv), [0, -2 / (2.0 * dr.pi)])
assert dr.allclose(dr.grad(si.uv), [0, -1 / 2.0])

# # If the ray origin is shifted along the x-axis, so does si.n
dr.enable_grad(ray.o)
Expand Down Expand Up @@ -308,7 +308,7 @@ def test08_differentiable_surface_interaction_ray_forward_follow_shape(variants_

assert dr.allclose(dr.grad(si.p), 0.0)
assert dr.allclose(dr.grad(si.n), 0.0)
assert dr.allclose(dr.grad(si.uv), [0.0, -0.5])
assert dr.allclose(dr.grad(si.uv), [0.0, -0.25 * dr.pi])


def test09_si_singularity(variants_all_rgb):
Expand All @@ -318,7 +318,7 @@ def test09_si_singularity(variants_all_rgb):
si = scene.ray_intersect(ray)

assert dr.allclose(si.dp_du, [0, 0, 0])
assert dr.allclose(si.dp_dv, [dr.pi, 0, 0])
assert dr.allclose(si.dp_dv, [2, 0, 0])
assert dr.allclose(si.sh_frame.s, [1, 0, 0])
assert dr.allclose(si.sh_frame.t, [0, -1, 0])
assert dr.allclose(si.sh_frame.n, [0, 0, -1])
Expand All @@ -331,7 +331,7 @@ def test10_si_singularity_centered(variants_all_rgb):
si = scene.ray_intersect(ray)

assert dr.allclose(si.dp_du, [0, 0, 0])
assert dr.allclose(si.dp_dv, [dr.pi, 0, 0])
assert dr.allclose(si.dp_dv, [2, 0, 0])
assert dr.allclose(si.sh_frame.s, [1, 0, 0])
assert dr.allclose(si.sh_frame.t, [0, 1, 0])
assert dr.allclose(si.sh_frame.n, [0, 0, 1])