UNPKG

@bokeh/bokehjs

Version:

Interactive, novel data visualization

17 lines (16 loc) 5.44 kB
const shader = ` precision mediump float;const int butt_cap=0;const int round_cap=1;const int square_cap=2;const int miter_join=0;const int round_join=1;const int bevel_join=2;attribute vec2 a_position;attribute vec2 a_point_prev;attribute vec2 a_point_start;attribute vec2 a_point_end;attribute vec2 a_point_next;attribute float a_show_prev;attribute float a_show_curr;attribute float a_show_next;attribute float a_linewidth;attribute vec4 a_line_color;attribute float a_line_cap;attribute float a_line_join; #ifdef DASHED attribute float a_length_so_far;attribute vec4 a_dash_tex_info;attribute float a_dash_scale;attribute float a_dash_offset; #endif uniform vec2 u_canvas_size;uniform float u_antialias;uniform float u_miter_limit;varying float v_linewidth;varying vec4 v_line_color;varying float v_line_cap;varying float v_line_join;varying float v_segment_length;varying vec2 v_coords;varying float v_flags;varying float v_cos_turn_angle_start;varying float v_cos_turn_angle_end; #ifdef DASHED varying float v_length_so_far;varying vec4 v_dash_tex_info;varying float v_dash_scale;varying float v_dash_offset; #endif #define SMALL 1e-6 float cross_z(in vec2 v0,in vec2 v1){return v0.x*v1.y-v0.y*v1.x;}vec2 right_vector(in vec2 v){return vec2(v.y,-v.x);}float calc_turn_angle(in bool has_cap,in vec2 segment_right,in vec2 other_right,out vec2 point_right,out float sin_turn_angle){float cos_turn_angle;vec2 diff=segment_right+other_right;float len=length(diff);if(has_cap||len<SMALL){point_right=segment_right;cos_turn_angle=-1.;sin_turn_angle=0.;}else{point_right=diff/len;cos_turn_angle=dot(segment_right,other_right);sin_turn_angle=cross_z(segment_right,other_right);}return cos_turn_angle;}bool miter_too_large(in int join_type,in float cos_turn_angle){float cos_half_angle_sqr=0.5*(1.+cos_turn_angle);return join_type==miter_join&&cos_half_angle_sqr<1./(u_miter_limit*u_miter_limit);}vec2 normalize_check_len(in vec2 vec,in float len){if(abs(len)<SMALL)return vec2(1.,0.);else return vec/len;}vec2 normalize_check(in vec2 vec){return normalize_check_len(vec,length(vec));}void main(){if(a_show_curr<0.5){gl_Position=vec4(-2.,-2.,0.,1.);return;}int join_type=int(a_line_join+0.5);int cap_type=int(a_line_cap+0.5);v_linewidth=a_linewidth;v_line_color=a_line_color;if(v_linewidth<1.){v_line_color.a*=v_linewidth;v_linewidth=1.;}float halfwidth=0.5*(v_linewidth+u_antialias);vec2 segment_along=a_point_end-a_point_start;v_segment_length=length(a_point_end-a_point_start);segment_along=normalize_check_len(segment_along,v_segment_length);vec2 segment_right=right_vector(segment_along);vec2 xy;vec2 prev_along=normalize_check(a_point_start-a_point_prev);vec2 prev_right=right_vector(prev_along);vec2 next_right=right_vector(normalize_check(a_point_next-a_point_end));v_coords.y=a_position.y*halfwidth;bool has_start_cap=a_show_prev<0.5;bool has_end_cap=a_show_next<0.5;vec2 point_right_start,point_right_end;float sin_turn_angle_start,sin_turn_angle_end;v_cos_turn_angle_start=calc_turn_angle(has_start_cap,segment_right,prev_right,point_right_start,sin_turn_angle_start);v_cos_turn_angle_end=calc_turn_angle(has_end_cap,segment_right,next_right,point_right_end,sin_turn_angle_end);float sign_turn_right_start=sin_turn_angle_start>=0.?1.:-1.;bool miter_too_large_start=!has_start_cap&&miter_too_large(join_type,v_cos_turn_angle_start);bool miter_too_large_end=!has_end_cap&&miter_too_large(join_type,v_cos_turn_angle_end);float sign_at_start=-sign(a_position.x);vec2 point=sign_at_start>0.?a_point_start:a_point_end;if((has_start_cap&&sign_at_start>0.)||(has_end_cap&&sign_at_start<0.)){xy=point-segment_right*(halfwidth*a_position.y);if(cap_type==butt_cap)xy-=sign_at_start*0.5*u_antialias*segment_along;else xy-=sign_at_start*halfwidth*segment_along;}else if(sign_at_start>0.){vec2 inside_point=a_point_start+segment_right*(sign_turn_right_start*halfwidth);vec2 prev_outside_point=a_point_start-prev_right*(sign_turn_right_start*halfwidth);if(join_type==round_join||join_type==bevel_join||miter_too_large_start){if(v_cos_turn_angle_start<=0.){xy=a_point_start-segment_right*(halfwidth*a_position.y)-halfwidth*segment_along;}else{if(a_position.x<-1.5){xy=prev_outside_point;v_coords.y=-dot(xy-a_point_start,segment_right);}else if(a_position.y*sign_turn_right_start>0.){float d=halfwidth*abs(sin_turn_angle_start);xy=a_point_start-segment_right*(halfwidth*a_position.y)-d*segment_along;}else{xy=inside_point;}}}else{if(a_position.x<-1.5){xy=prev_outside_point;v_coords.y=-dot(xy-a_point_start,segment_right);}else if(a_position.y*sign_turn_right_start>0.){float tan_half_turn_angle=(1.-v_cos_turn_angle_start)/sin_turn_angle_start;float d=sign_turn_right_start*halfwidth*tan_half_turn_angle;xy=a_point_start-segment_right*(halfwidth*a_position.y)-d*segment_along;}else{xy=inside_point;}}}else{xy=point-segment_right*(halfwidth*a_position.y);}vec2 pos=xy+0.5;pos/=u_canvas_size;gl_Position=vec4(2.*pos.x-1.,1.-2.*pos.y,0.,1.);bool turn_right_start=sin_turn_angle_start>=0.;bool turn_right_end=sin_turn_angle_end>=0.;v_coords.x=dot(xy-a_point_start,segment_along);v_flags=float(int(has_start_cap)+2*int(has_end_cap)+4*int(miter_too_large_start)+8*int(miter_too_large_end)+16*int(turn_right_start)+32*int(turn_right_end));v_line_cap=a_line_cap;v_line_join=a_line_join; #ifdef DASHED v_length_so_far=a_length_so_far;v_dash_tex_info=a_dash_tex_info;v_dash_scale=a_dash_scale;v_dash_offset=a_dash_offset; #endif }`; export default shader;