Implement post-transform coefficients #6

Merged
bspeice merged 1 commits from post_transform into main 2026-07-12 13:43:23 -04:00
4 changed files with 73 additions and 18 deletions
+1 -1
View File
@@ -24,7 +24,7 @@ bytemuck = { version = "1.25.0", features = ["derive"] }
glam = { version = "0.33.1", default-features = false, features = ["bytemuck", "scalar-math"] }
image = { version = "0.25.10", default-features = false, features = ["default-formats"]}
libm = "0.2.16"
rand = { version = "0.10.1", default-features = false }
rand = { version = "0.10.1", default-features = false }
rand_xoshiro = "0.8.1"
rspirv = "0.13.0"
tempfile = "3.27.0"
+15 -15
View File
@@ -17,21 +17,21 @@ const IMAGE_DIMENSION: UVec2 = uvec2(600, 600);
pub fn main() -> Result<()> {
let transforms = [
// F_0: (x / 2, y / 2)
Transform::new(
Affine2::from_coefficients(0.5, 0.0, 0.0, 0.0, 0.5, 0.0),
uvec2(0, 1),
),
// F_1: ((x + 1) / 2, y / 2)
Transform::new(
Affine2::from_coefficients(0.5, 0.0, 0.5, 0.0, 0.5, 0.0),
uvec2(0, 1),
),
// F_2: (x / 2, (y + 1) / 2)
Transform::new(
Affine2::from_coefficients(0.5, 0.0, 0.0, 0.0, 0.5, 0.5),
uvec2(0, 1),
),
{
// F_0: (x / 2, y / 2)
let coefficients = Affine2::from_coefficients(0.5, 0.0, 0.0, 0.0, 0.5, 0.0);
Transform::new(coefficients, Affine2::IDENTITY, uvec2(0, 1))
},
{
// F_1: ((x + 1) / 2, y / 2)
let coefficients = Affine2::from_coefficients(0.5, 0.0, 0.5, 0.0, 0.5, 0.0);
Transform::new(coefficients, Affine2::IDENTITY, uvec2(0, 1))
},
{
// F_2: (x / 2, (y + 1) / 2)
let coefficients = Affine2::from_coefficients(0.5, 0.0, 0.0, 0.0, 0.5, 0.5);
Transform::new(coefficients, Affine2::IDENTITY, uvec2(0, 1))
},
];
let weights = [1.0 / 3.0, 1.0 / 3.0, 1.0 / 3.0];
+51 -2
View File
@@ -13,14 +13,16 @@ use rand::Rng;
#[repr(C)]
pub struct Transform {
coefficients: Affine2,
coefficients_post: Affine2,
variation_range: UVec2,
}
impl Transform {
/// Create a new transform from an affine transformation matrix
pub fn new(coefficients: Affine2, variation_range: UVec2) -> Self {
pub fn new(coefficients: Affine2, coefficients_post: Affine2, variation_range: UVec2) -> Self {
Transform {
coefficients,
coefficients_post,
variation_range,
}
}
@@ -43,6 +45,53 @@ impl Transform {
point_output += variation.transform_point(point, rng, &self.coefficients)
}
point_output
self.coefficients_post.transform_point2(point)
}
}
#[cfg(test)]
mod test {
use crate::rng::xoshiro256starstar_from_seed;
use crate::transform::Transform;
use crate::variation::{Variation, VariationKind};
use glam::{Affine2, uvec2, vec2};
#[test]
fn transform_scaling() {
let scale_coefficients = vec2(2.0, 0.5);
let transform = Transform::new(
Affine2::from_scale(scale_coefficients),
Affine2::IDENTITY,
uvec2(0, 1),
);
let mut rng = xoshiro256starstar_from_seed([0; 32]);
let variations = [Variation::IDENTITY];
let point = vec2(1.0, 1.0);
assert_eq!(
transform.transform_point(&mut rng, &variations, point),
scale_coefficients
);
}
#[test]
fn transform_scaling_post() {
let scale_coefficients = vec2(2.0, 0.5);
let transform_pdj = Transform::new(Affine2::IDENTITY, Affine2::IDENTITY, uvec2(0, 1));
let transform_pdj_post = Transform::new(
Affine2::IDENTITY,
Affine2::from_scale(scale_coefficients),
uvec2(0, 1),
);
let mut rng = xoshiro256starstar_from_seed([0; 32]);
let variations = [Variation::new(VariationKind::Pdj, 1.0, [0.0f32; 4].into())];
let point = vec2(1.0, 1.0);
let point_pdj = transform_pdj.transform_point(&mut rng, &variations, point);
let point_pdj_post = transform_pdj_post.transform_point(&mut rng, &variations, point);
assert_eq!(point_pdj * scale_coefficients, point_pdj_post);
}
}
+6
View File
@@ -20,6 +20,12 @@ use rand::{Rng, RngExt};
#[repr(C)]
pub struct VariationParams([f32; 4]);
impl From<[f32; 4]> for VariationParams {
fn from(v: [f32; 4]) -> Self {
VariationParams(v)
}
}
/// Enum for all supported variation types
///
/// ID numbers are chosen to match the variation identifier also used by `flam3`