diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Cargo.lock | 323 | ||||
-rw-r--r-- | Cargo.toml | 2 | ||||
-rw-r--r-- | README.md | 3 | ||||
-rw-r--r-- | settings.txt | 1 | ||||
-rw-r--r-- | src/fshader_main.glsl | 2 | ||||
-rw-r--r-- | src/main.rs | 110 | ||||
-rw-r--r-- | src/sdf.rs | 1 | ||||
-rw-r--r-- | src/sdl.rs | 10 | ||||
-rw-r--r-- | src/vshader_post.glsl | 2 | ||||
-rw-r--r-- | src/win.rs | 43 |
11 files changed, 445 insertions, 53 deletions
@@ -1,5 +1,6 @@ target tags +screenshots *.swp *.out *.dll @@ -3,6 +3,21 @@ version = 3 [[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] name = "approx" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -21,10 +36,12 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" name = "autosdf" version = "0.1.0" dependencies = [ + "chrono", "gen_random", "gen_random_proc_macro", "gl", "nalgebra", + "png", "rand", "serde", "serde_cbor", @@ -33,18 +50,130 @@ dependencies = [ ] [[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bumpalo" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" + +[[package]] name = "bytemuck" version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aaa3a8d9a1ca92e282c96a32d6511b695d7d994d1d102ba85d279f9b2756947f" [[package]] +name = "cc" +version = "1.0.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d" + +[[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] +name = "chrono" +version = "0.4.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-integer", + "num-traits", + "time", + "wasm-bindgen", + "winapi", +] + +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "cxx" +version = "1.0.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b61a7545f753a88bcbe0a70de1fcc0221e10bfc752f576754fa91e663db1622e" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f464457d494b5ed6905c63b0c4704842aba319084a0a3561cdc1359536b53200" +dependencies = [ + "cc", + "codespan-reporting", + "once_cell", + "proc-macro2", + "quote", + "scratch", + "syn", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43c7119ce3a3701ed81aca8410b9acf6fc399d2629d057b87e2efa4e63a3aaea" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65e07508b90551e610910fa648a1878991d367064997a596135b86df30daf07e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "flate2" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] name = "gen_random" version = "0.1.0" dependencies = [ @@ -68,7 +197,7 @@ checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ "cfg-if", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", ] [[package]] @@ -98,6 +227,39 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" [[package]] +name = "iana-time-zone" +version = "0.1.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "winapi", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" +dependencies = [ + "cxx", + "cxx-build", +] + +[[package]] +name = "js-sys" +version = "0.3.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" +dependencies = [ + "wasm-bindgen", +] + +[[package]] name = "khronos_api" version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -110,6 +272,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" [[package]] +name = "link-cplusplus" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" +dependencies = [ + "cc", +] + +[[package]] name = "log" version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -128,6 +299,15 @@ dependencies = [ ] [[package]] +name = "miniz_oxide" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +dependencies = [ + "adler", +] + +[[package]] name = "nalgebra" version = "0.31.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -194,12 +374,30 @@ dependencies = [ ] [[package]] +name = "once_cell" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" + +[[package]] name = "paste" version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1" [[package]] +name = "png" +version = "0.17.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d708eaf860a19b19ce538740d2b4bdeeb8337fa53f7738455e706623ad5c638" +dependencies = [ + "bitflags", + "crc32fast", + "flate2", + "miniz_oxide", +] + +[[package]] name = "ppv-lite86" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -269,6 +467,12 @@ dependencies = [ ] [[package]] +name = "scratch" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2" + +[[package]] name = "serde" version = "1.0.150" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -320,6 +524,26 @@ dependencies = [ ] [[package]] +name = "termcolor" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "time" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" +dependencies = [ + "libc", + "wasi 0.10.0+wasi-snapshot-preview1", + "winapi", +] + +[[package]] name = "toml" version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -341,12 +565,78 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" [[package]] +name = "unicode-width" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" + +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + +[[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] +name = "wasm-bindgen" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" + +[[package]] name = "wide" version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -357,6 +647,37 @@ dependencies = [ ] [[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] name = "winres" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -14,6 +14,8 @@ serde = "1.0.150" serde_derive = "1.0.150" gl = "0.14.0" nalgebra = "0.31.4" +png = "0.17.7" +chrono = "0.4.23" [target.'cfg(windows)'.build-dependencies] winres = "0.1.12" @@ -12,7 +12,7 @@ you can also reduce `max-iterations` and increase `distance-threshold` if it's s - move mouse to look around - W,A,S,D/arrow keys to move forward/backwards/left/right + Q,E/PageUp,PageDown to move up/down - R to create a new SDF - use this a lot! most SDFs are boring! -- Space to "unpause time" (start animating). On some SDFs this might not do much. +- Space to "unpause time" (start animating). Press space again to pause time, and shift+space to rewind time. - [ and ] to go forwards and backwards in time - 0 to reset location + time @@ -20,6 +20,7 @@ you can also reduce `max-iterations` and increase `distance-threshold` if it's s - Ctrl+C to copy SDF to clipboard, Ctrl+V to paste SDF from clipboard. On Linux if you close the application the clipboard contents will be lost (thanks a lot X11). - F to go fullscreen +- F10 to take a screenshot (will be saved to a folder called `screenshots`) - Escape to quit - You can use Shift to move faster and Ctrl to move slower. diff --git a/settings.txt b/settings.txt index 16f7445..6456874 100644 --- a/settings.txt +++ b/settings.txt @@ -2,6 +2,7 @@ mouse-sensitivity 50 # you can set this to 0.5 to render the SDF at half resolution for example # (e.g. the SDF will be rendered at 960x540 on a 1080p monitor) # making this lower will increase performance significantly, but will look more pixelated +# you can also make this higher to take super high-res screenshots (but it will run slower) scale 1 # complexity of SDF # making this bigger will make more complex scenes, but will require more gpu computation diff --git a/src/fshader_main.glsl b/src/fshader_main.glsl index 0f13a01..2a6864a 100644 --- a/src/fshader_main.glsl +++ b/src/fshader_main.glsl @@ -20,6 +20,7 @@ uniform int u_flash_icon; #define ICON_PLAY 2 #define ICON_PAUSE 3 #define ICON_REWIND 4 +#define ICON_SCREENSHOT 5 %COMMON% %SDF% @@ -131,6 +132,7 @@ void main() { switch (u_flash_icon) { case 0: break; case ICON_COPY: + case ICON_SCREENSHOT: icon = abs(pos.x) > u_aspect_ratio - 0.1 || abs(pos.y) > 0.9; break; case ICON_PLAY: diff --git a/src/main.rs b/src/main.rs index 2651c9b..782ef32 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,9 @@ /* @TODO: -- screenshot - pause screen -- start time at -3 seconds - autoplay setting - strip ' ' and '\n' from *inside* string -- flash error on bad string +- flash error on bad string (see @TODO(error handling)) - RnToRn functions (& add back in RToR) - also add PerComponent(Box<RToR>,Box<RToR>,Box<RToR>) in R3ToR3 - ProjectX, ProjectY, ProjectZ in R3ToR? @@ -20,18 +18,21 @@ */ #![windows_subsystem = "windows"] +extern crate chrono; extern crate nalgebra; +extern crate png; pub mod sdf; mod sdl; pub mod win; +use chrono::prelude::*; use nalgebra::{Matrix3, Matrix4, Rotation3, Vector3}; use sdf::ImportExport; use std::{ collections::HashMap, fs::File, - io::{prelude::*, BufReader}, + io::{prelude::*, BufReader, BufWriter}, time::Instant, }; use win::{ColorF32, ColorGrayscaleF32, ColorU8}; @@ -49,6 +50,7 @@ enum Icon { Play = 2, Pause = 3, Rewind = 4, + Screenshot = 5, } #[derive(Clone)] @@ -160,7 +162,7 @@ impl Programs { .link_program(&mut self.test, vsource_test, &fsource_test) .map_err(|e| format!("Error compiling shader:\n{e}"))?; window - .link_program(&mut self.post, vsource_post, &fsource_post) + .link_program(&mut self.post, vsource_post, fsource_post) .map_err(|e| format!("Error compiling shader:\n{e}"))?; Ok(()) } @@ -275,15 +277,14 @@ impl State { win::FramebufferAttachment::Color0, &test_framebuffer_texture, ); - - + let main_texconfig = win::TextureParams { mag_filter: win::TextureFilter::Nearest, ..Default::default() }; let main_framebuffer_texture = window.create_texture(&main_texconfig); let main_framebuffer = window.create_framebuffer(); - + let mut main_buffer = window.create_buffer(); let mut test_buffer = window.create_buffer(); let mut post_buffer = window.create_buffer(); @@ -368,8 +369,8 @@ impl State { self.window.bind_framebuffer(None); let mut sdf_values: Vec<f32> = self - .window - .get_texture_data_vec::<ColorGrayscaleF32>(&self.test_framebuffer_texture) + .test_framebuffer_texture + .get_data_vec::<ColorGrayscaleF32>() .iter() .map(|c| c.value) .collect(); @@ -394,20 +395,64 @@ impl State { fn flash(&mut self, icon: Icon) { self.flash = match icon { Icon::None => ColorF32::BLACK, - Icon::Copy => ColorF32::GREEN, + Icon::Copy | Icon::Screenshot => ColorF32::GREEN, _ => ColorF32::rgb(1.0, 0.5, 0.0), }; self.flash_icon = icon; } - + fn render_resolution(&self) -> (i32, i32) { let scale = self.settings.get_f32("scale").unwrap_or(1.0); - if scale <= 0.0 || scale > 1.0 { + if scale <= 0.0 || scale > 100.0 { win::display_error_message(&format!("bad scale: {scale}")); std::process::exit(1); } let (w, h) = self.window.size(); - ((w as f32 * scale) as i32, (h as f32 * scale) as i32) + let w = (w as f32 * scale) as i32; + let h = (h as f32 * scale) as i32; + assert!(w >= 0); + assert!(h >= 0); + (w, h) + } + + /// save a screenshot + fn take_screenshot(&mut self) -> Result<(), String> { + let texture = &self.main_framebuffer_texture; + let size = (texture.width(), texture.height()); + let texture_data = texture.get_data_vec(); + if size.0 == 0 || size.1 == 0 { + // there isnt anything to save . why did you set the scale so small... + return Ok(()); + } + let time = Utc::now(); + let filename = time + .format("screenshots/autosdf-%Y-%m-%d-%H-%M-%S.png") + .to_string(); + if std::fs::create_dir("screenshots").is_err() { + // (do nothing.) + // we get an error if it already exists. + // even if this is another error, that will just make File::create fail. + } + let file = + File::create(&filename).map_err(|e| format!("error creating {filename}: {e}"))?; + let mut writer = BufWriter::new(file); + let mut encoder = png::Encoder::new(&mut writer, size.0 as u32, size.1 as u32); + encoder.set_color(png::ColorType::Rgba); + encoder.set_depth(png::BitDepth::Eight); + encoder + .add_text_chunk( + "\n\n\n\nAutoSDF scene".to_string(), + "\n".to_string() + &self.scene.export_string() + "\n\n\n\n", + ) + .map_err(|e| format!("error adding PNG tEXt chunk for {filename}: {e}"))?; + let mut png_writer = encoder + .write_header() + .map_err(|e| format!("error writing PNG header for {filename}: {e}"))?; + png_writer + .write_image_data(ColorU8::slice_to_bytes(&texture_data)) + .map_err(|e| format!("error writing {filename}: {e}"))?; + self.flash(Icon::Screenshot); + Ok(()) } // returns false if we should quit @@ -441,6 +486,7 @@ impl State { match self.window.set_clipboard_text(&self.scene.export_string()) { Ok(()) => {} Err(e) => { + // @TODO(error handling) eprintln!("couldn't copy text to clipboard: {e}") } } @@ -460,16 +506,27 @@ impl State { self.load_scene(new_scene); } None => { + // @TODO(error handling) eprintln!("bad string") } }, Err(e) => { - // very unlikely to happen + // @TODO(error handling) eprintln!("couldn't get clipboard text: {e}") } } } KeyDown { key: N0, .. } => self.view = self.initial_view.clone(), + KeyDown { key: F10, .. } => { + // screenshot + match self.take_screenshot() { + Ok(()) => {} + Err(e) => { + // @TODO(error handling) + eprintln!("screenshot fail: {e}"); + } + } + } KeyDown { key: Space, modifier, @@ -564,20 +621,24 @@ impl State { let render_resolution = self.render_resolution(); if render_resolution != self.main_framebuffer_size { - let result = self.main_framebuffer_texture.set_data::<ColorU8>(None, render_resolution.0 as usize, render_resolution.1 as usize); - + let result = self.main_framebuffer_texture.set_data::<ColorU8>( + None, + render_resolution.0 as usize, + render_resolution.1 as usize, + ); + match result { - Ok(()) => {}, + Ok(()) => {} Err(e) => eprintln!("warning:{e}"), } - + self.main_framebuffer.set_texture( win::FramebufferAttachment::Color0, &self.main_framebuffer_texture, ); self.main_framebuffer_size = render_resolution; } - + let window = &mut self.window; let view = &self.view; window.viewport(0, 0, render_resolution.0, render_resolution.1); @@ -585,7 +646,10 @@ impl State { window.clear_screen(win::ColorF32::BLACK); window.use_program(&self.programs.main); window.bind_framebuffer(Some(&self.main_framebuffer)); - window.uniform1f("u_aspect_ratio", render_resolution.0 as f32 / render_resolution.1 as f32); + window.uniform1f( + "u_aspect_ratio", + render_resolution.0 as f32 / render_resolution.1 as f32, + ); { let (w, h) = window.size(); window.uniform2f("u_screen_size", w as f32, h as f32); @@ -623,7 +687,7 @@ impl State { } self.main_array.draw(); - + window.bind_framebuffer(None); window.viewport_full_screen(); window.use_program(&self.programs.post); @@ -632,7 +696,7 @@ impl State { self.post_array.draw(); window.swap(); - + if self.show_debug_info { println!("frame time = {:?}ms", frame_dt * 1000.0); } @@ -30,7 +30,6 @@ impl GenRandomParams for SdfParams { fn inc_depth(self) -> Self { Self { max_depth: self.max_depth - 1, - ..self } } } @@ -738,16 +738,18 @@ impl SDL_Surface { self.flags } pub fn width(&self) -> i32 { - self.w.try_into().unwrap() + assert!(self.w >= 0); + self.w } pub fn height(&self) -> i32 { - self.h.try_into().unwrap() + assert!(self.h >= 0); + self.h } pub fn pitch(&self) -> i32 { - self.pitch.try_into().unwrap() + self.pitch } pub fn locked(&self) -> i32 { - self.locked.try_into().unwrap() + self.locked } pub fn pixel_format(&self) -> &SDL_PixelFormat { // SAFETY: this should be a valid pointer as long as self is a valid SDL_Surface diff --git a/src/vshader_post.glsl b/src/vshader_post.glsl index 89e76ff..964ace3 100644 --- a/src/vshader_post.glsl +++ b/src/vshader_post.glsl @@ -1,4 +1,4 @@ -attribute vec2 v_pos; +IN vec2 v_pos; OUT vec2 uv; void main() { @@ -561,6 +561,15 @@ impl ColorU8 { assert_eq!(suffix.len(), 0); colors } + + pub fn slice_to_bytes(slice: &[ColorU8]) -> &[u8] { + // SAFETY: it is safe to transmute since ColorU8 is repr(C) + let (prefix, bytes, suffix) = unsafe { slice.align_to() }; + // these should never panic since align_of(u8) == 1 + assert_eq!(prefix.len(), 0); + assert_eq!(suffix.len(), 0); + bytes + } } impl From<u32> for ColorU8 { @@ -1003,19 +1012,21 @@ impl Texture { } /// panicks if `data` is the wrong length (should be exactly `self.width() * self.height()`). - unsafe fn get_data<T: Color>(&self, data: &mut [T]) { + pub fn get_data<T: Color>(&self, data: &mut [T]) { assert_eq!(data.len(), self.width * self.height, "Bad data size."); self.bind(); - gl::GetTexImage( - gl::TEXTURE_2D, - 0, - T::GL_FORMAT, - T::GL_TYPE, - data.as_ptr() as *mut GLvoid, - ); + unsafe { + gl::GetTexImage( + gl::TEXTURE_2D, + 0, + T::GL_FORMAT, + T::GL_TYPE, + data.as_ptr() as *mut GLvoid, + ); + } } - unsafe fn get_data_vec<T: Color>(&self) -> Vec<T> { + pub fn get_data_vec<T: Color>(&self) -> Vec<T> { let mut data = vec![T::default(); self.width * self.height]; self.get_data(&mut data); data @@ -1120,7 +1131,7 @@ impl Framebuffer { pub fn set_texture(&mut self, attachment: FramebufferAttachment, texture: &Texture) { self.bind(); texture.bind(); - unsafe { + unsafe { gl::FramebufferTexture2D( gl::FRAMEBUFFER, attachment.to_gl(), @@ -1366,18 +1377,6 @@ impl Window { unsafe { Texture::new(params) } } - /// get texture image - /// - /// panicks if `data.len() != texture.width() * texture.height()` - pub fn get_texture_data<T: Color>(&mut self, texture: &Texture, data: &mut [T]) { - unsafe { texture.get_data(data) }; - } - - /// get texture image as a newly-allocated `Vec` - pub fn get_texture_data_vec<T: Color>(&mut self, texture: &Texture) -> Vec<T> { - unsafe { texture.get_data_vec() } - } - pub fn set_audio_callback(&mut self, callback: AudioCallback) -> Result<(), String> { if self.audio_data.is_some() { return Err("audio callback already set.".into()); |