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

Reply via email to