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); +} |