diff --git a/Cargo.toml b/Cargo.toml index 5464f102..5a29e1e3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,5 +12,6 @@ simple-stopwatch="0.1.4" ncollide2d = "0.19.1" nalgebra = "0.18.0" image = "0.21.2" +rand = "0.6.5" diff --git a/resources/background.jpg b/resources/background.jpg new file mode 100644 index 00000000..f37d7aed Binary files /dev/null and b/resources/background.jpg differ diff --git a/resources/devices.png b/resources/devices.png new file mode 100644 index 00000000..6b1cbc85 Binary files /dev/null and b/resources/devices.png differ diff --git a/resources/edge.frag b/resources/edge.frag new file mode 100644 index 00000000..7f869f53 --- /dev/null +++ b/resources/edge.frag @@ -0,0 +1,32 @@ +uniform sampler2D texture; +uniform float edge_threshold; + +void main() +{ + const float offset = 1.0 / 512.0; + vec2 offx = vec2(offset, 0.0); + vec2 offy = vec2(0.0, offset); + + vec4 hEdge = texture2D(texture, gl_TexCoord[0].xy - offy) * -2.0 + + texture2D(texture, gl_TexCoord[0].xy + offy) * 2.0 + + texture2D(texture, gl_TexCoord[0].xy - offx - offy) * -1.0 + + texture2D(texture, gl_TexCoord[0].xy - offx + offy) * 1.0 + + texture2D(texture, gl_TexCoord[0].xy + offx - offy) * -1.0 + + texture2D(texture, gl_TexCoord[0].xy + offx + offy) * 1.0; + + vec4 vEdge = texture2D(texture, gl_TexCoord[0].xy - offx) * 2.0 + + texture2D(texture, gl_TexCoord[0].xy + offx) * -2.0 + + texture2D(texture, gl_TexCoord[0].xy - offx - offy) * 1.0 + + texture2D(texture, gl_TexCoord[0].xy - offx + offy) * -1.0 + + texture2D(texture, gl_TexCoord[0].xy + offx - offy) * 1.0 + + texture2D(texture, gl_TexCoord[0].xy + offx + offy) * -1.0; + + vec3 result = sqrt(hEdge.rgb * hEdge.rgb + vEdge.rgb * vEdge.rgb); + float edge = length(result); + vec4 pixel = gl_Color * texture2D(texture, gl_TexCoord[0].xy); + if (edge > (edge_threshold * 8.0)) + pixel.rgb = vec3(0.0, 0.0, 0.0); + else + pixel.a = edge_threshold; + gl_FragColor = pixel; +} diff --git a/resources/sansation.ttf b/resources/sansation.ttf new file mode 100755 index 00000000..d85fbc81 Binary files /dev/null and b/resources/sansation.ttf differ diff --git a/resources/sfml.png b/resources/sfml.png new file mode 100644 index 00000000..1da719ff Binary files /dev/null and b/resources/sfml.png differ diff --git a/resources/text-background.png b/resources/text-background.png new file mode 100644 index 00000000..c86e9b6c Binary files /dev/null and b/resources/text-background.png differ diff --git a/src/main.rs b/src/main.rs index 2c77bf4e..28dd4f95 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,12 +6,17 @@ extern crate quick_xml; extern crate sfml; extern crate cgmath; extern crate image; +extern crate rand; + mod slider; mod timer; mod input; mod util; +use sfml::graphics::*; +use sfml::system::*; +use sfml::window::*; use crate::timer::Timer; use crate::input::Input; use crate::slider::Slider; @@ -26,6 +31,87 @@ use sfml::graphics::{ use sfml::window::{ Event, Key, Style}; use sfml::system::Vector2 as sfVec2; +// The container trait for all the shaders +trait Effect: Drawable { + fn update(&mut self, t: f32, x: f32, y: f32); + fn name(&self) -> &str; + fn as_drawable(&self) -> &Drawable; +} + + +// ======= LARGE MULTISPRITE SHADER DEMO =========== +struct Edge<'t> { + surface: RenderTexture, + bg_sprite: Sprite<'t>, + entities: Vec>, + shader: Shader<'static>, +} + +impl<'t> Edge<'t> { + fn new(bg_texture: &'t Texture, entity_texture: &'t Texture) -> Self { + let mut surface = RenderTexture::new(800, 600, false).unwrap(); + surface.set_smooth(true); + let mut bg_sprite = Sprite::with_texture(bg_texture); + bg_sprite.set_position((135., 100.)); + let mut entities = Vec::new(); + + for i in 0..6 { + let mut entity = Sprite::with_texture(entity_texture); + entity.set_texture_rect(&IntRect::new(96 * i, 0, 96, 96)); + entities.push(entity); + } + + let mut shader = Shader::from_file(None, None, Some("resources/edge.frag")).unwrap(); + shader.set_uniform_current_texture("texture"); + + Self { + surface, + bg_sprite, + entities, + shader, + } + } +} + +impl<'t> Drawable for Edge<'t> { + fn draw<'a: 'shader, 'texture, 'shader, 'shader_texture>( + &'a self, + target: &mut RenderTarget, + mut states: RenderStates<'texture, 'shader, 'shader_texture>, + ) { + states.shader = Some(&self.shader); + target.draw_with_renderstates(&Sprite::with_texture(self.surface.texture()), states); + } +} + +impl<'t> Effect for Edge<'t> { + fn update(&mut self, t: f32, x: f32, y: f32) { + self.shader + .set_uniform_float("edge_threshold", 1. - (x + y) / 2.); + let entities_len = self.entities.len() as f32; + + for (i, en) in self.entities.iter_mut().enumerate() { + let pos = ( + (0.25 * (t * i as f32 + (entities_len - i as f32))).cos() * 300. + 350., + (0.25 * (t * (entities_len - i as f32) + i as f32)).cos() * 200. + 250., + ); + en.set_position(pos); + } + self.surface.clear(&Color::WHITE); + self.surface.draw(&self.bg_sprite); + for en in &self.entities { + self.surface.draw(en); + } + self.surface.display(); + } + fn as_drawable(&self) -> &Drawable { + self + } + fn name(&self) -> &str { + "edge post-effect" + } +} + fn surrounding_pixels(x: u32, y: u32, img: &DynamicImage) -> Vec> { let mut pixels: Vec> = Vec::new(); @@ -96,6 +182,26 @@ fn main() { let mut timer = Timer::new(); let mut input = Input::new(); + //========================================== + let font = Font::from_file("resources/sansation.ttf").unwrap(); + + let mut bg_texture = Texture::from_file("resources/sfml.png").unwrap(); + bg_texture.set_smooth(true); + + let mut entity_texture = Texture::from_file("resources/devices.png").unwrap(); + entity_texture.set_smooth(true); + + let mut effects: [Box; 1] = [ + Box::new(Edge::new(&bg_texture, &entity_texture)), + ]; + let mut current = 0; + + let text_bg_texture = Texture::from_file("resources/text-background.png").unwrap(); + let mut text_bg = Sprite::with_texture(&text_bg_texture); + text_bg.set_position((0., 520.)); + text_bg.set_color(&Color::rgba(255, 255, 255, 200)); + //========================================== + let mut slider = Slider::new(40.0, None); @@ -141,12 +247,17 @@ fn main() { accumulator_time -= step_size; } + let x = window.mouse_position().x as f32 / window.size().x as f32; + let y = window.mouse_position().y as f32 / window.size().y as f32; + effects[current].update(elapsed_time*1000.0, x, y); + window.clear(&Color::BLACK); + window.draw(effects[current].as_drawable()); window.draw(&slider); window.display(); } -} \ No newline at end of file +}