Add animation!

This commit is contained in:
numzero 2024-12-22 01:32:57 +03:00
parent 36a6edf393
commit f44fba2572
4 changed files with 182 additions and 25 deletions

84
Cargo.lock generated
View File

@ -174,6 +174,12 @@ dependencies = [
"syn",
]
[[package]]
name = "byteorder"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "bytes"
version = "1.9.0"
@ -625,6 +631,12 @@ dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "libm"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa"
[[package]]
name = "libredox"
version = "0.1.3"
@ -763,6 +775,16 @@ dependencies = [
"jni-sys",
]
[[package]]
name = "num-traits"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
"libm",
]
[[package]]
name = "num_enum"
version = "0.7.3"
@ -1108,6 +1130,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f3a9f18d041e6d0e102a0a46750538147e5e8992d3b4873aaafee2520b00ce3"
[[package]]
name = "ppv-lite86"
version = "0.2.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
dependencies = [
"zerocopy",
]
[[package]]
name = "presser"
version = "0.3.1"
@ -1156,6 +1187,55 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom",
]
[[package]]
name = "rand_distr"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31"
dependencies = [
"num-traits",
"rand",
]
[[package]]
name = "rand_pcg"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59cad018caf63deb318e5a4586d99a24424a364f40f1e5778c29aca23f4fc73e"
dependencies = [
"rand_core",
]
[[package]]
name = "range-alloc"
version = "0.1.3"
@ -1175,6 +1255,9 @@ dependencies = [
"bytemuck",
"glam",
"pollster",
"rand",
"rand_distr",
"rand_pcg",
"wgpu",
"winit",
]
@ -2221,6 +2304,7 @@ version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
dependencies = [
"byteorder",
"zerocopy-derive",
]

View File

@ -7,5 +7,8 @@ edition = "2021"
bytemuck = { version = "1.21.0", features = ["derive"] }
glam = { version = "0.29.2", features = ["bytemuck"] }
pollster = "0.4.0"
rand = "0.8.5"
rand_distr = { version = "0.4.3", features = ["std_math"] }
rand_pcg = "0.3.1"
wgpu = "23.0.1"
winit = "0.30.6"

77
src/anim.rs Normal file
View File

@ -0,0 +1,77 @@
use glam::{vec3, Vec3};
use rand_distr::{Distribution, LogNormal, Uniform};
pub struct SphereParams {
pub radius: f32,
pub color: Vec3,
pub alpha: f32,
pub origin: Vec3,
pub amplitudes: Vec3,
pub frequencies: Vec3,
pub phases: Vec3,
}
pub struct SphereParamsDistribution {
pub drad: Uniform<f32>,
pub dpos: Uniform<f32>,
pub dcol: Uniform<f32>,
pub demit: LogNormal<f32>,
pub dampl: Uniform<f32>,
pub dfreq: Uniform<f32>,
pub dphase: Uniform<f32>,
}
impl Default for SphereParamsDistribution {
fn default() -> Self {
Self {
drad: Uniform::new(0.01, 0.10),
dpos: Uniform::new(-1.0, 1.0),
dcol: Uniform::new(0.0, 1.0),
demit: LogNormal::new(-0.8, 2.0).unwrap(),
dampl: Uniform::new(0.3, 0.8),
dfreq: Uniform::new(0.2, 1.5),
dphase: Uniform::new(0., 2. * std::f32::consts::PI),
}
}
}
impl SphereParamsDistribution {
pub fn make_params(&self, rgen: &mut impl rand::Rng) -> SphereParams {
SphereParams {
origin: self.dpos.sample3(rgen),
radius: self.drad.sample(rgen),
color: self.dcol.sample3(rgen).normalize(),
alpha: self.demit.sample(rgen),
amplitudes: self.dampl.sample3(rgen),
frequencies: self.dfreq.sample3(rgen),
phases: self.dphase.sample3(rgen),
}
}
}
impl SphereParams {
pub fn to_sphere(&self, time: f32) -> crate::Sphere {
let center = self.origin + self.amplitudes * (self.frequencies * time + self.phases).map(|x| x.sin());
let radius = self.radius;
let emit_color = self.alpha * self.color;
let reflect_color = 0.6 * self.color + Vec3::splat(0.2);
crate::Sphere {
center,
radius,
emit_color,
pad1: 0.0,
reflect_color,
pad2: 0.0,
}
}
}
trait VecDistribution {
fn sample3<R: rand::Rng + ?Sized>(&self, rng: &mut R) -> Vec3;
}
impl<T: Distribution<f32>> VecDistribution for T {
fn sample3<R: rand::Rng + ?Sized>(&self, rng: &mut R) -> Vec3 {
vec3(rng.sample(self), rng.sample(self), rng.sample(self))
}
}

View File

@ -1,15 +1,18 @@
use std::error::Error;
use glam::{vec2, vec3};
use trace::{Sphere, Tracer, TracerData, Vertex};
use trace::{Tracer, TracerData, Vertex};
use winit::{
event::{Event, WindowEvent},
event_loop::EventLoop,
window::{Window, WindowAttributes},
};
mod anim;
mod trace;
pub use trace::Sphere;
fn make_viewport(w: u32, h: u32) -> [Vertex; 4] {
let w = w as f32;
let h = h as f32;
@ -30,6 +33,8 @@ fn make_viewport(w: u32, h: u32) -> [Vertex; 4] {
})
}
const N_SPHERES: u32 = 42;
fn main() {
let event_loop = EventLoop::new().unwrap();
@ -46,32 +51,16 @@ fn main() {
trace::Params {
max_reflections: 3,
min_strength: 0.1,
sphere_count: 2,
sphere_count: N_SPHERES,
},
);
let sphere_params: Vec<_> = {
let mut rng = rand_pcg::Pcg32::new(42, 0);
let distr = anim::SphereParamsDistribution::default();
(0..N_SPHERES).map(|_| distr.make_params(&mut rng)).collect()
};
let mut data = TracerData::new(
&device,
&tracer,
&[
Sphere {
center: vec3(0.0, 0.0, 0.0),
radius: 0.5,
emit_color: vec3(0.0, 0.0, 0.5),
reflect_color: vec3(1.0, 0.5, 0.0),
pad1: 0.,
pad2: 0.,
},
Sphere {
center: vec3(-2.0, 0.0, 2.0),
radius: 0.5,
emit_color: vec3(0.5, 0.5, 0.5),
reflect_color: vec3(0.0, 0.5, 0.0),
pad1: 0.,
pad2: 0.,
},
],
);
let mut time = 0.0;
let mut surface_configured = false;
#[allow(deprecated)]
@ -101,6 +90,10 @@ fn main() {
if !surface_configured {
return;
}
time += 1. / 60.;
let spheres: Vec<_> = sphere_params.iter().map(|p| p.to_sphere(time)).collect();
let data = TracerData::new(&device, &tracer, &spheres);
let output = surface.get_current_texture().unwrap();
let view = output.texture.create_view(&wgpu::TextureViewDescriptor::default());
let mut encoder = device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None });
@ -139,7 +132,7 @@ async fn init_gpu(wnd: &Window) -> Result<(wgpu::Device, wgpu::Queue, wgpu::Surf
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::default(),
compatible_surface: None,
compatible_surface: Some(&surface),
force_fallback_adapter: false,
})
.await