Put in a GUI, provide the viewport information
This commit is contained in:
@ -5,48 +5,47 @@ use rand::Rng;
|
||||
use rand::distributions::Standard;
|
||||
use rand::prelude::Distribution;
|
||||
use rand_xoshiro::Xoshiro128Plus;
|
||||
use spirv_std::spirv;
|
||||
use spirv_std::num_traits::Float;
|
||||
use spirv_std::spirv;
|
||||
|
||||
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
||||
#[repr(C)]
|
||||
pub struct ImageConstants {
|
||||
accum_width: i32,
|
||||
accum_height: i32,
|
||||
viewport_width: i32,
|
||||
viewport_height: i32,
|
||||
background_color: Vec4,
|
||||
pub struct ViewportConstants {
|
||||
offset_x: i32,
|
||||
offset_y: i32,
|
||||
width: i32,
|
||||
height: i32,
|
||||
}
|
||||
|
||||
impl ImageConstants {
|
||||
impl ViewportConstants {
|
||||
pub fn new(
|
||||
accum_width: i32,
|
||||
accum_height: i32,
|
||||
viewport_width: i32,
|
||||
viewport_height: i32,
|
||||
background_color: Vec4,
|
||||
offset_x: i32,
|
||||
offset_y: i32,
|
||||
width: i32,
|
||||
height: i32,
|
||||
) -> Self {
|
||||
Self {
|
||||
accum_width,
|
||||
accum_height,
|
||||
viewport_width,
|
||||
viewport_height,
|
||||
background_color,
|
||||
offset_x, offset_y, width, height
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
||||
#[repr(C)]
|
||||
pub struct AccumConstants {
|
||||
pub width: i32,
|
||||
pub height: i32,
|
||||
}
|
||||
|
||||
impl AccumConstants {
|
||||
pub fn new(width: i32, height: i32) -> Self {
|
||||
Self {
|
||||
width, height
|
||||
}
|
||||
}
|
||||
|
||||
pub fn viewport_dimensions(&self) -> glam::IVec2 {
|
||||
glam::ivec2(self.viewport_width, self.viewport_height)
|
||||
}
|
||||
|
||||
pub fn with_accumulate(&mut self, width: i32, height: i32) {
|
||||
self.accum_width = width;
|
||||
self.accum_height = height;
|
||||
}
|
||||
|
||||
pub fn with_viewport(&mut self, width: i32, height: i32) {
|
||||
self.viewport_width = width;
|
||||
self.viewport_height = height;
|
||||
pub fn min_dimension(&self) -> i32 {
|
||||
if self.width < self.height { self.width } else { self.height }
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,6 +60,16 @@ pub struct CameraConstants {
|
||||
}
|
||||
|
||||
impl CameraConstants {
|
||||
pub fn new(scale: f32) -> Self {
|
||||
Self {
|
||||
scale,
|
||||
zoom: 0.0,
|
||||
rotate: 0.0,
|
||||
offset_x: 0.0,
|
||||
offset_y: 0.0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn camera(&self, image_width: i32, image_height: i32) -> glam::Affine2 {
|
||||
let zoom_factor = 2f32.powf(self.zoom);
|
||||
let zoom_rotate_offset = glam::Affine2::from_scale_angle_translation(
|
||||
@ -120,13 +129,23 @@ impl ThreadState {
|
||||
unsafe { core::mem::transmute::<_, Xoshiro128Plus>(*rng_state) }
|
||||
}
|
||||
|
||||
pub fn new(rng: &mut Xoshiro128Plus) -> Self {
|
||||
pub fn new<R: Rng>(rng: &mut R) -> Self {
|
||||
let mut rng_state: [u32; 4] = [0; 4];
|
||||
rng.fill(&mut rng_state);
|
||||
let point = vec2(rng.sample(BiUnit), rng.sample(BiUnit));
|
||||
let rng_state = Self::xoshiro_to_state(rng);
|
||||
rng.jump();
|
||||
Self { rng_state, point }
|
||||
}
|
||||
|
||||
pub fn jump(&self) -> Self {
|
||||
let mut rng = self.get_rng();
|
||||
rng.jump();
|
||||
let point = vec2(rng.sample(BiUnit), rng.sample(BiUnit));
|
||||
Self {
|
||||
rng_state: Self::xoshiro_to_state(&rng),
|
||||
point,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_rng(&self) -> Xoshiro128Plus {
|
||||
Self::state_to_xoshiro(&self.rng_state)
|
||||
}
|
||||
@ -238,11 +257,13 @@ fn next_transform<R: Rng + ?Sized>(
|
||||
|
||||
#[spirv(compute(threads(1)))]
|
||||
pub fn main_cs(
|
||||
#[spirv(push_constant)] image_constants: &ImageConstants,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 0)] thread_state: &mut [ThreadState],
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 1)] transforms: &[Transform],
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 2)] variations: &[Variation],
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 0)] _viewport_constants: &ViewportConstants,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 1)] accum_constants: &AccumConstants,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 2)] _camera_constants: &CameraConstants,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 3)] accum_image: &mut [Vec4],
|
||||
#[spirv(storage_buffer, descriptor_set = 1, binding = 0)] thread_state: &mut [ThreadState],
|
||||
#[spirv(storage_buffer, descriptor_set = 1, binding = 1)] transforms: &[Transform],
|
||||
#[spirv(storage_buffer, descriptor_set = 1, binding = 2)] variations: &[Variation],
|
||||
) {
|
||||
let mut rng = thread_state[0].get_rng();
|
||||
let mut point = thread_state[0].point;
|
||||
@ -258,7 +279,11 @@ pub fn main_cs(
|
||||
}
|
||||
|
||||
// ...because `<i32>.min(<i32>)` has compilation issues.
|
||||
let min_dimension = if image_constants.accum_width < image_constants.accum_height { image_constants.accum_width } else { image_constants.accum_height };
|
||||
let min_dimension = if accum_constants.width < accum_constants.height {
|
||||
accum_constants.width
|
||||
} else {
|
||||
accum_constants.height
|
||||
};
|
||||
|
||||
// Fixed camera, should be provided by a uniform in the future
|
||||
let camera = CameraConstants {
|
||||
@ -268,7 +293,8 @@ pub fn main_cs(
|
||||
offset_x: 0.5,
|
||||
offset_y: 0.5,
|
||||
}
|
||||
.camera(image_constants.accum_width, image_constants.accum_height);
|
||||
.camera(accum_constants.width, accum_constants.height);
|
||||
// let camera = camera_constants.camera(image_constants.accum_width, image_constants.accum_height);
|
||||
|
||||
// Iterate 100,000, should be provided by a uniform in the future
|
||||
for _i in 0..100_000 {
|
||||
@ -276,9 +302,9 @@ pub fn main_cs(
|
||||
|
||||
let pixel_coordinates = camera.transform_point2(point).as_ivec2();
|
||||
if pixel_coordinates.x < 0
|
||||
|| pixel_coordinates.x >= image_constants.accum_width
|
||||
|| pixel_coordinates.x >= accum_constants.width
|
||||
|| pixel_coordinates.y < 0
|
||||
|| pixel_coordinates.y >= image_constants.accum_height
|
||||
|| pixel_coordinates.y >= accum_constants.height
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -286,7 +312,7 @@ pub fn main_cs(
|
||||
let ii = image_index(
|
||||
pixel_coordinates.x,
|
||||
pixel_coordinates.y,
|
||||
image_constants.accum_width,
|
||||
accum_constants.width,
|
||||
);
|
||||
accum_image[ii as usize] = Color::WHITE;
|
||||
}
|
||||
@ -311,18 +337,24 @@ pub fn main_vs(
|
||||
#[spirv(fragment)]
|
||||
pub fn main_fs(
|
||||
#[spirv(frag_coord)] frag_coord: Vec4,
|
||||
#[spirv(push_constant)] ifs_constants: &ImageConstants,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 0)] accum_image: &[Vec4],
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 0)] viewport_constants: &ViewportConstants,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 1)] accum_constants: &AccumConstants,
|
||||
#[spirv(storage_buffer, descriptor_set = 0, binding = 2)] _accum_image: &mut [Vec4],
|
||||
output: &mut Vec4,
|
||||
) {
|
||||
// Bootleg texture sampling; map from viewport image pixel coordinates to accumulator image
|
||||
// pixel coordinates
|
||||
let viewport_coordinate = frag_coord.xy().as_uvec2();
|
||||
let viewport_offset = glam::ivec2(
|
||||
viewport_constants.offset_x,
|
||||
viewport_constants.offset_y,
|
||||
)
|
||||
.as_uvec2();
|
||||
let viewport_coordinate = frag_coord.xy().as_uvec2() - viewport_offset;
|
||||
|
||||
let a_width = ifs_constants.accum_width as f32;
|
||||
let a_height = ifs_constants.accum_height as f32;
|
||||
let v_width = ifs_constants.viewport_width as f32;
|
||||
let v_height = ifs_constants.viewport_height as f32;
|
||||
let a_width = accum_constants.width as f32;
|
||||
let a_height = accum_constants.height as f32;
|
||||
let v_width = viewport_constants.width as f32;
|
||||
let v_height = viewport_constants.height as f32;
|
||||
|
||||
// Scale both width and height by the same factor; preserves aspect ratio
|
||||
let scale_width = a_width / v_width;
|
||||
@ -333,8 +365,9 @@ pub fn main_fs(
|
||||
let offset_x = (v_width * scale - a_width) / 2.0;
|
||||
let offset_y = (v_height * scale - a_height) / 2.0;
|
||||
|
||||
let accum_coordinate = viewport_coordinate.as_vec2() * scale - vec2(offset_x, offset_y);
|
||||
let _accum_coordinate = viewport_coordinate.as_vec2() * scale - vec2(offset_x, offset_y);
|
||||
|
||||
/*
|
||||
if accum_coordinate.x < 0.0
|
||||
|| accum_coordinate.x >= ifs_constants.accum_width as f32
|
||||
|| accum_coordinate.y < 0.0
|
||||
@ -348,4 +381,13 @@ pub fn main_fs(
|
||||
ifs_constants.accum_width,
|
||||
) as usize];
|
||||
}
|
||||
*/
|
||||
|
||||
if viewport_coordinate.x == 0
|
||||
|| viewport_coordinate.x == viewport_constants.width as u32 - 1
|
||||
|| viewport_coordinate.y == 0
|
||||
|| viewport_coordinate.y == viewport_constants.height as u32 - 1
|
||||
{
|
||||
*output = glam::Vec4::splat(1.);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user