Commit: 4a73127a2b11056236c40e85ceb75230f2b4888d Author: Clément Foucault Date: Fri Apr 6 10:09:23 2018 +0200 Branches: blender2.8 https://developer.blender.org/rB4a73127a2b11056236c40e85ceb75230f2b4888d
UI: Perf: Improve ui_draw_dropshadow. Replace the 12 iterations of UI_draw_roundbox_4fv with only one batch. This mean less overdraw and less drawcalls. I had to hack the opacity falloff curve manually to get approximatly the same result as previous technique. I'm sure with a bit more brain power somebody could find the perfect function. =================================================================== M source/blender/editors/interface/interface_draw.c M source/blender/editors/interface/interface_intern.h M source/blender/editors/interface/interface_widgets.c M source/blender/gpu/CMakeLists.txt M source/blender/gpu/GPU_shader.h M source/blender/gpu/intern/gpu_shader.c A source/blender/gpu/shaders/gpu_shader_2D_widget_shadow_frag.glsl A source/blender/gpu/shaders/gpu_shader_2D_widget_shadow_vert.glsl =================================================================== diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index cc5cbba0f05..786c3637e3d 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -2125,16 +2125,40 @@ void ui_draw_dropshadow(const rctf *rct, float radius, float aspect, float alpha } glEnable(GL_BLEND); - const float dalpha = alpha * 2.0f / 255.0f; float calpha = dalpha; - for (; i--; a -= aspect) { + float visibility = 1.0f; + for (; i--;) { /* alpha ranges from 2 to 20 or so */ +#if 0 /* Old Method (pre 2.8) */ float color[4] = {0.0f, 0.0f, 0.0f, calpha}; UI_draw_roundbox_4fv(true, rct->xmin - a, rct->ymin - a, rct->xmax + a, rct->ymax - 10.0f + a, rad + a, color); +#endif + /* Compute final visibility to match old method result. */ + /* TODO we could just find a better fit function inside the shader instead of this. */ + visibility = visibility * (1.0f - calpha); calpha += dalpha; } + uiWidgetBaseParameters widget_params = { + .recti.xmin = rct->xmin, .recti.ymin = rct->ymin, + .recti.xmax = rct->xmax, .recti.ymax = rct->ymax - 10.0f, + .rect.xmin = rct->xmin - a, .rect.ymin = rct->ymin - a, + .rect.xmax = rct->xmax + a, .rect.ymax = rct->ymax - 10.0f + a, + .radi = rad, + .rad = rad + a, + .round_corners[0] = (roundboxtype & UI_CNR_BOTTOM_LEFT) ? 1.0f : 0.0f, + .round_corners[1] = (roundboxtype & UI_CNR_BOTTOM_RIGHT) ? 1.0f : 0.0f, + .round_corners[2] = (roundboxtype & UI_CNR_TOP_RIGHT) ? 1.0f : 0.0f, + .round_corners[3] = (roundboxtype & UI_CNR_TOP_LEFT) ? 1.0f : 0.0f, + }; + + Gwn_Batch *batch = ui_batch_roundbox_shadow_get(); + GWN_batch_program_set_builtin(batch, GPU_SHADER_2D_WIDGET_SHADOW); + GWN_batch_uniform_4fv_array(batch, "parameters", 4, (float *)&widget_params); + GWN_batch_uniform_1f(batch, "alpha", 1.0f - visibility); + GWN_batch_draw(batch); + /* outline emphasis */ glEnable(GL_LINE_SMOOTH); float color[4] = {0.0f, 0.0f, 0.0f, 0.4f}; diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 516dc1f4a29..86814c54fbb 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -727,6 +727,7 @@ enum { struct Gwn_Batch *ui_batch_roundbox_get(bool filled, bool antialiased); struct Gwn_Batch *ui_batch_roundbox_widget_get(int tria); +struct Gwn_Batch *ui_batch_roundbox_shadow_get(void); void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3, const float color[4]); void ui_draw_anti_roundbox(int mode, float minx, float miny, float maxx, float maxy, diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 6c473c0e0c9..ad51c9ef7ba 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -230,6 +230,7 @@ static struct { Gwn_Batch *roundbox_simple; Gwn_Batch *roundbox_simple_aa; Gwn_Batch *roundbox_simple_outline; + Gwn_Batch *roundbox_shadow; Gwn_VertFormat format; uint vflag_id; @@ -436,6 +437,41 @@ Gwn_Batch *ui_batch_roundbox_get(bool filled, bool antialiased) return *batch; } +Gwn_Batch *ui_batch_roundbox_shadow_get(void) +{ + if (g_ui_batch_cache.roundbox_shadow == NULL) { + uint32_t last_data; + Gwn_VertBufRaw vflag_step; + Gwn_VertBuf *vbo = GWN_vertbuf_create_with_format(vflag_format()); + int vcount = (WIDGET_SIZE_MAX + 1) * 2 + 2 + WIDGET_SIZE_MAX; + GWN_vertbuf_data_alloc(vbo, vcount); + GWN_vertbuf_attr_get_raw_data(vbo, g_ui_batch_cache.vflag_id, &vflag_step); + + for (int c = 0; c < 4; c++) { + for (int a = 0; a < WIDGET_CURVE_RESOLU; a++) { + set_roundbox_vertex(&vflag_step, c, a, NO_AA, true, false, INNER); + set_roundbox_vertex(&vflag_step, c, a, NO_AA, false, false, INNER); + } + } + /* close loop */ + last_data = set_roundbox_vertex(&vflag_step, 0, 0, NO_AA, true, false, INNER); + last_data = set_roundbox_vertex(&vflag_step, 0, 0, NO_AA, false, false, INNER); + /* restart */ + set_roundbox_vertex_data(&vflag_step, last_data); + set_roundbox_vertex(&vflag_step, 0, 0, NO_AA, true, false, INNER); + /* filled */ + for (int c1 = 0, c2 = 3; c1 < 2; c1++, c2--) { + for (int a1 = 0, a2 = WIDGET_CURVE_RESOLU -1; a2 >= 0; a1++, a2--) { + set_roundbox_vertex(&vflag_step, c1, a1, NO_AA, true, false, INNER); + set_roundbox_vertex(&vflag_step, c2, a2, NO_AA, true, false, INNER); + } + } + g_ui_batch_cache.roundbox_shadow = GWN_batch_create_ex(GWN_PRIM_TRI_STRIP, vbo, NULL, GWN_BATCH_OWNS_VBO); + gpu_batch_presets_register(g_ui_batch_cache.roundbox_shadow); + } + return g_ui_batch_cache.roundbox_shadow; +} + #undef INNER #undef OUTLINE #undef EMBOSS diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index de4d59ad10b..e6c6e6c0eb4 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -133,6 +133,8 @@ data_to_c_simple(shaders/gpu_shader_flat_color_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_flat_color_alpha_test_0_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_2D_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_2D_widget_base_vert.glsl SRC) +data_to_c_simple(shaders/gpu_shader_2D_widget_shadow_vert.glsl SRC) +data_to_c_simple(shaders/gpu_shader_2D_widget_shadow_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_2D_nodelink_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_2D_nodelink_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_2D_flat_color_vert.glsl SRC) diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h index 486aea561c4..8051855ffbe 100644 --- a/source/blender/gpu/GPU_shader.h +++ b/source/blender/gpu/GPU_shader.h @@ -173,6 +173,7 @@ typedef enum GPUBuiltinShader { GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR, /* specialized for UI drawing */ GPU_SHADER_2D_WIDGET_BASE, + GPU_SHADER_2D_WIDGET_SHADOW, GPU_SHADER_2D_NODELINK, GPU_SHADER_2D_NODELINK_INST, diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c index c2f0aaf65de..08a2c0c2c09 100644 --- a/source/blender/gpu/intern/gpu_shader.c +++ b/source/blender/gpu/intern/gpu_shader.c @@ -68,6 +68,8 @@ extern char datatoc_gpu_shader_2D_image_vert_glsl[]; extern char datatoc_gpu_shader_2D_image_rect_vert_glsl[]; extern char datatoc_gpu_shader_2D_image_multi_rect_vert_glsl[]; extern char datatoc_gpu_shader_2D_widget_base_vert_glsl[]; +extern char datatoc_gpu_shader_2D_widget_shadow_vert_glsl[]; +extern char datatoc_gpu_shader_2D_widget_shadow_frag_glsl[]; extern char datatoc_gpu_shader_2D_nodelink_frag_glsl[]; extern char datatoc_gpu_shader_2D_nodelink_vert_glsl[]; @@ -801,6 +803,8 @@ GPUShader *GPU_shader_get_builtin_shader(GPUBuiltinShader shader) [GPU_SHADER_2D_WIDGET_BASE] = { datatoc_gpu_shader_2D_widget_base_vert_glsl, datatoc_gpu_shader_2D_smooth_color_frag_glsl}, + [GPU_SHADER_2D_WIDGET_SHADOW] = { datatoc_gpu_shader_2D_widget_shadow_vert_glsl, + datatoc_gpu_shader_2D_widget_shadow_frag_glsl }, [GPU_SHADER_2D_NODELINK] = { datatoc_gpu_shader_2D_nodelink_vert_glsl, datatoc_gpu_shader_2D_nodelink_frag_glsl }, [GPU_SHADER_2D_NODELINK_INST] = { datatoc_gpu_shader_2D_nodelink_vert_glsl, diff --git a/source/blender/gpu/shaders/gpu_shader_2D_widget_shadow_frag.glsl b/source/blender/gpu/shaders/gpu_shader_2D_widget_shadow_frag.glsl new file mode 100644 index 00000000000..7587b2fc18a --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_2D_widget_shadow_frag.glsl @@ -0,0 +1,13 @@ + +in float shadowFalloff; + +out vec4 fragColor; + +uniform float alpha; + +void main() +{ + fragColor = vec4(0.0); + /* Manual curve fit of the falloff curve of previous drawing method. */ + fragColor.a = alpha * (shadowFalloff * shadowFalloff * 0.722 + shadowFalloff * 0.277); +} \ No newline at end of file diff --git a/source/blender/gpu/shaders/gpu_shader_2D_widget_shadow_vert.glsl b/source/blender/gpu/shaders/gpu_shader_2D_widget_shadow_vert.glsl new file mode 100644 index 00000000000..441f97e95f0 --- /dev/null +++ b/source/blender/gpu/shaders/gpu_shader_2D_widget_shadow_vert.glsl @@ -0,0 +1,64 @@ +#define BIT_RANGE(x) ((1u << x) - 1u) + +/* 2 bits for corner */ +/* Attention! Not the same order as in UI_interface.h! + * Ordered by drawing order. */ +#define BOTTOM_LEFT 0u +#define BOTTOM_RIGHT 1u +#define TOP_RIGHT 2u +#define TOP_LEFT 3u +#define CNR_FLAG_RANGE BIT_RANGE(2u) + +/* 4bits for corner id */ +#define CORNER_VEC_OFS 2u +#define CORNER_VEC_RANGE BIT_RANGE(4u) +const vec2 cornervec[36] = vec2[36]( + vec2(0.0, 1.0), vec2(0.02, 0.805), vec2(0.067, 0.617), vec2(0.169, 0.45), vec2(0.293, 0.293), vec2(0.45, 0.169), vec2(0.617, 0.076), vec2(0.805, 0.02), vec2(1.0, 0.0), + vec2(-1.0, 0.0), vec2(-0.805, 0.02), vec2(-0.617, 0.067), vec2(-0.45, 0.169), vec2(-0.293, 0.293), vec2(-0.169, 0.45), vec2(-0.076, 0.617), vec2(-0.02, 0.805), vec2(0.0, 1.0), + vec2(0.0, -1.0), vec2(-0.02, -0.805), vec2(-0.067, -0.617), vec2(-0.169, -0.45), vec2(-0.293, -0.293), vec2(-0.45, -0.169), vec2(-0.617, -0.076), vec2(-0.805, -0.02), vec2(-1.0, 0.0), + vec2(1.0, 0.0), vec2(0.805, -0.02), vec2(0.617, -0.067), vec2(0.45, -0.169), vec2(0.293, -0.293), vec2(0.169, -0.45), vec2(0.076, -0.617), vec2(0.02, -0.805), vec2(0.0, -1.0) +); + +#define INNER_FLAG (1u << 10u) /* is inner vert */ + +uniform mat4 ModelViewProjectionMatrix; + +uniform vec4 parameters[4]; +/* radi and rad per corner */ +#define recti parameters[0] +#define rect parameters[1] +#define radsi parameters[2].x +#define rads parameters[2].y +#define roundCorners parameters[3] + +in uint vflag; + +out float shadowFalloff; + +void main() +{ + uint cflag = vflag & CNR_FLAG_RANGE; + uint vofs = (vflag >> CORNER_VEC_OFS) & CORNER_VEC_RANGE; + + vec2 v = cornervec[cflag * 9u + vofs]; + + bool is_inner = (vflag & INNER_FLAG) != 0u; + + shadowFalloff = (is_inner) ? 1.0 : 0.0; + + /* Scale by corner radius */ + v *= roundCorners[cflag] * ((is_inner) ? radsi : rad @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org https://lists.blender.org/mailman/listinfo/bf-blender-cvs