Adjust mandelwow z limits and make glow fade non-linearly (tanh).
[mandelwow.git] / mandelwow.rs
index fc6bcf768b5dc3318186885f84c7df1ccde8da7b..80c46d4ba71aefe5f01b0e5c3f19e50611532216 100644 (file)
@@ -4,12 +4,16 @@
 
 extern crate glium;
 extern crate glutin;
+extern crate libxm;
+extern crate sdl2;
 
-use glium::DisplayBuild;
-use glium::Surface;
-use glium::index::PrimitiveType;
-use glium::index::IndexBuffer;
+use glium::{DisplayBuild, Surface};
+use glium::index::{IndexBuffer, PrimitiveType};
+use glutin::ElementState::Pressed;
+use glutin::Event::KeyboardInput;
+use glutin::VirtualKeyCode;
 
+mod sound;
 mod support;
 
 #[derive(Copy, Clone)]
@@ -80,8 +84,8 @@ fn mandelwow_program(display: &glium::Display) -> glium::Program {
                         float zx2 = zx * zx;
                         float zy2 = zy * zy;
                         if (zx2 * zy2 > 4.0) {
-                          float index = 1.0 - float(iter) / float(maxiter);
-                          f_color = vec4(index, index * 0.5, index, index * 0.5);
+                          float index = float(iter) / float(maxiter);
+                          f_color = vec4(index, 0.1, 0.5 - index / 2, 0.8 - index);
                           return;
                         }
                         zy = zx * zy * 2.0 + c.y;
@@ -149,7 +153,15 @@ fn bounding_box<U>(display: &glium::Display,
     ];
     let vb = glium::VertexBuffer::new(display, &cube).unwrap();
 
-    let params = Default::default();
+    let params = glium::DrawParameters {
+        depth: glium::Depth {
+            test: glium::draw_parameters::DepthTest::IfLess,
+            write: true,
+            ..Default::default()
+        },
+        blend: glium::Blend::alpha_blending(),
+        ..Default::default()
+    };
 
     let front_indices = IndexBuffer::new(display, PrimitiveType::LineLoop,
                                          &[0, 1, 2, 3u16]).unwrap();
@@ -223,10 +235,10 @@ fn mandel<U>(display: &glium::Display,
         depth: glium::Depth {
             test: glium::draw_parameters::DepthTest::IfLess,
             write: true,
-            .. Default::default()
+            ..Default::default()
         },
         blend: glium::Blend::alpha_blending(),
-        .. Default::default()
+        ..Default::default()
     };
 
     frame.draw(&vb, &indices, program, uniforms, &params).unwrap();
@@ -240,12 +252,13 @@ fn mandelwow(display: &glium::Display,
              bounds: &Cube,
              mandel_w: f32) {
     let mut z0 = [mandel_w, 0f32];
-    let zres = 50;
+    let zres = 30;
     let zmin = bounds.zmin;
     let zmax = bounds.zmax;
     let zstep = (zmax - zmin) / zres as f32;
     let mut zy = zmin;
-    for _ in 0..zres {
+    // zres + 1 to reach the other face of the cube (fencepost error)
+    for _ in 0..(zres + 1) {
         z0[1] = zy;
         zy += zstep;
 
@@ -261,16 +274,25 @@ fn mandelwow(display: &glium::Display,
 }
 
 fn main() {
+    sound::start();
+
     let display = glium::glutin::WindowBuilder::new()
-        .with_dimensions(1024, 768)
+        //.with_dimensions(1024, 768)
+        .with_fullscreen(glutin::get_primary_monitor())
         .with_depth_buffer(24)
+        .with_vsync()
         .with_title(format!("MandelWow"))
         .build_glium()
         .unwrap();
 
+    let program = mandelwow_program(&display);
+    let bounding_box_program = solid_fill_program(&display);
+
     let mut camera = support::camera::CameraState::new();
     let mut t: f32 = 0.0;
     let mut pause = false;
+    let mut bounding_box_enabled = true;
+    let mut fullscreen = true;
 
     support::start_loop(|| {
         camera.update();
@@ -286,8 +308,8 @@ fn main() {
             xmax:  0.7,
             ymin: -1.0,
             ymax:  1.0,
-            zmin: -1.2,
-            zmax:  1.2,
+            zmin: -1.1,
+            zmax:  1.1,
         };
 
         // Vary the wow factor to slice the Mandelwow along its 4th dimension.
@@ -309,38 +331,55 @@ fn main() {
             [     0.0,  0.0,      z_trans, 1.0f32]
         ];
 
-        let program = mandelwow_program(&display);
-        let bounding_box_program = solid_fill_program(&display);
+        // Draw the bounding box before the fractal, when the Z-buffer is still clear,
+        // so the lines behind the semi-translucent areas will be drawn.
+        if bounding_box_enabled {
+            let uniforms = uniform! {
+                model: model,
+                view:  camera.get_view(),
+                perspective: camera.get_perspective(),
+            };
+            bounding_box(&display, &mut frame, &bounding_box_program, &uniforms, &bounds);
+        }
 
         mandelwow(&display, &mut frame, &program, model, &camera, &bounds, wow);
-
-        let uniforms = uniform! {
-            model: model,
-            view:  camera.get_view(),
-            perspective: camera.get_perspective(),
-        };
-        bounding_box(&display, &mut frame, &bounding_box_program, &uniforms, &bounds);
+        frame.finish().unwrap();
 
         for ev in display.poll_events() {
             match ev {
-                glium::glutin::Event::Closed => {
-                    frame.finish().unwrap();
+                glium::glutin::Event::Closed |
+                KeyboardInput(Pressed, _, Some(VirtualKeyCode::Escape)) |
+                KeyboardInput(Pressed, _, Some(VirtualKeyCode::Q)) => {
                     return support::Action::Stop
                 },
-                glutin::Event::KeyboardInput(glutin::ElementState::Pressed, _, Some(glutin::VirtualKeyCode::PageUp)) => {
-                    t += 0.01;
+                KeyboardInput(Pressed, _, Some(VirtualKeyCode::B)) => {
+                    bounding_box_enabled ^= true;
                 },
-                glutin::Event::KeyboardInput(glutin::ElementState::Pressed, _, Some(glutin::VirtualKeyCode::PageDown)) => {
-                    t -= 0.01;
+                KeyboardInput(Pressed, _, Some(VirtualKeyCode::F)) => {
+                    fullscreen ^= true;
+                    if fullscreen {
+                        glutin::WindowBuilder::new()
+                            .with_fullscreen(glutin::get_primary_monitor())
+                            .rebuild_glium(&display).unwrap();
+                    } else {
+                        glutin::WindowBuilder::new()
+                            .rebuild_glium(&display).unwrap();
+                    }
                 },
-                glutin::Event::KeyboardInput(glutin::ElementState::Pressed, _, Some(glutin::VirtualKeyCode::P)) => {
+                KeyboardInput(Pressed, _, Some(VirtualKeyCode::P)) => {
                     pause ^= true;
                 },
+                KeyboardInput(Pressed, _, Some(VirtualKeyCode::PageUp)) => {
+                    t += 0.01;
+                },
+                KeyboardInput(Pressed, _, Some(VirtualKeyCode::PageDown)) => {
+                    t -= 0.01;
+                },
                 ev => camera.process_input(&ev),
             }
         }
 
-        frame.finish().unwrap();
         support::Action::Continue
     });
+
 }