[Bf-blender-cvs] [987c56c4b61] blender2.8: BLF: Opti: Draw only one quad per shadow/blurred glyph.

Clément Foucault noreply at git.blender.org
Sun Apr 8 00:54:38 CEST 2018


Commit: 987c56c4b6150afb67af245f7d71bc965ed5ffc8
Author: Clément Foucault
Date:   Sun Apr 8 00:44:35 2018 +0200
Branches: blender2.8
https://developer.blender.org/rB987c56c4b6150afb67af245f7d71bc965ed5ffc8

BLF: Opti: Draw only one quad per shadow/blurred glyph.

This port the Blurring of blf fonts to the final drawing shader.

We add a bit of extra padding to each glyph so that jittering the texture
coord does not sample the neighbor glyphs.

===================================================================

M	source/blender/blenfont/intern/blf_glyph.c
M	source/blender/gpu/shaders/gpu_shader_text_frag.glsl
M	source/blender/gpu/shaders/gpu_shader_text_geom.glsl
M	source/blender/gpu/shaders/gpu_shader_text_simple_geom.glsl

===================================================================

diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c
index 6183b54ebcc..03d5b3ea07f 100644
--- a/source/blender/blenfont/intern/blf_glyph.c
+++ b/source/blender/blenfont/intern/blf_glyph.c
@@ -150,9 +150,9 @@ GlyphCacheBLF *blf_glyph_cache_new(FontBLF *font)
 	gc->textures = (GLuint *)MEM_mallocN(sizeof(GLuint) * 256, __func__);
 	gc->textures_len = 256;
 	gc->texture_current = BLF_TEXTURE_UNSET;
-	gc->offset_x = 0;
-	gc->offset_y = 0;
-	gc->pad = 3;
+	gc->offset_x = 3; /* enough padding for blur */
+	gc->offset_y = 3; /* enough padding for blur */
+	gc->pad = 6;
 
 	gc->glyphs_len_max = (int)font->face->num_glyphs;
 	gc->glyphs_len_free = (int)font->face->num_glyphs;
@@ -375,7 +375,7 @@ void blf_glyph_free(GlyphBLF *g)
 	MEM_freeN(g);
 }
 
-static void blf_texture_draw(const unsigned char color[4], float uv[2][2], float x1, float y1, float x2, float y2)
+static void blf_texture_draw(const unsigned char color[4], const float uv[2][2], float x1, float y1, float x2, float y2)
 {
 	/* Only one vertex per glyph, geometry shader expand it into a quad. */
 	/* TODO Get rid of Geom Shader because it's not optimal AT ALL for the GPU */
@@ -390,54 +390,34 @@ static void blf_texture_draw(const unsigned char color[4], float uv[2][2], float
 	}
 }
 
-static void blf_texture5_draw(const unsigned char color_in[4], float uv[2][2], float x1, float y1, float x2, float y2)
+static void blf_texture5_draw(const unsigned char color_in[4], int tex_w, int tex_h, const float uv[2][2],
+                              float x1, float y1, float x2, float y2)
 {
-	const float soft[25] = {1 / 60.0f, 1 / 60.0f, 2 / 60.0f, 1 / 60.0f, 1 / 60.0f,
-	                        1 / 60.0f, 3 / 60.0f, 5 / 60.0f, 3 / 60.0f, 1 / 60.0f,
-	                        2 / 60.0f, 5 / 60.0f, 8 / 60.0f, 5 / 60.0f, 2 / 60.0f,
-	                        1 / 60.0f, 3 / 60.0f, 5 / 60.0f, 3 / 60.0f, 1 / 60.0f,
-	                        1 / 60.0f, 1 / 60.0f, 2 / 60.0f, 1 / 60.0f, 1 / 60.0f};
-
-	const float *fp = soft;
-	unsigned char color[4];
-	float dx, dy;
-
-	color[0] = color_in[0];
-	color[1] = color_in[1];
-	color[2] = color_in[2];
-
-	const float alpha_in = (1 / 255.0f) * color_in[3];
-
-	for (dx = -2; dx < 3; dx++) {
-		for (dy = -2; dy < 3; dy++, fp++) {
-			color[3] = FTOCHAR(*fp * alpha_in);
-			blf_texture_draw(color, uv, x1 + dx, y1 + dy, x2 + dx, y2 + dy);
-		}
-	}
+	float ofs[2] = { 2 / (float)tex_w, 2 / (float)tex_h };
+	float uv_flag[2][2];
+	copy_v4_v4((float *)uv_flag, (float *)uv);
+	/* flag the x and y component signs for 5x5 bluring */
+	uv_flag[0][0] = -(uv_flag[0][0] - ofs[0]);
+	uv_flag[0][1] = -(uv_flag[0][1] - ofs[1]);
+	uv_flag[1][0] = -(uv_flag[1][0] + ofs[0]);
+	uv_flag[1][1] = -(uv_flag[1][1] + ofs[1]);
+
+	blf_texture_draw(color_in, uv_flag, x1 - 2, y1 + 2, x2 + 2, y2 - 2);
 }
 
-static void blf_texture3_draw(const unsigned char color_in[4], float uv[2][2], float x1, float y1, float x2, float y2)
+static void blf_texture3_draw(const unsigned char color_in[4], int tex_w, int tex_h, const float uv[2][2],
+                              float x1, float y1, float x2, float y2)
 {
-	const float soft[9] = {1 / 16.0f, 2 / 16.0f, 1 / 16.0f,
-	                       2 / 16.0f, 4 / 16.0f, 2 / 16.0f,
-	                       1 / 16.0f, 2 / 16.0f, 1 / 16.0f};
-
-	const float *fp = soft;
-	unsigned char color[4];
-	float dx, dy;
-
-	color[0] = color_in[0];
-	color[1] = color_in[1];
-	color[2] = color_in[2];
-
-	const float alpha_in = (1 / 255.0f) * color_in[3];
-
-	for (dx = -1; dx < 2; dx++) {
-		for (dy = -1; dy < 2; dy++, fp++) {
-			color[3] = FTOCHAR(*fp * alpha_in);
-			blf_texture_draw(color, uv, x1 + dx, y1 + dy, x2 + dx, y2 + dy);
-		}
-	}
+	float ofs[2] = { 1 / (float)tex_w, 1 / (float)tex_h };
+	float uv_flag[2][2];
+	copy_v4_v4((float *)uv_flag, (float *)uv);
+	/* flag the x component sign for 3x3 bluring */
+	uv_flag[0][0] = -(uv_flag[0][0] - ofs[0]);
+	uv_flag[0][1] =  (uv_flag[0][1] - ofs[1]);
+	uv_flag[1][0] = -(uv_flag[1][0] + ofs[0]);
+	uv_flag[1][1] =  (uv_flag[1][1] + ofs[1]);
+
+	blf_texture_draw(color_in, uv_flag, x1 - 1, y1 + 1, x2 + 1, y2 - 1);
 }
 
 static void blf_glyph_calc_rect(rctf *rect, GlyphBLF *g, float x, float y)
@@ -466,7 +446,7 @@ void blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y)
 		if (gc->texture_current == BLF_TEXTURE_UNSET) {
 			blf_glyph_cache_texture(font, gc);
 			gc->offset_x = gc->pad;
-			gc->offset_y = 0;
+			gc->offset_y = 3; /* enough padding for blur */
 		}
 
 		if (gc->offset_x > (gc->p2_width - gc->glyph_width_max)) {
@@ -474,7 +454,7 @@ void blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y)
 			gc->offset_y += gc->glyph_height_max;
 
 			if (gc->offset_y > (gc->p2_height - gc->glyph_height_max)) {
-				gc->offset_y = 0;
+				gc->offset_y = 3; /* enough padding for blur */
 				blf_glyph_cache_texture(font, gc);
 			}
 		}
@@ -540,8 +520,6 @@ void blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y)
 		glBindTexture(GL_TEXTURE_2D, (font->tex_bind_state = g->tex));
 	}
 
-	/* TODO: blur & shadow in shader, single quad per glyph */
-
 	if (font->flags & BLF_SHADOW) {
 		rctf rect_ofs;
 		blf_glyph_calc_rect(&rect_ofs, g,
@@ -552,20 +530,24 @@ void blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y)
 			blf_texture_draw(font->shadow_color, g->uv, rect_ofs.xmin, rect_ofs.ymin, rect_ofs.xmax, rect_ofs.ymax);
 		}
 		else if (font->shadow <= 4) {
-			blf_texture3_draw(font->shadow_color, g->uv, rect_ofs.xmin, rect_ofs.ymin, rect_ofs.xmax, rect_ofs.ymax);
+			blf_texture3_draw(font->shadow_color, font->glyph_cache->p2_width, font->glyph_cache->p2_height, g->uv,
+			                  rect_ofs.xmin, rect_ofs.ymin, rect_ofs.xmax, rect_ofs.ymax);
 		}
 		else {
-			blf_texture5_draw(font->shadow_color, g->uv, rect_ofs.xmin, rect_ofs.ymin, rect_ofs.xmax, rect_ofs.ymax);
+			blf_texture5_draw(font->shadow_color, font->glyph_cache->p2_width, font->glyph_cache->p2_height, g->uv,
+			                  rect_ofs.xmin, rect_ofs.ymin, rect_ofs.xmax, rect_ofs.ymax);
 		}
 	}
 
 #if BLF_BLUR_ENABLE
 	switch (font->blur) {
 		case 3:
-			blf_texture3_draw(font->color, g->uv, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+			blf_texture3_draw(font->color, font->glyph_cache->p2_width, font->glyph_cache->p2_height, g->uv,
+			                  rect.xmin, rect.ymin, rect.xmax, rect.ymax);
 			break;
 		case 5:
-			blf_texture5_draw(font->color, g->uv, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+			blf_texture5_draw(font->color, font->glyph_cache->p2_width, font->glyph_cache->p2_height, g->uv,
+			                  rect.xmin, rect.ymin, rect.xmax, rect.ymax);
 			break;
 		default:
 			blf_texture_draw(font->color, g->uv, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
diff --git a/source/blender/gpu/shaders/gpu_shader_text_frag.glsl b/source/blender/gpu/shaders/gpu_shader_text_frag.glsl
index 7ff90ad4f21..3e5fdd8b90b 100644
--- a/source/blender/gpu/shaders/gpu_shader_text_frag.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_text_frag.glsl
@@ -1,15 +1,99 @@
 
 flat in vec4 color_flat;
+flat in vec4 texCoord_rect;
 noperspective in vec2 texCoord_interp;
 out vec4 fragColor;
 
 uniform sampler2D glyph;
 
+const vec2 offsets9[9] = vec2[9](
+	vec2(-1.0, -1.0), vec2( 0.0, -1.0), vec2( 1.0, -1.0),
+	vec2(-1.0,  0.0), vec2( 0.0,  0.0), vec2( 1.0,  0.0),
+	vec2(-1.0,  1.0), vec2( 0.0,  1.0), vec2( 1.0,  1.0)
+);
+
+const vec2 offsets25[25] = vec2[25](
+	vec2(-2.0, -2.0), vec2(-1.0, -2.0), vec2( 0.0, -2.0), vec2( 1.0, -2.0), vec2( 2.0, -2.0),
+	vec2(-2.0, -1.0), vec2(-1.0, -1.0), vec2( 0.0, -1.0), vec2( 1.0, -1.0), vec2( 2.0, -1.0),
+	vec2(-2.0,  0.0), vec2(-1.0,  0.0), vec2( 0.0,  0.0), vec2( 1.0,  0.0), vec2( 2.0,  0.0),
+	vec2(-2.0,  1.0), vec2(-1.0,  1.0), vec2( 0.0,  1.0), vec2( 1.0,  1.0), vec2( 2.0,  1.0),
+	vec2(-2.0,  2.0), vec2(-1.0,  2.0), vec2( 0.0,  2.0), vec2( 1.0,  2.0), vec2( 2.0,  2.0)
+);
+
+const float weights9[9] = float[9](
+	1.0 / 16.0, 2.0 / 16.0, 1.0 / 16.0,
+	2.0 / 16.0, 4.0 / 16.0, 2.0 / 16.0,
+	1.0 / 16.0, 2.0 / 16.0, 1.0 / 16.0
+);
+
+const float weights25[25] = float[25](
+	1.0 / 60.0, 1.0 / 60.0, 2.0 / 60.0, 1.0 / 60.0, 1.0 / 60.0,
+	1.0 / 60.0, 3.0 / 60.0, 5.0 / 60.0, 3.0 / 60.0, 1.0 / 60.0,
+	2.0 / 60.0, 5.0 / 60.0, 8.0 / 60.0, 5.0 / 60.0, 2.0 / 60.0,
+	1.0 / 60.0, 3.0 / 60.0, 5.0 / 60.0, 3.0 / 60.0, 1.0 / 60.0,
+	1.0 / 60.0, 1.0 / 60.0, 2.0 / 60.0, 1.0 / 60.0, 1.0 / 60.0
+);
+
+#define sample_glyph_offset(texco, texel, ofs) texture(glyph, texco + ofs * texel).r
+
 void main()
 {
 	// input color replaces texture color
 	fragColor.rgb = color_flat.rgb;
 
+	vec2 texel = 1.0 / vec2(textureSize(glyph, 0));
+	vec2 texco = mix(abs(texCoord_rect.xy), abs(texCoord_rect.zw), texCoord_interp);
+
 	// modulate input alpha & texture alpha
-	fragColor.a = color_flat.a * texture(glyph, texCoord_interp).r;
+	if (texCoord_rect.x > 0) {
+		fragColor.a = texture(glyph, texco).r;
+	}
+	else {
+		fragColor.a = 0.0;
+
+		if (texCoord_rect.w > 0) {
+			/* 3x3 blur */
+			/* Manual unroll for perf. (stupid glsl compiler) */
+			fragColor.a += sample_glyph_offset(texco, texel, offsets9[0]) * weights9[0];
+			fragColor.a += sample_glyph_offset(texco, texel, offsets9[1]) * weights9[1];
+			fragColor.a += sample_glyph_offset(texco, texel, offsets9[2]) * weights9[2];
+			fragColor.a += sample_glyph_offset(texco, texel, offsets9[3]) * weights9[3];
+			fragColor.a += sample_glyph_offset(texco, texel, offsets9[4]) * weights9[4];
+			fragColor.a += sample_glyph_offset(texco, texel, offsets9[5]) * weights9[5];
+			fragColor.a += sample_glyph_offset(texco, texel, offsets9[6]) * weights9[6];
+			fragColor.a += sample_glyph_offset(texco, texel, offsets9[7]) * weights9[7];
+			fragColor.a += sample_glyph_offset(texco, texel, offsets9[8]) * weights9[8];
+		}
+		else {
+			/* 5x5 blur */
+			/* Manual unroll for perf. (stupid glsl compiler) */
+			fragColor.a += sample_glyph_offset(texco, texel, offsets25[ 0]) * weights25[ 0];
+			fragColor.a += sample_glyph_offset(texco, texel, offsets25[ 1]) * weights25[ 1];
+			fragColor.a += sample_glyph_offset(texco, texel, offsets25[ 2]) * weights25[ 2];
+			fragColor.a += sample_glyph_offset(texco, texel, offsets25[ 3]) * weights25[ 3];

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list