faab612cddfa6d70bf062a6abe378fd7948c4b0a
[mandelwow.git] / mandel.rs
1 #[macro_use]
2
3 extern crate glium;
4
5 use glium::DisplayBuild;
6 use glium::Surface;
7 //use glium::index::PrimitiveType;
8
9 mod support;
10
11 #[derive(Copy, Clone)]
12 struct Vertex {
13     position: [f32; 3],
14     color: [f32; 3],
15 }
16 implement_vertex!(Vertex, position, color);
17
18 fn mand(cx: f32, cy: f32) -> [f32; 3] {
19     let mut maxiter = 64;
20     let mut iter = maxiter;
21     let mut zx = cx;
22     let mut zy = cy;
23     while iter > 0 {
24         let zx2 = zx * zx;
25         let zy2 = zy * zy;
26         if zx2 + zy2 > 4.0 {
27             return [iter as f32 / maxiter as f32, 1.0, 1.0];
28         }
29         zy = zx * zy * 2.0 + cy;
30         zx = zx2 - zy2 + cx;
31         iter -= 1;
32     }
33
34     [0.0, 0.0, 0.0]
35 }
36
37 fn mandel<U>(display: &glium::Display,
38           frame: &mut glium::Frame,
39           uniforms: &U,
40           t: f32) where U: glium::uniforms::Uniforms {
41     let program = program!(display,
42         140 => {
43             vertex: "
44                 #version 140
45                 uniform mat4 perspective;
46                 uniform mat4 view;
47                 uniform mat4 model;
48                 in vec3 position;
49                 in vec3 color;
50                 out vec2 c;
51                 void main() {
52                     mat4 modelview = view * model;
53                     gl_Position = perspective * modelview * vec4(position, 1.0);
54                     c = vec2(gl_Position.x, gl_Position.y);
55                 }
56             ",
57
58             fragment: "
59                 #version 140
60                 precision mediump float;
61                 in vec2 c;
62                 out vec4 f_color;
63
64                 void main() {
65                     float zx = c.x;
66                     float zy = c.y;
67                     int iter = 64;
68                     while (iter > 0) {
69                         float zx2 = zx * zx;
70                         float zy2 = zy * zy;
71                         if (zx2 * zy2 > 4.0) {
72                           f_color = vec4(0, 0, 0, 0);
73                           return;
74                         }
75                         zy = zx * zy * 2.0 + c.y;
76                         zx = zx2 - zy2 + c.x;
77                         iter -= 1;
78                     }
79                     f_color = vec4(1.0, 1.0, 1.0, 1.0);
80                     //f_color = vec4(vColor, 1.0);
81                 }
82             "
83         }).unwrap();
84
85     let xmin = -1.3;
86     let xmax =  0.7;
87     let ymin = -1.0;
88     let ymax =  1.0;
89     let width = xmax - xmin;
90     let height = ymax - ymin;
91     let xres: usize = 100;
92     let yres: usize = 100;
93     let xstep = width / xres as f32;
94     let ystep = height / yres as f32;
95     let vb_size = (xres * 2 + 4) * yres;
96     let mut v : Vec<Vertex> = Vec::with_capacity(vb_size);
97     v.resize(vb_size, Vertex { position: [0.0, 0.0, 1.0], color: [0.0, 0.0, 0.0] });
98     let mut i: usize = 0;
99     let mut vy = ymin;
100     for _ in 0..yres {
101         let mut vx = xmin;
102         v[i] = Vertex { position: [vx, vy+ystep, 1.0], color: [0.0, 0.0, 0.0] }; i+=1;
103         v[i] = Vertex { position: [vx, vy, 1.0], color: [vx, vy, 0.0] }; i+=1;
104         for _ in 0..xres {
105             let c = mand(vx, vy);
106             v[i] = Vertex { position: [vx+xstep, vy+ystep, 1.0], color: c }; i += 1;
107             v[i] = Vertex { position: [vx+xstep, vy      , 1.0], color: c }; i += 1;
108             vx += xstep;
109         }
110         v[i] = Vertex { position: [vx+xstep, vy, 1.0], color: [0.0, 0.0, 0.0] }; i+=1;
111         v[i] = Vertex { position: [vx+xstep, vy, 1.0], color: [0.0, 0.0, 0.0] }; i+=1;
112         vy += ystep;
113     }
114     //let vb = glium::VertexBuffer::empty_persistent(display, width*height*3).unwrap();
115     let vb = glium::VertexBuffer::new(display, &v).unwrap();
116
117     //let indices = glium::index::NoIndices(glium::index::PrimitiveType::TriangleStrip);
118     let indices = glium::index::NoIndices(glium::index::PrimitiveType::LineStrip);
119     //let indices = glium::IndexBuffer::new(display, PrimitiveType::TrianglesList,
120     //                                      &[0u16, 1, 2]).unwrap();
121
122     let params = glium::DrawParameters {
123         depth: glium::Depth {
124             test: glium::draw_parameters::DepthTest::IfLess,
125             write: true,
126             .. Default::default()
127         },
128         .. Default::default()
129     };
130
131     //let mut s = display.draw();
132     frame.draw(&vb, &indices, &program, uniforms, &params).unwrap();
133 }
134
135 fn main() {
136
137     let display = glium::glutin::WindowBuilder::new()
138         .with_dimensions(1024, 768)
139         .with_depth_buffer(24)
140         .with_title(format!("Mandel"))
141         .build_glium()
142         .unwrap();
143
144     let mut camera = support::camera::CameraState::new();
145
146     //let mut t: f32 = -0.5;
147     let mut t: f32 = 0.0;
148     support::start_loop(|| {
149         camera.update();
150
151         //t += 0.002;
152         //println!("t={}", t);
153
154         let mut frame = display.draw();
155         frame.clear_color_and_depth((0.0, 0.0, 0.5, 1.0), 1.0);
156
157         let model = [
158             [ (t*5.0).cos(), (t*3.0).sin(), 0.0, 0.0],
159             [-t.sin(),       -t.cos(),      0.0, 0.0],
160             [     0.0,                      0.0, 1.0, 0.0],
161             [       t,                      0.0, 0.0, 1.0f32]
162         ];
163
164         let uniforms = uniform! {
165             model: model,
166             view:  camera.get_view(), // view_matrix(&[2.0, -1.0, 1.0], &[-2.0, 1.0, 1.0], &[0.0, 1.0, 0.0]),
167             perspective: camera.get_perspective(), // perspective,
168         };
169
170         mandel(&display, &mut frame, &uniforms, t);
171
172         for ev in display.poll_events() {
173             match ev {
174                 glium::glutin::Event::Closed => return support::Action::Stop,
175                 ev => camera.process_input(&ev),
176             }
177         }
178
179         frame.finish().unwrap();
180         support::Action::Continue
181     });
182 }