浏览代码

Add overly dramatic atmosphere layer

Toggle with Ctrl+h
Johannes Hofmann 7 年前
父节点
当前提交
b3e327b59c
共有 7 个文件被更改,包括 180 次插入5 次删除
  1. 13
    0
      shader/atmos.frag
  2. 13
    0
      shader/atmos.vert
  3. 83
    0
      src/atmos_layer.rs
  4. 12
    2
      src/main.rs
  5. 26
    0
      src/map_view_gl.rs
  6. 6
    3
      src/orthografic_view.rs
  7. 27
    0
      src/program.rs

+ 13
- 0
shader/atmos.frag 查看文件

1
+#version 100
2
+precision mediump float;
3
+
4
+varying vec2 v_pos;
5
+
6
+void main() {
7
+    //float len = abs(1.0 - length(v_pos));
8
+    //float val = (1.0 - sqrt(sqrt(len*4.0))) * (1.0 - len*5.0);
9
+    float len = length(v_pos);
10
+    //float val = max(0.0, sqrt(1.1*1.1 - len*len) * 1.5) * step(0.99, len);
11
+    float val = exp(abs(1.0 - len)*(-16.0 - step(1.0, len)*16.0));
12
+    gl_FragColor = vec4(sin(val*1.0) * 0.8 + 0.2, sin(val*1.5) * 0.8 + 0.2 , 1.0, val * 1.0);
13
+}

+ 13
- 0
shader/atmos.vert 查看文件

1
+#version 100
2
+precision mediump float;
3
+
4
+attribute vec2 position;
5
+
6
+uniform vec2 scale;
7
+
8
+varying vec2 v_pos;
9
+
10
+void main() {
11
+    gl_Position = vec4(position * scale, 0.0, 1.0);
12
+    v_pos = position;
13
+}

+ 83
- 0
src/atmos_layer.rs 查看文件

1
+use ::std::ffi::CStr;
2
+use buffer::{Buffer, DrawMode};
3
+use context::Context;
4
+use map_view::MapView;
5
+use orthografic_view::OrthograficView;
6
+use program::{Program, UniformId};
7
+use std::f32::consts::PI;
8
+use vertex_attrib::VertexAttribParams;
9
+
10
+
11
+#[derive(Debug)]
12
+pub struct AtmosLayer {
13
+    buffer: Buffer,
14
+    program: Program,
15
+    scale_uniform: UniformId,
16
+}
17
+
18
+impl AtmosLayer {
19
+    pub fn new(cx: &mut Context) -> AtmosLayer {
20
+        let vertex_data = {
21
+            let mut vertex_data: Vec<f32> = Vec::with_capacity(17 * 4);
22
+
23
+            let radius_a = 0.75;
24
+            let radius_b = 1.25;
25
+            for x in 0..17 {
26
+                let angle = x as f32 * (PI * 2.0 / 16.0);
27
+                vertex_data.extend(&[
28
+                    angle.cos() * radius_a,
29
+                    angle.sin() * radius_a,
30
+                    angle.cos() * radius_b,
31
+                    angle.sin() * radius_b,
32
+                ]);
33
+            }
34
+
35
+            vertex_data
36
+        };
37
+
38
+        let buffer = Buffer::new(cx, &vertex_data, vertex_data.len() / 2);
39
+
40
+        let mut program = Program::new(
41
+            cx,
42
+            include_bytes!("../shader/atmos.vert"),
43
+            include_bytes!("../shader/atmos.frag"),
44
+        ).unwrap();
45
+
46
+        program.add_attribute(
47
+            cx,
48
+            CStr::from_bytes_with_nul(b"position\0").unwrap(),
49
+            &VertexAttribParams::new(2, 2, 0)
50
+        );
51
+
52
+        let scale_uniform = program.get_uniform_id(cx, CStr::from_bytes_with_nul(b"scale\0").unwrap()).unwrap();
53
+
54
+        check_gl_errors!(cx);
55
+
56
+        AtmosLayer {
57
+            buffer,
58
+            program,
59
+            scale_uniform,
60
+        }
61
+    }
62
+
63
+    // Has to be called once before one or multiple calls to `draw`.
64
+    pub fn prepare_draw(&mut self, cx: &mut Context) {
65
+        self.program.enable_vertex_attribs(cx);
66
+        self.program.set_vertex_attribs(cx, &self.buffer);
67
+    }
68
+
69
+    pub fn draw(
70
+        &mut self,
71
+        cx: &mut Context,
72
+        map_view: &MapView,
73
+    ) {
74
+        let (scale_x, scale_y) = {
75
+            let radius = OrthograficView::radius_physical_pixels(map_view);
76
+            ((radius / map_view.width) as f32, (radius / map_view.height) as f32)
77
+        };
78
+
79
+        self.program.set_uniform_2f(cx, self.scale_uniform, scale_x, scale_y);
80
+
81
+        self.buffer.draw(cx, &self.program, DrawMode::TriangleStrip);
82
+    }
83
+}

+ 12
- 2
src/main.rs 查看文件

17
 extern crate scoped_threadpool;
17
 extern crate scoped_threadpool;
18
 extern crate toml;
18
 extern crate toml;
19
 
19
 
20
+#[macro_use]
21
+pub mod context;
22
+
20
 pub mod args;
23
 pub mod args;
24
+pub mod atmos_layer;
21
 pub mod buffer;
25
 pub mod buffer;
22
 pub mod config;
26
 pub mod config;
23
-#[macro_use]
24
-pub mod context;
25
 pub mod coord;
27
 pub mod coord;
26
 pub mod map_view;
28
 pub mod map_view;
27
 pub mod map_view_gl;
29
 pub mod map_view_gl;
213
                             Action::Nothing
215
                             Action::Nothing
214
                         }
216
                         }
215
                     },
217
                     },
218
+                    VirtualKeyCode::H => {
219
+                        if modifiers.ctrl {
220
+                            map.toggle_atmosphere();
221
+                            Action::Redraw
222
+                        } else {
223
+                            Action::Nothing
224
+                        }
225
+                    },
216
                     _ => Action::Nothing,
226
                     _ => Action::Nothing,
217
                 }
227
                 }
218
             },
228
             },

+ 26
- 0
src/map_view_gl.rs 查看文件

1
+use atmos_layer::AtmosLayer;
1
 use context::Context;
2
 use context::Context;
2
 use coord::{MapCoord, ScreenCoord};
3
 use coord::{MapCoord, ScreenCoord};
3
 use map_view::MapView;
4
 use map_view::MapView;
27
     mercator_tile_layer: MercatorTileLayer,
28
     mercator_tile_layer: MercatorTileLayer,
28
     marker_layer: MarkerLayer,
29
     marker_layer: MarkerLayer,
29
     ortho_tile_layer: OrthoTileLayer,
30
     ortho_tile_layer: OrthoTileLayer,
31
+    atmos_layer: AtmosLayer,
30
     projection: Projection,
32
     projection: Projection,
33
+    show_atmos: bool,
31
     last_draw_type: DrawType,
34
     last_draw_type: DrawType,
32
 }
35
 }
33
 
36
 
37
     Tiles,
40
     Tiles,
38
     Markers,
41
     Markers,
39
     OrthoTiles,
42
     OrthoTiles,
43
+    Atmos,
40
 }
44
 }
41
 
45
 
42
 impl MapViewGl {
46
 impl MapViewGl {
83
 
87
 
84
         let mercator_tile_layer = MercatorTileLayer::new(cx, &tile_atlas);
88
         let mercator_tile_layer = MercatorTileLayer::new(cx, &tile_atlas);
85
         let ortho_tile_layer = OrthoTileLayer::new(cx, &tile_atlas);
89
         let ortho_tile_layer = OrthoTileLayer::new(cx, &tile_atlas);
90
+        let atmos_layer = AtmosLayer::new(cx);
86
 
91
 
87
         MapViewGl {
92
         MapViewGl {
88
             map_view,
93
             map_view,
93
             mercator_tile_layer,
98
             mercator_tile_layer,
94
             marker_layer: MarkerLayer::new(cx),
99
             marker_layer: MarkerLayer::new(cx),
95
             ortho_tile_layer,
100
             ortho_tile_layer,
101
+            atmos_layer,
96
             projection: Projection::Mercator,
102
             projection: Projection::Mercator,
103
+            show_atmos: false,
97
             last_draw_type: DrawType::Null,
104
             last_draw_type: DrawType::Null,
98
         }
105
         }
99
     }
106
     }
132
         };
139
         };
133
     }
140
     }
134
 
141
 
142
+    pub fn toggle_atmosphere(&mut self) {
143
+        self.show_atmos = !self.show_atmos;
144
+    }
145
+
135
     fn draw_mercator_tiles(&mut self, cx: &mut Context, source: &TileSource, snap_to_pixel: bool)
146
     fn draw_mercator_tiles(&mut self, cx: &mut Context, source: &TileSource, snap_to_pixel: bool)
136
         -> Result<usize, usize>
147
         -> Result<usize, usize>
137
     {
148
     {
192
         )
203
         )
193
     }
204
     }
194
 
205
 
206
+    fn draw_atmos(&mut self, cx: &mut Context) {
207
+        if self.last_draw_type != DrawType::Atmos {
208
+            self.last_draw_type = DrawType::Atmos;
209
+            self.atmos_layer.prepare_draw(cx);
210
+        }
211
+
212
+        self.atmos_layer.draw(
213
+            cx,
214
+            &self.map_view,
215
+        )
216
+    }
217
+
195
     /// Returns `Err` when tile cache is too small for this view.
218
     /// Returns `Err` when tile cache is too small for this view.
196
     /// Returns the number of OpenGL draw calls, which can be decreased to `1` by increasing the
219
     /// Returns the number of OpenGL draw calls, which can be decreased to `1` by increasing the
197
     /// size of the tile atlas.
220
     /// size of the tile atlas.
212
                 if !self.marker_layer.is_empty() {
235
                 if !self.marker_layer.is_empty() {
213
                     self.draw_ortho_marker(cx);
236
                     self.draw_ortho_marker(cx);
214
                 }
237
                 }
238
+                if self.show_atmos {
239
+                    self.draw_atmos(cx);
240
+                }
215
                 ret
241
                 ret
216
             },
242
             },
217
         }
243
         }

+ 6
- 3
src/orthografic_view.rs 查看文件

217
         tiles
217
         tiles
218
     }
218
     }
219
 
219
 
220
+    pub fn radius_physical_pixels(map_view: &MapView) -> f64 {
221
+        2.0f64.powf(map_view.zoom) * (FRAC_1_PI * map_view.tile_size as f64)
222
+    }
223
+
220
     pub fn transformation_matrix(map_view: &MapView) -> Matrix3<f64> {
224
     pub fn transformation_matrix(map_view: &MapView) -> Matrix3<f64> {
221
         let (scale_x, scale_y) = {
225
         let (scale_x, scale_y) = {
222
-            let factor = 2.0f64.powf(map_view.zoom) *
223
-                (FRAC_1_PI * map_view.tile_size as f64);
224
-            (factor / map_view.width, factor / map_view.height)
226
+            let radius = Self::radius_physical_pixels(map_view);
227
+            (radius / map_view.width, radius / map_view.height)
225
         };
228
         };
226
 
229
 
227
         let scale_mat: Matrix3<f64> = Matrix3::from_cols(
230
         let scale_mat: Matrix3<f64> = Matrix3::from_cols(

+ 27
- 0
src/program.rs 查看文件

25
     id: u32,
25
     id: u32,
26
 }
26
 }
27
 
27
 
28
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
29
+pub struct UniformId {
30
+    id: i32,
31
+}
32
+
28
 impl ProgramId {
33
 impl ProgramId {
29
     /// Returns an invalid `ProgramId`.
34
     /// Returns an invalid `ProgramId`.
30
     pub fn invalid() -> Self {
35
     pub fn invalid() -> Self {
135
         }
140
         }
136
     }
141
     }
137
 
142
 
143
+
144
+    pub fn get_uniform_id(&mut self, cx: &mut Context, uniform_name: &CStr) -> Option<UniformId> {
145
+        cx.use_program(self.program_id);
146
+        let loc: i32 = unsafe {
147
+            cx.gl.GetUniformLocation(self.program_id.index(), uniform_name.as_ptr() as *const _)
148
+        };
149
+        check_gl_errors!(cx);
150
+
151
+        if loc == -1 {
152
+            None
153
+        } else {
154
+            Some(UniformId { id: loc })
155
+        }
156
+    }
157
+
158
+    pub fn set_uniform_2f(&mut self, cx: &mut Context, uniform_id: UniformId, v0: f32, v1: f32) {
159
+        cx.use_program(self.program_id);
160
+        unsafe {
161
+            cx.gl.Uniform2f(uniform_id.id, v0, v1);
162
+        };
163
+    }
164
+
138
     //TODO rename function or integrate into new()
165
     //TODO rename function or integrate into new()
139
     pub fn add_attribute(
166
     pub fn add_attribute(
140
         &mut self,
167
         &mut self,