Break texture module into multiple files.
This commit is contained in:
parent
66d599b50d
commit
f483f2905b
@ -1,160 +0,0 @@
|
|||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use image::RgbImage;
|
|
||||||
use rand;
|
|
||||||
|
|
||||||
use perlin::Perlin;
|
|
||||||
use vec3::Vec3;
|
|
||||||
|
|
||||||
pub trait Texture: Send + Sync {
|
|
||||||
fn value(&self, u: f32, v: f32, p: Vec3) -> Vec3;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Texture for Arc<Texture> {
|
|
||||||
fn value(&self, u: f32, v: f32, p: Vec3) -> Vec3 {
|
|
||||||
(**self).value(u, v, p)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
|
||||||
pub struct ConstantTexture {
|
|
||||||
color: Vec3,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ConstantTexture {
|
|
||||||
pub fn new<V>(color: V) -> ConstantTexture
|
|
||||||
where
|
|
||||||
V: Into<Vec3>,
|
|
||||||
{
|
|
||||||
ConstantTexture {
|
|
||||||
color: color.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Texture for ConstantTexture {
|
|
||||||
fn value(&self, _u: f32, _v: f32, _p: Vec3) -> Vec3 {
|
|
||||||
self.color
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct CheckerTexture<T>
|
|
||||||
where
|
|
||||||
T: Texture,
|
|
||||||
{
|
|
||||||
odd: T,
|
|
||||||
even: T,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> CheckerTexture<T>
|
|
||||||
where
|
|
||||||
T: Texture,
|
|
||||||
{
|
|
||||||
pub fn new(odd: T, even: T) -> CheckerTexture<T> {
|
|
||||||
CheckerTexture { odd, even }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Texture for CheckerTexture<T>
|
|
||||||
where
|
|
||||||
T: Texture,
|
|
||||||
{
|
|
||||||
fn value(&self, u: f32, v: f32, p: Vec3) -> Vec3 {
|
|
||||||
let sines = (10. * p.x).sin() * (10. * p.y).sin() * (10. * p.z).sin();
|
|
||||||
if sines < 0. {
|
|
||||||
self.odd.value(u, v, p)
|
|
||||||
} else {
|
|
||||||
self.even.value(u, v, p)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct NoiseTexture {
|
|
||||||
scale: f32,
|
|
||||||
perlin: Perlin,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl NoiseTexture {
|
|
||||||
pub fn new<R>(rng: &mut R) -> NoiseTexture
|
|
||||||
where
|
|
||||||
R: rand::Rng,
|
|
||||||
{
|
|
||||||
NoiseTexture::with_scale(rng, 1.)
|
|
||||||
}
|
|
||||||
pub fn with_scale<R>(rng: &mut R, scale: f32) -> NoiseTexture
|
|
||||||
where
|
|
||||||
R: rand::Rng,
|
|
||||||
{
|
|
||||||
NoiseTexture {
|
|
||||||
scale,
|
|
||||||
perlin: Perlin::new(rng),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Texture for NoiseTexture {
|
|
||||||
fn value(&self, _u: f32, _v: f32, p: Vec3) -> Vec3 {
|
|
||||||
Vec3::new(1., 1., 1.) * 0.5 * (1. + self.perlin.noise(self.scale * p))
|
|
||||||
|
|
||||||
//Vec3::new(1., 1., 1.) * turb(self.scale * p, 7)
|
|
||||||
//Vec3::new(1., 1., 1.) * 0.5 * (1. + turb(self.scale * p, 7))
|
|
||||||
//Vec3::new(1., 1., 1.) * 0.5 * (1. + (self.scale * p.z + 10. * self.perlin.turb(p, 7)).sin())
|
|
||||||
//Vec3::new(1., 1., 1.) * 0.5 * (1. + GENERATOR.noise(self.scale * p))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct ImageTexture {
|
|
||||||
img: RgbImage,
|
|
||||||
width: f32,
|
|
||||||
height: f32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ImageTexture {
|
|
||||||
pub fn new(img: RgbImage) -> ImageTexture {
|
|
||||||
let (w, h) = img.dimensions();
|
|
||||||
ImageTexture {
|
|
||||||
img,
|
|
||||||
width: f32::from(w.min(64000) as u16),
|
|
||||||
height: f32::from(h.min(64000) as u16),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Texture for ImageTexture {
|
|
||||||
fn value(&self, u: f32, v: f32, _p: Vec3) -> Vec3 {
|
|
||||||
// Wrap texcoords by default.
|
|
||||||
let x = (u % 1. * (self.width - 1.)) as u32;
|
|
||||||
let y = ((1. - v % 1.) * (self.height - 1.)) as u32;
|
|
||||||
if x >= self.width as u32 {
|
|
||||||
panic!(format!(
|
|
||||||
"u {} v {} x {} y {} w {} h {}",
|
|
||||||
u, v, x, y, self.width, self.height
|
|
||||||
));
|
|
||||||
}
|
|
||||||
if y >= self.height as u32 {
|
|
||||||
panic!(format!(
|
|
||||||
"u {} v {} x {} y {} w {} h {}",
|
|
||||||
u, v, x, y, self.width, self.height
|
|
||||||
));
|
|
||||||
}
|
|
||||||
let pixel = self.img.get_pixel(x, y);
|
|
||||||
Vec3::new(
|
|
||||||
f32::from(pixel[0]) / 255.,
|
|
||||||
f32::from(pixel[1]) / 255.,
|
|
||||||
f32::from(pixel[2]) / 255.,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn constant_texture_from_array() {
|
|
||||||
assert_eq!(
|
|
||||||
ConstantTexture::new(Vec3::new(1., 2., 3.)),
|
|
||||||
ConstantTexture::new([1., 2., 3.])
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
33
rtiow/src/texture/checker.rs
Normal file
33
rtiow/src/texture/checker.rs
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
use texture::Texture;
|
||||||
|
use vec3::Vec3;
|
||||||
|
|
||||||
|
pub struct CheckerTexture<T>
|
||||||
|
where
|
||||||
|
T: Texture,
|
||||||
|
{
|
||||||
|
odd: T,
|
||||||
|
even: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> CheckerTexture<T>
|
||||||
|
where
|
||||||
|
T: Texture,
|
||||||
|
{
|
||||||
|
pub fn new(odd: T, even: T) -> CheckerTexture<T> {
|
||||||
|
CheckerTexture { odd, even }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Texture for CheckerTexture<T>
|
||||||
|
where
|
||||||
|
T: Texture,
|
||||||
|
{
|
||||||
|
fn value(&self, u: f32, v: f32, p: Vec3) -> Vec3 {
|
||||||
|
let sines = (10. * p.x).sin() * (10. * p.y).sin() * (10. * p.z).sin();
|
||||||
|
if sines < 0. {
|
||||||
|
self.odd.value(u, v, p)
|
||||||
|
} else {
|
||||||
|
self.even.value(u, v, p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
24
rtiow/src/texture/constant.rs
Normal file
24
rtiow/src/texture/constant.rs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
use texture::Texture;
|
||||||
|
use vec3::Vec3;
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub struct ConstantTexture {
|
||||||
|
color: Vec3,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConstantTexture {
|
||||||
|
pub fn new<V>(color: V) -> ConstantTexture
|
||||||
|
where
|
||||||
|
V: Into<Vec3>,
|
||||||
|
{
|
||||||
|
ConstantTexture {
|
||||||
|
color: color.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Texture for ConstantTexture {
|
||||||
|
fn value(&self, _u: f32, _v: f32, _p: Vec3) -> Vec3 {
|
||||||
|
self.color
|
||||||
|
}
|
||||||
|
}
|
||||||
47
rtiow/src/texture/image.rs
Normal file
47
rtiow/src/texture/image.rs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
use image::RgbImage;
|
||||||
|
|
||||||
|
use texture::Texture;
|
||||||
|
use vec3::Vec3;
|
||||||
|
|
||||||
|
pub struct ImageTexture {
|
||||||
|
img: RgbImage,
|
||||||
|
width: f32,
|
||||||
|
height: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ImageTexture {
|
||||||
|
pub fn new(img: RgbImage) -> ImageTexture {
|
||||||
|
let (w, h) = img.dimensions();
|
||||||
|
ImageTexture {
|
||||||
|
img,
|
||||||
|
width: f32::from(w.min(64000) as u16),
|
||||||
|
height: f32::from(h.min(64000) as u16),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Texture for ImageTexture {
|
||||||
|
fn value(&self, u: f32, v: f32, _p: Vec3) -> Vec3 {
|
||||||
|
// Wrap texcoords by default.
|
||||||
|
let x = (u % 1. * (self.width - 1.)) as u32;
|
||||||
|
let y = ((1. - v % 1.) * (self.height - 1.)) as u32;
|
||||||
|
if x >= self.width as u32 {
|
||||||
|
panic!(format!(
|
||||||
|
"u {} v {} x {} y {} w {} h {}",
|
||||||
|
u, v, x, y, self.width, self.height
|
||||||
|
));
|
||||||
|
}
|
||||||
|
if y >= self.height as u32 {
|
||||||
|
panic!(format!(
|
||||||
|
"u {} v {} x {} y {} w {} h {}",
|
||||||
|
u, v, x, y, self.width, self.height
|
||||||
|
));
|
||||||
|
}
|
||||||
|
let pixel = self.img.get_pixel(x, y);
|
||||||
|
Vec3::new(
|
||||||
|
f32::from(pixel[0]) / 255.,
|
||||||
|
f32::from(pixel[1]) / 255.,
|
||||||
|
f32::from(pixel[2]) / 255.,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
35
rtiow/src/texture/mod.rs
Normal file
35
rtiow/src/texture/mod.rs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
mod checker;
|
||||||
|
mod constant;
|
||||||
|
mod image;
|
||||||
|
mod noise;
|
||||||
|
pub use texture::checker::CheckerTexture;
|
||||||
|
pub use texture::constant::ConstantTexture;
|
||||||
|
pub use texture::image::ImageTexture;
|
||||||
|
pub use texture::noise::NoiseTexture;
|
||||||
|
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use vec3::Vec3;
|
||||||
|
|
||||||
|
pub trait Texture: Send + Sync {
|
||||||
|
fn value(&self, u: f32, v: f32, p: Vec3) -> Vec3;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Texture for Arc<Texture> {
|
||||||
|
fn value(&self, u: f32, v: f32, p: Vec3) -> Vec3 {
|
||||||
|
(**self).value(u, v, p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn constant_texture_from_array() {
|
||||||
|
assert_eq!(
|
||||||
|
ConstantTexture::new(Vec3::new(1., 2., 3.)),
|
||||||
|
ConstantTexture::new([1., 2., 3.])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
39
rtiow/src/texture/noise.rs
Normal file
39
rtiow/src/texture/noise.rs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
use rand;
|
||||||
|
|
||||||
|
use perlin::Perlin;
|
||||||
|
use texture::Texture;
|
||||||
|
use vec3::Vec3;
|
||||||
|
|
||||||
|
pub struct NoiseTexture {
|
||||||
|
scale: f32,
|
||||||
|
perlin: Perlin,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NoiseTexture {
|
||||||
|
pub fn new<R>(rng: &mut R) -> NoiseTexture
|
||||||
|
where
|
||||||
|
R: rand::Rng,
|
||||||
|
{
|
||||||
|
NoiseTexture::with_scale(rng, 1.)
|
||||||
|
}
|
||||||
|
pub fn with_scale<R>(rng: &mut R, scale: f32) -> NoiseTexture
|
||||||
|
where
|
||||||
|
R: rand::Rng,
|
||||||
|
{
|
||||||
|
NoiseTexture {
|
||||||
|
scale,
|
||||||
|
perlin: Perlin::new(rng),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Texture for NoiseTexture {
|
||||||
|
fn value(&self, _u: f32, _v: f32, p: Vec3) -> Vec3 {
|
||||||
|
Vec3::new(1., 1., 1.) * 0.5 * (1. + self.perlin.noise(self.scale * p))
|
||||||
|
|
||||||
|
//Vec3::new(1., 1., 1.) * turb(self.scale * p, 7)
|
||||||
|
//Vec3::new(1., 1., 1.) * 0.5 * (1. + turb(self.scale * p, 7))
|
||||||
|
//Vec3::new(1., 1., 1.) * 0.5 * (1. + (self.scale * p.z + 10. * self.perlin.turb(p, 7)).sin())
|
||||||
|
//Vec3::new(1., 1., 1.) * 0.5 * (1. + GENERATOR.noise(self.scale * p))
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user