Quellcode durchsuchen

Add overly dramatic atmosphere layer

Toggle with Ctrl+h
Johannes Hofmann vor 7 Jahren
Ursprung
Commit
b3e327b59c
7 geänderte Dateien mit 180 neuen und 5 gelöschten Zeilen
  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 Datei anzeigen

@@ -0,0 +1,13 @@
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 Datei anzeigen

@@ -0,0 +1,13 @@
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 Datei anzeigen

@@ -0,0 +1,83 @@
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 Datei anzeigen

@@ -17,11 +17,13 @@ extern crate reqwest;
17 17
 extern crate scoped_threadpool;
18 18
 extern crate toml;
19 19
 
20
+#[macro_use]
21
+pub mod context;
22
+
20 23
 pub mod args;
24
+pub mod atmos_layer;
21 25
 pub mod buffer;
22 26
 pub mod config;
23
-#[macro_use]
24
-pub mod context;
25 27
 pub mod coord;
26 28
 pub mod map_view;
27 29
 pub mod map_view_gl;
@@ -213,6 +215,14 @@ fn handle_event(
213 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 226
                     _ => Action::Nothing,
217 227
                 }
218 228
             },

+ 26
- 0
src/map_view_gl.rs Datei anzeigen

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

+ 6
- 3
src/orthografic_view.rs Datei anzeigen

@@ -217,11 +217,14 @@ impl OrthograficView {
217 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 224
     pub fn transformation_matrix(map_view: &MapView) -> Matrix3<f64> {
221 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 230
         let scale_mat: Matrix3<f64> = Matrix3::from_cols(

+ 27
- 0
src/program.rs Datei anzeigen

@@ -25,6 +25,11 @@ pub struct ProgramId {
25 25
     id: u32,
26 26
 }
27 27
 
28
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
29
+pub struct UniformId {
30
+    id: i32,
31
+}
32
+
28 33
 impl ProgramId {
29 34
     /// Returns an invalid `ProgramId`.
30 35
     pub fn invalid() -> Self {
@@ -135,6 +140,28 @@ impl Program {
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 165
     //TODO rename function or integrate into new()
139 166
     pub fn add_attribute(
140 167
         &mut self,