|
1 | 1 | module RayTracingWeekend
|
2 | 2 |
|
3 |
| -using Images, LinearAlgebra, Random, RandomNumbers.Xorshifts, StaticArrays |
| 3 | +using Images |
| 4 | +using LinearAlgebra |
| 5 | +using Random |
| 6 | +using RandomNumbers.Xorshifts |
| 7 | +using StaticArrays |
4 | 8 |
|
5 | 9 | export color_vec3_in_rgb, default_camera, get_ray, hit, near_zero, point, random_between, random_vec2,
|
6 | 10 | random_vec2_in_disk, random_vec3, random_vec3_in_sphere, random_vec3_on_sphere, ray_color, ray_to_HitRecord, reflect,
|
7 | 11 | reflectance, refract, render, reseed!, rgb, rgb_gamma2, scatter, skycolor, squared_length, trand
|
8 | 12 | export Camera, Dielectric, Hittable, HittableList, HitRecord, Lambertian, Material, Metal, Ray, Scatter, Sphere, Vec3
|
9 | 13 | export scene_2_spheres, scene_4_spheres, scene_blue_red_spheres, scene_diel_spheres, scene_random_spheres
|
10 |
| - |
11 |
| -export TRNG |
| 14 | +export TRNG |
12 | 15 |
|
13 | 16 | const Vec3{T<:AbstractFloat} = SVector{3, T}
|
14 | 17 |
|
|
43 | 46 | (one(T)-t)*white + t*skyblue
|
44 | 47 | end
|
45 | 48 |
|
46 |
| -# Instantiate 1 RNG (Random Number Generator) per thread, for performance |
47 |
| -# Fix the random seeds, to make it easier to benchmark changes. |
48 |
| -const TRNG = [Xoroshiro128Plus(i) for i = 1:Threads.nthreads()] |
| 49 | +# Per-thread Random Number Generator. Initialized later... |
| 50 | +const TRNG = Xoroshiro128Plus[] |
49 | 51 |
|
50 |
| -reseed!() = for (i,rng) in enumerate(TRNG) Random.seed!(rng, i) end # reset the seed |
51 |
| -reseed!() |
| 52 | +function __init__() |
| 53 | + # Instantiate 1 RNG (Random Number Generator) per thread, for performance. |
| 54 | + # This can't be done during precompilation since the number of threads isn't known then. |
| 55 | + resize!(TRNG, Threads.nthreads()) |
| 56 | + for i in 1:Threads.nthreads() |
| 57 | + TRNG[i] = Xoroshiro128Plus(i) |
| 58 | + end |
| 59 | + nothing |
| 60 | +end |
52 | 61 |
|
53 |
| -@inline function trand() # thread-local rand() |
54 |
| - @inbounds rng = TRNG[Threads.threadid()] |
55 |
| - rand(rng) |
| 62 | +# Reset the per-thread random seeds to make results reproducible |
| 63 | +reseed!() = for i in 1:Threads.nthreads() Random.seed!(TRNG[i], i) end |
| 64 | + |
| 65 | +"Per-thread rand()" |
| 66 | +@inline function trand() |
| 67 | + @inbounds rng = TRNG[Threads.threadid()] |
| 68 | + rand(rng) |
56 | 69 | end
|
57 | 70 |
|
58 |
| -@inline function trand(::Type{T}) where T # thread-local rand() |
59 |
| - @inbounds rng = TRNG[Threads.threadid()] |
60 |
| - rand(rng, T) |
| 71 | +@inline function trand(::Type{T}) where T |
| 72 | + @inbounds rng = TRNG[Threads.threadid()] |
| 73 | + rand(rng, T) |
61 | 74 | end
|
62 | 75 |
|
63 | 76 | @inline function random_vec3_in_sphere(::Type{T}) where T # equiv to random_in_unit_sphere()
|
@@ -271,6 +284,11 @@ function default_camera(lookfrom::Vec3{T}=(SA{T}[0,0,0]),
|
271 | 284 | Camera{T}(origin, lower_left_corner, horizontal, vertical, u, v, w, lens_radius)
|
272 | 285 | end
|
273 | 286 |
|
| 287 | +default_camera(lookfrom, lookat, vup, vfov, aspect_ratio, aperture, focus_dist; elem_type::Type{T}) where T = |
| 288 | + default_camera(Vec3{T}(lookfrom), Vec3{T}(lookat), Vec3{T}(vup), |
| 289 | + T(vfov), T(aspect_ratio), T(aperture), T(focus_dist) |
| 290 | + ) |
| 291 | + |
274 | 292 | @inline @fastmath function get_ray(c::Camera{T}, s::T, t::T) where T
|
275 | 293 | rd = SVector{2,T}(c.lens_radius * random_vec2_in_disk(T))
|
276 | 294 | offset = c.u * rd.x + c.v * rd.y #offset = c.u * rd.x + c.v * rd.y
|
@@ -330,8 +348,7 @@ function render(scene::HittableList, cam::Camera{T}, image_width=400,
|
330 | 348 | # Makes comparing performance more accurate.
|
331 | 349 | reseed!()
|
332 | 350 |
|
333 |
| - #Threads.@threads # claforte: uncomment for CRASH?! |
334 |
| - for i in 1:image_height |
| 351 | + Threads.@threads for i in 1:image_height |
335 | 352 | @inbounds for j in 1:image_width # iterate over each row (FASTER?!)
|
336 | 353 | accum_color = SA{T}[0,0,0]
|
337 | 354 | u = convert(T, j/image_width)
|
|
0 commit comments