Skip to content

Commit 2fed719

Browse files
committed
Add shadow offset for triangle meshes
1 parent 6722426 commit 2fed719

File tree

3 files changed

+33
-12
lines changed

3 files changed

+33
-12
lines changed

include/mitsuba/render/interaction.h

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ struct Interaction {
100100
/// Position of the interaction in world coordinates
101101
Point3f p;
102102

103+
/// Offset position to be used for shadow rays (equals to p for most shapes).
104+
Point3f p_shadow;
105+
103106
/// Geometric normal (only valid for \c SurfaceInteraction)
104107
Normal3f n;
105108

@@ -113,7 +116,7 @@ struct Interaction {
113116
/// Constructor
114117
Interaction(Float t, Float time, const Wavelength &wavelengths,
115118
const Point3f &p, const Normal3f &n = 0.f)
116-
: t(t), time(time), wavelengths(wavelengths), p(p), n(n) { }
119+
: t(t), time(time), wavelengths(wavelengths), p(p), p_shadow(p), n(n) { }
117120

118121
/// Virtual destructor
119122
virtual ~Interaction() = default;
@@ -128,6 +131,7 @@ struct Interaction {
128131
time = dr::zeros<Float>(size);
129132
wavelengths = dr::zeros<Wavelength>(size);
130133
p = dr::zeros<Point3f>(size);
134+
p_shadow = dr::zeros<Point3f>(size);
131135
n = dr::zeros<Normal3f>(size);
132136
}
133137

@@ -138,12 +142,12 @@ struct Interaction {
138142

139143
/// Spawn a semi-infinite ray towards the given direction
140144
Ray3f spawn_ray(const Vector3f &d) const {
141-
return Ray3f(offset_p(d), d, dr::Largest<Float>, time, wavelengths);
145+
return Ray3f(offset_p(p, d), d, dr::Largest<Float>, time, wavelengths);
142146
}
143147

144148
/// Spawn a finite ray towards the given position
145149
Ray3f spawn_ray_to(const Point3f &t) const {
146-
Point3f o = offset_p(t - p);
150+
Point3f o = offset_p(p_shadow, t - p);
147151
Vector3f d = t - o;
148152
Float dist = dr::norm(d);
149153
d /= dist;
@@ -154,18 +158,18 @@ struct Interaction {
154158
//! @}
155159
// =============================================================
156160

157-
DRJIT_STRUCT(Interaction, t, time, wavelengths, p, n);
161+
DRJIT_STRUCT(Interaction, t, time, wavelengths, p, n, p_shadow);
158162

159163
private:
160164
/**
161165
* Compute an offset position, used when spawning a ray from this
162166
* interaction. When the interaction is on the surface of a shape, the
163167
* position is offset along the surface normal to prevent self intersection.
164168
*/
165-
Point3f offset_p(const Vector3f &d) const {
166-
Float mag = (1.f + dr::max(dr::abs(p))) * math::RayEpsilon<Float>;
169+
Point3f offset_p(const Vector3f &ref_p, const Vector3f &d) const {
170+
Float mag = (1.f + dr::max(dr::abs(ref_p))) * math::RayEpsilon<Float>;
167171
mag = dr::detach(dr::mulsign(mag, dr::dot(n, d)));
168-
return dr::fmadd(mag, dr::detach(n), p);
172+
return dr::fmadd(mag, dr::detach(n), ref_p);
169173
}
170174
};
171175

@@ -186,7 +190,7 @@ struct SurfaceInteraction : Interaction<Float_, Spectrum_> {
186190
using Spectrum = Spectrum_;
187191

188192
// Make parent fields/functions visible
189-
MI_IMPORT_BASE(Interaction, t, time, wavelengths, p, n, is_valid)
193+
MI_IMPORT_BASE(Interaction, t, time, wavelengths, p, p_shadow, n, is_valid)
190194

191195
MI_IMPORT_RENDER_BASIC_TYPES()
192196
MI_IMPORT_OBJECT_TYPES()
@@ -524,8 +528,8 @@ struct SurfaceInteraction : Interaction<Float_, Spectrum_> {
524528
//! @}
525529
// =============================================================
526530

527-
DRJIT_STRUCT(SurfaceInteraction, t, time, wavelengths, p, n, shape, uv,
528-
sh_frame, dp_du, dp_dv, dn_du, dn_dv, duv_dx,
531+
DRJIT_STRUCT(SurfaceInteraction, t, time, wavelengths, p, p_shadow, n,
532+
shape, uv, sh_frame, dp_du, dp_dv, dn_du, dn_dv, duv_dx,
529533
duv_dy, wi, prim_index, instance)
530534
};
531535

@@ -545,7 +549,7 @@ struct MediumInteraction : Interaction<Float_, Spectrum_> {
545549
using Index = typename CoreAliases::UInt32;
546550

547551
// Make parent fields/functions visible
548-
MI_IMPORT_BASE(Interaction, t, time, wavelengths, p, n, is_valid)
552+
MI_IMPORT_BASE(Interaction, t, time, wavelengths, p, p_shadow, n, is_valid)
549553
//! @}
550554
// =============================================================
551555

@@ -609,7 +613,7 @@ struct MediumInteraction : Interaction<Float_, Spectrum_> {
609613
//! @}
610614
// =============================================================
611615

612-
DRJIT_STRUCT(MediumInteraction, t, time, wavelengths, p, n, medium,
616+
DRJIT_STRUCT(MediumInteraction, t, time, wavelengths, p, p_shadow, n, medium,
613617
sh_frame, wi, sigma_s, sigma_n, sigma_t,
614618
combined_extinction, mint)
615619
};

include/mitsuba/render/mesh.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,7 @@ class MI_EXPORT_LIB Mesh : public Shape<Float, Spectrum> {
594594
/// Flag that can be set by the user to disable loading/computation of vertex normals
595595
bool m_face_normals = false;
596596
bool m_flip_normals = false;
597+
ScalarFloat m_shadow_offset_scale = 1.0f;
597598

598599
/* Surface area distribution -- generated on demand when \ref
599600
prepare_area_pmf() is first called. */

src/render/mesh.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ MI_VARIANT Mesh<Float, Spectrum>::Mesh(const Properties &props) : Base(props) {
2828
appearance. Default: ``false`` */
2929
m_face_normals = props.get<bool>("face_normals", false);
3030
m_flip_normals = props.get<bool>("flip_normals", false);
31+
m_shadow_offset_scale = props.get<ScalarFloat>("shadow_offset_scale", 1.0f);
3132

3233
m_discontinuity_types = (uint32_t) DiscontinuityFlags::PerimeterType;
3334

@@ -1547,6 +1548,21 @@ Mesh<Float, Spectrum>::compute_surface_interaction(const Ray3f &ray,
15471548
si.sh_frame.n = si.n;
15481549
}
15491550

1551+
if (has_vertex_normals() && (m_shadow_offset_scale > 0.f)) {
1552+
Vector3f tmp0 = si.p - p0,
1553+
tmp1 = si.p - p1,
1554+
tmp2 = si.p - p2;
1555+
Float dot0 = dr::minimum(dr::dot(tmp0, n0), 0.0f),
1556+
dot1 = dr::minimum(dr::dot(tmp1, n1), 0.0f),
1557+
dot2 = dr::minimum(dr::dot(tmp2, n2), 0.0f);
1558+
tmp0 -= dot0 * n0;
1559+
tmp1 -= dot1 * n1;
1560+
tmp2 -= dot2 * n2;
1561+
si.p_shadow = si.p + m_shadow_offset_scale * dr::fmadd(tmp0, b0, dr::fmadd(tmp1, b1, tmp2 * b2));
1562+
} else {
1563+
si.p_shadow = si.p;
1564+
}
1565+
15501566
if (m_flip_normals) {
15511567
si.n = -si.n;
15521568
si.sh_frame.n = -si.sh_frame.n;

0 commit comments

Comments
 (0)