diff --git a/include/gfx/font.h b/include/gfx/font.h index 65ab5af..993b038 100644 --- a/include/gfx/font.h +++ b/include/gfx/font.h @@ -132,7 +132,7 @@ int gfx_get_font_space(void); SDL_Color gfx_get_font_color(void); void gfx_set_font_name(const char *name); -int gfx_render_text(Texture *dst, float x, int y, char *msg, struct text_style *ts); +int gfx_render_text(Texture *dst, float x, int y, char *msg, struct text_style *ts, bool blend); void gfx_draw_text_to_amap(Texture *dst, int x, int y, char *text); void gfx_draw_text_to_pmap(Texture *dst, int x, int y, char *text); float gfx_size_char(struct text_style *ts, const char *ch); diff --git a/include/gfx/gfx.h b/include/gfx/gfx.h index e897d18..966c632 100644 --- a/include/gfx/gfx.h +++ b/include/gfx/gfx.h @@ -170,7 +170,7 @@ void gfx_copy_stretch_with_alpha_map(Texture *dst, int dx, int dy, int dw, int d void gfx_copy_grayscale(Texture *dst, int dx, int dy, Texture *src, int sx, int sy, int w, int h); void gfx_draw_line(Texture *dst, int x0, int y0, int x1, int y1, int r, int g, int b); void gfx_draw_line_to_amap(Texture *dst, int x0, int y0, int x1, int y1, int a); -void gfx_draw_glyph(Texture *dst, float dx, int dy, Texture *glyph, SDL_Color color, float scale_x, float bold_width); +void gfx_draw_glyph(Texture *dst, float dx, int dy, Texture *glyph, SDL_Color color, float scale_x, float bold_width, bool blend); void gfx_draw_glyph_to_pmap(Texture *dst, float dx, int dy, Texture *glyph, Rectangle glyph_pos, SDL_Color color, float scale_x); void gfx_draw_glyph_to_amap(Texture *dst, float dx, int dy, Texture *glyph, Rectangle glyph_pos, float scale_x); diff --git a/shaders/blend_rmap_color.f.glsl b/shaders/blend_rmap_color.f.glsl index f10b608..9621af7 100644 --- a/shaders/blend_rmap_color.f.glsl +++ b/shaders/blend_rmap_color.f.glsl @@ -15,12 +15,14 @@ */ uniform sampler2D tex; -uniform vec4 color; +uniform vec4 color; // .a is the discard threshold in vec2 tex_coord; out vec4 frag_color; void main() { - vec4 texel = texture(tex, tex_coord); - frag_color = vec4(color.rgb, texel.r * color.a); + vec4 texel = texture(tex, tex_coord); + if (texel.r < color.a) + discard; + frag_color = vec4(color.rgb, texel.r); } diff --git a/shaders/dilate.f.glsl b/shaders/dilate.f.glsl index 4497bdc..9993dfe 100644 --- a/shaders/dilate.f.glsl +++ b/shaders/dilate.f.glsl @@ -16,7 +16,7 @@ uniform sampler2D tex; uniform float threshold; -uniform vec4 color; +uniform vec4 color; // .a is the discard threshold in vec2 tex_coord; out vec4 frag_color; @@ -43,5 +43,7 @@ void main() { } } + if (a_out < color.a) + discard; frag_color = vec4(color.rgb, min(a_out, 1.0)); } diff --git a/src/draw.c b/src/draw.c index ecfbf45..f0cb753 100644 --- a/src/draw.c +++ b/src/draw.c @@ -1118,29 +1118,23 @@ void gfx_draw_line_to_amap(Texture *dst, int x0, int y0, int x1, int y1, int a) } // XXX: Not an actual DrawGraph function; used for rendering text -void gfx_draw_glyph(Texture *dst, float dx, int dy, Texture *glyph, SDL_Color color, float scale_x, float bold_width) +void gfx_draw_glyph(Texture *dst, float dx, int dy, Texture *glyph, SDL_Color color, float scale_x, float bold_width, bool blend) { + if (blend) { + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE); + } else { + glBlendFunc(GL_ONE, GL_ZERO); + glBlendEquationSeparate(GL_FUNC_ADD, GL_MAX); + } + dx = roundf(dx); - - glBlendFuncSeparate(GL_ONE, GL_ZERO, GL_ZERO, GL_ONE); - struct copy_data fill_data = COPY_DATA(dx, dy, dx, dy, glyph->w * scale_x, glyph->h); - fill_data.r = color.r / 255.0; - fill_data.g = color.g / 255.0; - fill_data.b = color.b / 255.0; - fill_data.a = 0.0; - fill_data.threshold = 0.001; - run_copy_shader(&fill_amap_under_border_shader.s, dst, dst, &fill_data); - - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glBlendEquationSeparate(GL_FUNC_ADD, GL_MAX); - struct copy_data data = STRETCH_DATA( dx, dy, glyph->w * scale_x, glyph->h, 0, 0, glyph->w, glyph->h); data.r = color.r / 255.0; data.g = color.g / 255.0; data.b = color.b / 255.0; - data.a = 1.0; + data.a = 0.01; // discard threshold if (bold_width < 0.01) { run_copy_shader(&blend_rmap_color_shader.s, dst, glyph, &data); @@ -1160,7 +1154,7 @@ void gfx_draw_glyph_to_pmap(Texture *dst, float dx, int dy, Texture *glyph, Rect data.r = color.r / 255.0; data.g = color.g / 255.0; data.b = color.b / 255.0; - data.a = 1.0; + data.a = 0.01; // discard threshold glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE); run_copy_shader(&blend_rmap_color_shader.s, dst, glyph, &data); restore_blend_mode(); @@ -1174,7 +1168,7 @@ void gfx_draw_glyph_to_amap(Texture *dst, float dx, int dy, Texture *glyph, Rect data.r = 1.0; data.g = 1.0; data.b = 1.0; - data.a = 1.0; + data.a = 0.0; // discard threshold glBlendFuncSeparate(GL_ZERO, GL_ONE, GL_ONE, GL_ZERO); run_copy_shader(&blend_rmap_color_shader.s, dst, glyph, &data); restore_blend_mode(); diff --git a/src/hll/CharSpriteManager.c b/src/hll/CharSpriteManager.c index 219523b..4f77854 100644 --- a/src/hll/CharSpriteManager.c +++ b/src/hll/CharSpriteManager.c @@ -181,7 +181,7 @@ static void charsprite_render(struct charsprite *cs) sprite_init_color(&cs->sp, w, h, 0, 0, 0, 0); sprite_get_texture(&cs->sp); // XXX: force initialization of texture - gfx_render_text(&cs->sp.texture, 0.0f, 0, ch, &cs->ts); + gfx_render_text(&cs->sp.texture, 0.0f, 0, ch, &cs->ts, false); sprite_dirty(&cs->sp); } diff --git a/src/hll/Gpx2Plus.c b/src/hll/Gpx2Plus.c index 2a3458c..31cd3f6 100644 --- a/src/hll/Gpx2Plus.c +++ b/src/hll/Gpx2Plus.c @@ -529,7 +529,7 @@ static void Gpx2Plus_MsgDraw(int surface, int x, int y) skiplen = strlen(s); } pos.y += line_height - ts.size; // bottom align - pos.x += gfx_render_text(dst, pos.x, pos.y, s, &ts); + pos.x += gfx_render_text(dst, pos.x, pos.y, s, &ts, true); pos.y -= line_height - ts.size; if (lb) *lb = '<'; diff --git a/src/hll/SengokuRanceFont.c b/src/hll/SengokuRanceFont.c index 71dd02b..581ecc0 100644 --- a/src/hll/SengokuRanceFont.c +++ b/src/hll/SengokuRanceFont.c @@ -343,7 +343,7 @@ static float sp_text_draw(struct sact_sprite *sp, struct sr_text_properties *tp, tp->last_char = last_char; sprite_dirty(sp); - return gfx_render_text(tex, x ,y, text->text, &tp->ts); + return gfx_render_text(tex, x ,y, text->text, &tp->ts, false); } static void SengokuRanceFont_SP_TextDraw(int sp_no, struct string *text) diff --git a/src/hll/StoatSpriteEngine.c b/src/hll/StoatSpriteEngine.c index 6ccc647..d11d8f1 100644 --- a/src/hll/StoatSpriteEngine.c +++ b/src/hll/StoatSpriteEngine.c @@ -120,7 +120,7 @@ bool StoatSpriteEngine_SP_SetTextSprite(int sp_no, struct string *text) w /= 2; struct sact_sprite *sp = sact_create_sprite(sp_no, w, h, 0, 0, 0, 0); sprite_get_texture(sp); // XXX: force initialization of texture - gfx_render_text(&sp->texture, 0.0f, 0, s, &text_sprite_ts); + gfx_render_text(&sp->texture, 0.0f, 0, s, &text_sprite_ts, false); sprite_dirty(sp); return true; } @@ -457,7 +457,7 @@ static bool StoatSpriteEngine_MultiSprite_SetText(int type, int n, struct string int h = ms->ts.size; sprite_init_color(&ms->sp, w, h, 0, 0, 0, 0); sprite_get_texture(&ms->sp); // XXX: force initialization of texture - gfx_render_text(&ms->sp.texture, 0.0f, 0, text->text, &ms->ts); + gfx_render_text(&ms->sp.texture, 0.0f, 0, text->text, &ms->ts, false); sprite_dirty(&ms->sp); ms->cg = 1; diff --git a/src/hll/vmDrawMsg.c b/src/hll/vmDrawMsg.c index e03922a..cebf738 100644 --- a/src/hll/vmDrawMsg.c +++ b/src/hll/vmDrawMsg.c @@ -161,17 +161,17 @@ static int vmDrawMsg_Draw(int handle) struct vm_surface *sf = vm_surface_get(dm->surfaces[SURFACE_DROP_SHADOW]); int x = dm->pos.x + dm->style.drop_shadow; int y = dm->pos.y + dm->style.drop_shadow; - gfx_render_text(&sf->texture, x, y, s, &ts); + gfx_render_text(&sf->texture, x, y, s, &ts, false); } if (dm->style.bold) { struct text_style ts = dm->style.ts; ts.bold_width = dm->style.bold; ts.color = dm->style.bold_color; struct vm_surface *sf = vm_surface_get(dm->surfaces[SURFACE_BOLD]); - gfx_render_text(&sf->texture, dm->pos.x, dm->pos.y, s, &ts); + gfx_render_text(&sf->texture, dm->pos.x, dm->pos.y, s, &ts, false); } struct vm_surface *sf = vm_surface_get(dm->surfaces[SURFACE_TEXT]); - dm->pos.x += gfx_render_text(&sf->texture, dm->pos.x, dm->pos.y, s, &dm->style.ts); + dm->pos.x += gfx_render_text(&sf->texture, dm->pos.x, dm->pos.y, s, &dm->style.ts, false); if (lb) *lb = '<'; } else if (sscanf(s, "%n", &a1, &a2, &a3, &skiplen) == 3) { diff --git a/src/parts/construction.c b/src/parts/construction.c index fa58d9d..61772ed 100644 --- a/src/parts/construction.c +++ b/src/parts/construction.c @@ -352,7 +352,7 @@ static void build_copy_cut_cg(struct parts_construction_process *cproc, struct p static void build_draw_text(struct parts_construction_process *cproc, struct parts_cp_text *op) { - gfx_render_text(&cproc->common.texture, op->x, op->y, op->text->text, &op->style); + gfx_render_text(&cproc->common.texture, op->x, op->y, op->text->text, &op->style, true); } static void build_copy_text(struct parts_construction_process *cproc, struct parts_cp_text *op) @@ -361,7 +361,7 @@ static void build_copy_text(struct parts_construction_process *cproc, struct par int h = ceilf(op->style.size + op->style.edge_up + op->style.edge_down); gfx_fill_with_alpha(&cproc->common.texture, op->x, op->y, w, h, op->style.edge_color.r, op->style.edge_color.g, op->style.edge_color.b, 0); - gfx_render_text(&cproc->common.texture, op->x, op->y, op->text->text, &op->style); + gfx_render_text(&cproc->common.texture, op->x, op->y, op->text->text, &op->style, false); } bool parts_build_construction_process(struct parts *parts, diff --git a/src/parts/text.c b/src/parts/text.c index 425d50c..617b39b 100644 --- a/src/parts/text.c +++ b/src/parts/text.c @@ -83,7 +83,7 @@ static const char *parts_text_append_char(struct parts_text *t, const char *str) int width = text_style_width(&t->ts, ch->ch); int height = text_style_height(&t->ts); gfx_init_texture_rgba(&ch->t, width, height, (SDL_Color){0,0,0,0}); - ch->advance = gfx_render_text(&ch->t, 0, 0, ch->ch, &t->ts); + ch->advance = gfx_render_text(&ch->t, 0, 0, ch->ch, &t->ts, false); line->width += width; line->height = max(line->height, height); diff --git a/src/sprite.c b/src/sprite.c index 7946242..d71b598 100644 --- a/src/sprite.c +++ b/src/sprite.c @@ -372,17 +372,11 @@ void sprite_set_text_pos(struct sact_sprite *sp, int x, int y) void sprite_text_draw(struct sact_sprite *sp, struct string *text, struct text_style *ts) { if (!sp->text.texture.handle) { - SDL_Color c; - if (text_style_has_edge(ts)) - c = ts->edge_color; - else - c = ts->color; - c.a = 0; - gfx_init_texture_rgba(&sp->text.texture, sp->rect.w, sp->rect.h, c); + gfx_init_texture_rgba(&sp->text.texture, sp->rect.w, sp->rect.h, COLOR(0, 0, 0, 0)); } ts->font_spacing = sp->text.char_space; - sp->text.pos.x += gfx_render_text(&sp->text.texture, sp->text.pos.x, sp->text.pos.y, text->text, ts); + sp->text.pos.x += gfx_render_text(&sp->text.texture, sp->text.pos.x, sp->text.pos.y, text->text, ts, false); if (sp->text.current_line_height < ts->size) sp->text.current_line_height = ts->size; sprite_dirty(sp); diff --git a/src/text.c b/src/text.c index 0a1e9cc..cdbab65 100644 --- a/src/text.c +++ b/src/text.c @@ -201,6 +201,7 @@ float gfx_get_actual_font_size_round_down(unsigned face, float size) } enum text_render_mode { + RENDER_COPY, RENDER_BLENDED, RENDER_PMAP, RENDER_AMAP, @@ -237,10 +238,14 @@ static int render_text(Texture *dst, char *msg, struct text_render_metrics *tm) // render glyph Texture *t = &glyph->t[tm->weight]; - if (tm->mode == RENDER_BLENDED) { + if (tm->mode == RENDER_COPY) { float x = pos_x - glyph->rect.x; int y = pos_y - glyph->rect.y; - gfx_draw_glyph(dst, x, y, t, tm->color, config.text_x_scale, tm->edge_width); + gfx_draw_glyph(dst, x, y, t, tm->color, config.text_x_scale, tm->edge_width, false); + } else if (tm->mode == RENDER_BLENDED) { + float x = pos_x - glyph->rect.x; + int y = pos_y - glyph->rect.y; + gfx_draw_glyph(dst, x, y, t, tm->color, config.text_x_scale, tm->edge_width, true); } else if (tm->mode == RENDER_PMAP) { gfx_draw_glyph_to_pmap(dst, pos_x, pos_y, t, glyph->rect, tm->color, config.text_x_scale); } else if (tm->mode == RENDER_AMAP) { @@ -271,11 +276,12 @@ static enum font_weight int_to_font_weight(int weight) return (weight % 1000) < 551 ? FONT_WEIGHT_BOLD : FONT_WEIGHT_HEAVY; } -int gfx_render_text(Texture *dst, float x, int y, char *msg, struct text_style *ts) +int gfx_render_text(Texture *dst, float x, int y, char *msg, struct text_style *ts, bool blend) { enum font_weight weight = int_to_font_weight(ts->weight); struct font_size *font_size = text_style_font_size(ts); float edge_width = text_style_edge_width(ts); + enum text_render_mode mode = blend ? RENDER_BLENDED : RENDER_COPY; if (edge_width > 0.01f) { struct text_render_metrics metrics = { .x = x, @@ -287,10 +293,11 @@ int gfx_render_text(Texture *dst, float x, int y, char *msg, struct text_style * .space_scale_x = ts->space_scale_x, .font_spacing = ts->font_spacing, .edge_spacing = gfx_text_advance_edges ? edge_width : 0.0, - .mode = RENDER_BLENDED, + .mode = mode, .font_size = font_size, }; render_text(dst, msg, &metrics); + mode = RENDER_BLENDED; // core text is blended on top of the edge } struct text_render_metrics metrics = { .x = x, @@ -302,7 +309,7 @@ int gfx_render_text(Texture *dst, float x, int y, char *msg, struct text_style * .space_scale_x = ts->space_scale_x, .font_spacing = ts->font_spacing, .edge_spacing = gfx_text_advance_edges ? edge_width : 0.0, - .mode = RENDER_BLENDED, + .mode = mode, .font_size = font_size, }; return render_text(dst, msg, &metrics);