pbrt/shared/src/textures/dots.rs

81 lines
2.2 KiB
Rust

use crate::Float;
use crate::core::geometry::{Point2f, VectorLike};
use crate::core::texture::{
FloatTexture, SpectrumTexture, TextureEvalContext, TextureMapping2D,
};
use crate::spectra::sampled::{SampledSpectrum, SampledWavelengths};
use crate::utils::Ptr;
use crate::utils::math::square;
use crate::utils::noise::noise_2d;
use num_traits::Float as NumFloat;
fn inside_polka_dot(st: Point2f) -> bool {
let s_cell = (st[0] + 0.5).floor();
let t_cell = (st[1] + 0.5).floor();
if noise_2d(s_cell + 0.5, t_cell + 0.5) > 0. {
let radius = 0.35;
let max_shift = 0.5 + radius;
let s_center = s_cell + max_shift * noise_2d(s_cell + 1.5, t_cell + 2.8);
let t_center = t_cell + max_shift * noise_2d(s_cell + 4.5, t_cell + 9.8);
let dst = st - Point2f::new(s_center, t_center);
if dst.norm_squared() < square(radius) {
return true;
}
}
return false;
}
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct FloatDotsTexture {
pub mapping: TextureMapping2D,
pub outside_dot: Ptr<FloatTexture>,
pub inside_dot: Ptr<FloatTexture>,
}
impl FloatDotsTexture {
pub fn evaluate(&self, ctx: &TextureEvalContext) -> Float {
let c = self.mapping.map(ctx);
let target_texture = if inside_polka_dot(c.st) {
self.inside_dot
} else {
self.outside_dot
};
if !target_texture.is_null() {
target_texture.evaluate(ctx)
} else {
0.0
}
}
}
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct SpectrumDotsTexture {
pub mapping: TextureMapping2D,
pub outside_dot: Ptr<SpectrumTexture>,
pub inside_dot: Ptr<SpectrumTexture>,
}
impl SpectrumDotsTexture {
pub fn evaluate(
&self,
ctx: &TextureEvalContext,
lambda: &SampledWavelengths,
) -> SampledSpectrum {
let c = self.mapping.map(ctx);
let target_texture = if inside_polka_dot(c.st) {
self.inside_dot
} else {
self.outside_dot
};
if !target_texture.is_null() {
target_texture.evaluate(ctx, lambda)
} else {
SampledSpectrum::new(0.0)
}
}
}