[gtk+/wip/baedert/gl: 154/177] gl renderer: Implement blur nodes



commit d6a500b2c3d932f2a0632cfea32eac034078140c
Author: Timm Bäder <mail baedert org>
Date:   Sat Nov 25 08:56:50 2017 +0100

    gl renderer: Implement blur nodes

 gsk/gl/gskglrenderer.c          |   62 ++++++++++++++++++++++++++++++++++++++-
 gsk/gl/gskglrenderopsprivate.h  |   15 +++++++--
 gsk/meson.build                 |    2 +
 gsk/resources/glsl/blur.fs.glsl |   42 ++++++++++++++++++++++++++
 gsk/resources/glsl/blur.vs.glsl |    9 +++++
 5 files changed, 126 insertions(+), 4 deletions(-)
---
diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c
index 0142e86..b8883d9 100644
--- a/gsk/gl/gskglrenderer.c
+++ b/gsk/gl/gskglrenderer.c
@@ -130,6 +130,7 @@ struct _GskGLRenderer
       Program coloring_program;
       Program color_matrix_program;
       Program linear_gradient_program;
+      Program blur_program;
     };
   };
 
@@ -371,6 +372,22 @@ gsk_gl_renderer_create_programs (GskGLRenderer  *self,
   INIT_PROGRAM_UNIFORM_LOCATION (linear_gradient_program, start_point_location, "uStartPoint");
   INIT_PROGRAM_UNIFORM_LOCATION (linear_gradient_program, end_point_location, "uEndPoint");
 
+  self->blur_program.id = gsk_shader_builder_create_program (builder,
+                                                             "blur.vs.glsl", "blur.fs.glsl",
+                                                             &shader_error);
+  if (shader_error != NULL)
+    {
+      g_propagate_prefixed_error (error,
+                                  shader_error,
+                                  "Unable to create 'blur' program: ");
+      goto out;
+    }
+  self->blur_program.index = 6;
+  self->blur_program.name = "blur";
+  init_common_locations (self, builder, &self->blur_program);
+  INIT_PROGRAM_UNIFORM_LOCATION (blur_program, blur_radius_location, "uBlurRadius");
+  INIT_PROGRAM_UNIFORM_LOCATION (blur_program, blur_size_location, "uSize");
+
   res = TRUE;
 
 out:
@@ -950,11 +967,48 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer   *self,
       }
     break;
 
+    case GSK_BLUR_NODE:
+      {
+        int texture_id;
+        gboolean is_offscreen;
+        RenderOp op;
+        add_offscreen_ops (self, builder, min_x, max_x, min_y, max_y,
+                           gsk_blur_node_get_child (node),
+                           &texture_id, &is_offscreen);
+
+        ops_set_program (builder, &self->blur_program);
+        op.op = OP_CHANGE_BLUR;
+        graphene_size_init_from_size (&op.blur.size, &node->bounds.size);
+        op.blur.radius = gsk_blur_node_get_radius (node);
+        ops_add (builder, &op);
+
+        ops_set_texture (builder, texture_id);
+
+        if (is_offscreen)
+          {
+            GskQuadVertex vertex_data[GL_N_VERTICES] = {
+              { { min_x, min_y }, { 0, 1 }, },
+              { { min_x, max_y }, { 0, 0 }, },
+              { { max_x, min_y }, { 1, 1 }, },
+
+              { { max_x, max_y }, { 1, 0 }, },
+              { { min_x, max_y }, { 0, 0 }, },
+              { { max_x, min_y }, { 1, 1 }, },
+            };
+
+            ops_draw (builder, vertex_data);
+          }
+        else
+          {
+            ops_draw (builder, vertex_data);
+          }
+      }
+    break;
+
     case GSK_REPEATING_LINEAR_GRADIENT_NODE:
     case GSK_BORDER_NODE:
     case GSK_INSET_SHADOW_NODE:
     case GSK_OUTSET_SHADOW_NODE:
-    case GSK_BLUR_NODE:
     case GSK_SHADOW_NODE:
     case GSK_CROSS_FADE_NODE:
     case GSK_BLEND_NODE:
@@ -1245,6 +1299,12 @@ gsk_gl_renderer_render_ops (GskGLRenderer *self,
                          op->linear_gradient.end_point.x, op->linear_gradient.end_point.y);
           break;
 
+       case OP_CHANGE_BLUR:
+          g_assert (program == &self->blur_program);
+          glUniform1f (program->blur_radius_location, op->blur.radius);
+          glUniform2f (program->blur_size_location, op->blur.size.width, op->blur.size.height);
+          break;
+
         case OP_DRAW:
           OP_PRINT (" -> draw %ld, size %ld and program %s\n",
                     op->draw.vao_offset, op->draw.vao_size, program->name);
diff --git a/gsk/gl/gskglrenderopsprivate.h b/gsk/gl/gskglrenderopsprivate.h
index b4ea6a4..31559b1 100644
--- a/gsk/gl/gskglrenderopsprivate.h
+++ b/gsk/gl/gskglrenderopsprivate.h
@@ -10,7 +10,7 @@
 #include "gskglrendererprivate.h"
 
 #define GL_N_VERTICES 6
-#define GL_N_PROGRAMS 6
+#define GL_N_PROGRAMS 7
 
 enum {
   OP_NONE,
@@ -26,8 +26,9 @@ enum {
   OP_CHANGE_VAO             =  10,
   OP_CHANGE_LINEAR_GRADIENT =  11,
   OP_CHANGE_COLOR_MATRIX    =  12,
-  OP_CLEAR                  =  13,
-  OP_DRAW                   =  14,
+  OP_CHANGE_BLUR            =  13,
+  OP_CLEAR                  =  14,
+  OP_DRAW                   =  15,
 };
 
 typedef struct
@@ -71,6 +72,10 @@ typedef struct
       int corner_widths_location;
       int corner_heights_location;
     };
+    struct {
+      int blur_radius_location;
+      int blur_size_location;
+    };
   };
 } Program;
 
@@ -104,6 +109,10 @@ typedef struct
       graphene_matrix_t matrix;
       graphene_vec4_t offset;
     } color_matrix;
+    struct {
+      float radius;
+      graphene_size_t size;
+    } blur;
   };
 } RenderOp;
 
diff --git a/gsk/meson.build b/gsk/meson.build
index c544a6c..548c193 100644
--- a/gsk/meson.build
+++ b/gsk/meson.build
@@ -7,6 +7,8 @@ gsk_private_source_shaders = [
   'resources/glsl/coloring.fs.glsl',
   'resources/glsl/color_matrix.fs.glsl',
   'resources/glsl/linear_gradient.fs.glsl',
+  'resources/glsl/blur.vs.glsl',
+  'resources/glsl/blur.fs.glsl',
   'resources/glsl/es2_common.fs.glsl',
   'resources/glsl/es2_common.vs.glsl',
   'resources/glsl/gl3_common.fs.glsl',
diff --git a/gsk/resources/glsl/blur.fs.glsl b/gsk/resources/glsl/blur.fs.glsl
new file mode 100644
index 0000000..16c2b6f
--- /dev/null
+++ b/gsk/resources/glsl/blur.fs.glsl
@@ -0,0 +1,42 @@
+
+uniform float uBlurRadius = 4.0;
+uniform vec2 uSize;
+
+const int   samples_x    = 15;  // must be odd
+const int   samples_y    = 15;  // must be odd
+
+const int   half_samples_x = samples_x / 2;
+const int   half_samples_y = samples_y / 2;
+
+float Gaussian (float sigma, float x)
+{
+  return exp ( - (x * x) / (2.0 * sigma * sigma));
+}
+
+vec4 blur_pixel (in vec2 uv)
+{
+  float total = 0.0;
+  vec4 ret = vec4 (0);
+  float pixel_size_x = (1.0 / uSize.x);
+  float pixel_size_y = (1.0 / uSize.y);
+
+  for (int y = 0; y < samples_y; ++y)
+    {
+      float fy = Gaussian (uBlurRadius, float(y) - float(half_samples_x));
+      float offset_y = float(y - half_samples_y) * pixel_size_y;
+      for (int x = 0; x < samples_x; ++x)
+        {
+          float fx = Gaussian (uBlurRadius, float(x) - float(half_samples_x));
+          float offset_x = float(x - half_samples_x) * pixel_size_x;
+          total += fx * fy;
+          ret += Texture(uSource, uv + vec2(offset_x, offset_y)) * fx * fy;
+        }
+    }
+  return ret / total;
+}
+
+void main()
+{
+  /*color = clip (inPos, blur_pixel (inTexCoord));*/
+  setOutputColor(blur_pixel(vUv));
+}
diff --git a/gsk/resources/glsl/blur.vs.glsl b/gsk/resources/glsl/blur.vs.glsl
new file mode 100644
index 0000000..fe52014
--- /dev/null
+++ b/gsk/resources/glsl/blur.vs.glsl
@@ -0,0 +1,9 @@
+
+out vec2 size;
+void main() {
+  gl_Position = uProjection * uModelview * vec4(aPosition, 0.0, 1.0);
+
+
+  vUv = vec2(aUv.x, aUv.y);
+  /*size = vec2(aPosition.z - aPosition.z, aPosition.y - aPosition.w);*/
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]