1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
//! Materials in Rustic Zen are defined as closures that act on a single ray when intersecting wtth an object.
//!
//! For object safety these closures are stored in a `std::sync::Arc` which can then be cloned to as many users as needed.
//! As there is a constant generic type assosiated with the material, `R` it is usually easiest to implement the Arc inside a
//! generator function that yeilds the Arc and accepts a type argument.
//!
//! # Examples:
//! ## Create a trivial shader and assign it to several `Segments`
//! ```
//! use rustic_zen::prelude::*;
//! use std::sync::Arc;
//!
//! // This shader will fire all incoming rays in the direction of the surface normal.
//! // This is actually surprisingly useful for testing normals.
//! fn always_normal<R>() -> material::Material<R> {
//! Arc::new(move |_, normal: &Vector, _, _, _: &mut R| {
//! Some(normal.clone())
//! })
//! }
//!
//! let m = always_normal(); // R fixed to a concrete type here by the `Scene` below
//!
//! let s = Segment::line_from_points((0.0, 0.0), (10.0, 10.0), m.clone());
//! let s2 = Segment::line_from_points((10.0, 10.0), (20.0, 0.0), m);
//!
//! // you may get unknown type for <R> if you do not add all your segments to a scene.
//! let _ = Scene::new(100, 100).with_object(s).with_object(s2);
//! ```
//!
//! ## Create a more useful shader that refects 50% of incoming light and apply it to several `Segments`:
//! ```
//! use rustic_zen::prelude::*;
//! use std::sync::Arc;
//!
//! // This shader will reflect half of the rays and absorb the other half
//! fn mirror<R: Rng + 'static>() -> material::Material<R> {
//! let s = Sampler::<f64, R>::new_range(0.0, 1.0);
//! Arc::new(move |direction: &Vector, normal: &Vector, _, _, rng: &mut R| {
//! if s.sample(rng) < 0.5 {
//! None
//! } else {
//! Some(direction.reflect(normal))
//! }
//! })
//! }
//!
//! let m = mirror(); // R fixed to a concrete type here by the `Scene` below
//!
//! let s = Segment::line_from_points((0.0, 0.0), (10.0, 10.0), m.clone());
//! let s2 = Segment::line_from_points((10.0, 10.0), (20.0, 0.0), m);
//!
//! // you may get unknown type for <R> if you do not add all your segments to a scene.
//! let _ = Scene::new(100, 100).with_object(s).with_object(s2);
//! ```
//!
//! Admittedly this could probably be less clunky.
//!
//! Creating more imaginative shaders is left as an exersize for the reader.
use crateVector;
use *;
use PI;
use Arc;
/// Shader Type
///
/// This Closure Represents a shader in the HQZ system. For a given incident ray an outcome is calculated.
///
/// Wavelength is provided instead of colour to encourage the design of physically based
/// shaders. Colour can be calculated from the wavelength using Rustic's spectrum module.
///
/// * It returns a wrapped vector of the direction of the bounced ray.
/// If the ray is absorbed then it returns `None`.
///
/// # Parameters:
/// - __direction__: Vector of the direction of the inbound ray.
/// - __normal__: Computed normal to the hit surface. This can be used in `direction.reflect(normal)`, to get a mirror reflection.
/// - __wavelength__: Wavelength of inbound ray (no way to change this for the outbound ray, sorry).
/// - __alpha__: how far along the object the inbound ray hit. clamped 0.0 to 1.0
/// - __rng__: random number generator for use during the function, (don't spawn your own, way to slow.)
pub type Material<R> =
;
/// Reference / Legacy implementation of Material trait.
///
/// This implementation models the behavour of shaders from the original HQZ.
/// When called this will return an `Arc` containing the shader closure. It only has to be called
/// once for each set of parameters desired as the arc can be cloned to multiple objects.
///
/// # Parameters:
/// * __diffuse__: proportion of rays bounced diffusely (completely random direction)
/// * __relective__: proportion of rays that are perfectly reflected
/// * __transparent__: proportion of rays that pass through the material as if it was transparent.
///
/// The proportion of rays absorbed is `1.0 - d - r - t`
///
/// # Panics:
/// Panics if `d + r + t > 1.0`
/// Default Settings for `hqz_legacy`, makes a fast and predictable testing shader where needed.
///
/// Default Values:
/// * __diffuse__: 0.1
/// * __reflective__: 0.4
/// * __transparent__: 0.4
/// * absorbsion is 0.1