From a734d7de86ba47e8cba8a75dce6def630f09ff62 Mon Sep 17 00:00:00 2001 From: shivshank Date: Sat, 28 Jul 2018 16:59:02 -0400 Subject: [PATCH] Add post process, input handling, and game of life example --- README.md | 78 ++++++++++++++++++++++++++++++++++------ examples/game_of_life.rs | 29 ++++++++++++--- src/lib.rs | 2 +- 3 files changed, 92 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 6a5e917..c90f2cd 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,65 @@ fn main() { time. You can bring your own timing mechanism, whether it's just `sleep(ms)` or something more sophisticated. +# Support for simplified basic input handling + +Get access to mouse position and key inputs with no hassle. The following is extracted from the +Game of Life example: + +```rust + +let mut fb = mini_gl_fb::gotta_go_fast("Hello world!", 800.0, 600.0); +let buffer = vec![[128u8, 0, 0, 255]; 800 * 600]; + +// ... + +fb.glutin_handle_basic_input(|fb, input| { + let elapsed = previous.elapsed().unwrap(); + let seconds = elapsed.as_secs() as f64 + elapsed.subsec_nanos() as f64 * 1e-9; + + if input.key_is_down(VirtualKeyCode::Escape) { + return false; + } + + if input.mouse_is_down(MouseButton::Left) { + // Mouse was pressed + let (x, y) = input.mouse_pos; + cells[y * WIDTH + x] = true; + fb.update_buffer(&cells); + // Give the user extra time to make something pretty each time they click + previous = SystemTime::now(); + extra_delay = (extra_delay + 0.5).min(2.0); + } + + // Each generation should stay on screen for half a second + if seconds > 0.5 + extra_delay { + previous = SystemTime::now(); + calculate_neighbors(&mut cells, &mut neighbors); + make_some_babies(&mut cells, &mut neighbors); + fb.update_buffer(&cells); + extra_delay = 0.0; + } else if input.resized { + fb.redraw(); + } + + true +}); +``` + +# Shader playground + +Post process with GLSL shaders inspired by ShaderToy. This is a work in progress but there is +basic support for simple effects. The following is the default behavior but illustrates the +API: + +```rust +fb.use_post_process_shader(" +void main_image( out vec4 r_frag_color, in vec2 v_uv ) { + r_frag_color = texture(u_buffer, v_uv); +} +"); +``` + # Get full access to glutin for custom event handling You can also "breakout" and get access to the underlying glutin window while still having easy @@ -51,20 +110,17 @@ fb.update_buffer(/*...*/); See the [docs](https://docs.rs/mini_gl_fb/) for more info. -# Planned Features +# Planned Features (depends on demand) -Listed in rough order of importance and ease (which are surprisingly correlated here!). +Feel free to open an issue if you have a suggestion or want to see one of these soon! - - Shader playground. Add a method for using shadertoy-like fragment shaders to be applied to - your submitted pixel data. + - More simplified input handling methods - - Some built in managed ways of getting interactivity, possibly such as a functional reactive - style draw function that renders based on a provided Store struct. Other simpler - alternatives include automatically drawing after running some event handlers and some - methods for drawing at intervals (fixed/dynamic delta time). + - Enhanced and more thorough shader playground - - Fully replace and customize the vertex, geometry, and fragment shader, including adding your - own uniforms (but probably not adding any vertex attributes). + - Support for running ShaderToy examples directly (a conversion function) - Support for more textures, possibly actual OpenGL framebuffers for complex sequences of - post processing. I am undecided on whether this is appropriate for this library. + post processing + + - An HTML canvas-like API that allows drawing over your buffer diff --git a/examples/game_of_life.rs b/examples/game_of_life.rs index 7a67fe9..d7d5ecd 100644 --- a/examples/game_of_life.rs +++ b/examples/game_of_life.rs @@ -1,6 +1,7 @@ extern crate mini_gl_fb; use mini_gl_fb::{Config, BufferFormat}; +use mini_gl_fb::glutin::{MouseButton, VirtualKeyCode}; use std::time::SystemTime; @@ -26,21 +27,39 @@ fn main() { cells[5 * WIDTH + 12] = true; let mut previous = SystemTime::now(); + let mut extra_delay: f64 = 0.0; - while fb.is_running() { + fb.glutin_handle_basic_input(|fb, input| { let elapsed = previous.elapsed().unwrap(); let seconds = elapsed.as_secs() as f64 + elapsed.subsec_nanos() as f64 * 1e-9; + if input.key_is_down(VirtualKeyCode::Escape) { + return false; + } + + if input.mouse_is_down(MouseButton::Left) { + // Mouse was pressed + let (x, y) = input.mouse_pos; + cells[y * WIDTH + x] = true; + fb.update_buffer(&cells); + // Give the user extra time to make something pretty each time they click + previous = SystemTime::now(); + extra_delay = (extra_delay + 0.5).min(2.0); + } + // Each generation should stay on screen for half a second - if seconds > 0.5 { + if seconds > 0.5 + extra_delay { previous = SystemTime::now(); calculate_neighbors(&mut cells, &mut neighbors); make_some_babies(&mut cells, &mut neighbors); - // Vsync should be enabled by default (open an issue if you need it disabled) - // Vsync should cause this to block so we don't run too often or too fast #robust fb.update_buffer(&cells); + extra_delay = 0.0; + } else if input.resized { + fb.redraw(); } - } + + true + }); } fn calculate_neighbors(cells: &mut [bool], neighbors: &mut [u32]) { diff --git a/src/lib.rs b/src/lib.rs index 5a48f64..3e9b892 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,7 +3,7 @@ //! # Basic Usage //! //! Start with the function `gotta_go_fast`. This will create a basic window and give you a buffer -//! that you can draw to in one line. +//! that you can draw to in one line. The main public API is available through the `MiniGlFb` type. //! //! ```rust //! extern crate mini_gl_fb;