Add documentation for recent functions
This commit is contained in:
@@ -77,10 +77,11 @@ pub fn main() -> Result<()> {
|
|||||||
let temp = NamedTempFile::with_suffix(".png").context("Unable to create file for image")?;
|
let temp = NamedTempFile::with_suffix(".png").context("Unable to create file for image")?;
|
||||||
image.save(temp.path()).context("Unable to save image")?;
|
image.save(temp.path()).context("Unable to save image")?;
|
||||||
|
|
||||||
let open_program = cfg_select! {
|
let open_program: &str = cfg_select! {
|
||||||
unix => "xdg-open",
|
unix => Some("xdg-open"),
|
||||||
_ => panic!("Unknown system"),
|
_ => None,
|
||||||
};
|
}
|
||||||
|
.expect("No available program to open images");
|
||||||
|
|
||||||
Command::new(open_program)
|
Command::new(open_program)
|
||||||
.arg(temp.path())
|
.arg(temp.path())
|
||||||
|
|||||||
@@ -90,11 +90,13 @@ impl Camera {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Shader entry point for running the camera transformation over a list of IFS coordinates
|
||||||
pub mod entry {
|
pub mod entry {
|
||||||
use crate::camera::Camera;
|
use crate::camera::Camera;
|
||||||
use spirv_std::glam::{IVec2, Vec2};
|
use spirv_std::glam::{IVec2, Vec2};
|
||||||
use spirv_std::spirv;
|
use spirv_std::spirv;
|
||||||
|
|
||||||
|
/// Transform IFS coordinates to pixel coordinates
|
||||||
#[spirv(compute(entry_point_name = "main_camera", threads(1)))]
|
#[spirv(compute(entry_point_name = "main_camera", threads(1)))]
|
||||||
pub fn main_camera(
|
pub fn main_camera(
|
||||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 0)] camera: &Camera,
|
#[spirv(storage_buffer, descriptor_set = 0, binding = 0)] camera: &Camera,
|
||||||
|
|||||||
@@ -107,23 +107,21 @@ impl<'a, R: Rng> Iterator for ChaosGame<'a, R> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Shader entry point for running the chaos game to produce new IFS coordinates
|
||||||
pub mod entry {
|
pub mod entry {
|
||||||
use crate::chaos_game::ChaosGame;
|
use crate::chaos_game::ChaosGame;
|
||||||
|
use crate::rng::xoshiro_from_state;
|
||||||
use crate::transform::Transform;
|
use crate::transform::Transform;
|
||||||
use crate::variation::Variation;
|
use crate::variation::Variation;
|
||||||
use glam::Vec2;
|
use glam::Vec2;
|
||||||
use rand_xoshiro::Xoshiro256StarStar;
|
|
||||||
use spirv_std::spirv;
|
use spirv_std::spirv;
|
||||||
|
|
||||||
fn xoshiro_from_state(rng_state: [u8; 32]) -> Xoshiro256StarStar {
|
/// Given a set of fractal flame parameters, generate new IFS coordinates
|
||||||
let mut rng_state_actual = [1u64, 2u64, 3u64, 4u64];
|
/// and store them in the output array.
|
||||||
unsafe { core::mem::transmute(rng_state_actual) }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[spirv(compute(entry_point_name = "main_chaos_game", threads(1)))]
|
#[spirv(compute(entry_point_name = "main_chaos_game", threads(1)))]
|
||||||
pub extern "C" fn main_chaos_game(
|
pub fn main_chaos_game(
|
||||||
#[spirv(spec_constant(id = 1, default = 20))] iteration_discard: u32,
|
#[spirv(spec_constant(id = 1, default = 20))] iteration_discard: u32,
|
||||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 0)] rng_seed: &[u8],
|
#[spirv(storage_buffer, descriptor_set = 0, binding = 0)] _rng_seed: &[u8],
|
||||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 1)] transforms: &[Transform],
|
#[spirv(storage_buffer, descriptor_set = 0, binding = 1)] transforms: &[Transform],
|
||||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 2)] weights: &[f32],
|
#[spirv(storage_buffer, descriptor_set = 0, binding = 2)] weights: &[f32],
|
||||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 3)] variations: &[Variation],
|
#[spirv(storage_buffer, descriptor_set = 0, binding = 3)] variations: &[Variation],
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
pub mod camera;
|
pub mod camera;
|
||||||
pub mod chaos_game;
|
pub mod chaos_game;
|
||||||
|
mod rng;
|
||||||
pub mod transform;
|
pub mod transform;
|
||||||
pub mod variation;
|
pub mod variation;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
use rand::SeedableRng;
|
||||||
|
use rand_xoshiro::Xoshiro256StarStar;
|
||||||
|
|
||||||
|
/// Convert an RNG state buffer to an instance of [`Xoshiro256StarStar`].
|
||||||
|
///
|
||||||
|
/// While [`SeedableRng::from_seed`] is an infallible function,
|
||||||
|
/// it relies on some methods that can't be compiled by the SPIR-V
|
||||||
|
/// backend (specifically, formatting functions in the core crate).
|
||||||
|
///
|
||||||
|
/// In practice, the xoshiro RNG state is entirely defined by its seed,
|
||||||
|
/// so this function does the work of [`SeedableRng::from_seed`] by
|
||||||
|
/// transmuting the seed value to an RNG instance.
|
||||||
|
///
|
||||||
|
/// This function assumes a properly-initialized state array;
|
||||||
|
/// output may silently degenerate if the initial state is all zeros,
|
||||||
|
/// so this module is private to the crate.
|
||||||
|
pub(crate) fn xoshiro_from_state(
|
||||||
|
_rng_state: <Xoshiro256StarStar as SeedableRng>::Seed,
|
||||||
|
) -> Xoshiro256StarStar {
|
||||||
|
let rng_state_actual = [1u64, 2u64, 3u64, 4u64];
|
||||||
|
unsafe { core::mem::transmute(rng_state_actual) }
|
||||||
|
}
|
||||||
@@ -1,4 +1,8 @@
|
|||||||
//! # Variation
|
//! # Variation
|
||||||
|
//!
|
||||||
|
//! Variations extend the fractal flame iterated function system
|
||||||
|
//! with non-linear transforms (as opposed to [`Transform`]s,
|
||||||
|
//! which are strictly affine transformations).
|
||||||
use crate::Coefficients2;
|
use crate::Coefficients2;
|
||||||
use bytemuck::{Pod, Zeroable};
|
use bytemuck::{Pod, Zeroable};
|
||||||
use core::f32::consts::PI;
|
use core::f32::consts::PI;
|
||||||
@@ -7,14 +11,25 @@ use libm::{atan2f, cosf, powf, sinf, sqrtf, tanf};
|
|||||||
use rand::distr::StandardUniform;
|
use rand::distr::StandardUniform;
|
||||||
use rand::{Rng, RngExt};
|
use rand::{Rng, RngExt};
|
||||||
|
|
||||||
|
/// Generic variation parameters
|
||||||
|
///
|
||||||
|
/// Not all variations will use these parameters, but passing them
|
||||||
|
/// as an array per variation allows shaders to use a consistent struct size
|
||||||
|
/// no matter what the variation actually needs.
|
||||||
#[derive(Copy, Clone, Pod, Zeroable)]
|
#[derive(Copy, Clone, Pod, Zeroable)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct VariationParams([f32; 4]);
|
pub struct VariationParams([f32; 4]);
|
||||||
|
|
||||||
|
/// Enum for all supported variation types
|
||||||
|
///
|
||||||
|
/// ID numbers are chosen to match the variation identifier also used by `flam3`
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
|
#[allow(missing_docs)]
|
||||||
pub enum VariationKind {
|
pub enum VariationKind {
|
||||||
|
/// Identity variation, returns the point as-is
|
||||||
Linear = 0,
|
Linear = 0,
|
||||||
|
|
||||||
Julia = 13,
|
Julia = 13,
|
||||||
Popcorn = 17,
|
Popcorn = 17,
|
||||||
Pdj = 24,
|
Pdj = 24,
|
||||||
@@ -25,6 +40,10 @@ unsafe impl bytemuck::Zeroable for VariationKind {}
|
|||||||
// UNSAFE: Sound because enum has guaranteed layout (u32) and defined zero-value
|
// UNSAFE: Sound because enum has guaranteed layout (u32) and defined zero-value
|
||||||
unsafe impl bytemuck::Pod for VariationKind {}
|
unsafe impl bytemuck::Pod for VariationKind {}
|
||||||
|
|
||||||
|
/// Parameters required for shaders to run the variation function.
|
||||||
|
///
|
||||||
|
/// Not all variations use the [`VariationParams`], but using the struct
|
||||||
|
/// makes it easy to provide parameters to the shader.
|
||||||
#[derive(Copy, Clone, Pod, Zeroable)]
|
#[derive(Copy, Clone, Pod, Zeroable)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct Variation {
|
pub struct Variation {
|
||||||
@@ -34,12 +53,15 @@ pub struct Variation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Variation {
|
impl Variation {
|
||||||
|
/// Identity variation; calling [`transform_point`] will yield
|
||||||
|
/// the same point as the input.
|
||||||
pub const IDENTITY: Variation = Variation {
|
pub const IDENTITY: Variation = Variation {
|
||||||
kind: VariationKind::Linear,
|
kind: VariationKind::Linear,
|
||||||
weight: 1.0,
|
weight: 1.0,
|
||||||
params: VariationParams([0f32; 4]),
|
params: VariationParams([0f32; 4]),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Create a new variation by providing the variation kind, weight, and parameters.
|
||||||
pub fn new(kind: VariationKind, weight: f32, params: VariationParams) -> Variation {
|
pub fn new(kind: VariationKind, weight: f32, params: VariationParams) -> Variation {
|
||||||
Variation {
|
Variation {
|
||||||
kind,
|
kind,
|
||||||
@@ -48,6 +70,9 @@ impl Variation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Transform a point by applying this variation.
|
||||||
|
///
|
||||||
|
/// Output points are scaled by this variation's weight.
|
||||||
pub fn transform_point<R: Rng>(
|
pub fn transform_point<R: Rng>(
|
||||||
&self,
|
&self,
|
||||||
point: Vec2,
|
point: Vec2,
|
||||||
|
|||||||
Reference in New Issue
Block a user