Add a parameter to gfx_draw_glyph() for controlling blending behavior

This adds a new parameter `blend` to `gfx_draw_glyph()`. When `blend` is
true, the function performs normal alpha blending (same as
`gfx_draw_glyph_to_pmap()`).

If `blend` is false, the resulting pixel color will be the text color
and the alpha value will be copied from the glyph texture. However, if
the alpha value is less than 0.01, the pixel will not be written.

If you are drawing on a transparent texture (which will later be blended
into another texture), `blend` should be false. If you are drawing on top
of an image, `blend` should be true.

`gfx_draw_glyph()` used to fill transparent pixels with text color, but
this step is no longer needed and has been removed.
This commit is contained in:
kichikuou
2024-06-15 14:34:58 +09:00
parent d7fd6d4e1e
commit b155b4b79f
14 changed files with 46 additions and 47 deletions
+1 -1
View File
@@ -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);
+1 -1
View File
@@ -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);
+5 -3
View File
@@ -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);
}
+3 -1
View File
@@ -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));
}
+11 -17
View File
@@ -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();
+1 -1
View File
@@ -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);
}
+1 -1
View File
@@ -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 = '<';
+1 -1
View File
@@ -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)
+2 -2
View File
@@ -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;
+3 -3
View File
@@ -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, "<C%d,%d,%d>%n", &a1, &a2, &a3, &skiplen) == 3) {
+2 -2
View File
@@ -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,
+1 -1
View File
@@ -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);
+2 -8
View File
@@ -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);
+12 -5
View File
@@ -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);