diff options
Diffstat (limited to 'source/blender')
4 files changed, 135 insertions, 65 deletions
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]; + fragColor.a += sample_glyph_offset(texco, texel, offsets25[ 4]) * weights25[ 4]; + fragColor.a += sample_glyph_offset(texco, texel, offsets25[ 5]) * weights25[ 5]; + fragColor.a += sample_glyph_offset(texco, texel, offsets25[ 6]) * weights25[ 6]; + fragColor.a += sample_glyph_offset(texco, texel, offsets25[ 7]) * weights25[ 7]; + fragColor.a += sample_glyph_offset(texco, texel, offsets25[ 8]) * weights25[ 8]; + fragColor.a += sample_glyph_offset(texco, texel, offsets25[ 9]) * weights25[ 9]; + fragColor.a += sample_glyph_offset(texco, texel, offsets25[10]) * weights25[10]; + fragColor.a += sample_glyph_offset(texco, texel, offsets25[11]) * weights25[11]; + fragColor.a += sample_glyph_offset(texco, texel, offsets25[12]) * weights25[12]; + fragColor.a += sample_glyph_offset(texco, texel, offsets25[13]) * weights25[13]; + fragColor.a += sample_glyph_offset(texco, texel, offsets25[14]) * weights25[14]; + fragColor.a += sample_glyph_offset(texco, texel, offsets25[15]) * weights25[15]; + fragColor.a += sample_glyph_offset(texco, texel, offsets25[16]) * weights25[16]; + fragColor.a += sample_glyph_offset(texco, texel, offsets25[17]) * weights25[17]; + fragColor.a += sample_glyph_offset(texco, texel, offsets25[18]) * weights25[18]; + fragColor.a += sample_glyph_offset(texco, texel, offsets25[19]) * weights25[19]; + fragColor.a += sample_glyph_offset(texco, texel, offsets25[20]) * weights25[20]; + fragColor.a += sample_glyph_offset(texco, texel, offsets25[21]) * weights25[21]; + fragColor.a += sample_glyph_offset(texco, texel, offsets25[22]) * weights25[22]; + fragColor.a += sample_glyph_offset(texco, texel, offsets25[23]) * weights25[23]; + fragColor.a += sample_glyph_offset(texco, texel, offsets25[24]) * weights25[24]; + } + } + + fragColor.a *= color_flat.a; } diff --git a/source/blender/gpu/shaders/gpu_shader_text_geom.glsl b/source/blender/gpu/shaders/gpu_shader_text_geom.glsl index d4d86db6bc3..0acd2106f7a 100644 --- a/source/blender/gpu/shaders/gpu_shader_text_geom.glsl +++ b/source/blender/gpu/shaders/gpu_shader_text_geom.glsl @@ -9,26 +9,28 @@ in vec4 tex_rect[]; in vec4 color[]; flat out vec4 color_flat; +flat out vec4 texCoord_rect; noperspective out vec2 texCoord_interp; void main() { color_flat = color[0]; + texCoord_rect = tex_rect[0]; gl_Position = (ModelViewProjectionMatrix * vec4(pos_rect[0].xy, 0.0, 1.0)); - texCoord_interp = tex_rect[0].xy; + texCoord_interp = vec2(0.0, 0.0); EmitVertex(); gl_Position = (ModelViewProjectionMatrix * vec4(pos_rect[0].zy, 0.0, 1.0)); - texCoord_interp = tex_rect[0].zy; + texCoord_interp = vec2(1.0, 0.0); EmitVertex(); gl_Position = (ModelViewProjectionMatrix * vec4(pos_rect[0].xw, 0.0, 1.0)); - texCoord_interp = tex_rect[0].xw; + texCoord_interp = vec2(0.0, 1.0); EmitVertex(); gl_Position = (ModelViewProjectionMatrix * vec4(pos_rect[0].zw, 0.0, 1.0)); - texCoord_interp = tex_rect[0].zw; + texCoord_interp = vec2(1.0, 1.0); EmitVertex(); EndPrimitive(); diff --git a/source/blender/gpu/shaders/gpu_shader_text_simple_geom.glsl b/source/blender/gpu/shaders/gpu_shader_text_simple_geom.glsl index 79dc996997b..8903fd1df57 100644 --- a/source/blender/gpu/shaders/gpu_shader_text_simple_geom.glsl +++ b/source/blender/gpu/shaders/gpu_shader_text_simple_geom.glsl @@ -7,27 +7,29 @@ in vec4 tex_rect[]; in vec4 color[]; flat out vec4 color_flat; +flat out vec4 texCoord_rect; noperspective out vec2 texCoord_interp; void main() { color_flat = color[0]; + texCoord_rect = tex_rect[0]; gl_Position.zw = vec2(0.0, 1.0); gl_Position.xy = pos_rect[0].xy; - texCoord_interp = tex_rect[0].xy; + texCoord_interp = vec2(0.0, 0.0); EmitVertex(); gl_Position.xy = pos_rect[0].zy; - texCoord_interp = tex_rect[0].zy; + texCoord_interp = vec2(1.0, 0.0); EmitVertex(); gl_Position.xy = pos_rect[0].xw; - texCoord_interp = tex_rect[0].xw; + texCoord_interp = vec2(0.0, 1.0); EmitVertex(); gl_Position.xy = pos_rect[0].zw; - texCoord_interp = tex_rect[0].zw; + texCoord_interp = vec2(1.0, 1.0); EmitVertex(); EndPrimitive(); |