patterns: add Gradient pattern.
This commit is contained in:
parent
bdcee49d5a
commit
74fe69188a
@ -45,7 +45,7 @@ pub mod prelude {
|
||||
lights::{PointLight, PointLightBuilder},
|
||||
materials::{Material, MaterialBuilder},
|
||||
matrices::{identity, rotation_x, rotation_y, rotation_z, scaling, shearing, translation},
|
||||
patterns::stripe_pattern,
|
||||
patterns::{gradient_pattern, stripe_pattern},
|
||||
shapes::{plane, sphere, test_shape},
|
||||
transformations::view_transform,
|
||||
tuples::{point, vector, Color},
|
||||
|
||||
@ -16,6 +16,8 @@ pub enum ColorMapper {
|
||||
/// Pattern that alternates between the given colors along each unit of the X-axis. The strip
|
||||
/// extends infinitely in the positive and negative Y and Z axes.
|
||||
Stripe { a: Color, b: Color },
|
||||
/// Linear blend between `a` and `b` along the X-axis.
|
||||
Gradient { a: Color, b: Color },
|
||||
}
|
||||
|
||||
#[derive(Builder, Debug, PartialEq, Clone)]
|
||||
@ -56,28 +58,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Builder for creating a material pattern that alternates between the given colors along each unit of the
|
||||
/// X-axis. The strip extends infinitely in the positive and negative Y and Z axes.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use rtchallenge::{
|
||||
/// patterns::{stripe_pattern, ColorMapper},
|
||||
/// BLACK, WHITE,
|
||||
/// };
|
||||
///
|
||||
/// # fn main() -> Result<(), Box<std::error::Error>> {
|
||||
///
|
||||
/// let pattern = stripe_pattern(BLACK, WHITE).build()?;
|
||||
/// assert_eq!(pattern.color, ColorMapper::Stripe { a: BLACK, b: WHITE });
|
||||
///
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn stripe_pattern(a: Color, b: Color) -> PatternBuilder {
|
||||
PatternBuilder::default().color(ColorMapper::Stripe { a, b })
|
||||
}
|
||||
|
||||
/// Builder for creating a material pattern used for testing. The color returned is the pattern space point
|
||||
/// after going through world->object and object->pattern space translation.
|
||||
///
|
||||
@ -101,28 +81,53 @@ pub fn test_pattern() -> PatternBuilder {
|
||||
PatternBuilder::default().color(ColorMapper::TestPattern)
|
||||
}
|
||||
|
||||
/// Builder for creating a material pattern that alternates between the given colors along each unit of the
|
||||
/// X-axis. The strip extends infinitely in the positive and negative Y and Z axes.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use rtchallenge::{
|
||||
/// patterns::{stripe_pattern, ColorMapper},
|
||||
/// BLACK, WHITE,
|
||||
/// };
|
||||
///
|
||||
/// # fn main() -> Result<(), Box<std::error::Error>> {
|
||||
///
|
||||
/// let pattern = stripe_pattern(BLACK, WHITE).build()?;
|
||||
/// assert_eq!(pattern.color, ColorMapper::Stripe { a: BLACK, b: WHITE });
|
||||
///
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn stripe_pattern(a: Color, b: Color) -> PatternBuilder {
|
||||
PatternBuilder::default().color(ColorMapper::Stripe { a, b })
|
||||
}
|
||||
|
||||
/// Builder for creating a material pattern that gradually blends between the given colors along
|
||||
/// the X-axis.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use rtchallenge::{
|
||||
/// matrices::Matrix4x4,
|
||||
/// patterns::{gradient_pattern, ColorMapper},
|
||||
/// BLACK, WHITE,
|
||||
/// };
|
||||
///
|
||||
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
///
|
||||
/// let pattern = gradient_pattern(WHITE, BLACK).build()?;
|
||||
/// assert_eq!(pattern.color, ColorMapper::Gradient { a: WHITE, b: BLACK });
|
||||
///
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn gradient_pattern(a: Color, b: Color) -> PatternBuilder {
|
||||
PatternBuilder::default().color(ColorMapper::Gradient { a, b })
|
||||
}
|
||||
|
||||
/// Generic implementation for mapping points to colors according to the given [ColorMapper].
|
||||
impl Pattern {
|
||||
/// Create a pattern that alternates between the given colors along each unit of the
|
||||
/// X-axis. The strip extends infinitely in the positive and negative Y and Z axes.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use rtchallenge::{
|
||||
/// patterns::{ColorMapper, Pattern},
|
||||
/// BLACK, WHITE,
|
||||
/// };
|
||||
///
|
||||
/// let pattern = Pattern::stripe(BLACK, WHITE);
|
||||
/// assert_eq!(pattern.color, ColorMapper::Stripe { a: BLACK, b: WHITE });
|
||||
/// ```
|
||||
pub fn stripe(a: Color, b: Color) -> Pattern {
|
||||
Pattern {
|
||||
color: ColorMapper::Stripe { a, b },
|
||||
..Pattern::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a pattern used for testing. The color returned is the pattern space point
|
||||
/// after going through world->object and object->pattern space translation.
|
||||
///
|
||||
@ -148,16 +153,60 @@ impl Pattern {
|
||||
..Pattern::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a pattern that alternates between the given colors along each unit of the
|
||||
/// X-axis. The strip extends infinitely in the positive and negative Y and Z axes.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use rtchallenge::{
|
||||
/// patterns::{ColorMapper, Pattern},
|
||||
/// BLACK, WHITE,
|
||||
/// };
|
||||
///
|
||||
/// let pattern = Pattern::stripe(BLACK, WHITE);
|
||||
/// assert_eq!(pattern.color, ColorMapper::Stripe { a: BLACK, b: WHITE });
|
||||
/// ```
|
||||
pub fn stripe(a: Color, b: Color) -> Pattern {
|
||||
Pattern {
|
||||
color: ColorMapper::Stripe { a, b },
|
||||
..Pattern::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a pattern that alternates between the given colors along each unit of the
|
||||
/// X-axis. The strip extends infinitely in the positive and negative Y and Z axes.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use rtchallenge::{
|
||||
/// patterns::{ColorMapper, Pattern},
|
||||
/// BLACK, WHITE,
|
||||
/// };
|
||||
///
|
||||
/// let pattern = Pattern::gradient(BLACK, WHITE);
|
||||
/// assert_eq!(pattern.color, ColorMapper::Gradient { a: BLACK, b: WHITE });
|
||||
/// ```
|
||||
pub fn gradient(a: Color, b: Color) -> Pattern {
|
||||
Pattern {
|
||||
color: ColorMapper::Gradient { a, b },
|
||||
..Pattern::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// Sample the color at the given point in untranslated object space.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// use rtchallenge::{patterns::stripe_pattern, tuples::point, BLACK, WHITE};
|
||||
/// use rtchallenge::{patterns::Pattern, tuples::point, BLACK, WHITE};
|
||||
///
|
||||
/// # fn main() -> Result<(), Box<std::error::Error>> {
|
||||
///
|
||||
/// let pattern = stripe_pattern(WHITE, BLACK).build()?;
|
||||
/// // A test returns the pattern space coordinates of the point.
|
||||
/// let pattern = Pattern::test();
|
||||
/// let p = point(1., 2., 3.);
|
||||
/// assert_eq!(pattern.pattern_at(p), [p.x, p.y, p.z].into());
|
||||
///
|
||||
/// // A stripe alternates between two colors.
|
||||
/// let pattern = Pattern::stripe(WHITE, BLACK);
|
||||
/// for (p, want) in &[
|
||||
/// // A stripe pattern is constant in y.
|
||||
/// (point(0., 0., 0.), WHITE),
|
||||
@ -178,8 +227,21 @@ impl Pattern {
|
||||
/// assert_eq!(pattern.pattern_at(*p), *want, "{:?}", p);
|
||||
/// }
|
||||
///
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// // A gradient linearly interpolates between two colors.
|
||||
/// let pattern = Pattern::gradient(WHITE, BLACK);
|
||||
/// assert_eq!(pattern.pattern_at(point(0., 0., 0.)), WHITE);
|
||||
/// assert_eq!(
|
||||
/// pattern.pattern_at(point(0.25, 0., 0.)),
|
||||
/// [0.75, 0.75, 0.75].into()
|
||||
/// );
|
||||
/// assert_eq!(
|
||||
/// pattern.pattern_at(point(0.5, 0., 0.)),
|
||||
/// [0.5, 0.5, 0.5].into()
|
||||
/// );
|
||||
/// assert_eq!(
|
||||
/// pattern.pattern_at(point(0.75, 0., 0.)),
|
||||
/// [0.25, 0.25, 0.25].into()
|
||||
/// );
|
||||
/// ```
|
||||
pub fn pattern_at(&self, point: Tuple) -> Color {
|
||||
match self.color {
|
||||
@ -201,6 +263,11 @@ impl Pattern {
|
||||
b
|
||||
}
|
||||
}
|
||||
ColorMapper::Gradient { a, b } => {
|
||||
let distance = b - a;
|
||||
let fraction = point.x - point.x.floor();
|
||||
a + distance * fraction
|
||||
}
|
||||
}
|
||||
}
|
||||
/// Sample the color at the given world point on the given object.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user