mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-29 04:35:51 +03:00
add basic hatching support to fragment shader. use it to visualize map
edits when zoomed in
This commit is contained in:
parent
ba71d2d5e6
commit
f4620c1951
@ -179,18 +179,9 @@ impl EditMode {
|
||||
);
|
||||
common.draw(g, &state.ui);
|
||||
|
||||
// TODO Similar to drawing areas with traffic or not -- would be convenient to just
|
||||
// supply a set of things to highlight and have something else take care of drawing
|
||||
// with detail or not.
|
||||
let zoomed = g.canvas.cam_zoom >= MIN_ZOOM_FOR_DETAIL;
|
||||
let color = if zoomed {
|
||||
state
|
||||
.ui
|
||||
.cs
|
||||
.get_def("zoomed map diffs", Color::RED.alpha(0.5))
|
||||
} else {
|
||||
state.ui.cs.get_def("unzoomed map diffs", Color::RED)
|
||||
};
|
||||
// More generally we might want to show the diff between two edits, but for now,
|
||||
// just show diff relative to basemap.
|
||||
let edits = state.ui.primary.map.get_edits();
|
||||
|
||||
let ctx = DrawCtx {
|
||||
cs: &state.ui.cs,
|
||||
@ -200,33 +191,55 @@ impl EditMode {
|
||||
};
|
||||
let mut opts = DrawOptions::new();
|
||||
|
||||
// More generally we might want to show the diff between two edits, but for now,
|
||||
// just show diff relative to basemap.
|
||||
let edits = state.ui.primary.map.get_edits();
|
||||
for l in edits.lane_overrides.keys() {
|
||||
if zoomed {
|
||||
opts.override_colors.insert(ID::Lane(*l), color);
|
||||
state.ui.primary.draw_map.get_l(*l).draw(g, &opts, &ctx);
|
||||
} else {
|
||||
g.draw_polygon(
|
||||
color,
|
||||
&state
|
||||
.ui
|
||||
.primary
|
||||
.map
|
||||
.get_parent(*l)
|
||||
.get_thick_polygon()
|
||||
.unwrap(),
|
||||
);
|
||||
// TODO Similar to drawing areas with traffic or not -- would be convenient to just
|
||||
// supply a set of things to highlight and have something else take care of drawing
|
||||
// with detail or not.
|
||||
if g.canvas.cam_zoom >= MIN_ZOOM_FOR_DETAIL {
|
||||
g.enable_hatching();
|
||||
|
||||
for l in edits.lane_overrides.keys() {
|
||||
ctx.draw_map.get_l(*l).draw(g, &opts, &ctx);
|
||||
}
|
||||
for i in edits
|
||||
.stop_sign_overrides
|
||||
.keys()
|
||||
.chain(edits.traffic_signal_overrides.keys())
|
||||
{
|
||||
ctx.draw_map.get_i(*i).draw(g, &opts, &ctx);
|
||||
}
|
||||
|
||||
g.disable_hatching();
|
||||
|
||||
// The hatching covers up the selection outline, so redraw it.
|
||||
match state.ui.primary.current_selection {
|
||||
Some(ID::Lane(l)) => {
|
||||
g.draw_polygon(
|
||||
state.ui.cs.get("selected"),
|
||||
&ctx.draw_map.get_l(l).get_outline(&ctx.map),
|
||||
);
|
||||
}
|
||||
Some(ID::Intersection(i)) => {
|
||||
g.draw_polygon(
|
||||
state.ui.cs.get("selected"),
|
||||
&ctx.draw_map.get_i(i).get_outline(&ctx.map),
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
} else {
|
||||
let color = state.ui.cs.get_def("unzoomed map diffs", Color::RED);
|
||||
for l in edits.lane_overrides.keys() {
|
||||
g.draw_polygon(color, &ctx.map.get_parent(*l).get_thick_polygon().unwrap());
|
||||
}
|
||||
|
||||
for i in edits
|
||||
.stop_sign_overrides
|
||||
.keys()
|
||||
.chain(edits.traffic_signal_overrides.keys())
|
||||
{
|
||||
opts.override_colors.insert(ID::Intersection(*i), color);
|
||||
ctx.draw_map.get_i(*i).draw(g, &opts, &ctx);
|
||||
}
|
||||
}
|
||||
for i in edits
|
||||
.stop_sign_overrides
|
||||
.keys()
|
||||
.chain(edits.traffic_signal_overrides.keys())
|
||||
{
|
||||
opts.override_colors.insert(ID::Intersection(*i), color);
|
||||
state.ui.primary.draw_map.get_i(*i).draw(g, &opts, &ctx);
|
||||
}
|
||||
|
||||
menu.draw(g);
|
||||
|
@ -1,7 +1,12 @@
|
||||
#version 110
|
||||
|
||||
varying vec4 pass_color;
|
||||
varying float pass_hatching;
|
||||
|
||||
void main() {
|
||||
gl_FragColor = pass_color;
|
||||
|
||||
if (pass_hatching == 1.0 && mod(gl_FragCoord.x + gl_FragCoord.y, 20.0) <= 5.0) {
|
||||
gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,13 @@
|
||||
#version 140
|
||||
|
||||
in vec4 pass_color;
|
||||
in float pass_hatching;
|
||||
out vec4 f_color;
|
||||
|
||||
void main() {
|
||||
f_color = pass_color;
|
||||
|
||||
if (pass_hatching == 1.0 && mod(gl_FragCoord.x + gl_FragCoord.y, 20.0) <= 5.0) {
|
||||
f_color = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
}
|
||||
|
@ -2,15 +2,17 @@
|
||||
|
||||
// (x offset, y offset, zoom)
|
||||
uniform vec3 transform;
|
||||
// (window width, window height)
|
||||
uniform vec2 window;
|
||||
// (window width, window height, hatching == 1.0)
|
||||
uniform vec3 window;
|
||||
|
||||
attribute vec2 position;
|
||||
attribute vec4 color;
|
||||
varying vec4 pass_color;
|
||||
varying float pass_hatching;
|
||||
|
||||
void main() {
|
||||
pass_color = color / 255.0;
|
||||
pass_hatching = window[2];
|
||||
|
||||
// This is map_to_screen
|
||||
float screen_x = (position[0] * transform[2]) - transform[0];
|
||||
|
@ -2,15 +2,17 @@
|
||||
|
||||
// (x offset, y offset, zoom)
|
||||
uniform vec3 transform;
|
||||
// (window width, window height)
|
||||
uniform vec2 window;
|
||||
// (window width, window height, hatching == 1.0)
|
||||
uniform vec3 window;
|
||||
|
||||
in vec2 position;
|
||||
in vec4 color;
|
||||
out vec4 pass_color;
|
||||
out float pass_hatching;
|
||||
|
||||
void main() {
|
||||
pass_color = color / 255.0;
|
||||
pass_hatching = window[2];
|
||||
|
||||
// This is map_to_screen
|
||||
float screen_x = (position[0] * transform[2]) - transform[0];
|
||||
|
@ -6,11 +6,16 @@ use crate::{
|
||||
use geom::{Bounds, Circle, Distance, Line, Polygon, Pt2D};
|
||||
use glium::{uniform, Surface};
|
||||
|
||||
// transform is (cam_x, cam_y, cam_zoom)
|
||||
// window is (window_width, window_height, hatching == 1.0)
|
||||
// Things are awkwardly grouped because passing uniforms is either broken or horribly documented.
|
||||
type Uniforms<'a> = glium::uniforms::UniformsStorage<
|
||||
'a,
|
||||
[f32; 2],
|
||||
[f32; 3],
|
||||
glium::uniforms::UniformsStorage<'a, [f32; 3], glium::uniforms::EmptyUniforms>,
|
||||
>;
|
||||
const NO_HATCHING: f32 = 0.0;
|
||||
const HATCHING: f32 = 1.0;
|
||||
|
||||
pub struct GfxCtx<'a> {
|
||||
pub(crate) target: &'a mut glium::Frame,
|
||||
@ -28,6 +33,7 @@ pub struct GfxCtx<'a> {
|
||||
context_menu: &'a ContextMenu,
|
||||
|
||||
pub num_draw_calls: usize,
|
||||
hatching: f32,
|
||||
}
|
||||
|
||||
impl<'a> GfxCtx<'a> {
|
||||
@ -47,7 +53,7 @@ impl<'a> GfxCtx<'a> {
|
||||
|
||||
let uniforms = uniform! {
|
||||
transform: [canvas.cam_x as f32, canvas.cam_y as f32, canvas.cam_zoom as f32],
|
||||
window: [canvas.window_width as f32, canvas.window_height as f32],
|
||||
window: [canvas.window_width as f32, canvas.window_height as f32, NO_HATCHING],
|
||||
};
|
||||
|
||||
GfxCtx {
|
||||
@ -62,6 +68,7 @@ impl<'a> GfxCtx<'a> {
|
||||
screencap_mode,
|
||||
naming_hint: None,
|
||||
context_menu,
|
||||
hatching: NO_HATCHING,
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,21 +82,21 @@ impl<'a> GfxCtx<'a> {
|
||||
|
||||
self.uniforms = uniform! {
|
||||
transform: [cam_x as f32, cam_y as f32, zoom as f32],
|
||||
window: [self.canvas.window_width as f32, self.canvas.window_height as f32],
|
||||
window: [self.canvas.window_width as f32, self.canvas.window_height as f32, self.hatching],
|
||||
};
|
||||
}
|
||||
|
||||
pub fn fork_screenspace(&mut self) {
|
||||
self.uniforms = uniform! {
|
||||
transform: [0.0, 0.0, 1.0],
|
||||
window: [self.canvas.window_width as f32, self.canvas.window_height as f32],
|
||||
window: [self.canvas.window_width as f32, self.canvas.window_height as f32, self.hatching],
|
||||
};
|
||||
}
|
||||
|
||||
pub fn unfork(&mut self) {
|
||||
self.uniforms = uniform! {
|
||||
transform: [self.canvas.cam_x as f32, self.canvas.cam_y as f32, self.canvas.cam_zoom as f32],
|
||||
window: [self.canvas.window_width as f32, self.canvas.window_height as f32],
|
||||
window: [self.canvas.window_width as f32, self.canvas.window_height as f32, self.hatching],
|
||||
};
|
||||
}
|
||||
|
||||
@ -149,6 +156,18 @@ impl<'a> GfxCtx<'a> {
|
||||
self.num_draw_calls += 1;
|
||||
}
|
||||
|
||||
pub fn enable_hatching(&mut self) {
|
||||
assert_eq!(self.hatching, NO_HATCHING);
|
||||
self.hatching = HATCHING;
|
||||
self.unfork();
|
||||
}
|
||||
|
||||
pub fn disable_hatching(&mut self) {
|
||||
assert_eq!(self.hatching, HATCHING);
|
||||
self.hatching = NO_HATCHING;
|
||||
self.unfork();
|
||||
}
|
||||
|
||||
// Canvas stuff.
|
||||
|
||||
// The text box covers up what's beneath and eats the cursor (for get_cursor_in_map_space).
|
||||
|
@ -163,6 +163,21 @@ pub fn run<G: GUI, F: FnOnce(&mut EventCtx) -> G>(
|
||||
);
|
||||
};
|
||||
|
||||
// To quickly iterate on shaders without recompiling...
|
||||
/*let mut vert = String::new();
|
||||
let mut frag = String::new();
|
||||
let (vertex_shader, fragment_shader) = {
|
||||
use std::io::Read;
|
||||
|
||||
let mut f1 = std::fs::File:: open("../ezgui/src/assets/vertex_110.glsl").unwrap();
|
||||
f1.read_to_string(&mut vert).unwrap();
|
||||
|
||||
let mut f2 = std::fs::File:: open("../ezgui/src/assets/fragment_110.glsl").unwrap();
|
||||
f2.read_to_string(&mut frag).unwrap();
|
||||
|
||||
(&vert, &frag)
|
||||
};*/
|
||||
|
||||
let program = glium::Program::new(
|
||||
&display,
|
||||
glium::program::ProgramCreationInput::SourceCode {
|
||||
|
Loading…
Reference in New Issue
Block a user