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; | |||||
| 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) | |||||
| { | |||||
| for( int i = 0; i < len; i++ ) | |||||
| { | |||||
| for (int j = -1; j <= 1; j += 2){ | |||||
| texCoord = float(j) / 2. + 0.5; | |||||
| geomColor = mix(vertColor[0], vertColor[1], smoothstep(0.0, 1.0, float(i)/float(SUB-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], in vec2 coo_1, in vec2 coo_2) | |||||
| { | |||||
| vec2 d_xy; | |||||
| float len; | |||||
| 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 = normalize(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]) | |||||
| { | |||||
| vec2 b[4]; | |||||
| 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(SUB - 1); | |||||
| v_a[0].pos = b[0].xy; | |||||
| for( int i = 1; i < SUB; i++ ) | |||||
| { | |||||
| float t = i * OneOverDetail; | |||||
| v_a[i].pos = evaluateBezierPosition( b, t ); | |||||
| v_a[i].norm = calc_normal(v_a[i-1].pos, v_a[i].pos); | |||||
| } | |||||
| v_a[0].norm = v_a[1].norm; | |||||
| for( int i = 1; i < SUB - 1; i++ ) | |||||
| { | |||||
| v_a[i].norm = normalize(v_a[i-1].norm + v_a[i+1].norm); | |||||
| } | |||||
| } | |||||
| void main() | |||||
| { | |||||
| Vertex vertex_array[SUB]; | |||||
| make_bezier_vertex_array(vertex_array); | |||||
| draw_line(vertex_array, SUB, line_width); | |||||
| if (drawarrow == 1) { | |||||
| make_arrow_vertex_array(vertex_array, vertex_array[int(SUB/2)].pos.xy, vertex_array[int(SUB/2) -1].pos.xy); | |||||
| draw_line(vertex_array, 3, line_width); | |||||
| } | |||||
| } | |||||