diff options
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | README.txt | 2 | ||||
| -rw-r--r-- | configs/exuberantplasma.xml | 22 | ||||
| -rw-r--r-- | doc/exuberantplasma.6.md | 77 | ||||
| -rw-r--r-- | src/bin/exuberantplasma.rs | 134 | 
5 files changed, 236 insertions, 1 deletions
@@ -4,7 +4,7 @@  # This Makefile is self-documenting (via the 'help' target)  # see: http://marmelab.com/blog/2016/02/29/auto-documented-makefile.html -HACKS=exuberantbovines +HACKS=exuberantbovines exuberantplasma  CARGO ?= cargo  CARGO_OPTS ?= @@ -56,6 +56,8 @@ You'll need to create at least three files with the same base name ("$HACK"):  - an XML config file (configs/$HACK.xml)  - a manpage in Markdown format (doc/$HACK.6.md) +Then just add your HACK to the list in Makefile. +  See also XScreensaver's "Writing new XScreenSaver modules"      https://github.com/Zygo/xscreensaver/blob/master2/README.hacking diff --git a/configs/exuberantplasma.xml b/configs/exuberantplasma.xml new file mode 100644 index 0000000..9034255 --- /dev/null +++ b/configs/exuberantplasma.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> + +<screensaver name="exuberantplasma" _label="ExuberantPlasma" gl="yes"> + +  <command arg="--root"/> + +  <number id="delay" type="slider" arg="--delay %" +          _label="Frame rate" _low-label="Low" _high-label="High" +          low="0" high="100000" default="30000" +          convert="invert"/> + +  <boolean id="wire"    _label="Wireframe"              arg-set="--wireframe"/> +  <boolean id="showfps" _label="Show frame rate" arg-set="--fps"/> + +  <xscreensaver-updater /> + +  <_description> +A port of classic GLSL plasma effect to Rust. + +A good template for basic GLSL/shader screensavers. +  </_description> +</screensaver> diff --git a/doc/exuberantplasma.6.md b/doc/exuberantplasma.6.md new file mode 100644 index 0000000..a04be58 --- /dev/null +++ b/doc/exuberantplasma.6.md @@ -0,0 +1,77 @@ +% exuberantplasma(6) | XScreenSaver manual + +NAME +==== + +**exuberantplasma** — classic GLSL screensaver + +SYNOPSIS +======== + +| **exuberantplasma** \[**-h**|**--help**] \[**--window-id** _id_] \[**--root**] +| \[**--wireframe**] \[**--fps**] + +DESCRIPTION +=========== + +This is a "hack" for the XScreensaver screen locker. It shows a wavey color +background. + +OPTIONS +========= + +_exuberantplasma_ accepts the following options. Note that some long options (like +**root** and **window-id** can be passed with either a single dash (**-root**) +or a double-dash (**--root**) for backwards compatibility with XScreensaver. + +-h, --help + +:   Prints brief usage information. + +--wireframe + +:   Render in wireframe instead of solid. (UNIMPLEMENTED) + +--fps + +:   Display the current frame rate, CPU load, and polygon count. (UNIMPLEMENTED) + + +FILES +===== + +*~/.xscreensaver* + +:   Per-user configuration file. If there isn't a line for this hack in the +    file, xscreensaver-demo won't find or run this hack. + +*/usr/share/xscreensaver/config/exuberantplasma.xml* + +:   Configuration options for this hack + +ENVIRONMENT +=========== + +**XSCREENSAVER_WINDOW** + +:   Optional ID number of the X window to draw into. + +Note that **XENVIRONMENT** and **DISPLAY** are *not* implemented. + +BUGS +==== + +A lot of features (like fps, root-window-finding, wireframe, etc) aren't +implemented yet. + +See GitHub Issues: <https://github.com/bnewbold/exuberant-bovines/issues> + +AUTHOR +====== + +Bryan Newbold <bnewbold@robocracy.org> + +SEE ALSO +======== + +**xscreensaver(1)**, **xscreensaver-demo(1)** diff --git a/src/bin/exuberantplasma.rs b/src/bin/exuberantplasma.rs new file mode 100644 index 0000000..5d49a56 --- /dev/null +++ b/src/bin/exuberantplasma.rs @@ -0,0 +1,134 @@ + +extern crate exuberant; +extern crate getopts; + +#[macro_use] +extern crate glium;  + +use exuberant::ExuberantHack; +use getopts::Options; +use glium::Surface; + +#[derive(Copy, Clone)] +struct Vertex { +    position: [f32; 2], +} +implement_vertex!(Vertex, position); + +struct ExuberantPlasma { +    display: glium::Display, +    program: glium::Program, +} +  +impl ExuberantPlasma { + +    pub fn new(display: glium::Display) -> ExuberantPlasma { + +        let vertex_shader_src = r#" #version 140  +             +            in vec2 position; +            out vec2 v_coords; + +            void main() { +                v_coords = position; +                gl_Position = vec4(position, 0.0, 1.0); +            } +        "#;  + +        // This fragment shader verbatim from: +        // http://www.bidouille.org/prog/plasma +        let fragment_shader_src = r#" #version 140 + +            precision mediump float; +            #define PI 3.1415926535897932384626433832795 +             +            uniform float u_time; +            uniform vec2 u_k; +            varying vec2 v_coords; +             +            void main() { +                float v = 0.0; +                vec2 c = v_coords * u_k - u_k/2.0; +                v += sin((c.x+u_time)); +                v += sin((c.y+u_time)/2.0); +                v += sin((c.x+c.y+u_time)/2.0); +                c += u_k/2.0 * vec2(sin(u_time/3.0), cos(u_time/2.0)); +                v += sin(sqrt(c.x*c.x+c.y*c.y+1.0)+u_time); +                v = v/2.0; +                vec3 col = vec3(1, sin(PI*v), cos(PI*v)); +                gl_FragColor = vec4(col*.5 + .5, 1); +            } +        "#; + + +        let program = glium::Program::from_source( +            &display, +            vertex_shader_src, +            fragment_shader_src, +            None).unwrap(); + +        ExuberantPlasma { +            display: display, +            program: program, +        } +    } +} + +impl ExuberantHack for ExuberantPlasma { + +    fn draw_frame(&mut self, t: f64) -> Result<(), String> { + +        let vertex1 = Vertex { position: [-1.0, -1.0] }; +        let vertex2 = Vertex { position: [ 3.0, -1.0] }; +        let vertex3 = Vertex { position: [-1.0,  3.0] }; +        let shape = vec![vertex1, vertex2, vertex3]; + +        let vertex_buffer = glium::VertexBuffer::new(&self.display, &shape).unwrap(); + +        let indices = glium::index::NoIndices(glium::index::PrimitiveType::TrianglesList); + +        // Drawing Pipeline +        let mut target = self.display.draw(); + +        let uniforms = uniform! { +            u_time: (t % (12.0 * 3.141592)) as f32, +            u_k: [10.0 as f32, 10.0 as f32], +        }; + +        // Set black background +        target.clear_color_and_depth((0.0, 0.0, 0.0, 1.0), 1.0); + +        let params = glium::DrawParameters { +            .. Default::default() +        }; + +        target.draw(&vertex_buffer, +                    &indices, +                    &self.program, +                    &uniforms, +                    ¶ms).unwrap(); + +        target.finish().or(Err("Failure rendering".to_string())) +    } + +    fn get_display(&self) -> &glium::Display { +        &self.display +    } +} + +fn main() { + +    let mut opts = Options::new(); +    opts.optopt("c", "count", "how many cows? (1 to 9) (IGNORED)", "NUM"); +    opts.optopt("s", "speed", "how fast? ratio, with 1.0 as normal (IGNORED)", "NUM"); +    opts.optflag("", "wireframe", "wireframe mode (IGNORED)"); + +    let conf = exuberant::main_helper(opts); +    let dislpay = exuberant::make_display(&conf); +    let mut hack = ExuberantPlasma::new(dislpay); + +    // Here is where you would configure the hack based on command line options + +    // Ok, actually run it (loops forever) +    exuberant::run(&mut hack, &conf); +}  | 
