@bokeh/bokehjs
Version:
Interactive, novel data visualization
223 lines (191 loc) • 6.07 kB
JavaScript
const shader = `
precision mediump float;
attribute vec2 a_position;
attribute vec2 a_center;
attribute float a_width; // or radius or outer_radius
attribute float a_height; // or inner_radius
attribute float a_angle; // or start_angle
attribute float a_aux; // or end_angle
attribute float a_linewidth;
attribute vec4 a_line_color;
attribute vec4 a_fill_color;
attribute float a_line_cap;
attribute float a_line_join;
attribute float a_show;
attribute float a_hatch_pattern;
attribute float a_hatch_scale;
attribute float a_hatch_weight;
attribute vec4 a_hatch_color;
uniform vec2 u_canvas_size;
uniform float u_antialias;
uniform float u_size_hint;
uniform vec4 u_border_radius;
varying vec4 v_border_radius;
varying float v_outer_radius;
varying float v_inner_radius;
varying float v_start_angle;
varying float v_end_angle;
varying float v_outer_radius;
varying float v_inner_radius;
varying float v_radius;
varying float v_start_angle;
varying float v_end_angle;
varying float v_radius;
varying float v_n;
varying float v_linewidth;
varying vec2 v_size; // 2D size for rects compared to 1D for markers.
varying vec4 v_line_color;
varying vec4 v_fill_color;
varying float v_line_cap;
varying float v_line_join;
varying vec2 v_coords;
varying float v_hatch_pattern;
varying float v_hatch_scale;
varying float v_hatch_weight;
varying vec4 v_hatch_color;
varying vec2 v_hatch_coords;
vec2 enclosing_size() {
// Need extra size of (v_linewidth+u_antialias) if edge of marker parallel to
// edge of bounding box. If symmetric spike towards edge then multiply by
// 1/cos(theta) where theta is angle between spike and bbox edges.
int size_hint = int(u_size_hint + 0.5);
if (size_hint == M_DASH)
return vec2(v_size.x + v_linewidth + u_antialias,
v_linewidth + u_antialias);
else if (size_hint == M_DOT)
return 0.25*v_size + u_antialias;
else if (size_hint == M_DIAMOND)
return vec2(v_size.x*(2.0/3.0) + (v_linewidth + u_antialias)*1.20185,
v_size.y + (v_linewidth + u_antialias)*1.80278);
else if (size_hint == M_HEX)
return v_size + (v_linewidth + u_antialias)*vec2(2.0/sqrt(3.0), 1.0);
else if (size_hint == M_SQUARE_PIN) // Square pin
return v_size + (v_linewidth + u_antialias)*3.1;
else if (size_hint == M_TRIANGLE)
return vec2(v_size.x + (v_linewidth + u_antialias)*sqrt(3.0),
v_size.y*(2.0/sqrt(3.0)) + (v_linewidth + u_antialias)*2.0);
else if (size_hint == M_TRIANGLE_PIN)
return v_size + (v_linewidth + u_antialias)*vec2(4.8, 6.0);
else if (size_hint == M_STAR)
return vec2(v_size.x*0.95106 + (v_linewidth + u_antialias)*3.0,
v_size.y + (v_linewidth + u_antialias)*3.2);
else
return v_size + v_linewidth + u_antialias;
}
vec2 enclosing_size() {
return v_size + v_linewidth + u_antialias;
}
void main()
{
v_size = vec2(a_width, a_height);
v_size = vec2(2.0*a_width, 2.0*a_width);
v_size = vec2(a_width, a_width);
v_n = a_aux;
if (a_show < 0.5 || v_size.x < 0.0 || v_size.y < 0.0 || (v_size.x == 0.0 && v_size.y == 0.0)
|| v_n < 3.0
) {
// Do not show this marker.
gl_Position = vec4(-2.0, -2.0, 0.0, 1.0);
return;
}
v_outer_radius = a_width;
v_inner_radius = a_height;
v_start_angle = a_angle;
v_end_angle = a_aux;
v_outer_radius = a_width;
v_inner_radius = a_height;
v_radius = a_width;
v_start_angle = a_angle;
v_end_angle = a_aux;
v_radius = 0.5*a_width;
// Scale corner radii if they are too large, the same as canvas
// https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-roundrect
// Order of border_radius is top_left, top_right, bottom_right, bottom_left
const vec2 unit2 = vec2(1.0, 1.0);
float scale = min(v_size.x / max(dot(u_border_radius.xy, unit2), dot(u_border_radius.zw, unit2)),
v_size.y / max(dot(u_border_radius.yz, unit2), dot(u_border_radius.wx, unit2)));
v_border_radius = u_border_radius*min(scale, 1.0);
v_linewidth = a_linewidth;
v_line_color = a_line_color;
v_fill_color = a_fill_color;
v_line_cap = a_line_cap;
v_line_join = a_line_join;
if (v_linewidth < 1.0) {
// Linewidth less than 1 is implemented as 1 but with reduced alpha.
v_line_color.a *= v_linewidth;
v_linewidth = 1.0;
}
v_hatch_pattern = a_hatch_pattern;
v_hatch_scale = a_hatch_scale;
v_hatch_weight = a_hatch_weight;
v_hatch_color = a_hatch_color;
// Coordinates in rotated frame with respect to center of marker, used for
// distance functions in fragment shader.
v_coords = a_position*enclosing_size();
vec2 pos = a_center + v_coords;
float c = cos(-a_angle);
float s = sin(-a_angle);
mat2 rotation = mat2(c, -s, s, c);
vec2 pos = a_center + rotation*v_coords;
// Coordinates for hatching in unrotated frame of reference.
v_hatch_coords = pos - 0.5;
pos += 0.5; // Make up for Bokeh's offset.
pos /= u_canvas_size; // 0 to 1.
gl_Position = vec4(2.0*pos.x - 1.0, 1.0 - 2.0*pos.y, 0.0, 1.0);
}
`;
export default shader;