Compare commits
No commits in common. "946617f98884700452cfc34abdd590c1975f19f8" and "453a67a93f4fb8287d0278a01893e6fe8a060801" have entirely different histories.
946617f988
...
453a67a93f
|
|
@ -1,9 +1,8 @@
|
||||||
use std::env::args;
|
use std::env::args;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::io::{stdout, Write};
|
use std::fs;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::{fs, io};
|
|
||||||
|
|
||||||
use glam::{uvec2, UVec2};
|
use glam::{uvec2, UVec2};
|
||||||
use image::buffer::ConvertBuffer;
|
use image::buffer::ConvertBuffer;
|
||||||
|
|
@ -12,73 +11,39 @@ use raytracing3::scene::{load_envmap, Renderer, SceneParams};
|
||||||
|
|
||||||
const SIZE: UVec2 = uvec2(1920, 1080);
|
const SIZE: UVec2 = uvec2(1920, 1080);
|
||||||
const FRAME_RATE: u32 = 60;
|
const FRAME_RATE: u32 = 60;
|
||||||
|
const DURATION_SECONDS: u32 = 120;
|
||||||
|
const N_FRAMES: u32 = DURATION_SECONDS * FRAME_RATE;
|
||||||
const N_SPHERES: u32 = 100;
|
const N_SPHERES: u32 = 100;
|
||||||
const RAYS_PER_PIXEL: u32 = 1024;
|
const RAYS_PER_PIXEL: u32 = 1024;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let path: PathBuf;
|
let args: Vec<_> = args().collect();
|
||||||
let start_frame;
|
let [_, path] = args.as_slice() else {
|
||||||
let stop_frame;
|
panic!("invalid arguments");
|
||||||
match args().collect::<Vec<_>>().as_slice() {
|
};
|
||||||
[_, apath] => {
|
let path: PathBuf = path.into();
|
||||||
path = apath.into();
|
fs::create_dir(&path).expect("failed to create the output directory");
|
||||||
start_frame = 0;
|
|
||||||
stop_frame = 5;
|
|
||||||
}
|
|
||||||
[_, apath, aframes] => {
|
|
||||||
path = apath.into();
|
|
||||||
start_frame = 0;
|
|
||||||
stop_frame = aframes.parse().unwrap();
|
|
||||||
}
|
|
||||||
[_, apath, astart_frame, astop_frame] => {
|
|
||||||
path = apath.into();
|
|
||||||
start_frame = astart_frame.parse().unwrap();
|
|
||||||
stop_frame = astop_frame.parse().unwrap();
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
panic!("invalid arguments");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
println!(
|
|
||||||
"Rendering frames {start_frame} to {stop_frame} ({} total)",
|
|
||||||
stop_frame - start_frame
|
|
||||||
);
|
|
||||||
match fs::create_dir(&path) {
|
|
||||||
Ok(_) => (),
|
|
||||||
Err(err) if err.kind() == io::ErrorKind::AlreadyExists => (),
|
|
||||||
Err(err) => panic!("failed to create the output directory: {err}"),
|
|
||||||
}
|
|
||||||
|
|
||||||
let n_threads = std::thread::available_parallelism().map(|n| n.get()).unwrap_or(2);
|
|
||||||
let (img_sender, img_receiver) = async_channel::bounded::<Frame>(2 * n_threads);
|
|
||||||
std::thread::scope(|s| {
|
std::thread::scope(|s| {
|
||||||
for _ in 0..n_threads {
|
let (img_sender, img_receiver) = async_channel::bounded::<(u32, Arc<wgpu::Buffer>)>(50);
|
||||||
start_saver(s, &path, &img_receiver);
|
for _ in 0..16 {
|
||||||
|
let img_receiver = img_receiver.clone();
|
||||||
|
let path = &path;
|
||||||
|
s.spawn(move || {
|
||||||
|
while let Ok((frame, buffer)) = img_receiver.recv_blocking() {
|
||||||
|
let img = image::RgbaImage::from_raw(SIZE.x, SIZE.y, buffer.slice(..).get_mapped_range().to_vec())
|
||||||
|
.expect("read failure!");
|
||||||
|
let img: image::RgbImage = img.convert();
|
||||||
|
img.save(path.join(&format!("frame{frame:06}.webp")))
|
||||||
|
.expect("save failure!");
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
do_work(img_sender, start_frame, stop_frame);
|
do_work(img_sender);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
type Frame = (u32, Arc<wgpu::Buffer>);
|
fn do_work(img_sender: async_channel::Sender<(u32, Arc<wgpu::Buffer>)>) {
|
||||||
|
|
||||||
fn start_saver<'a>(
|
|
||||||
scope: &'a std::thread::Scope<'a, '_>,
|
|
||||||
path: &'a Path,
|
|
||||||
img_receiver: &'a async_channel::Receiver<Frame>,
|
|
||||||
) {
|
|
||||||
scope.spawn(move || {
|
|
||||||
while let Ok((frame, buffer)) = img_receiver.recv_blocking() {
|
|
||||||
let img = image::RgbaImage::from_raw(SIZE.x, SIZE.y, buffer.slice(..).get_mapped_range().to_vec())
|
|
||||||
.expect("read failure!");
|
|
||||||
let img: image::RgbImage = img.convert();
|
|
||||||
img.save(path.join(&format!("frame{frame:06}.webp")))
|
|
||||||
.expect("save failure!");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
fn do_work(img_sender: async_channel::Sender<Frame>, start_frame: u32, stop_frame: u32) {
|
|
||||||
println!("Loading...");
|
|
||||||
let img_sender = Arc::new(img_sender);
|
let img_sender = Arc::new(img_sender);
|
||||||
|
|
||||||
let (device, queue) = pollster::block_on(init_gpu()).unwrap();
|
let (device, queue) = pollster::block_on(init_gpu()).unwrap();
|
||||||
|
|
@ -98,11 +63,7 @@ fn do_work(img_sender: async_channel::Sender<Frame>, start_frame: u32, stop_fram
|
||||||
let renderer = Renderer::new(&device, envmap);
|
let renderer = Renderer::new(&device, envmap);
|
||||||
let presenter = Presenter::new(&device, output_format);
|
let presenter = Presenter::new(&device, output_format);
|
||||||
|
|
||||||
println!("Rendering...");
|
for frame in 0..N_FRAMES {
|
||||||
for frame in start_frame..stop_frame {
|
|
||||||
if frame % FRAME_RATE == 0 {
|
|
||||||
println!("{frame}");
|
|
||||||
}
|
|
||||||
let output = device.create_texture(&wgpu::TextureDescriptor {
|
let output = device.create_texture(&wgpu::TextureDescriptor {
|
||||||
label: None,
|
label: None,
|
||||||
size: texsize,
|
size: texsize,
|
||||||
|
|
@ -175,12 +136,8 @@ fn do_work(img_sender: async_channel::Sender<Frame>, start_frame: u32, stop_fram
|
||||||
res.unwrap();
|
res.unwrap();
|
||||||
img_sender.send_blocking((frame, buffer)).unwrap();
|
img_sender.send_blocking((frame, buffer)).unwrap();
|
||||||
});
|
});
|
||||||
print!(".");
|
|
||||||
stdout().flush().unwrap();
|
|
||||||
}
|
}
|
||||||
println!("{stop_frame}");
|
|
||||||
device.poll(wgpu::Maintain::Wait);
|
device.poll(wgpu::Maintain::Wait);
|
||||||
println!("Done!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn init_gpu() -> Result<(wgpu::Device, wgpu::Queue), Box<dyn Error>> {
|
async fn init_gpu() -> Result<(wgpu::Device, wgpu::Queue), Box<dyn Error>> {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user