Forgot to actually implement FilterTrait

This commit is contained in:
pingu 2025-12-30 18:19:17 +00:00
parent 75655ed774
commit cc557dfa50
7 changed files with 44 additions and 32 deletions

View file

@ -1,6 +1,6 @@
use crate::core::camera::CameraTransform; use crate::core::camera::CameraTransform;
use crate::core::color::{MatrixMulColor, RGB, SRGB, XYZ, white_balance}; use crate::core::color::{MatrixMulColor, RGB, SRGB, XYZ, white_balance};
use crate::core::filter::Filter; use crate::core::filter::{Filter, FilterTrait};
use crate::core::geometry::{ use crate::core::geometry::{
Bounds2f, Bounds2fi, Bounds2i, Normal3f, Point2f, Point2i, Point3f, Tuple, Vector2f, Vector2fi, Bounds2f, Bounds2fi, Bounds2i, Normal3f, Point2f, Point2i, Point3f, Tuple, Vector2f, Vector2fi,
Vector2i, Vector3f, Vector2i, Vector3f,
@ -90,7 +90,7 @@ impl RGBFilm {
pub fn get_sensor(&self) -> &PixelSensor { pub fn get_sensor(&self) -> &PixelSensor {
#[cfg(not(target_os = "cuda"))] #[cfg(not(target_os = "cuda"))]
{ {
if self.sensor.is_null() { if self.film.sensor.is_null() {
panic!( panic!(
"FilmBase error: PixelSensor pointer is null. This should have been checked during construction." "FilmBase error: PixelSensor pointer is null. This should have been checked during construction."
); );
@ -208,7 +208,7 @@ struct GBufferPixel {
} }
#[repr(C)] #[repr(C)]
#[derive(Debug, Default)] #[derive(Debug, Copy)]
#[cfg_attr(target_os = "cuda", derive(Copy, Clone))] #[cfg_attr(target_os = "cuda", derive(Copy, Clone))]
pub struct GBufferFilm { pub struct GBufferFilm {
pub base: FilmBase, pub base: FilmBase,
@ -570,7 +570,7 @@ impl VisibleSurface {
} }
#[repr(C)] #[repr(C)]
#[derive(Default, Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub struct FilmBase { pub struct FilmBase {
pub full_resolution: Point2i, pub full_resolution: Point2i,
pub pixel_bounds: Bounds2i, pub pixel_bounds: Bounds2i,

View file

@ -59,6 +59,7 @@ impl FilterSampler {
} }
} }
#[enum_dispatch]
pub trait FilterTrait { pub trait FilterTrait {
fn radius(&self) -> Vector2f; fn radius(&self) -> Vector2f;
fn evaluate(&self, p: Point2f) -> Float; fn evaluate(&self, p: Point2f) -> Float;

View file

@ -1,9 +1,10 @@
use crate::Float; use crate::Float;
use crate::core::filter::FilterSample; use crate::core::filter::{FilterSample, FilterTrait};
use crate::core::geometry::{Point2f, Vector2f}; use crate::core::geometry::{Point2f, Vector2f};
use crate::utils::math::lerp; use crate::utils::math::lerp;
#[derive(Clone, Debug)] #[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct BoxFilter { pub struct BoxFilter {
pub radius: Vector2f, pub radius: Vector2f,
} }
@ -12,12 +13,13 @@ impl BoxFilter {
pub fn new(radius: Vector2f) -> Self { pub fn new(radius: Vector2f) -> Self {
Self { radius } Self { radius }
} }
}
pub fn radius(&self) -> Vector2f { impl FilterTrait for BoxFilter {
fn radius(&self) -> Vector2f {
self.radius self.radius
} }
pub fn evaluate(&self, p: Point2f) -> Float { fn evaluate(&self, p: Point2f) -> Float {
if p.x().abs() <= self.radius.x() && p.y().abs() <= self.radius.y() { if p.x().abs() <= self.radius.x() && p.y().abs() <= self.radius.y() {
1. 1.
} else { } else {
@ -25,11 +27,11 @@ impl BoxFilter {
} }
} }
pub fn integral(&self) -> Float { fn integral(&self) -> Float {
(2.0 * self.radius.x()) * (2.0 * self.radius.y()) (2.0 * self.radius.x()) * (2.0 * self.radius.y())
} }
pub fn sample(&self, u: Point2f) -> FilterSample { fn sample(&self, u: Point2f) -> FilterSample {
let p = Point2f::new( let p = Point2f::new(
lerp(u[0], -self.radius.x(), self.radius.x()), lerp(u[0], -self.radius.x(), self.radius.x()),
lerp(u[1], -self.radius.y(), self.radius.y()), lerp(u[1], -self.radius.y(), self.radius.y()),

View file

@ -1,5 +1,5 @@
use crate::Float; use crate::Float;
use crate::core::filter::{FilterSample, FilterSampler}; use crate::core::filter::{FilterSample, FilterSampler, FilterTrait};
use crate::core::geometry::{Point2f, Vector2f}; use crate::core::geometry::{Point2f, Vector2f};
use crate::utils::math::{gaussian, gaussian_integral}; use crate::utils::math::{gaussian, gaussian_integral};
@ -32,24 +32,26 @@ impl GaussianFilter {
sampler, sampler,
} }
} }
}
pub fn radius(&self) -> Vector2f { impl FilterTrait for GaussianFilter {
fn radius(&self) -> Vector2f {
self.radius self.radius
} }
pub fn evaluate(&self, p: Point2f) -> Float { fn evaluate(&self, p: Point2f) -> Float {
(gaussian(p.x(), 0.0, self.sigma) - self.exp_x).max(0.0) (gaussian(p.x(), 0.0, self.sigma) - self.exp_x).max(0.0)
* (gaussian(p.y(), 0.0, self.sigma) - self.exp_y).max(0.0) * (gaussian(p.y(), 0.0, self.sigma) - self.exp_y).max(0.0)
} }
pub fn integral(&self) -> Float { fn integral(&self) -> Float {
(gaussian_integral(-self.radius.x(), self.radius.x(), 0.0, self.sigma) (gaussian_integral(-self.radius.x(), self.radius.x(), 0.0, self.sigma)
- 2.0 * self.radius.x() * self.exp_x) - 2.0 * self.radius.x() * self.exp_x)
* (gaussian_integral(-self.radius.y(), self.radius.y(), 0.0, self.sigma) * (gaussian_integral(-self.radius.y(), self.radius.y(), 0.0, self.sigma)
- 2.0 * self.radius.y() * self.exp_y) - 2.0 * self.radius.y() * self.exp_y)
} }
pub fn sample(&self, u: Point2f) -> FilterSample { fn sample(&self, u: Point2f) -> FilterSample {
self.sampler.sample(u) self.sampler.sample(u)
} }
} }

View file

@ -1,5 +1,5 @@
use crate::Float; use crate::Float;
use crate::core::filter::{FilterSample, FilterSampler}; use crate::core::filter::{FilterSample, FilterSampler, FilterTrait};
use crate::core::geometry::{Point2f, Vector2f}; use crate::core::geometry::{Point2f, Vector2f};
use crate::utils::math::{lerp, windowed_sinc}; use crate::utils::math::{lerp, windowed_sinc};
use rand::Rng; use rand::Rng;
@ -24,17 +24,19 @@ impl LanczosSincFilter {
sampler, sampler,
} }
} }
}
pub fn radius(&self) -> Vector2f { impl FilterTrait for LanczosSincFilter {
fn radius(&self) -> Vector2f {
self.radius self.radius
} }
pub fn evaluate(&self, p: Point2f) -> Float { fn evaluate(&self, p: Point2f) -> Float {
windowed_sinc(p.x(), self.radius.x(), self.tau) windowed_sinc(p.x(), self.radius.x(), self.tau)
* windowed_sinc(p.y(), self.radius.y(), self.tau) * windowed_sinc(p.y(), self.radius.y(), self.tau)
} }
pub fn integral(&self) -> Float { fn integral(&self) -> Float {
let sqrt_samples = 64; let sqrt_samples = 64;
let n_samples = sqrt_samples * sqrt_samples; let n_samples = sqrt_samples * sqrt_samples;
let area = (2.0 * self.radius.x()) * (2.0 * self.radius.y()); let area = (2.0 * self.radius.x()) * (2.0 * self.radius.y());
@ -57,7 +59,7 @@ impl LanczosSincFilter {
sum / n_samples as Float * area sum / n_samples as Float * area
} }
pub fn sample(&self, u: Point2f) -> FilterSample { fn sample(&self, u: Point2f) -> FilterSample {
self.sampler.sample(u) self.sampler.sample(u)
} }
} }

View file

@ -1,8 +1,9 @@
use crate::Float; use crate::Float;
use crate::core::filter::{FilterSample, FilterSampler}; use crate::core::filter::{FilterSample, FilterSampler, FilterTrait};
use crate::core::geometry::{Point2f, Vector2f}; use crate::core::geometry::{Point2f, Vector2f};
#[derive(Clone, Debug)] #[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct MitchellFilter { pub struct MitchellFilter {
pub radius: Vector2f, pub radius: Vector2f,
pub b: Float, pub b: Float,
@ -47,21 +48,23 @@ impl MitchellFilter {
fn mitchell_1d(&self, x: Float) -> Float { fn mitchell_1d(&self, x: Float) -> Float {
Self::mitchell_1d_eval(self.b, self.c, x) Self::mitchell_1d_eval(self.b, self.c, x)
} }
}
pub fn radius(&self) -> Vector2f { impl FilterTrait for MitchellFilter {
fn radius(&self) -> Vector2f {
self.radius self.radius
} }
pub fn evaluate(&self, p: Point2f) -> Float { fn evaluate(&self, p: Point2f) -> Float {
self.mitchell_1d(2.0 * p.x() / self.radius.x()) self.mitchell_1d(2.0 * p.x() / self.radius.x())
* self.mitchell_1d(2.0 * p.y() / self.radius.y()) * self.mitchell_1d(2.0 * p.y() / self.radius.y())
} }
pub fn integral(&self) -> Float { fn integral(&self) -> Float {
self.radius.x() * self.radius.y() / 4.0 self.radius.x() * self.radius.y() / 4.0
} }
pub fn sample(&self, u: Point2f) -> FilterSample { fn sample(&self, u: Point2f) -> FilterSample {
self.sampler.sample(u) self.sampler.sample(u)
} }
} }

View file

@ -1,5 +1,5 @@
use crate::Float; use crate::Float;
use crate::core::filter::FilterSample; use crate::core::filter::{FilterSample, FilterTrait};
use crate::core::geometry::{Point2f, Vector2f}; use crate::core::geometry::{Point2f, Vector2f};
use crate::utils::math::sample_tent; use crate::utils::math::sample_tent;
@ -13,20 +13,22 @@ impl TriangleFilter {
pub fn new(radius: Vector2f) -> Self { pub fn new(radius: Vector2f) -> Self {
Self { radius } Self { radius }
} }
}
pub fn radius(&self) -> Vector2f { impl FilterTrait for TriangleFilter {
fn radius(&self) -> Vector2f {
self.radius self.radius
} }
pub fn evaluate(&self, p: Point2f) -> Float { fn evaluate(&self, p: Point2f) -> Float {
(self.radius.x() - p.x().abs()).max(0.0) * (self.radius.y() - p.y().abs()).max(0.0) (self.radius.x() - p.x().abs()).max(0.0) * (self.radius.y() - p.y().abs()).max(0.0)
} }
pub fn integral(&self) -> Float { fn integral(&self) -> Float {
self.radius.x().powi(2) * self.radius.y().powi(2) self.radius.x().powi(2) * self.radius.y().powi(2)
} }
pub fn sample(&self, u: Point2f) -> FilterSample { fn sample(&self, u: Point2f) -> FilterSample {
let p = Point2f::new( let p = Point2f::new(
sample_tent(u[0], self.radius.x()), sample_tent(u[0], self.radius.x()),
sample_tent(u[1], self.radius.y()), sample_tent(u[1], self.radius.y()),