diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2020-06-22 20:57:53 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2020-06-22 20:57:53 +0300 |
commit | 15dda0115c783805753119984decb4d9249b1f01 (patch) | |
tree | c2d674f83d02edd6eb694c2510dbe1aaff510fe7 /source/blender/editors/interface/interface_widgets.c | |
parent | 3cea42ce29cb986cf9614d9b712d72915d52e546 (diff) |
UI: Widget: Replace geometry by fragment shader drawing
This means all the antiailasing is done inside the fragment shader.
We use a Signed Distance Field to draw the 2D rounded boxes. This ensure
the best quality for AA.
This reduce the averge Batch for widget to 16 verts instead of ~600 and
reduce overshading a lot.
Theme Emboss alpha and tria alpha needs to be changed after this refactor.
The shadow drawing is left unchanged and still use geometry.
Reviewed By: Severin
Differential Revision: https://developer.blender.org/D7833
Diffstat (limited to 'source/blender/editors/interface/interface_widgets.c')
-rw-r--r-- | source/blender/editors/interface/interface_widgets.c | 250 |
1 files changed, 32 insertions, 218 deletions
diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 0498b312618..16a5a13885b 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -393,35 +393,14 @@ static const uint g_shape_preset_hold_action_face[2][3] = {{2, 0, 1}, {3, 5, 4}} * * \{ */ -/* offset in triavec[] in shader per type */ -static const int tria_ofs[ROUNDBOX_TRIA_MAX] = { - [ROUNDBOX_TRIA_NONE] = 0, - [ROUNDBOX_TRIA_ARROWS] = 0, - [ROUNDBOX_TRIA_SCROLL] = 12, - [ROUNDBOX_TRIA_MENU] = 28, - [ROUNDBOX_TRIA_CHECK] = 34, - [ROUNDBOX_TRIA_HOLD_ACTION_ARROW] = 40, -}; -static const int tria_vcount[ROUNDBOX_TRIA_MAX] = { - [ROUNDBOX_TRIA_NONE] = 0, - [ROUNDBOX_TRIA_ARROWS] = 6, - [ROUNDBOX_TRIA_SCROLL] = 16, - [ROUNDBOX_TRIA_MENU] = 6, - [ROUNDBOX_TRIA_CHECK] = 6, - [ROUNDBOX_TRIA_HOLD_ACTION_ARROW] = 3, -}; - static struct { - GPUBatch *roundbox_widget[ROUNDBOX_TRIA_MAX]; - - GPUBatch *roundbox_simple; - GPUBatch *roundbox_simple_aa; - GPUBatch *roundbox_simple_outline; + GPUBatch *roundbox_widget; GPUBatch *roundbox_shadow; + /* TODO remove */ GPUVertFormat format; uint vflag_id; -} g_ui_batch_cache = {{0}}; +} g_ui_batch_cache = {0}; static GPUVertFormat *vflag_format(void) { @@ -436,7 +415,7 @@ static GPUVertFormat *vflag_format(void) #define INNER 0 #define OUTLINE 1 #define EMBOSS 2 -#define NO_AA WIDGET_AA_JITTER +#define NO_AA 0 static void set_roundbox_vertex_data(GPUVertBufRaw *vflag_step, uint32_t d) { @@ -462,176 +441,30 @@ static uint32_t set_roundbox_vertex(GPUVertBufRaw *vflag_step, return *data; } -static uint32_t set_tria_vertex( - GPUVertBufRaw *vflag_step, int tria_type, int tria_v, int tria_id, int jit_v) -{ - uint32_t *data = GPU_vertbuf_raw_step(vflag_step); - if (ELEM(tria_type, ROUNDBOX_TRIA_ARROWS)) { - tria_v += tria_id * tria_vcount[ROUNDBOX_TRIA_ARROWS]; - } - *data = tria_ofs[tria_type] + tria_v; - *data |= jit_v << 6; - *data |= (tria_id == 0) ? (1 << 10) : 0; /* is first tria */ - *data |= 1 << 14; /* is tria vert */ - return *data; -} - -static void roundbox_batch_add_tria(GPUVertBufRaw *vflag_step, int tria, uint32_t last_data) +GPUBatch *ui_batch_roundbox_widget_get(void) { - const int tria_num = - ELEM(tria, ROUNDBOX_TRIA_CHECK, ROUNDBOX_TRIA_HOLD_ACTION_ARROW, ROUNDBOX_TRIA_MENU) ? 1 : 2; - /* for each tria */ - for (int t = 0; t < tria_num; t++) { - for (int j = 0; j < WIDGET_AA_JITTER; j++) { - /* restart */ - set_roundbox_vertex_data(vflag_step, last_data); - set_tria_vertex(vflag_step, tria, 0, t, j); - for (int v = 0; v < tria_vcount[tria]; v++) { - last_data = set_tria_vertex(vflag_step, tria, v, t, j); - } - } - } -} - -GPUBatch *ui_batch_roundbox_widget_get(int tria) -{ - if (g_ui_batch_cache.roundbox_widget[tria] == NULL) { - uint32_t last_data; - GPUVertBufRaw vflag_step; + if (g_ui_batch_cache.roundbox_widget == NULL) { GPUVertBuf *vbo = GPU_vertbuf_create_with_format(vflag_format()); - int vcount = WIDGET_SIZE_MAX; /* inner */ - vcount += 2; /* restart */ - vcount += ((WIDGET_SIZE_MAX + 1) * 2) * WIDGET_AA_JITTER; /* outline (edges) */ - vcount += 2; /* restart */ - vcount += ((WIDGET_CURVE_RESOLU * 2) * 2) * WIDGET_AA_JITTER; /* emboss */ - if (tria) { - vcount += (tria_vcount[tria] + 2) * WIDGET_AA_JITTER; /* tria1 */ - if (!ELEM(tria, ROUNDBOX_TRIA_CHECK, ROUNDBOX_TRIA_HOLD_ACTION_ARROW, ROUNDBOX_TRIA_MENU)) { - vcount += (tria_vcount[tria] + 2) * WIDGET_AA_JITTER; /* tria2 */ - } - } - GPU_vertbuf_data_alloc(vbo, vcount); - GPU_vertbuf_attr_get_raw_data(vbo, g_ui_batch_cache.vflag_id, &vflag_step); - /* Inner */ - for (int c1 = 0, c2 = 3; c1 < 2; c1++, c2--) { - for (int a1 = 0, a2 = WIDGET_CURVE_RESOLU - 1; a2 >= 0; a1++, a2--) { - last_data = set_roundbox_vertex(&vflag_step, c1, a1, NO_AA, true, false, INNER); - last_data = set_roundbox_vertex(&vflag_step, c2, a2, NO_AA, true, false, INNER); - } - } - /* restart */ - set_roundbox_vertex_data(&vflag_step, last_data); - set_roundbox_vertex(&vflag_step, 0, 0, 0, true, false, OUTLINE); - /* Outlines */ - for (int j = 0; j < WIDGET_AA_JITTER; j++) { - for (int c = 0; c < 4; c++) { - for (int a = 0; a < WIDGET_CURVE_RESOLU; a++) { - set_roundbox_vertex(&vflag_step, c, a, j, true, false, OUTLINE); - set_roundbox_vertex(&vflag_step, c, a, j, false, false, OUTLINE); - } - } - /* Close the loop. */ - set_roundbox_vertex(&vflag_step, 0, 0, j, true, false, OUTLINE); - last_data = set_roundbox_vertex(&vflag_step, 0, 0, j, false, false, OUTLINE); - } - /* restart */ - set_roundbox_vertex_data(&vflag_step, last_data); - set_roundbox_vertex(&vflag_step, 0, 0, 0, false, false, EMBOSS); - /* Emboss */ - /* go back and forth : avoid degenerate triangle (but beware of backface cull) */ - bool rev = false; - for (int j = 0; j < WIDGET_AA_JITTER; j++, rev = !rev) { - for (int c = (rev) ? 1 : 0; (rev) ? c >= 0 : c < 2; (rev) ? c-- : c++) { - int sta = (rev) ? WIDGET_CURVE_RESOLU - 1 : 0; - int end = WIDGET_CURVE_RESOLU; - for (int a = sta; (rev) ? a >= 0 : a < end; (rev) ? a-- : a++) { - set_roundbox_vertex(&vflag_step, c, a, j, false, false, EMBOSS); - last_data = set_roundbox_vertex(&vflag_step, c, a, j, false, true, EMBOSS); - } - } - } - if (tria) { - roundbox_batch_add_tria(&vflag_step, tria, last_data); - } - g_ui_batch_cache.roundbox_widget[tria] = GPU_batch_create_ex( - GPU_PRIM_TRI_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO); - gpu_batch_presets_register(g_ui_batch_cache.roundbox_widget[tria]); - } - return g_ui_batch_cache.roundbox_widget[tria]; -} -GPUBatch *ui_batch_roundbox_get(bool filled, bool antialiased) -{ - GPUBatch **batch = NULL; + GPU_vertbuf_data_alloc(vbo, 12); - if (filled) { - if (antialiased) { - batch = &g_ui_batch_cache.roundbox_simple_aa; - } - else { - batch = &g_ui_batch_cache.roundbox_simple; - } - } - else { - if (antialiased) { - BLI_assert(0); /* Use GL_LINE_SMOOTH instead!!: */ - } - else { - batch = &g_ui_batch_cache.roundbox_simple_outline; - } - } + GPUIndexBufBuilder ibuf; + GPU_indexbuf_init(&ibuf, GPU_PRIM_TRIS, 6, 12); + /* Widget */ + GPU_indexbuf_add_tri_verts(&ibuf, 0, 1, 2); + GPU_indexbuf_add_tri_verts(&ibuf, 2, 1, 3); + /* Trias */ + GPU_indexbuf_add_tri_verts(&ibuf, 4, 5, 6); + GPU_indexbuf_add_tri_verts(&ibuf, 6, 5, 7); - if (*batch == NULL) { - uint32_t last_data; - GPUVertBufRaw vflag_step; - GPUVertBuf *vbo = GPU_vertbuf_create_with_format(vflag_format()); - int vcount = WIDGET_SIZE_MAX; - vcount += (filled) ? 2 : 0; - vcount *= (antialiased) ? WIDGET_AA_JITTER : 1; - GPU_vertbuf_data_alloc(vbo, vcount); - GPU_vertbuf_attr_get_raw_data(vbo, g_ui_batch_cache.vflag_id, &vflag_step); + GPU_indexbuf_add_tri_verts(&ibuf, 8, 9, 10); + GPU_indexbuf_add_tri_verts(&ibuf, 10, 9, 11); - if (filled) { - for (int j = 0; j < WIDGET_AA_JITTER; j++) { - if (!antialiased) { - j = NO_AA; - } - /* restart */ - set_roundbox_vertex(&vflag_step, 0, 0, j, true, false, INNER); - for (int c1 = 0, c2 = 3; c1 < 2; c1++, c2--) { - for (int a1 = 0, a2 = WIDGET_CURVE_RESOLU - 1; a2 >= 0; a1++, a2--) { - last_data = set_roundbox_vertex(&vflag_step, c1, a1, j, true, false, INNER); - last_data = set_roundbox_vertex(&vflag_step, c2, a2, j, true, false, INNER); - } - } - /* restart */ - set_roundbox_vertex_data(&vflag_step, last_data); - if (!antialiased) { - break; - } - } - *batch = GPU_batch_create_ex(GPU_PRIM_TRI_STRIP, vbo, NULL, GPU_BATCH_OWNS_VBO); - } - else { - for (int j = 0; j < WIDGET_AA_JITTER; j++) { - if (!antialiased) { - j = NO_AA; - } - for (int c = 0; c < 4; c++) { - for (int a = 0; a < WIDGET_CURVE_RESOLU; a++) { - set_roundbox_vertex(&vflag_step, c, a, j, true, false, INNER); - } - } - if (!antialiased) { - break; - } - } - *batch = GPU_batch_create_ex(GPU_PRIM_LINE_LOOP, vbo, NULL, GPU_BATCH_OWNS_VBO); - } - - gpu_batch_presets_register(*batch); + g_ui_batch_cache.roundbox_widget = GPU_batch_create_ex( + GPU_PRIM_TRIS, vbo, GPU_indexbuf_build(&ibuf), GPU_BATCH_OWNS_INDEX | GPU_BATCH_OWNS_VBO); + gpu_batch_presets_register(g_ui_batch_cache.roundbox_widget); } - return *batch; + return g_ui_batch_cache.roundbox_widget; } GPUBatch *ui_batch_roundbox_shadow_get(void) @@ -1314,14 +1147,13 @@ static void widgetbase_set_uniform_colors_ubv(uiWidgetBase *wtb, /* keep in sync with shader */ #define MAX_WIDGET_BASE_BATCH 6 -#define MAX_WIDGET_PARAMETERS 11 +#define MAX_WIDGET_PARAMETERS 12 static struct { - GPUBatch *batch; /* Batch type */ uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]; int count; bool enabled; -} g_widget_base_batch = {0}; +} g_widget_base_batch = {{{{0}}}}; void UI_widgetbase_draw_cache_flush(void) { @@ -1332,7 +1164,7 @@ void UI_widgetbase_draw_cache_flush(void) return; } - GPUBatch *batch = g_widget_base_batch.batch; + GPUBatch *batch = ui_batch_roundbox_widget_get(); if (g_widget_base_batch.count == 1) { /* draw single */ GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE); @@ -1376,31 +1208,15 @@ void UI_widgetbase_draw_cache_end(void) GPU_blend(false); } -static void draw_widgetbase_batch(GPUBatch *batch, uiWidgetBase *wtb) +static void draw_widgetbase_batch(uiWidgetBase *wtb) { + wtb->uniform_params.tria_type = wtb->tria1.type; wtb->uniform_params.tria1_size = wtb->tria1.size; wtb->uniform_params.tria2_size = wtb->tria2.size; copy_v2_v2(wtb->uniform_params.tria1_center, wtb->tria1.center); copy_v2_v2(wtb->uniform_params.tria2_center, wtb->tria2.center); if (g_widget_base_batch.enabled) { - if (g_widget_base_batch.batch == NULL) { - g_widget_base_batch.batch = ui_batch_roundbox_widget_get(ROUNDBOX_TRIA_ARROWS); - } - - /* draw multi */ - if (batch != g_ui_batch_cache.roundbox_widget[ROUNDBOX_TRIA_NONE] && - batch != g_widget_base_batch.batch) { - /* issue previous calls before changing batch type. */ - UI_widgetbase_draw_cache_flush(); - g_widget_base_batch.batch = batch; - } - - /* No need to change batch if tria is not visible. Just scale it to 0. */ - if (batch == g_ui_batch_cache.roundbox_widget[ROUNDBOX_TRIA_NONE]) { - wtb->uniform_params.tria1_size = wtb->uniform_params.tria2_size = 0; - } - g_widget_base_batch.params[g_widget_base_batch.count] = wtb->uniform_params; g_widget_base_batch.count++; @@ -1412,6 +1228,7 @@ static void draw_widgetbase_batch(GPUBatch *batch, uiWidgetBase *wtb) const float checker_params[3] = { UI_ALPHA_CHECKER_DARK / 255.0f, UI_ALPHA_CHECKER_LIGHT / 255.0f, 8.0f}; /* draw single */ + GPUBatch *batch = ui_batch_roundbox_widget_get(); GPU_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_BASE); GPU_batch_uniform_4fv_array( batch, "parameters", MAX_WIDGET_PARAMETERS, (float *)&wtb->uniform_params); @@ -1434,8 +1251,6 @@ static void widgetbase_draw_ex(uiWidgetBase *wtb, show_alpha_checkers = false; } - GPU_blend(true); - /* backdrop non AA */ if (wtb->draw_inner) { if (wcol->shaded == 0) { @@ -1455,7 +1270,7 @@ static void widgetbase_draw_ex(uiWidgetBase *wtb, outline_col[0] = wcol->outline[0]; outline_col[1] = wcol->outline[1]; outline_col[2] = wcol->outline[2]; - outline_col[3] = wcol->outline[3] / WIDGET_AA_JITTER; + outline_col[3] = wcol->outline[3]; /* emboss bottom shadow */ if (wtb->draw_emboss) { @@ -1467,7 +1282,7 @@ static void widgetbase_draw_ex(uiWidgetBase *wtb, tria_col[0] = wcol->item[0]; tria_col[1] = wcol->item[1]; tria_col[2] = wcol->item[2]; - tria_col[3] = (uchar)((float)wcol->item[3] / WIDGET_AA_JITTER); + tria_col[3] = wcol->item[3]; } /* Draw everything in one drawcall */ @@ -1476,11 +1291,10 @@ static void widgetbase_draw_ex(uiWidgetBase *wtb, widgetbase_set_uniform_colors_ubv( wtb, inner_col1, inner_col2, outline_col, emboss_col, tria_col, show_alpha_checkers); - GPUBatch *roundbox_batch = ui_batch_roundbox_widget_get(wtb->tria1.type); - draw_widgetbase_batch(roundbox_batch, wtb); + GPU_blend(true); + draw_widgetbase_batch(wtb); + GPU_blend(false); } - - GPU_blend(false); } static void widgetbase_draw(uiWidgetBase *wtb, const uiWidgetColors *wcol) |