Changeset View
Changeset View
Standalone View
Standalone View
source/blender/gpu/shaders/gpu_shader_2D_bezier_curve_geom.glsl
- This file was added.
| #define SUB 30 | |||||
| #define ARROW_SIZE 7 | |||||
| uniform int drawarrow = 0, straigh_line = 0; | |||||
| uniform float line_width = 1., triple_width = 0., scale = 1.; | |||||
| uniform mat4 ModelViewProjectionMatrix; | |||||
| layout(lines) in; | |||||
| noperspective in vec4 vertColor[]; | |||||
| in vec2 vert_pos_handle[]; | |||||
| out float texCoord; | |||||
| out vec4 geomColor; | |||||
| layout(triangle_strip, max_vertices = 66) out; // 30 * 2 for bezier curve and 6 for arrow | |||||
| struct Vertex { | |||||
| vec2 pos; | |||||
| vec2 norm; | |||||
| }; | |||||
| vec2 calc_normal(in vec2 a, in vec2 b) | |||||
| { | |||||
| vec2 dxy = b - a; | |||||
| return normalize(vec2(-dxy.y, dxy.x)); | |||||
| } | |||||
| void draw_line(in Vertex p[SUB], int len, float width, int da) | |||||
| { | |||||
| for( int i = 0; i < len; i++ ) | |||||
| { | |||||
| for (int j = -1; j <= 1; j += 2){ | |||||
| texCoord = float(j) / 2. + 0.5; | |||||
| if (da == 1) | |||||
| geomColor = max(vertColor[0], vertColor[1]); | |||||
| else | |||||
| geomColor = mix(vertColor[0], vertColor[1], smoothstep(0.0, 1.0, float(i)/float(len-1))); | |||||
| gl_Position = ModelViewProjectionMatrix | |||||
| * vec4(p[i].pos + j * (width + (clamp(triple_width, width, triple_width) - width)) / 2 | |||||
| * p[i].norm / scale, 0.0, 1.0); | |||||
| EmitVertex(); | |||||
| } | |||||
| } | |||||
| EndPrimitive(); | |||||
| } | |||||
| void make_arrow_vertex_array(inout Vertex arrows[SUB], int resol) | |||||
| { | |||||
| vec2 d_xy, coo_1, coo_2; | |||||
| float len; | |||||
| if (resol > 2) | |||||
| { | |||||
| coo_1 = arrows[int(resol/2)].pos.xy; | |||||
| coo_2 = arrows[int(resol/2) -1].pos.xy; | |||||
| } | |||||
| else | |||||
| { | |||||
| coo_1 = arrows[0].pos.xy + vec2(arrows[1].pos.xy - arrows[0].pos.xy) / 2; | |||||
| coo_2 = arrows[0].pos.xy; | |||||
| } | |||||
| d_xy = coo_1 - coo_2; | |||||
| len = length(d_xy); | |||||
| d_xy *= ARROW_SIZE / len; | |||||
| arrows[0].pos.x = coo_1.x - d_xy.x + d_xy.y; | |||||
| arrows[0].pos.y = coo_1.y - d_xy.x - d_xy.y; | |||||
| arrows[1].pos = coo_1; | |||||
| arrows[2].pos.x = coo_1.x - d_xy.x - d_xy.y; | |||||
| arrows[2].pos.y = coo_1.y + d_xy.x - d_xy.y; | |||||
| arrows[0].norm = calc_normal(arrows[0].pos, arrows[1].pos); | |||||
| arrows[2].norm = calc_normal(arrows[1].pos, arrows[2].pos); | |||||
| arrows[1].norm = arrows[0].norm + arrows[2].norm; | |||||
| } | |||||
| vec2 evaluateBezierPosition( vec2 v[4], float t ) | |||||
| { | |||||
| float OneMinusT = 1.0 - t; | |||||
| float b0 = OneMinusT*OneMinusT*OneMinusT; | |||||
| float b1 = 3.0*t*OneMinusT*OneMinusT; | |||||
| float b2 = 3.0*t*t*OneMinusT; | |||||
| float b3 = t*t*t; | |||||
| return b0*v[0] + b1*v[1] + b2*v[2] + b3*v[3]; | |||||
| } | |||||
| void make_bezier_vertex_array(inout Vertex v_a[SUB], int resol) | |||||
| { | |||||
| vec2 b[4]; | |||||
| Vertex tmp_v_a[SUB]; | |||||
| b[0] = gl_in[0].gl_Position.xy; | |||||
| b[1] = vert_pos_handle[0].xy; | |||||
| b[2] = vert_pos_handle[1].xy; | |||||
| b[3] = gl_in[1].gl_Position.xy; | |||||
| float OneOverDetail = 1.0 / float(resol - 1); | |||||
| v_a[0].pos = b[0].xy; | |||||
| for( int i = 1; i < resol; i++ ) | |||||
| { | |||||
| float t = i * OneOverDetail; | |||||
| v_a[i].pos = evaluateBezierPosition( b, t ); | |||||
| tmp_v_a[i].norm = calc_normal(v_a[i-1].pos, v_a[i].pos); | |||||
| } | |||||
| tmp_v_a[0].norm = tmp_v_a[1].norm; | |||||
| v_a[0].norm = tmp_v_a[1].norm; | |||||
| if (resol > 2) | |||||
| { | |||||
| for( int i = 1; i < resol - 1; i++ ) | |||||
| { | |||||
| v_a[i].norm = (tmp_v_a[i-1].norm + tmp_v_a[i+1].norm) / 2; | |||||
| } | |||||
| } | |||||
| v_a[resol - 1].norm = tmp_v_a[resol - 1].norm; | |||||
| } | |||||
| int find_resolution() | |||||
| { | |||||
| int resol = int(0.25 * scale * length(gl_in[0].gl_Position.xy - gl_in[1].gl_Position.xy)); | |||||
| if (straigh_line == 1) | |||||
| resol = 2; | |||||
| else | |||||
| resol = clamp(resol, 2, SUB); | |||||
| return resol; | |||||
| } | |||||
| void main() | |||||
| { | |||||
| Vertex vertex_array[SUB]; | |||||
| int resol = find_resolution(); | |||||
| make_bezier_vertex_array(vertex_array, resol); | |||||
| draw_line(vertex_array, resol, line_width, 0); | |||||
| if (drawarrow == 1) { | |||||
| make_arrow_vertex_array(vertex_array, resol); | |||||
| draw_line(vertex_array, 3, line_width, 1); | |||||
| } | |||||
| } | |||||