[gtk/wip/baedert/for-master: 3/4] gl renderer: Blur shader improvements
- From: Timm Bäder <baedert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/baedert/for-master: 3/4] gl renderer: Blur shader improvements
- Date: Fri, 22 Nov 2019 04:59:16 +0000 (UTC)
commit dc340bcb233962e63922d907236897e65b47de01
Author: Timm Bäder <mail baedert org>
Date: Thu Nov 21 17:21:09 2019 +0100
gl renderer: Blur shader improvements
Use a two-pass shader
gsk/gl/gskglrenderer.c | 93 +++++++++++++++++++++++++++++++++++++----
gsk/gl/gskglrenderopsprivate.h | 2 +-
gsk/resources/glsl/blur.fs.glsl | 61 +++++++++++++--------------
3 files changed, 114 insertions(+), 42 deletions(-)
---
diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c
index bcf179b010..adf92919fa 100644
--- a/gsk/gl/gskglrenderer.c
+++ b/gsk/gl/gskglrenderer.c
@@ -1277,11 +1277,21 @@ render_blur_node (GskGLRenderer *self,
RenderOpBuilder *builder,
GskQuadVertex *vertex_data)
{
+ const float scale = ops_get_scale (builder);
const float blur_radius = gsk_blur_node_get_radius (node);
+ const float texture_width = ceilf (node->bounds.size.width * scale);
+ const float texture_height = ceilf (node->bounds.size.height * scale);
GskRenderNode *child = gsk_blur_node_get_child (node);
TextureRegion region;
gboolean is_offscreen;
OpBlur *op;
+ int prev_render_target;
+ int pass1_texture_id, pass1_render_target;
+ int pass2_texture_id, pass2_render_target;
+ graphene_matrix_t prev_projection;
+ graphene_rect_t prev_viewport;
+ graphene_matrix_t item_proj;
+ GskRoundedRect r = GSK_ROUNDED_RECT_INIT (0, 0, texture_width, texture_height);
if (blur_radius <= 0)
{
@@ -1293,25 +1303,92 @@ render_blur_node (GskGLRenderer *self,
* so the resulting offscreen texture is bigger by the gaussian blur factor
* (see gsk_blur_node_new), but we didn't have to do that if the blur
* shader could handle that situation. */
-
add_offscreen_ops (self, builder,
&node->bounds,
child,
®ion, &is_offscreen,
RESET_CLIP | FORCE_OFFSCREEN | RESET_OPACITY);
+ g_assert (is_offscreen);
+
+ gsk_gl_driver_create_render_target (self->gl_driver,
+ texture_width, texture_height,
+ &pass1_texture_id, &pass1_render_target);
+
+ gsk_gl_driver_create_render_target (self->gl_driver,
+ texture_width, texture_height,
+ &pass2_texture_id, &pass2_render_target);
+
+
+
+ graphene_matrix_init_ortho (&item_proj,
+ 0, texture_width, 0, texture_height,
+ ORTHO_NEAR_PLANE, ORTHO_FAR_PLANE);
+ graphene_matrix_scale (&item_proj, 1, -1, 1);
+
+ prev_projection = ops_set_projection (builder, &item_proj);
+ ops_set_modelview (builder, NULL);
+ prev_viewport = ops_set_viewport (builder, &GRAPHENE_RECT_INIT (0, 0, texture_width, texture_height));
+ ops_push_clip (builder, &r);
+
+ prev_render_target = ops_set_render_target (builder, pass1_render_target);
+ ops_begin (builder, OP_CLEAR);
ops_set_program (builder, &self->blur_program);
op = ops_begin (builder, OP_CHANGE_BLUR);
- graphene_size_init_from_size (&op->size, &node->bounds.size);
+ op->size.width = texture_width;
+ op->size.height = texture_height;
+ op->size.width = node->bounds.size.width;
+ op->size.height = node->bounds.size.height;
op->radius = blur_radius;
-
+ op->dir[0] = 1;
+ op->dir[1] = 0;
ops_set_texture (builder, region.texture_id);
- if (is_offscreen)
- flip_vertex_data_y (vertex_data);
+ ops_draw (builder, (GskQuadVertex[GL_N_VERTICES]) {
+ { { 0, }, { 0, 1 }, },
+ { { 0, texture_height }, { 0, 0 }, },
+ { { texture_width, }, { 1, 1 }, },
- ops_draw (builder, vertex_data);
+ { { texture_width, texture_height }, { 1, 0 }, },
+ { { 0, texture_height }, { 0, 0 }, },
+ { { texture_width, }, { 1, 1 }, },
+ });
+
+ op = ops_begin (builder, OP_CHANGE_BLUR);
+ op->size.width = texture_width;
+ op->size.height = texture_height;
+ op->size.width = texture_width;
+ op->size.height = texture_height;
+ op->size.width = node->bounds.size.width;
+ op->size.height = node->bounds.size.height;
+ op->radius = blur_radius;
+ op->dir[0] = 0;
+ op->dir[1] = 1;
+ ops_set_texture (builder, pass1_texture_id);
+ ops_set_render_target (builder, pass2_render_target);
+ ops_begin (builder, OP_CLEAR);
+ ops_draw (builder, (GskQuadVertex[GL_N_VERTICES]) { /* render pass 2 */
+ { { 0, }, { 0, 1 }, },
+ { { 0, texture_height }, { 0, 0 }, },
+ { { texture_width, }, { 1, 1 }, },
+
+ { { texture_width, texture_height }, { 1, 0 }, },
+ { { 0, texture_height }, { 0, 0 }, },
+ { { texture_width, }, { 1, 1 }, },
+ });
+
+ ops_set_render_target (builder, prev_render_target);
+ ops_set_viewport (builder, &prev_viewport);
+ ops_set_projection (builder, &prev_projection);
+ ops_pop_modelview (builder);
+ ops_pop_clip (builder);
+
+ /* Draw the result */
+ flip_vertex_data_y (vertex_data);
+ ops_set_program (builder, &self->blit_program);
+ ops_set_texture (builder, pass2_texture_id);
+ ops_draw (builder, vertex_data); /* Render result to screen */
}
static inline void
@@ -2282,7 +2359,7 @@ apply_blur_op (const Program *program,
OP_PRINT (" -> Blur");
glUniform1f (program->blur.blur_radius_location, op->radius);
glUniform2f (program->blur.blur_size_location, op->size.width, op->size.height);
- /*glUniform2f (program->blur.dir_location, op->dir[0], op->dir[1]);*/
+ glUniform2f (program->blur.blur_dir_location, op->dir[0], op->dir[1]);
}
static inline void
@@ -2449,7 +2526,7 @@ gsk_gl_renderer_create_programs (GskGLRenderer *self,
/* blur */
INIT_PROGRAM_UNIFORM_LOCATION (blur, blur_radius);
INIT_PROGRAM_UNIFORM_LOCATION (blur, blur_size);
- /*INIT_PROGRAM_UNIFORM_LOCATION (blur, dir);*/
+ INIT_PROGRAM_UNIFORM_LOCATION (blur, blur_dir);
/* inset shadow */
INIT_PROGRAM_UNIFORM_LOCATION (inset_shadow, color);
diff --git a/gsk/gl/gskglrenderopsprivate.h b/gsk/gl/gskglrenderopsprivate.h
index e555653617..93f504f287 100644
--- a/gsk/gl/gskglrenderopsprivate.h
+++ b/gsk/gl/gskglrenderopsprivate.h
@@ -73,7 +73,7 @@ struct _Program
struct {
int blur_radius_location;
int blur_size_location;
- int dir_location;
+ int blur_dir_location;
} blur;
struct {
int color_location;
diff --git a/gsk/resources/glsl/blur.fs.glsl b/gsk/resources/glsl/blur.fs.glsl
index abad1c1f30..14dd40f3f7 100644
--- a/gsk/resources/glsl/blur.fs.glsl
+++ b/gsk/resources/glsl/blur.fs.glsl
@@ -1,39 +1,34 @@
-uniform float u_blur_radius;// = 40.0;
-uniform vec2 u_blur_size;// = vec2(393, 393);
+uniform float u_blur_radius;
+uniform vec2 u_blur_size;
+uniform vec2 u_blur_dir;
-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 / u_blur_size.x);
- float pixel_size_y = (1.0 / u_blur_size.y);
-
- // XXX The magic value here is GAUSSIAN_SCALE_FACTOR from gskcairoblur.c
- float radius = u_blur_radius * 2.30348;
-
- int half_radius = max(int(radius / 2.0), 1);
-
- for (int y = -half_radius; y < half_radius; y ++) {
- float fy = Gaussian (radius / 2.0, float(y));
- float offset_y = float(y) * pixel_size_y;
+const float PI = 3.141;
- for (int x = -half_radius; x < half_radius; x ++) {
- float fx = Gaussian (radius / 2.0, float(x));
- float offset_x = float(x) * pixel_size_x;
-
- vec4 c = Texture(u_source, uv + vec2(offset_x, offset_y));
- total += fx * fy;
- ret += c * fx * fy;
- }
+// Partially from http://callumhay.blogspot.com/2010/09/gaussian-blur-shader-glsl.html
+void main() {
+ float sigma = u_blur_radius / 2.0;
+ vec3 incrementalGaussian;
+ incrementalGaussian.x = 1.0 / (sqrt(2.0 * PI) * sigma);
+ incrementalGaussian.y = exp(-0.5 / (sigma * sigma));
+ incrementalGaussian.z = incrementalGaussian.y * incrementalGaussian.y;
+
+ vec2 blur = vec2(1.0) / u_blur_size;
+ float coefficientSum = 0;
+
+ vec4 sum = Texture(u_source, vUv) * incrementalGaussian.x;
+ coefficientSum += incrementalGaussian.x;
+ incrementalGaussian.xy *= incrementalGaussian.yz;
+
+ int pixels_per_side = int(floor(u_blur_radius / 2.0));
+ for (int i = 1; i <= pixels_per_side; i++) {
+ sum += Texture(u_source, vUv.xy - i * blur * u_blur_dir) * incrementalGaussian.x;
+ sum += Texture(u_source, vUv.xy + i * blur * u_blur_dir) * incrementalGaussian.x;
+
+ coefficientSum += 2 * incrementalGaussian.x;
+ incrementalGaussian.xy *= incrementalGaussian.yz;
}
- return ret / total;
-}
+ sum /= coefficientSum;
-void main() {
- vec4 color = blur_pixel(vUv);
- setOutputColor(color);
+ setOutputColor(sum);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]