Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2018-04-05 16:41:17 +0300
committerClément Foucault <foucault.clem@gmail.com>2018-04-05 17:08:46 +0300
commit72bfa849ee9769e899399ac90c0921618ea18004 (patch)
tree376b0c1cfa8b09800e7333c0c67d63176313f67e /source/blender/editors/space_node/drawnode.c
parentc65c4fb77bfac81d1ad1e1883256f682d0c63983 (diff)
UI: Node Editor: Port nodelink drawing to shader based drawing.
Use the new GPU_SHADER_2D_NODELINK and GPU_SHADER_2D_NODELINK_INST to accelerate nodelink drawing. This commit does not include the batching functionnality. So this should not make a lot of difference.
Diffstat (limited to 'source/blender/editors/space_node/drawnode.c')
-rw-r--r--source/blender/editors/space_node/drawnode.c334
1 files changed, 224 insertions, 110 deletions
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index 3c00114579e..8865e7b40f9 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -53,6 +53,7 @@
#include "BIF_glutil.h"
#include "GPU_draw.h"
+#include "GPU_batch.h"
#include "GPU_immediate.h"
#include "GPU_matrix.h"
@@ -3292,11 +3293,10 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode, b
BKE_image_release_ibuf(ima, ibuf, lock);
}
-
-/* if v2d not NULL, it clips and returns 0 if not visible */
-bool node_link_bezier_points(View2D *v2d, SpaceNode *snode, bNodeLink *link, float coord_array[][2], int resol)
+/* return quadratic beziers points for a given nodelink and clip if v2d is not NULL. */
+static bool node_link_bezier_handles(View2D *v2d, SpaceNode *snode, bNodeLink *link, float vec[4][2])
{
- float dist, vec[4][2];
+ float dist;
float deltax, deltay;
float cursor[2] = {0.0f, 0.0f};
int toreroute, fromreroute;
@@ -3364,13 +3364,23 @@ bool node_link_bezier_points(View2D *v2d, SpaceNode *snode, bNodeLink *link, flo
vec[2][0] = vec[3][0] - dist;
vec[2][1] = vec[3][1];
}
+
if (v2d && min_ffff(vec[0][0], vec[1][0], vec[2][0], vec[3][0]) > v2d->cur.xmax) {
- /* clipped */
+ return 0; /* clipped */
}
else if (v2d && max_ffff(vec[0][0], vec[1][0], vec[2][0], vec[3][0]) < v2d->cur.xmin) {
- /* clipped */
+ return 0; /* clipped */
}
- else {
+
+ return 1;
+}
+
+/* if v2d not NULL, it clips and returns 0 if not visible */
+bool node_link_bezier_points(View2D *v2d, SpaceNode *snode, bNodeLink *link, float coord_array[][2], int resol)
+{
+ float vec[4][2];
+
+ if (node_link_bezier_handles(v2d, snode, link, vec)) {
/* always do all three, to prevent data hanging around */
BKE_curve_forward_diff_bezier(vec[0][0], vec[1][0], vec[2][0], vec[3][0],
coord_array[0] + 0, resol, sizeof(float) * 2);
@@ -3382,135 +3392,241 @@ bool node_link_bezier_points(View2D *v2d, SpaceNode *snode, bNodeLink *link, flo
return 0;
}
+#define NODELINK_GROUP_SIZE 256
#define LINK_RESOL 24
-#define LINK_ARROW 12 /* position of arrow on the link, LINK_RESOL/2 */
-#define ARROW_SIZE (7 * UI_DPI_FAC)
-void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link,
- int th_col1, bool do_shaded, int th_col2, bool do_triple, int th_col3)
-{
- float coord_array[LINK_RESOL + 1][2];
-
- if (node_link_bezier_points(v2d, snode, link, coord_array, LINK_RESOL)) {
- float dist, spline_step = 0.0f;
- int i;
- int drawarrow;
- /* store current linewidth */
- float linew;
- float arrow[2], arrow1[2], arrow2[2];
- glGetFloatv(GL_LINE_WIDTH, &linew);
- unsigned int pos;
-
- /* we can reuse the dist variable here to increment the GL curve eval amount*/
- dist = 1.0f / (float)LINK_RESOL;
-
- glEnable(GL_LINE_SMOOTH);
-
- drawarrow = ((link->tonode && (link->tonode->type == NODE_REROUTE)) &&
- (link->fromnode && (link->fromnode->type == NODE_REROUTE)));
-
- if (drawarrow) {
- /* draw arrow in line segment LINK_ARROW */
- float d_xy[2], len;
-
- sub_v2_v2v2(d_xy, coord_array[LINK_ARROW], coord_array[LINK_ARROW - 1]);
- len = len_v2(d_xy);
- mul_v2_fl(d_xy, ARROW_SIZE / len);
- arrow1[0] = coord_array[LINK_ARROW][0] - d_xy[0] + d_xy[1];
- arrow1[1] = coord_array[LINK_ARROW][1] - d_xy[1] - d_xy[0];
- arrow2[0] = coord_array[LINK_ARROW][0] - d_xy[0] - d_xy[1];
- arrow2[1] = coord_array[LINK_ARROW][1] - d_xy[1] + d_xy[0];
- arrow[0] = coord_array[LINK_ARROW][0];
- arrow[1] = coord_array[LINK_ARROW][1];
+#define LINK_WIDTH 2.5f
+// #define ARROW_SIZE (7 * UI_DPI_FAC)
+#define ARROW_SIZE 7
+
+static float arrow_verts[3][2] = {{-ARROW_SIZE, ARROW_SIZE}, {0.0f, 0.0f}, {-ARROW_SIZE, -ARROW_SIZE}};
+static float arrow_expand_axis[3][2] = {{0.7071f, 0.7071f}, {M_SQRT2, 0.0f}, {0.7071f, -0.7071f}};
+
+struct {
+ Gwn_Batch *batch; /* for batching line together */
+ Gwn_Batch *batch_single; /* for single line */
+ Gwn_VertBuf *inst_vbo;
+ unsigned int p0_id, p1_id, p2_id, p3_id;
+ unsigned int colid_id;
+ Gwn_VertBufRaw p0_step, p1_step, p2_step, p3_step;
+ Gwn_VertBufRaw colid_step;
+ unsigned int count;
+ bool enabled;
+} g_batch_link = {0};
+
+static void nodelink_batch_reset(void)
+{
+ GWN_vertbuf_attr_get_raw_data(g_batch_link.inst_vbo, g_batch_link.p0_id, &g_batch_link.p0_step);
+ GWN_vertbuf_attr_get_raw_data(g_batch_link.inst_vbo, g_batch_link.p1_id, &g_batch_link.p1_step);
+ GWN_vertbuf_attr_get_raw_data(g_batch_link.inst_vbo, g_batch_link.p2_id, &g_batch_link.p2_step);
+ GWN_vertbuf_attr_get_raw_data(g_batch_link.inst_vbo, g_batch_link.p3_id, &g_batch_link.p3_step);
+ GWN_vertbuf_attr_get_raw_data(g_batch_link.inst_vbo, g_batch_link.colid_id, &g_batch_link.colid_step);
+ g_batch_link.count = 0;
+}
+
+static void set_nodelink_vertex(
+ Gwn_VertBuf *vbo,
+ unsigned int uv_id, unsigned int pos_id, unsigned int exp_id, unsigned int v,
+ const unsigned char uv[2], const float pos[2], const float exp[2])
+{
+ GWN_vertbuf_attr_set(vbo, uv_id, v, uv);
+ GWN_vertbuf_attr_set(vbo, pos_id, v, pos);
+ GWN_vertbuf_attr_set(vbo, exp_id, v, exp);
+}
+
+static void nodelink_batch_init(void)
+{
+ Gwn_VertFormat format = {0};
+ unsigned int uv_id = GWN_vertformat_attr_add(&format, "uv", GWN_COMP_U8, 2, GWN_FETCH_INT_TO_FLOAT_UNIT);
+ unsigned int pos_id = GWN_vertformat_attr_add(&format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ unsigned int expand_id = GWN_vertformat_attr_add(&format, "expand", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format_ex(&format, GWN_USAGE_STATIC);
+ int vcount = LINK_RESOL * 2; /* curve */
+ vcount += 2; /* restart strip */
+ vcount += 3*2; /* arrow */
+ vcount *= 2; /* shadow */
+ vcount += 2; /* restart strip */
+ GWN_vertbuf_data_alloc(vbo, vcount);
+ int v = 0;
+
+ for (int k = 0; k < 2; ++k) {
+ unsigned char uv[2] = {0, 0};
+ float pos[2] = {0.0f, 0.0f};
+ float exp[2] = {0.0f, 1.0f};
+
+ /* restart */
+ if (k == 1)
+ set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
+
+ /* curve strip */
+ for (int i = 0; i < LINK_RESOL; ++i) {
+ uv[0] = 255 * (i / (float)(LINK_RESOL-1));
+ uv[1] = 0;
+ set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
+ uv[1] = 255;
+ set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
}
-
- if (do_triple || drawarrow || (!do_shaded)) {
- pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+ /* restart */
+ set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
+
+ uv[0] = 127;
+ uv[1] = 0;
+ copy_v2_v2(pos, arrow_verts[0]);
+ copy_v2_v2(exp, arrow_expand_axis[0]);
+ set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
+ /* arrow */
+ for (int i = 0; i < 3; ++i) {
+ uv[1] = 0;
+ copy_v2_v2(pos, arrow_verts[i]);
+ copy_v2_v2(exp, arrow_expand_axis[i]);
+ set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
+
+ uv[1] = 255;
+ set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
}
- if (do_triple) {
- immUniformThemeColorShadeAlpha(th_col3, -80, -120);
- glLineWidth(4.0f);
+ /* restart */
+ if (k == 0)
+ set_nodelink_vertex(vbo, uv_id, pos_id, expand_id, v++, uv, pos, exp);
+ }
- immBegin(GWN_PRIM_LINE_STRIP, (LINK_RESOL + 1));
+ g_batch_link.batch = GWN_batch_create_ex(GWN_PRIM_TRI_STRIP, vbo, NULL, GWN_BATCH_OWNS_VBO);
+ gpu_batch_presets_register(g_batch_link.batch);
- for (i = 0; i <= LINK_RESOL; i++) {
- immVertex2fv(pos, coord_array[i]);
- }
+ g_batch_link.batch_single = GWN_batch_create_ex(GWN_PRIM_TRI_STRIP, vbo, NULL, 0);
+ gpu_batch_presets_register(g_batch_link.batch_single);
- immEnd();
+ /* Instances data */
+ Gwn_VertFormat format_inst = {0};
+ g_batch_link.p0_id = GWN_vertformat_attr_add(&format_inst, "P0", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ g_batch_link.p1_id = GWN_vertformat_attr_add(&format_inst, "P1", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ g_batch_link.p2_id = GWN_vertformat_attr_add(&format_inst, "P2", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ g_batch_link.p3_id = GWN_vertformat_attr_add(&format_inst, "P3", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+ g_batch_link.colid_id = GWN_vertformat_attr_add(&format_inst, "colid_doarrow", GWN_COMP_U8, 4, GWN_FETCH_INT);
+ g_batch_link.inst_vbo = GWN_vertbuf_create_with_format_ex(&format_inst, GWN_USAGE_STREAM);
+ GWN_vertbuf_data_alloc(g_batch_link.inst_vbo, NODELINK_GROUP_SIZE); /* Alloc max count but only draw the range we need. */
- if (drawarrow) {
- immBegin(GWN_PRIM_LINE_STRIP, 3);
- immVertex2fv(pos, arrow1);
- immVertex2fv(pos, arrow);
- immVertex2fv(pos, arrow2);
- immEnd();
- }
- }
+ GWN_batch_instbuf_set(g_batch_link.batch, g_batch_link.inst_vbo, true);
- glLineWidth(1.5f);
+ nodelink_batch_reset();
+}
- if (drawarrow) {
- immUniformThemeColorBlend(th_col1, th_col2, 0.5f);
+static char nodelink_get_color_id(int th_col)
+{
+ switch (th_col) {
+ case TH_WIRE: return 1;
+ case TH_WIRE_INNER: return 2;
+ case TH_ACTIVE: return 3;
+ case TH_EDGE_SELECT: return 4;
+ case TH_REDALERT: return 5;
+ }
+ return 0;
+}
- immBegin(GWN_PRIM_LINE_STRIP, 3);
- immVertex2fv(pos, arrow1);
- immVertex2fv(pos, arrow);
- immVertex2fv(pos, arrow2);
- immEnd();
- }
+static void nodelink_batch_draw(SpaceNode *snode)
+{
+ if (g_batch_link.count == 0)
+ return;
- if (!do_shaded) {
- immUniformThemeColor(th_col1);
+ glEnable(GL_BLEND);
- immBegin(GWN_PRIM_LINE_STRIP, (LINK_RESOL + 1));
+ float colors[6][4] = {{0.0f}};
+ UI_GetThemeColor4fv(TH_WIRE_INNER, colors[nodelink_get_color_id(TH_WIRE_INNER)]);
+ UI_GetThemeColor4fv(TH_WIRE, colors[nodelink_get_color_id(TH_WIRE)]);
+ UI_GetThemeColor4fv(TH_ACTIVE, colors[nodelink_get_color_id(TH_ACTIVE)]);
+ UI_GetThemeColor4fv(TH_EDGE_SELECT, colors[nodelink_get_color_id(TH_EDGE_SELECT)]);
+ UI_GetThemeColor4fv(TH_REDALERT, colors[nodelink_get_color_id(TH_REDALERT)]);
- for (i = 0; i <= LINK_RESOL; i++) {
- immVertex2fv(pos, coord_array[i]);
- }
+ GWN_vertbuf_vertex_count_set(g_batch_link.inst_vbo, g_batch_link.count);
+ GWN_vertbuf_use(g_batch_link.inst_vbo); /* force update. */
- immEnd();
- }
+ GWN_batch_program_set_builtin(g_batch_link.batch, GPU_SHADER_2D_NODELINK_INST);
+ GWN_batch_uniform_4fv_array(g_batch_link.batch, "colors", 6, (float *)colors);
+ GWN_batch_uniform_1f(g_batch_link.batch, "expandSize", snode->aspect * LINK_WIDTH);
+ GWN_batch_draw(g_batch_link.batch);
- if (do_triple || drawarrow || (!do_shaded)) {
- immUnbindProgram();
- }
+ nodelink_batch_reset();
- if (do_shaded) {
- unsigned char col[3];
+ glDisable(GL_BLEND);
+}
- Gwn_VertFormat *format = immVertexFormat();
- pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
- unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_U8, 3, GWN_FETCH_INT_TO_FLOAT_UNIT);
+void nodelink_batch_start(SpaceNode *UNUSED(snode))
+{
+ g_batch_link.enabled = true;
+}
- immBindBuiltinProgram(GPU_SHADER_2D_SMOOTH_COLOR);
+void nodelink_batch_end(SpaceNode *snode)
+{
+ nodelink_batch_draw(snode);
+ g_batch_link.enabled = false;
+}
- immBegin(GWN_PRIM_LINE_STRIP, (LINK_RESOL + 1));
+static void nodelink_batch_add_link(
+ SpaceNode *snode,
+ const float p0[2], const float p1[2], const float p2[2], const float p3[2],
+ int th_col1, int th_col2, int th_col3, bool drawarrow)
+{
+ /* Only allow these colors. If more is needed, you need to modify the shader accordingly. */
+ BLI_assert(ELEM(th_col1, TH_WIRE_INNER, TH_WIRE, TH_ACTIVE, TH_EDGE_SELECT, TH_REDALERT));
+ BLI_assert(ELEM(th_col2, TH_WIRE_INNER, TH_WIRE, TH_ACTIVE, TH_EDGE_SELECT, TH_REDALERT));
+ BLI_assert(ELEM(th_col3, TH_WIRE, -1));
- for (i = 0; i <= LINK_RESOL; i++) {
- UI_GetThemeColorBlend3ubv(th_col1, th_col2, spline_step, col);
- immAttrib3ubv(color, col);
+ g_batch_link.count++;
+ copy_v2_v2(GWN_vertbuf_raw_step(&g_batch_link.p0_step), p0);
+ copy_v2_v2(GWN_vertbuf_raw_step(&g_batch_link.p1_step), p1);
+ copy_v2_v2(GWN_vertbuf_raw_step(&g_batch_link.p2_step), p2);
+ copy_v2_v2(GWN_vertbuf_raw_step(&g_batch_link.p3_step), p3);
+ char *colid = GWN_vertbuf_raw_step(&g_batch_link.colid_step);
+ colid[0] = nodelink_get_color_id(th_col1);
+ colid[1] = nodelink_get_color_id(th_col2);
+ colid[2] = nodelink_get_color_id(th_col3);
+ colid[3] = drawarrow;
- immVertex2fv(pos, coord_array[i]);
+ if (g_batch_link.count == NODELINK_GROUP_SIZE) {
+ nodelink_batch_draw(snode);
+ }
+}
- spline_step += dist;
- }
+/* don't do shadows if th_col3 is -1. */
+void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link,
+ int th_col1, int th_col2, int th_col3)
+{
+ float vec[4][2];
- immEnd();
+ if (node_link_bezier_handles(v2d, snode, link, vec)) {
+ int drawarrow = ((link->tonode && (link->tonode->type == NODE_REROUTE)) &&
+ (link->fromnode && (link->fromnode->type == NODE_REROUTE)));
- immUnbindProgram();
+ if (g_batch_link.batch == NULL) {
+ nodelink_batch_init();
+ }
+
+ if (g_batch_link.enabled) {
+ /* Add link to batch. */
+ nodelink_batch_add_link(snode, vec[0], vec[1], vec[2], vec[3], th_col1, th_col2, th_col3, drawarrow);
+ }
+ else {
+ /* Draw single link. */
+ float colors[3][4] = {{0.0f}};
+ if (th_col3 != -1) {
+ UI_GetThemeColor4fv(th_col3, colors[0]);
+ }
+ UI_GetThemeColor4fv(th_col1, colors[1]);
+ UI_GetThemeColor4fv(th_col2, colors[2]);
+
+ Gwn_Batch *batch = g_batch_link.batch_single;
+ GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_NODELINK);
+ GWN_batch_uniform_2fv_array(batch, "bezierPts", 4, (float *)vec);
+ GWN_batch_uniform_4fv_array(batch, "colors", 3, (float *)colors);
+ GWN_batch_uniform_1f(batch, "expandSize", snode->aspect * LINK_WIDTH);
+ GWN_batch_uniform_1i(batch, "doArrow", drawarrow);
+ GWN_batch_draw(batch);
}
-
- glDisable(GL_LINE_SMOOTH);
}
}
/* note; this is used for fake links in groups too */
void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link)
{
- bool do_shaded = false;
- bool do_triple = false;
int th_col1 = TH_WIRE_INNER, th_col2 = TH_WIRE_INNER, th_col3 = TH_WIRE;
if (link->fromsock == NULL && link->tosock == NULL)
@@ -3518,8 +3634,7 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link)
/* new connection */
if (!link->fromsock || !link->tosock) {
- th_col1 = TH_ACTIVE;
- do_triple = true;
+ th_col1 = th_col2 = TH_ACTIVE;
}
else {
/* going to give issues once... */
@@ -3540,15 +3655,14 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link)
if (link->tonode && link->tonode->flag & SELECT)
th_col2 = TH_EDGE_SELECT;
}
- do_shaded = true;
- do_triple = true;
}
else {
- th_col1 = TH_REDALERT;
+ th_col1 = th_col2 = TH_REDALERT;
+ // th_col3 = -1; /* no shadow */
}
}
- node_draw_link_bezier(v2d, snode, link, th_col1, do_shaded, th_col2, do_triple, th_col3);
+ node_draw_link_bezier(v2d, snode, link, th_col1, th_col2, th_col3);
// node_draw_link_straight(v2d, snode, link, th_col1, do_shaded, th_col2, do_triple, th_col3);
}