[gtk/wip/baedert/gl-rework] gl renderer: Move rect transformation to the vertex shader



commit 2f097ec8a76151eceb7fc44641b5c53d806234f4
Author: Timm Bäder <mail baedert org>
Date:   Sun Jan 19 20:08:23 2020 +0100

    gl renderer: Move rect transformation to the vertex shader
    
    No need to do this for every fragment.

 gsk/gl/gskglrenderer.c                          |  1 +
 gsk/gl/gskglshaderbuilder.c                     | 12 +++-
 gsk/gl/gskglshaderbuilderprivate.h              |  2 +
 gsk/meson.build                                 |  1 +
 gsk/resources/glsl/border.glsl                  | 28 +++++----
 gsk/resources/glsl/inset_shadow.glsl            | 34 ++++++-----
 gsk/resources/glsl/outset_shadow.glsl           | 14 +++--
 gsk/resources/glsl/preamble.fs.glsl             | 80 +++----------------------
 gsk/resources/glsl/preamble.glsl                | 37 ++++++++++++
 gsk/resources/glsl/preamble.vs.glsl             | 66 ++++++++++++++++----
 gsk/resources/glsl/unblurred_outset_shadow.glsl | 36 ++++++-----
 11 files changed, 181 insertions(+), 130 deletions(-)
---
diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c
index f9130a17b5..88c774ad7c 100644
--- a/gsk/gl/gskglrenderer.c
+++ b/gsk/gl/gskglrenderer.c
@@ -2565,6 +2565,7 @@ gsk_gl_renderer_create_programs (GskGLRenderer  *self,
   gboolean success = TRUE;
 
   gsk_gl_shader_builder_init (&shader_builder,
+                              "/org/gtk/libgsk/glsl/preamble.glsl",
                               "/org/gtk/libgsk/glsl/preamble.vs.glsl",
                               "/org/gtk/libgsk/glsl/preamble.fs.glsl");
 
diff --git a/gsk/gl/gskglshaderbuilder.c b/gsk/gl/gskglshaderbuilder.c
index f28bf127f7..a133527784 100644
--- a/gsk/gl/gskglshaderbuilder.c
+++ b/gsk/gl/gskglshaderbuilder.c
@@ -9,14 +9,17 @@
 
 void
 gsk_gl_shader_builder_init (GskGLShaderBuilder *self,
+                            const char         *common_preamble_resource_path,
                             const char         *vs_preamble_resource_path,
                             const char         *fs_preamble_resource_path)
 {
   memset (self, 0, sizeof (*self));
 
+  self->preamble = g_resources_lookup_data (common_preamble_resource_path, 0, NULL);
   self->vs_preamble = g_resources_lookup_data (vs_preamble_resource_path, 0, NULL);
   self->fs_preamble = g_resources_lookup_data (fs_preamble_resource_path, 0, NULL);
 
+  g_assert (self->preamble);
   g_assert (self->vs_preamble);
   g_assert (self->fs_preamble);
 }
@@ -24,6 +27,7 @@ gsk_gl_shader_builder_init (GskGLShaderBuilder *self,
 void
 gsk_gl_shader_builder_finish (GskGLShaderBuilder *self)
 {
+  g_bytes_unref (self->preamble);
   g_bytes_unref (self->vs_preamble);
   g_bytes_unref (self->fs_preamble);
 }
@@ -102,13 +106,14 @@ gsk_gl_shader_builder_create_program (GskGLShaderBuilder  *self,
               "#version %d\n", self->version);
 
   vertex_id = glCreateShader (GL_VERTEX_SHADER);
-  glShaderSource (vertex_id, 7,
+  glShaderSource (vertex_id, 8,
                   (const char *[]) {
                     version_buffer,
                     self->debugging ? "#define GSK_DEBUG 1\n" : "",
                     self->legacy ? "#define GSK_LEGACY 1\n" : "",
                     self->gl3 ? "#define GSK_GL3 1\n" : "",
                     self->gles ? "#define GSK_GLES 1\n" : "",
+                    g_bytes_get_data (self->preamble, NULL),
                     g_bytes_get_data (self->vs_preamble, NULL),
                     vertex_shader_start
                   },
@@ -119,6 +124,7 @@ gsk_gl_shader_builder_create_program (GskGLShaderBuilder  *self,
                     -1,
                     -1,
                     -1,
+                    -1,
                     fragment_shader_start - vertex_shader_start
                   });
   glCompileShader (vertex_id);
@@ -130,13 +136,14 @@ gsk_gl_shader_builder_create_program (GskGLShaderBuilder  *self,
     }
 
   fragment_id = glCreateShader (GL_FRAGMENT_SHADER);
-  glShaderSource (fragment_id, 7,
+  glShaderSource (fragment_id, 8,
                   (const char *[]) {
                     version_buffer,
                     self->debugging ? "#define GSK_DEBUG 1\n" : "",
                     self->legacy ? "#define GSK_LEGACY 1\n" : "",
                     self->gl3 ? "#define GSK_GL3 1\n" : "",
                     self->gles ? "#define GSK_GLES 1\n" : "",
+                    g_bytes_get_data (self->preamble, NULL),
                     g_bytes_get_data (self->fs_preamble, NULL),
                     fragment_shader_start
                   },
@@ -148,6 +155,7 @@ gsk_gl_shader_builder_create_program (GskGLShaderBuilder  *self,
                     -1,
                     -1,
                     -1,
+                    -1,
                   });
   glCompileShader (fragment_id);
 
diff --git a/gsk/gl/gskglshaderbuilderprivate.h b/gsk/gl/gskglshaderbuilderprivate.h
index 209fa5ff91..ec9cd66845 100644
--- a/gsk/gl/gskglshaderbuilderprivate.h
+++ b/gsk/gl/gskglshaderbuilderprivate.h
@@ -8,6 +8,7 @@ G_BEGIN_DECLS
 
 typedef struct
 {
+  GBytes *preamble;
   GBytes *vs_preamble;
   GBytes *fs_preamble;
 
@@ -22,6 +23,7 @@ typedef struct
 
 
 void   gsk_gl_shader_builder_init             (GskGLShaderBuilder  *self,
+                                               const char          *common_preamble_resource_path,
                                                const char          *vs_preamble_resource_path,
                                                const char          *fs_preamble_resource_path);
 void   gsk_gl_shader_builder_finish           (GskGLShaderBuilder  *self);
diff --git a/gsk/meson.build b/gsk/meson.build
index 6dd4925155..8aeae9e7e8 100644
--- a/gsk/meson.build
+++ b/gsk/meson.build
@@ -1,4 +1,5 @@
 gsk_private_gl_shaders = [
+  'resources/glsl/preamble.glsl',
   'resources/glsl/preamble.fs.glsl',
   'resources/glsl/preamble.vs.glsl',
   'resources/glsl/border.glsl',
diff --git a/gsk/resources/glsl/border.glsl b/gsk/resources/glsl/border.glsl
index 505c850217..812d365431 100644
--- a/gsk/resources/glsl/border.glsl
+++ b/gsk/resources/glsl/border.glsl
@@ -1,7 +1,11 @@
 // VERTEX_SHADER:
 uniform vec4 u_color;
+uniform vec4 u_widths;
+uniform vec4[3] u_outline_rect;
 
 _OUT_ vec4 final_color;
+_OUT_ _ROUNDED_RECT_UNIFORM_ transformed_outside_outline;
+_OUT_ _ROUNDED_RECT_UNIFORM_ transformed_inside_outline;
 
 void main() {
   gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
@@ -9,28 +13,32 @@ void main() {
   final_color = u_color;
   final_color.rgb *= final_color.a; // pre-multiply
   final_color *= u_alpha;
+
+  RoundedRect outside = create_rect(u_outline_rect);
+  RoundedRect inside = rounded_rect_shrink (outside, u_widths);
+
+  rounded_rect_transform(outside, u_modelview);
+  rounded_rect_transform(inside, u_modelview);
+
+  rounded_rect_encode(outside, transformed_outside_outline);
+  rounded_rect_encode(inside, transformed_inside_outline);
 }
 
 // FRAGMENT_SHADER:
-uniform vec4 u_widths;
 uniform vec4[3] u_outline_rect;
 
 _IN_ vec4 final_color;
+_IN_ _ROUNDED_RECT_UNIFORM_ transformed_outside_outline;
+_IN_ _ROUNDED_RECT_UNIFORM_ transformed_inside_outline;
 
 void main() {
   vec4 f = gl_FragCoord;
   f.x += u_viewport.x;
   f.y = (u_viewport.y + u_viewport.w) - f.y;
 
-  RoundedRect outside = create_rect(u_outline_rect);
-  RoundedRect inside = rounded_rect_shrink (outside, u_widths);
-
-  rounded_rect_transform(outside, u_modelview);
-  rounded_rect_transform(inside, u_modelview);
-
-  float alpha = clamp (rounded_rect_coverage (outside, f.xy) -
-                       rounded_rect_coverage (inside, f.xy),
-                       0.0, 1.0);
+  float alpha = clamp(rounded_rect_coverage(decode_rect(transformed_outside_outline), f.xy) -
+                      rounded_rect_coverage(decode_rect(transformed_inside_outline), f.xy),
+                      0.0, 1.0);
 
   setOutputColor(final_color * alpha);
 }
diff --git a/gsk/resources/glsl/inset_shadow.glsl b/gsk/resources/glsl/inset_shadow.glsl
index 087798abaf..b3ba05a41f 100644
--- a/gsk/resources/glsl/inset_shadow.glsl
+++ b/gsk/resources/glsl/inset_shadow.glsl
@@ -1,7 +1,12 @@
 // VERTEX_SHADER:
 uniform vec4 u_color;
+uniform float u_spread;
+uniform vec2 u_offset;
+uniform vec4[3] u_outline_rect;
 
 _OUT_ vec4 final_color;
+_OUT_ _ROUNDED_RECT_UNIFORM_ transformed_outside_outline;
+_OUT_ _ROUNDED_RECT_UNIFORM_ transformed_inside_outline;
 
 void main() {
   gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
@@ -9,14 +14,23 @@ void main() {
   final_color = u_color;
   final_color.rgb *= final_color.a;
   final_color *= u_alpha;
+
+  RoundedRect outside = create_rect(u_outline_rect);
+  RoundedRect inside = rounded_rect_shrink(outside, vec4(u_spread));
+
+  rounded_rect_offset(inside, u_offset);
+
+  rounded_rect_transform(outside, u_modelview);
+  rounded_rect_transform(inside, u_modelview);
+
+  rounded_rect_encode(outside, transformed_outside_outline);
+  rounded_rect_encode(inside, transformed_inside_outline);
 }
 
 // FRAGMENT_SHADER:
-uniform float u_spread;
-uniform vec2 u_offset;
-uniform vec4[3] u_outline_rect;
-
 _IN_ vec4 final_color;
+_IN_ _ROUNDED_RECT_UNIFORM_ transformed_outside_outline;
+_IN_ _ROUNDED_RECT_UNIFORM_ transformed_inside_outline;
 
 void main() {
   vec4 f = gl_FragCoord;
@@ -24,16 +38,8 @@ void main() {
   f.x += u_viewport.x;
   f.y = (u_viewport.y + u_viewport.w) - f.y;
 
-  RoundedRect outside = create_rect(u_outline_rect);
-  RoundedRect inside = rounded_rect_shrink(outside, vec4(u_spread));
-
-  rounded_rect_offset(inside, u_offset);
-
-  rounded_rect_transform(outside, u_modelview);
-  rounded_rect_transform(inside, u_modelview);
-
-  float alpha = clamp (rounded_rect_coverage (outside, f.xy) -
-                       rounded_rect_coverage (inside, f.xy),
+  float alpha = clamp (rounded_rect_coverage(decode_rect(transformed_outside_outline), f.xy) -
+                       rounded_rect_coverage(decode_rect(transformed_inside_outline), f.xy),
                        0.0, 1.0);
 
   setOutputColor(final_color * alpha);
diff --git a/gsk/resources/glsl/outset_shadow.glsl b/gsk/resources/glsl/outset_shadow.glsl
index ada444d612..4111ddcea8 100644
--- a/gsk/resources/glsl/outset_shadow.glsl
+++ b/gsk/resources/glsl/outset_shadow.glsl
@@ -1,7 +1,9 @@
 // VERTEX_SHADER:
 uniform vec4 u_color;
+uniform vec4[3] u_outline_rect;
 
 _OUT_ vec4 final_color;
+_OUT_ _ROUNDED_RECT_UNIFORM_ transformed_outline;
 
 void main() {
   gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
@@ -12,12 +14,15 @@ void main() {
   // pre-multiply
   final_color.rgb *= final_color.a;
   final_color *= u_alpha;
+
+  RoundedRect outline = create_rect(u_outline_rect);
+  rounded_rect_transform(outline, u_modelview);
+  rounded_rect_encode(outline, transformed_outline);
 }
 
 // FRAGMENT_SHADER:
-uniform vec4[3] u_outline_rect;
-
 _IN_ vec4 final_color;
+_IN_ _ROUNDED_RECT_UNIFORM_ transformed_outline;
 
 void main() {
   vec4 f = gl_FragCoord;
@@ -25,11 +30,8 @@ void main() {
   f.x += u_viewport.x;
   f.y = (u_viewport.y + u_viewport.w) - f.y;
 
-  RoundedRect outline = create_rect(u_outline_rect);
-  rounded_rect_transform(outline, u_modelview);
-
   float alpha = Texture(u_source, vUv).a;
-  alpha *= (1.0 -  clamp(rounded_rect_coverage(outline, f.xy), 0.0, 1.0));
+  alpha *= (1.0 -  clamp(rounded_rect_coverage(decode_rect(transformed_outline), f.xy), 0.0, 1.0));
 
   vec4 color = final_color * alpha;
 
diff --git a/gsk/resources/glsl/preamble.fs.glsl b/gsk/resources/glsl/preamble.fs.glsl
index 056a4a27b7..b5c958ebf1 100644
--- a/gsk/resources/glsl/preamble.fs.glsl
+++ b/gsk/resources/glsl/preamble.fs.glsl
@@ -1,11 +1,3 @@
-#ifdef GSK_GL3
-precision highp float;
-#endif
-
-#ifdef GSK_GLES
-precision highp float;
-#endif
-
 uniform sampler2D u_source;
 uniform mat4 u_projection;
 uniform mat4 u_modelview;
@@ -14,42 +6,23 @@ uniform vec4 u_viewport;
 uniform vec4[3] u_clip_rect;
 
 #if GSK_GLES
-#define _OUT_ varying
-#define _IN_ varying
 #elif GSK_LEGACY
-#define _OUT_ varying
-#define _IN_ varying
 _OUT_ vec4 outputColor;
 #else
-#define _OUT_ out
-#define _IN_ in
 _OUT_ vec4 outputColor;
 #endif
+
 _IN_ vec2 vUv;
 
 
 
-struct RoundedRect
-{
-  vec4 bounds;
-  // Look, arrays can't be in structs if you want to return the struct
-  // from a function in gles or whatever. Just kill me.
-  vec4 corner_points1; // xy = top left, zw = top right
-  vec4 corner_points2; // xy = bottom right, zw = bottom left
-};
-
-// Transform from a GskRoundedRect to a RoundedRect as we need it.
-RoundedRect
-create_rect(vec4[3] data)
+RoundedRect decode_rect(_ROUNDED_RECT_UNIFORM_ r)
 {
-  vec4 bounds = vec4(data[0].xy, data[0].xy + data[0].zw);
-
-  vec4 corner_points1 = vec4(bounds.xy + data[1].xy,
-                             bounds.zy + vec2(data[1].zw * vec2(-1, 1)));
-  vec4 corner_points2 = vec4(bounds.zw + (data[2].xy * vec2(-1, -1)),
-                             bounds.xw + vec2(data[2].zw * vec2(1, -1)));
-
-  return RoundedRect(bounds, corner_points1, corner_points2);
+#if defined(GSK_GLES) || defined(GSK_LEGACY)
+  return RoundedRect(r[0], r[1], r[2]);
+#else
+  return r;
+#endif
 }
 
 float
@@ -103,45 +76,6 @@ rounded_rect_coverage (RoundedRect r, vec2 p)
   return 1.0 - dot(vec4(is_out), corner_coverages);
 }
 
-// amount is: top, right, bottom, left
-RoundedRect
-rounded_rect_shrink (RoundedRect r, vec4 amount)
-{
-  vec4 new_bounds = r.bounds + vec4(1.0,1.0,-1.0,-1.0) * amount.wxyz;
-  vec4 new_corner_points1 = r.corner_points1;
-  vec4 new_corner_points2 = r.corner_points2;
-
-  if (r.corner_points1.xy == r.bounds.xy) new_corner_points1.xy = new_bounds.xy;
-  if (r.corner_points1.zw == r.bounds.zy) new_corner_points1.zw = new_bounds.zy;
-  if (r.corner_points2.xy == r.bounds.zw) new_corner_points2.xy = new_bounds.zw;
-  if (r.corner_points2.zw == r.bounds.xw) new_corner_points2.zw = new_bounds.xw;
-
-  return RoundedRect (new_bounds, new_corner_points1, new_corner_points2);
-}
-
-void
-rounded_rect_offset(inout RoundedRect r, vec2 offset)
-{
-  r.bounds.xy += offset;
-  r.bounds.zw += offset;
-  r.corner_points1.xy += offset;
-  r.corner_points1.zw += offset;
-  r.corner_points2.xy += offset;
-  r.corner_points2.zw += offset;
-}
-
-void rounded_rect_transform(inout RoundedRect r, mat4 mat)
-{
-  r.bounds.xy = (mat * vec4(r.bounds.xy, 0.0, 1.0)).xy;
-  r.bounds.zw = (mat * vec4(r.bounds.zw, 0.0, 1.0)).xy;
-
-  r.corner_points1.xy = (mat * vec4(r.corner_points1.xy, 0.0, 1.0)).xy;
-  r.corner_points1.zw = (mat * vec4(r.corner_points1.zw, 0.0, 1.0)).xy;
-
-  r.corner_points2.xy = (mat * vec4(r.corner_points2.xy, 0.0, 1.0)).xy;
-  r.corner_points2.zw = (mat * vec4(r.corner_points2.zw, 0.0, 1.0)).xy;
-}
-
 vec4 Texture(sampler2D sampler, vec2 texCoords) {
 #if GSK_GLES
   return texture2D(sampler, texCoords);
diff --git a/gsk/resources/glsl/preamble.glsl b/gsk/resources/glsl/preamble.glsl
new file mode 100644
index 0000000000..9dd711cbd2
--- /dev/null
+++ b/gsk/resources/glsl/preamble.glsl
@@ -0,0 +1,37 @@
+#ifndef GSK_LEGACY
+precision highp float;
+#endif
+
+#if defined(GSK_GLES) || defined(GSK_LEGACY)
+#define _OUT_ varying
+#define _IN_ varying
+#define _ROUNDED_RECT_UNIFORM_ vec4[3]
+#else
+#define _OUT_ out
+#define _IN_ in
+#define _ROUNDED_RECT_UNIFORM_ RoundedRect
+#endif
+
+
+struct RoundedRect
+{
+  vec4 bounds;
+  // Look, arrays can't be in structs if you want to return the struct
+  // from a function in gles or whatever. Just kill me.
+  vec4 corner_points1; // xy = top left, zw = top right
+  vec4 corner_points2; // xy = bottom right, zw = bottom left
+};
+
+// Transform from a GskRoundedRect to a RoundedRect as we need it.
+RoundedRect
+create_rect(vec4[3] data)
+{
+  vec4 bounds = vec4(data[0].xy, data[0].xy + data[0].zw);
+
+  vec4 corner_points1 = vec4(bounds.xy + data[1].xy,
+                             bounds.zy + vec2(data[1].zw * vec2(-1, 1)));
+  vec4 corner_points2 = vec4(bounds.zw + (data[2].xy * vec2(-1, -1)),
+                             bounds.xw + vec2(data[2].zw * vec2(1, -1)));
+
+  return RoundedRect(bounds, corner_points1, corner_points2);
+}
diff --git a/gsk/resources/glsl/preamble.vs.glsl b/gsk/resources/glsl/preamble.vs.glsl
index 94c4f276a4..1dc4a5e7bf 100644
--- a/gsk/resources/glsl/preamble.vs.glsl
+++ b/gsk/resources/glsl/preamble.vs.glsl
@@ -2,26 +2,72 @@ uniform mat4 u_projection;
 uniform mat4 u_modelview;
 uniform float u_alpha;
 
-#ifdef GSK_GLES
-precision highp float;
-#endif
-
 #if GSK_GLES
-#define _OUT_ varying
-#define _IN_ varying
 attribute vec2 aPosition;
 attribute vec2 aUv;
 _OUT_ vec2 vUv;
 #elif GSK_LEGACY
-#define _OUT_ varying
-#define _IN_ varying
 attribute vec2 aPosition;
 attribute vec2 aUv;
 _OUT_ vec2 vUv;
 #else
-#define _OUT_ out
-#define _IN_ in
 _IN_ vec2 aPosition;
 _IN_ vec2 aUv;
 _OUT_ vec2 vUv;
 #endif
+
+// amount is: top, right, bottom, left
+RoundedRect
+rounded_rect_shrink (RoundedRect r, vec4 amount)
+{
+  vec4 new_bounds = r.bounds + vec4(1.0,1.0,-1.0,-1.0) * amount.wxyz;
+  vec4 new_corner_points1 = r.corner_points1;
+  vec4 new_corner_points2 = r.corner_points2;
+
+  if (r.corner_points1.xy == r.bounds.xy) new_corner_points1.xy = new_bounds.xy;
+  if (r.corner_points1.zw == r.bounds.zy) new_corner_points1.zw = new_bounds.zy;
+  if (r.corner_points2.xy == r.bounds.zw) new_corner_points2.xy = new_bounds.zw;
+  if (r.corner_points2.zw == r.bounds.xw) new_corner_points2.zw = new_bounds.xw;
+
+  return RoundedRect (new_bounds, new_corner_points1, new_corner_points2);
+}
+
+void
+rounded_rect_offset(inout RoundedRect r, vec2 offset)
+{
+  r.bounds.xy += offset;
+  r.bounds.zw += offset;
+  r.corner_points1.xy += offset;
+  r.corner_points1.zw += offset;
+  r.corner_points2.xy += offset;
+  r.corner_points2.zw += offset;
+}
+
+void rounded_rect_transform(inout RoundedRect r, mat4 mat)
+{
+  r.bounds.xy = (mat * vec4(r.bounds.xy, 0.0, 1.0)).xy;
+  r.bounds.zw = (mat * vec4(r.bounds.zw, 0.0, 1.0)).xy;
+
+  r.corner_points1.xy = (mat * vec4(r.corner_points1.xy, 0.0, 1.0)).xy;
+  r.corner_points1.zw = (mat * vec4(r.corner_points1.zw, 0.0, 1.0)).xy;
+
+  r.corner_points2.xy = (mat * vec4(r.corner_points2.xy, 0.0, 1.0)).xy;
+  r.corner_points2.zw = (mat * vec4(r.corner_points2.zw, 0.0, 1.0)).xy;
+}
+
+#if defined(GSK_LEGACY)
+// Can't have out or inout array parameters...
+#define rounded_rect_encode(r, uni) uni[0] = r.bounds; uni[1] = r.corner_points1; uni[2] = r.corner_points2;
+#else
+void rounded_rect_encode(RoundedRect r, out _ROUNDED_RECT_UNIFORM_ out_r)
+{
+#if defined(GSK_GLES)
+  out_r[0] = r.bounds;
+  out_r[1] = r.corner_points1;
+  out_r[2] = r.corner_points2;
+#else
+  out_r = r;
+#endif
+}
+
+#endif
diff --git a/gsk/resources/glsl/unblurred_outset_shadow.glsl b/gsk/resources/glsl/unblurred_outset_shadow.glsl
index c5190d392e..77c02be8e1 100644
--- a/gsk/resources/glsl/unblurred_outset_shadow.glsl
+++ b/gsk/resources/glsl/unblurred_outset_shadow.glsl
@@ -1,7 +1,12 @@
 // VERTEX_SHADER:
 uniform vec4 u_color;
+uniform float u_spread;
+uniform vec2 u_offset;
+uniform vec4[3] u_outline_rect;
 
 _OUT_ vec4 final_color;
+_OUT_ _ROUNDED_RECT_UNIFORM_ transformed_outside_outline;
+_OUT_ _ROUNDED_RECT_UNIFORM_ transformed_inside_outline;
 
 void main() {
   gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);
@@ -9,14 +14,23 @@ void main() {
   final_color = u_color;
   final_color.rgb *= final_color.a;
   final_color *= u_alpha;
+
+  RoundedRect inside = create_rect(u_outline_rect);
+  RoundedRect outside = rounded_rect_shrink(inside, vec4(- u_spread));
+
+  rounded_rect_offset(outside, u_offset);
+
+  rounded_rect_transform(outside, u_modelview);
+  rounded_rect_transform(inside, u_modelview);
+
+  rounded_rect_encode(outside, transformed_outside_outline);
+  rounded_rect_encode(inside, transformed_inside_outline);
 }
 
 // FRAGMENT_SHADER:
-uniform float u_spread;
-uniform vec2 u_offset;
-uniform vec4[3] u_outline_rect;
-
 _IN_ vec4 final_color;
+_IN_ _ROUNDED_RECT_UNIFORM_ transformed_outside_outline;
+_IN_ _ROUNDED_RECT_UNIFORM_ transformed_inside_outline;
 
 void main() {
   vec4 f = gl_FragCoord;
@@ -24,17 +38,9 @@ void main() {
   f.x += u_viewport.x;
   f.y = (u_viewport.y + u_viewport.w) - f.y;
 
-  RoundedRect inside = create_rect(u_outline_rect);
-  RoundedRect outside = rounded_rect_shrink(inside, vec4(- u_spread));
-
-  rounded_rect_offset(outside, u_offset);
-
-  rounded_rect_transform(outside, u_modelview);
-  rounded_rect_transform(inside, u_modelview);
-
-  float alpha = clamp (rounded_rect_coverage (outside, f.xy) -
-                       rounded_rect_coverage (inside, f.xy),
-                       0.0, 1.0);
+  float alpha = clamp(rounded_rect_coverage(decode_rect(transformed_outside_outline), f.xy) -
+                      rounded_rect_coverage(decode_rect(transformed_inside_outline), f.xy),
+                      0.0, 1.0);
 
   setOutputColor(final_color * alpha);
 }


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