Skip to content

Commit 2711fdb

Browse files
committed
use immutables for SurfaceInteraction
1 parent 57f7818 commit 2711fdb

File tree

6 files changed

+245
-103
lines changed

6 files changed

+245
-103
lines changed

src/Trace.jl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
module Trace
22

3-
# using Assimp
43
import FileIO
54
using ImageCore
65
using ImageIO

src/integrators/sampler.jl

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ end
2626
end
2727

2828
@noinline function sample_kernel(mempools, i, camera, scene, film, film_tile, tile_bounds)
29+
2930
pool = mempools[Threads.threadid()]
3031
t_sampler = deepcopy(i.sampler)
3132
spp_sqr = 1f0 / Float32(t_sampler.samples_per_pixel)
@@ -40,6 +41,7 @@ end
4041
Render scene.
4142
"""
4243
function (i::SamplerIntegrator)(scene::Scene)
44+
4345
sample_bounds = get_sample_bounds(get_film(i.camera))
4446
sample_extent = diagonal(sample_bounds)
4547
tile_size = 16
@@ -76,8 +78,9 @@ function (i::SamplerIntegrator)(scene::Scene)
7678
end
7779

7880
function li(
79-
pool, i::WhittedIntegrator, ray::RayDifferentials, scene::Scene, depth::Int64,
80-
)::RGBSpectrum
81+
pool, i::WhittedIntegrator, ray::RayDifferentials, scene::Scene, depth::Int64,
82+
)::RGBSpectrum
83+
8184
l = RGBSpectrum(0f0)
8285
# Find closest ray intersection or return background radiance.
8386
hit, primitive, si = intersect!(pool, scene, ray)
@@ -93,7 +96,7 @@ function li(
9396
n = si.shading.n
9497
wo = core.wo
9598
# Compute scattering functions for surface interaction.
96-
bsdf = compute_scattering!(pool, primitive, si, ray)
99+
si, bsdf = compute_scattering!(pool, primitive, si, ray)
97100
if bsdf.bxdfs.last == 0
98101
return li(
99102
pool, spawn_ray(pool, si, ray.d),
@@ -122,9 +125,9 @@ function li(
122125
end
123126

124127
function specular_reflect(
125-
pool, bsdf, i::I, ray::RayDifferentials,
126-
surface_intersect::SurfaceInteraction, scene::Scene, depth::Int64,
127-
) where I<:SamplerIntegrator
128+
pool, bsdf, i::I, ray::RayDifferentials,
129+
surface_intersect::SurfaceInteraction, scene::Scene, depth::Int64,
130+
) where I<:SamplerIntegrator
128131

129132
# Compute specular reflection direction `wi` and BSDF value.
130133

@@ -166,9 +169,10 @@ function specular_reflect(
166169
end
167170

168171
function specular_transmit(
169-
pool, bsdf, i::S, ray::RayDifferentials,
170-
surface_intersect::SurfaceInteraction, scene::Scene, depth::Int64,
171-
) where S<:SamplerIntegrator
172+
pool, bsdf, i::S, ray::RayDifferentials,
173+
surface_intersect::SurfaceInteraction, scene::Scene, depth::Int64,
174+
) where S<:SamplerIntegrator
175+
172176
# Compute specular reflection direction `wi` and BSDF value.
173177
wo = surface_intersect.core.wo
174178
type = BSDF_TRANSMISSION | BSDF_SPECULAR

src/lights/point.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ function sample_li(pool, p::PointLight, ref::Interaction, ::Point2f)
5151
wi = normalize(Vec3f(p.position - ref.p))
5252
pdf = 1f0
5353
visibility = VisibilityTester(
54-
pool, ref, allocate(pool, Interaction, (p.position, ref.time, Vec3f(0f0), Normal3f(0f0))),
54+
pool, ref, Interaction(p.position, ref.time, Vec3f(0f0), Normal3f(0f0)),
5555
)
5656
radiance = p.i / distance_squared(p.position, ref.p)
5757
radiance, wi, pdf, visibility

src/shapes/sphere.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,8 @@ function ∂n(
123123
end
124124

125125
function intersect(
126-
pool, s::Sphere, ray::Union{Ray,RayDifferentials}, ::Bool = false,
127-
)::Tuple{Bool,Float32,SurfaceInteraction}
126+
pool, s::Sphere, ray::Union{Ray,RayDifferentials}, ::Bool = false,
127+
)::Tuple{Bool,Float32,SurfaceInteraction}
128128
# Transform ray to object space.
129129
sf = SurfaceInteraction()
130130
or = apply!(s.core.world_to_object, copy(pool, ray))
@@ -157,11 +157,11 @@ function intersect(
157157
∂p∂u, ∂p∂v = ∂p(s, hit_point, θ, sin_ϕ, cos_ϕ)
158158
∂n∂u, ∂n∂v = ∂n(s, hit_point, sin_ϕ, cos_ϕ, ∂p∂u, ∂p∂v)
159159
reverse_normal = (s.core.reverse_orientation s.core.transform_swaps_handedness)
160-
sf = SurfaceInteraction(pool,
160+
si = SurfaceInteraction(pool,
161161
hit_point, ray.time, -ray.d, Point2f(u, v),
162162
∂p∂u, ∂p∂v, ∂n∂u, ∂n∂v, reverse_normal
163163
)
164-
apply!(s.core.object_to_world, sf)
164+
si = apply(s.core.object_to_world, si)
165165
true, shape_hit, sf
166166
end
167167

src/shapes/triangle_mesh.jl

Lines changed: 116 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,17 @@ struct Triangle <: AbstractShape
4040
end
4141
end
4242

43+
@inline function shading_normal(shape::Triangle, core_n, shading_n)
44+
if !isempty(shape.mesh.normals)
45+
core_n = face_forward(
46+
core_n, shading_n,
47+
)
48+
elseif shape.core.reverse_orientation shape.core.transform_swaps_handedness
49+
core_n = shading_n = -core_n
50+
end
51+
return core_n, shading_n
52+
end
53+
4354
function create_triangle_mesh(
4455
core::ShapeCore,
4556
indices::Vector{UInt32},
@@ -178,21 +189,21 @@ function ∂n(
178189
∂n∂u, ∂n∂v
179190
end
180191

181-
function _init_triangle_shading_geometry!(
182-
t::Triangle, interaction::SurfaceInteraction,
192+
function _init_triangle_shading_geometry(
193+
t::Triangle, si::SurfaceInteraction,
183194
barycentric::Point3f, uv::AbstractVector{Point2f},
184195
)
185-
!(!isempty(t.mesh.normals) || !isempty(t.mesh.tangents)) && return
196+
!(!isempty(t.mesh.normals) || !isempty(t.mesh.tangents)) && return si
186197
# Initialize triangle shading geometry.
187198
# Compute shading normal, tangent & bitangent.
188-
ns = interaction.core.n
199+
ns = si.core.n
189200
if !isempty(t.mesh.normals)
190201
ns = normalize(sum_mul(barycentric, normals(t)))
191202
end
192203
if !isempty(t.mesh.tangents)
193204
ss = normalize(sum_mul(barycentric, tangents(t)))
194205
else
195-
ss = normalize(interaction.∂p∂u)
206+
ss = normalize(si.∂p∂u)
196207
end
197208
ts = ns × ss
198209
if (ts ts) > 0
@@ -202,9 +213,93 @@ function _init_triangle_shading_geometry!(
202213
_, ss, ts = coordinate_system(ns)
203214
end
204215
∂n∂u, ∂n∂v = ∂n(t, uv)
205-
set_shading_geometry!(t, interaction, ss, ts, ∂n∂u, ∂n∂v, true)
216+
217+
return set_shading_geometry(t, si, ss, ts, ∂n∂u, ∂n∂v, true)
218+
end
219+
220+
function create_surface_interaction(
221+
t, normal, ray, hitpoint, uvs, uv, barycentric, ∂p∂u, ∂p∂v,
222+
orientation_is_authoritative, reverse_normal)
223+
224+
∂n∂u = Normal3f(0)
225+
∂n∂v = Normal3f(0)
226+
time = ray.time
227+
wo = -ray.d
228+
core_n = normal
229+
shading_n = normal
230+
shading_∂p∂u = ∂p∂u
231+
shading_∂p∂v = ∂p∂v
232+
shading_∂n∂u = ∂n∂u
233+
shading_∂n∂v = ∂n∂v
234+
235+
if t.mesh isa Nothing || !(!isempty(t.mesh.normals) || !isempty(t.mesh.tangents))
236+
return SurfaceInteraction(
237+
Interaction(hitpoint, time, wo, core_n),
238+
ShadingInteraction(shading_n, shading_∂p∂u, shading_∂p∂v, shading_∂n∂u, shading_∂n∂v),
239+
uv, ∂p∂u, ∂p∂v, ∂n∂u, ∂n∂v,
240+
0.0f0, 0.0f0, 0.0f0, 0.0f0, Vec3f(0.0f0), Vec3f(0.0f0)
241+
)
242+
end
243+
244+
# Initialize triangle shading geometry.
245+
# Compute shading normal, tangent & bitangent.
246+
247+
ns = core_n
248+
if !isempty(t.mesh.normals)
249+
ns = normalize(sum_mul(barycentric, normals(t)))
250+
end
251+
if !isempty(t.mesh.tangents)
252+
ss = normalize(sum_mul(barycentric, tangents(t)))
253+
else
254+
ss = normalize(∂p∂u)
255+
end
256+
ts = ns × ss
257+
if (ts ts) > 0
258+
ts = Vec3f(normalize(ts))
259+
ss = Vec3f(ts × ns)
260+
else
261+
_, ss, ts = coordinate_system(ns)
262+
end
263+
∂n∂u, ∂n∂v = ∂n(t, uvs)
264+
265+
shading_n = normalize(∂n∂v × ∂n∂v)
266+
if reverse_normal
267+
shading_n *= -1
268+
end
269+
if orientation_is_authoritative
270+
core_n = face_forward(core_n, shading_n)
271+
else
272+
shading_n = face_forward(shading_n, core_n)
273+
end
274+
275+
shading_∂p∂u = ∂n∂u
276+
shading_∂p∂v = ∂n∂v
277+
shading_∂n∂u = ∂n∂u
278+
shading_∂n∂v = ∂n∂v
279+
280+
# Ensure correct orientation of the geometric normal.
281+
if !isempty(t.mesh.normals)
282+
core_n = face_forward(core_n, shading_n)
283+
elseif t.core.reverse_orientation t.core.transform_swaps_handedness
284+
core_n = shading_n = -core_n
285+
end
286+
return SurfaceInteraction(
287+
288+
Interaction(hitpoint, time, wo, core_n),
289+
290+
ShadingInteraction(shading_n, shading_∂p∂u, shading_∂p∂v, shading_∂n∂u, shading_∂n∂v),
291+
uv,
292+
293+
∂p∂u,
294+
∂p∂v,
295+
∂n∂u,
296+
∂n∂v,
297+
298+
0f0, 0f0, 0f0, 0f0, Vec3f(0f0), Vec3f(0f0)
299+
)
206300
end
207301

302+
208303
function intersect(
209304
pool, t::Triangle, ray::Union{Ray,RayDifferentials}, ::Bool = false,
210305
)::Tuple{Bool,Float32,SurfaceInteraction}
@@ -213,10 +308,12 @@ function intersect(
213308
si = SurfaceInteraction()
214309
is_degenerate(vs) && return false, 0.0f0, si
215310
t_vs, shear = _to_ray_coordinate_space(vs, ray)
311+
216312
# Compute edge function coefficients.
313+
217314
edges = _edge_function(t_vs)
218315
if iszero(edges) # Fall-back to double precision.
219-
edges = _edge_function((x -> x .|> Float64).(t_vs))
316+
edges = _edge_function(Float64.(t_vs))
220317
end
221318
# Perform triangle edge & determinant tests.
222319
# Point is inside a triangle if all edges have the same sign.
@@ -245,31 +342,25 @@ function intersect(
245342
# Interpolate (u, v) paramteric coordinates and hit point.
246343
hit_point = sum_mul(barycentric, vs)
247344
uv_hit = sum_mul(barycentric, uv)
345+
normal = normalize(δp_13 × δp_23)
248346

249-
reverse_normal = (t.core.reverse_orientation t.core.transform_swaps_handedness)
250-
si = SurfaceInteraction(pool,
251-
hit_point, ray.time, -ray.d, uv_hit,
252-
∂p∂u, ∂p∂v, Normal3f(0), Normal3f(0), reverse_normal
347+
si = SurfaceInteraction(
348+
normal, hit_point, ray.time, -ray.d, uv_hit,
349+
∂p∂u, ∂p∂v, Normal3f(0), Normal3f(0)
253350
)
254-
si.core.n = si.shading.n = normalize(δp_13 × δp_23)
255-
t.mesh isa Nothing && return true, t_hit, si
256-
257-
_init_triangle_shading_geometry!(t, si, barycentric, uv)
258-
# Ensure correct orientation of the geometric normal.
259-
if !isempty(t.mesh.normals)
260-
si.core.n = face_forward(
261-
si.core.n, si.shading.n,
262-
)
263-
elseif t.core.reverse_orientation t.core.transform_swaps_handedness
264-
si.core.n = si.shading.n = -si.core.n
351+
if t.mesh isa Nothing
352+
return true, t_hit, si
265353
end
354+
355+
si = _init_triangle_shading_geometry(t, si, barycentric, uv)
266356
# TODO test against alpha texture if present.
267-
true, t_hit, si
357+
return true, t_hit, si
268358
end
269359

270360
function intersect_p(
271-
pool, t::Triangle, ray::Union{Ray,RayDifferentials}, ::Bool = false,
272-
)::Bool
361+
pool, t::Triangle, ray::Union{Ray,RayDifferentials}, ::Bool = false,
362+
)::Bool
363+
273364
vs = vertices(t)
274365
is_degenerate(vs) && return false
275366
t_vs, shear = _to_ray_coordinate_space(vs, ray)

0 commit comments

Comments
 (0)