Skip to content

Commit

Permalink
Fix normalmap
Browse files Browse the repository at this point in the history
  • Loading branch information
tomix1024 committed Sep 18, 2023
1 parent 5016304 commit ea4cca6
Showing 1 changed file with 32 additions and 18 deletions.
50 changes: 32 additions & 18 deletions src/bsdfs/normalmap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,19 +118,21 @@ class NormalMap final : public BSDF<Float, Spectrum> {
const Point2f &sample2,
Mask active) const override {
// Sample nested BSDF with perturbed shading frame
auto [ perturbed_frame_wrt_si, perturbed_frame_wrt_world ] = frame(si, active);
SurfaceInteraction3f perturbed_si(si);
perturbed_si.sh_frame = frame(si, active);
perturbed_si.wi = perturbed_si.to_local(si.wi);
perturbed_si.sh_frame = perturbed_frame_wrt_world;
perturbed_si.wi = perturbed_frame_wrt_si.to_local(si.wi);
auto [bs, weight] = m_nested_bsdf->sample(ctx, perturbed_si,
sample1, sample2, active);
active &= dr::any(dr::neq(unpolarized_spectrum(weight), 0.f));
if (dr::none_or<false>(active))
return { bs, 0.f };

// Transform sampled 'wo' back to original frame and check orientation
Vector3f perturbed_wo = perturbed_si.to_world(bs.wo);
Vector3f perturbed_wo = perturbed_frame_wrt_si.to_world(bs.wo);
active &= Frame3f::cos_theta(bs.wo) *
Frame3f::cos_theta(perturbed_wo) > 0.f;
bs.pdf = dr::select(active, bs.pdf, 0.f);
bs.wo = perturbed_wo;

return { bs, weight & active };
Expand All @@ -140,10 +142,11 @@ class NormalMap final : public BSDF<Float, Spectrum> {
Spectrum eval(const BSDFContext &ctx, const SurfaceInteraction3f &si,
const Vector3f &wo, Mask active) const override {
// Evaluate nested BSDF with perturbed shading frame
auto [ perturbed_frame_wrt_si, perturbed_frame_wrt_world ] = frame(si, active);
SurfaceInteraction3f perturbed_si(si);
perturbed_si.sh_frame = frame(si, active);
perturbed_si.wi = perturbed_si.to_local(si.wi);
Vector3f perturbed_wo = perturbed_si.to_local(wo);
perturbed_si.sh_frame = perturbed_frame_wrt_world;
perturbed_si.wi = perturbed_frame_wrt_si.to_local(si.wi);
Vector3f perturbed_wo = perturbed_frame_wrt_si.to_local(wo);

active &= Frame3f::cos_theta(wo) *
Frame3f::cos_theta(perturbed_wo) > 0.f;
Expand All @@ -155,10 +158,11 @@ class NormalMap final : public BSDF<Float, Spectrum> {
Float pdf(const BSDFContext &ctx, const SurfaceInteraction3f &si,
const Vector3f &wo, Mask active) const override {
// Evaluate nested BSDF with perturbed shading frame
auto [ perturbed_frame_wrt_si, perturbed_frame_wrt_world ] = frame(si, active);
SurfaceInteraction3f perturbed_si(si);
perturbed_si.sh_frame = frame(si, active);
perturbed_si.wi = perturbed_si.to_local(si.wi);
Vector3f perturbed_wo = perturbed_si.to_local(wo);
perturbed_si.sh_frame = perturbed_frame_wrt_world;
perturbed_si.wi = perturbed_frame_wrt_si.to_local(si.wi);
Vector3f perturbed_wo = perturbed_frame_wrt_si.to_local(wo);

active &= Frame3f::cos_theta(wo) *
Frame3f::cos_theta(perturbed_wo) > 0.f;
Expand All @@ -173,10 +177,11 @@ class NormalMap final : public BSDF<Float, Spectrum> {
MI_MASKED_FUNCTION(ProfilerPhase::BSDFEvaluate, active);

// Evaluate nested BSDF with perturbed shading frame
auto [ perturbed_frame_wrt_si, perturbed_frame_wrt_world ] = frame(si, active);
SurfaceInteraction3f perturbed_si(si);
perturbed_si.sh_frame = frame(si, active);
perturbed_si.wi = perturbed_si.to_local(si.wi);
Vector3f perturbed_wo = perturbed_si.to_local(wo);
perturbed_si.sh_frame = perturbed_frame_wrt_world;
perturbed_si.wi = perturbed_frame_wrt_si.to_local(si.wi);
Vector3f perturbed_wo = perturbed_frame_wrt_si.to_local(wo);

active &= Frame3f::cos_theta(wo) *
Frame3f::cos_theta(perturbed_wo) > 0.f;
Expand All @@ -185,14 +190,23 @@ class NormalMap final : public BSDF<Float, Spectrum> {
return { value & active, dr::select(active, pdf, 0.f) };
}

Frame3f frame(const SurfaceInteraction3f &si, Mask active) const {
/** \brief Compute the perturbation due to the normal map relative to \c si.sh_frame,
* as well as the full \c sh_frame of the perturbation in the world coordinate system.
*/
std::pair<Frame3f, Frame3f> frame(const SurfaceInteraction3f &si, Mask active) const {
Normal3f n = dr::fmadd(m_normalmap->eval_3(si, active), 2, -1.f);

Frame3f result;
result.n = dr::normalize(n);
result.s = dr::normalize(dr::fnmadd(result.n, dr::dot(result.n, si.dp_du), si.dp_du));
result.t = dr::cross(result.n, result.s);
return result;
Frame3f frame_wrt_si;
frame_wrt_si.n = dr::normalize(n);
frame_wrt_si.s = dr::normalize(dr::fnmadd(frame_wrt_si.n, frame_wrt_si.n.x(), ScalarVector3f(1, 0, 0)));
frame_wrt_si.t = dr::cross(frame_wrt_si.n, frame_wrt_si.s);

Frame3f frame_wrt_world;
frame_wrt_world.n = si.to_world(frame_wrt_si.n);
frame_wrt_world.s = si.to_world(frame_wrt_si.s);
frame_wrt_world.t = si.to_world(frame_wrt_si.t);

return { frame_wrt_si, frame_wrt_world };
}

Spectrum eval_diffuse_reflectance(const SurfaceInteraction3f &si,
Expand Down

0 comments on commit ea4cca6

Please sign in to comment.