Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3c5563c940 |
@@ -77,10 +77,11 @@ pub fn main() -> Result<()> {
|
||||
let temp = NamedTempFile::with_suffix(".png").context("Unable to create file for image")?;
|
||||
image.save(temp.path()).context("Unable to save image")?;
|
||||
|
||||
let open_program = cfg_select! {
|
||||
unix => "xdg-open",
|
||||
_ => panic!("Unknown system"),
|
||||
};
|
||||
let open_program: &str = cfg_select! {
|
||||
unix => Some("xdg-open"),
|
||||
_ => None,
|
||||
}
|
||||
.expect("No available program to open images");
|
||||
|
||||
Command::new(open_program)
|
||||
.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 {
|
||||
use crate::camera::Camera;
|
||||
use spirv_std::glam::{IVec2, Vec2};
|
||||
use spirv_std::spirv;
|
||||
|
||||
/// Transform IFS coordinates to pixel coordinates
|
||||
#[spirv(compute(entry_point_name = "main_camera", threads(1)))]
|
||||
pub fn main_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 {
|
||||
use crate::chaos_game::ChaosGame;
|
||||
use crate::rng::xoshiro_from_state;
|
||||
use crate::transform::Transform;
|
||||
use crate::variation::Variation;
|
||||
use glam::Vec2;
|
||||
use rand_xoshiro::Xoshiro256StarStar;
|
||||
use spirv_std::spirv;
|
||||
|
||||
fn xoshiro_from_state(rng_state: [u8; 32]) -> Xoshiro256StarStar {
|
||||
let mut rng_state_actual = [1u64, 2u64, 3u64, 4u64];
|
||||
unsafe { core::mem::transmute(rng_state_actual) }
|
||||
}
|
||||
|
||||
/// Given a set of fractal flame parameters, generate new IFS coordinates
|
||||
/// and store them in the output array.
|
||||
#[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(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 = 2)] weights: &[f32],
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 3)] variations: &[Variation],
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
pub mod camera;
|
||||
pub mod chaos_game;
|
||||
mod rng;
|
||||
pub mod transform;
|
||||
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
|
||||
//!
|
||||
//! 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 bytemuck::{Pod, Zeroable};
|
||||
use core::f32::consts::PI;
|
||||
@@ -7,14 +11,25 @@ use libm::{atan2f, cosf, powf, sinf, sqrtf, tanf};
|
||||
use rand::distr::StandardUniform;
|
||||
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)]
|
||||
#[repr(C)]
|
||||
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)]
|
||||
#[repr(u32)]
|
||||
#[allow(missing_docs)]
|
||||
pub enum VariationKind {
|
||||
/// Identity variation, returns the point as-is
|
||||
Linear = 0,
|
||||
|
||||
Julia = 13,
|
||||
Popcorn = 17,
|
||||
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 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)]
|
||||
#[repr(C)]
|
||||
pub struct Variation {
|
||||
@@ -34,12 +53,15 @@ pub struct Variation {
|
||||
}
|
||||
|
||||
impl Variation {
|
||||
/// Identity variation; calling [`transform_point`] will yield
|
||||
/// the same point as the input.
|
||||
pub const IDENTITY: Variation = Variation {
|
||||
kind: VariationKind::Linear,
|
||||
weight: 1.0,
|
||||
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 {
|
||||
Variation {
|
||||
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>(
|
||||
&self,
|
||||
point: Vec2,
|
||||
|
||||
Reference in New Issue
Block a user