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

View file

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

View file

@ -1,9 +1,10 @@
use crate::Float;
use crate::core::filter::FilterSample;
use crate::core::filter::{FilterSample, FilterTrait};
use crate::core::geometry::{Point2f, Vector2f};
use crate::utils::math::lerp;
#[derive(Clone, Debug)]
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct BoxFilter {
pub radius: Vector2f,
}
@ -12,12 +13,13 @@ impl BoxFilter {
pub fn new(radius: Vector2f) -> Self {
Self { radius }
}
pub fn radius(&self) -> Vector2f {
}
impl FilterTrait for BoxFilter {
fn radius(&self) -> Vector2f {
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() {
1.
} 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())
}
pub fn sample(&self, u: Point2f) -> FilterSample {
fn sample(&self, u: Point2f) -> FilterSample {
let p = Point2f::new(
lerp(u[0], -self.radius.x(), self.radius.x()),
lerp(u[1], -self.radius.y(), self.radius.y()),

View file

@ -1,5 +1,5 @@
use crate::Float;
use crate::core::filter::{FilterSample, FilterSampler};
use crate::core::filter::{FilterSample, FilterSampler, FilterTrait};
use crate::core::geometry::{Point2f, Vector2f};
use crate::utils::math::{gaussian, gaussian_integral};
@ -32,24 +32,26 @@ impl GaussianFilter {
sampler,
}
}
}
pub fn radius(&self) -> Vector2f {
impl FilterTrait for GaussianFilter {
fn radius(&self) -> Vector2f {
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.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)
- 2.0 * self.radius.x() * self.exp_x)
* (gaussian_integral(-self.radius.y(), self.radius.y(), 0.0, self.sigma)
- 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)
}
}

View file

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

View file

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

View file

@ -1,5 +1,5 @@
use crate::Float;
use crate::core::filter::FilterSample;
use crate::core::filter::{FilterSample, FilterTrait};
use crate::core::geometry::{Point2f, Vector2f};
use crate::utils::math::sample_tent;
@ -13,20 +13,22 @@ impl TriangleFilter {
pub fn new(radius: Vector2f) -> Self {
Self { radius }
}
}
pub fn radius(&self) -> Vector2f {
impl FilterTrait for TriangleFilter {
fn radius(&self) -> Vector2f {
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)
}
pub fn integral(&self) -> Float {
fn integral(&self) -> Float {
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(
sample_tent(u[0], self.radius.x()),
sample_tent(u[1], self.radius.y()),