Remove ui::painter::draw_glyph, introduce ui::painter::color_mode used for switching between mix/multiply in draw_image
This commit is contained in:
parent
395464ebd5
commit
43c18eb4d2
5 changed files with 49 additions and 133 deletions
|
|
@ -13,11 +13,18 @@ namespace psemek::ui
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
|
||||||
|
enum class color_mode
|
||||||
|
{
|
||||||
|
mix,
|
||||||
|
multiply,
|
||||||
|
};
|
||||||
|
|
||||||
// Have to define this struct outside of ui::painter to workaround
|
// Have to define this struct outside of ui::painter to workaround
|
||||||
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88165
|
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88165
|
||||||
struct image_options
|
struct image_options
|
||||||
{
|
{
|
||||||
gfx::color_rgba color{0, 0, 0, 0};
|
gfx::color_rgba color{0, 0, 0, 0};
|
||||||
|
color_mode mode = color_mode::mix;
|
||||||
float rotation{0.f};
|
float rotation{0.f};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -28,9 +35,9 @@ namespace psemek::ui
|
||||||
virtual void draw_rect(geom::box<float, 2> const & rect, gfx::color_rgba const & color) = 0;
|
virtual void draw_rect(geom::box<float, 2> const & rect, gfx::color_rgba const & color) = 0;
|
||||||
virtual void draw_triangle(geom::triangle<geom::point<float, 2>> const & tri, gfx::color_rgba const & color) = 0;
|
virtual void draw_triangle(geom::triangle<geom::point<float, 2>> const & tri, gfx::color_rgba const & color) = 0;
|
||||||
|
|
||||||
|
using color_mode = detail::color_mode;
|
||||||
using image_options = detail::image_options;
|
using image_options = detail::image_options;
|
||||||
|
|
||||||
virtual void draw_glyph(font const & f, char32_t c, geom::box<float, 2> const & rect, gfx::color_rgba const & color) = 0;
|
|
||||||
virtual void draw_image(geom::box<float, 2> const & rect, gfx::texture_view_2d const & tex, image_options const & opts = image_options{}) = 0;
|
virtual void draw_image(geom::box<float, 2> const & rect, gfx::texture_view_2d const & tex, image_options const & opts = image_options{}) = 0;
|
||||||
|
|
||||||
virtual void begin_stencil() = 0;
|
virtual void begin_stencil() = 0;
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,6 @@ namespace psemek::ui
|
||||||
void draw_rect(geom::box<float, 2> const & rect, gfx::color_rgba const & color) override;
|
void draw_rect(geom::box<float, 2> const & rect, gfx::color_rgba const & color) override;
|
||||||
void draw_triangle(geom::triangle<geom::point<float, 2>> const & tri, gfx::color_rgba const & color) override;
|
void draw_triangle(geom::triangle<geom::point<float, 2>> const & tri, gfx::color_rgba const & color) override;
|
||||||
|
|
||||||
void draw_glyph(font const & f, char32_t c, geom::box<float, 2> const & rect, gfx::color_rgba const & color) override;
|
|
||||||
void draw_image(geom::box<float, 2> const & rect, gfx::texture_view_2d const & tex, image_options const & opts) override;
|
void draw_image(geom::box<float, 2> const & rect, gfx::texture_view_2d const & tex, image_options const & opts) override;
|
||||||
|
|
||||||
void begin_stencil() override;
|
void begin_stencil() override;
|
||||||
|
|
|
||||||
|
|
@ -450,11 +450,11 @@ namespace psemek::ui
|
||||||
{
|
{
|
||||||
auto shoffset = offset + geom::cast<float>(*st->text_shadow_offset);
|
auto shoffset = offset + geom::cast<float>(*st->text_shadow_offset);
|
||||||
for (auto const & i : cached_state_->images)
|
for (auto const & i : cached_state_->images)
|
||||||
p.draw_image(i.position + shoffset, {cached_state_->texture, i.texcoords}, {*st->shadow_color});
|
p.draw_image(i.position + shoffset, {cached_state_->texture, i.texcoords}, {*st->shadow_color, painter::color_mode::multiply});
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto const & i : cached_state_->images)
|
for (auto const & i : cached_state_->images)
|
||||||
p.draw_image(i.position + offset, {cached_state_->texture, i.texcoords}, {*st->text_color});
|
p.draw_image(i.position + offset, {cached_state_->texture, i.texcoords}, {*st->text_color, painter::color_mode::multiply});
|
||||||
|
|
||||||
p.end_stencil();
|
p.end_stencil();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -111,12 +111,12 @@ namespace psemek::ui
|
||||||
auto const offset = geom::cast<float>(*st->text_shadow_offset);
|
auto const offset = geom::cast<float>(*st->text_shadow_offset);
|
||||||
for (auto const & batch : cached_state_->batches)
|
for (auto const & batch : cached_state_->batches)
|
||||||
for (auto const & image : batch.images)
|
for (auto const & image : batch.images)
|
||||||
p.draw_image(image.position + offset, gfx::texture_view_2d{batch.texture, image.texcoords}, {*st->shadow_color});
|
p.draw_image(image.position + offset, gfx::texture_view_2d{batch.texture, image.texcoords}, {*st->shadow_color, painter::color_mode::multiply});
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto const & batch : cached_state_->batches)
|
for (auto const & batch : cached_state_->batches)
|
||||||
for (auto const & image : batch.images)
|
for (auto const & image : batch.images)
|
||||||
p.draw_image(image.position, gfx::texture_view_2d{batch.texture, image.texcoords}, {*st->text_color});
|
p.draw_image(image.position, gfx::texture_view_2d{batch.texture, image.texcoords}, {*st->text_color, painter::color_mode::multiply});
|
||||||
}
|
}
|
||||||
|
|
||||||
void label::on_state_changed()
|
void label::on_state_changed()
|
||||||
|
|
|
||||||
|
|
@ -44,45 +44,6 @@ void main()
|
||||||
{
|
{
|
||||||
out_color = color;
|
out_color = color;
|
||||||
}
|
}
|
||||||
)";
|
|
||||||
|
|
||||||
char const bitmap_text_vs[] =
|
|
||||||
R"(#version 330
|
|
||||||
|
|
||||||
uniform mat4 u_transform;
|
|
||||||
|
|
||||||
uniform vec2 u_atlas_size;
|
|
||||||
|
|
||||||
layout (location = 0) in vec2 in_position;
|
|
||||||
layout (location = 1) in float in_depth;
|
|
||||||
layout (location = 2) in vec4 in_color;
|
|
||||||
layout (location = 3) in vec2 in_texcoord;
|
|
||||||
|
|
||||||
out vec4 color;
|
|
||||||
out vec2 texcoord;
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
gl_Position = u_transform * vec4(in_position, 1.0 - float(in_depth) / 16777216.0 * 2.0, 1.0);
|
|
||||||
color = in_color;
|
|
||||||
texcoord = in_texcoord / u_atlas_size;
|
|
||||||
}
|
|
||||||
)";
|
|
||||||
|
|
||||||
char const bitmap_text_fs[] =
|
|
||||||
R"(#version 330
|
|
||||||
|
|
||||||
uniform sampler2D u_atlas;
|
|
||||||
|
|
||||||
in vec2 texcoord;
|
|
||||||
in vec4 color;
|
|
||||||
|
|
||||||
out vec4 out_color;
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
out_color = vec4(color.rgb, texture(u_atlas, texcoord) * color.a);
|
|
||||||
}
|
|
||||||
)";
|
)";
|
||||||
|
|
||||||
char const textured_vs[] =
|
char const textured_vs[] =
|
||||||
|
|
@ -108,7 +69,7 @@ void main()
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
|
||||||
char const textured_fs[] =
|
char const textured_mix_fs[] =
|
||||||
R"(#version 330
|
R"(#version 330
|
||||||
|
|
||||||
uniform sampler2D u_texture;
|
uniform sampler2D u_texture;
|
||||||
|
|
@ -123,6 +84,23 @@ void main()
|
||||||
vec4 tex_color = texture(u_texture, texcoord);
|
vec4 tex_color = texture(u_texture, texcoord);
|
||||||
out_color = vec4(mix(tex_color.rgb, color.rgb, color.a), tex_color.a);
|
out_color = vec4(mix(tex_color.rgb, color.rgb, color.a), tex_color.a);
|
||||||
}
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
char const textured_multiply_fs[] =
|
||||||
|
R"(#version 330
|
||||||
|
|
||||||
|
uniform sampler2D u_texture;
|
||||||
|
|
||||||
|
in vec2 texcoord;
|
||||||
|
in vec4 color;
|
||||||
|
|
||||||
|
out vec4 out_color;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec4 tex_color = texture(u_texture, texcoord);
|
||||||
|
out_color = tex_color * color;
|
||||||
|
}
|
||||||
)";
|
)";
|
||||||
|
|
||||||
struct colored_vertex
|
struct colored_vertex
|
||||||
|
|
@ -144,27 +122,6 @@ void main()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct bitmap_text_vertex
|
|
||||||
{
|
|
||||||
geom::point<float, 2> position;
|
|
||||||
std::uint32_t depth;
|
|
||||||
gfx::color_rgba color;
|
|
||||||
geom::vector<std::uint16_t, 2> texcoords;
|
|
||||||
};
|
|
||||||
static_assert(sizeof(bitmap_text_vertex) == 20);
|
|
||||||
|
|
||||||
struct bitmap_text_batch
|
|
||||||
{
|
|
||||||
gfx::texture_2d const * atlas = nullptr;
|
|
||||||
std::vector<bitmap_text_vertex> vertices{};
|
|
||||||
std::vector<std::uint32_t> indices{};
|
|
||||||
};
|
|
||||||
|
|
||||||
bool operator == (bitmap_text_batch const & b1, bitmap_text_batch const & b2)
|
|
||||||
{
|
|
||||||
return b1.atlas == b2.atlas;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct textured_vertex
|
struct textured_vertex
|
||||||
{
|
{
|
||||||
geom::point<float, 2> position;
|
geom::point<float, 2> position;
|
||||||
|
|
@ -177,13 +134,14 @@ void main()
|
||||||
struct textured_batch
|
struct textured_batch
|
||||||
{
|
{
|
||||||
gfx::texture_2d const * texture = nullptr;
|
gfx::texture_2d const * texture = nullptr;
|
||||||
|
painter::color_mode mode = painter::color_mode::mix;
|
||||||
std::vector<textured_vertex> vertices{};
|
std::vector<textured_vertex> vertices{};
|
||||||
std::vector<std::uint32_t> indices{};
|
std::vector<std::uint32_t> indices{};
|
||||||
};
|
};
|
||||||
|
|
||||||
bool operator == (textured_batch const & b1, textured_batch const & b2)
|
bool operator == (textured_batch const & b1, textured_batch const & b2)
|
||||||
{
|
{
|
||||||
return b1.texture == b2.texture;
|
return b1.texture == b2.texture && b1.mode == b2.mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct stencil_batch
|
struct stencil_batch
|
||||||
|
|
@ -212,10 +170,8 @@ void main()
|
||||||
gfx::program colored_program;
|
gfx::program colored_program;
|
||||||
gfx::mesh colored_mesh;
|
gfx::mesh colored_mesh;
|
||||||
|
|
||||||
gfx::program bitmap_text_program;
|
gfx::program textured_mix_program;
|
||||||
gfx::mesh bitmap_text_mesh;
|
gfx::program textured_multiply_program;
|
||||||
|
|
||||||
gfx::program textured_program;
|
|
||||||
gfx::mesh textured_mesh;
|
gfx::mesh textured_mesh;
|
||||||
|
|
||||||
int stencil_level = 0;
|
int stencil_level = 0;
|
||||||
|
|
@ -224,7 +180,7 @@ void main()
|
||||||
|
|
||||||
geom::box<float, 2> draw_bbox;
|
geom::box<float, 2> draw_bbox;
|
||||||
|
|
||||||
std::vector<std::variant<colored_batch, bitmap_text_batch, textured_batch, stencil_batch>> batches;
|
std::vector<std::variant<colored_batch, textured_batch, stencil_batch>> batches;
|
||||||
|
|
||||||
std::size_t max_batch_count = 0;
|
std::size_t max_batch_count = 0;
|
||||||
|
|
||||||
|
|
@ -246,17 +202,16 @@ void main()
|
||||||
|
|
||||||
painter_impl::impl::impl()
|
painter_impl::impl::impl()
|
||||||
: colored_program{colored_vs, colored_fs}
|
: colored_program{colored_vs, colored_fs}
|
||||||
, bitmap_text_program{bitmap_text_vs, bitmap_text_fs}
|
, textured_mix_program{textured_vs, textured_mix_fs}
|
||||||
, textured_program{textured_vs, textured_fs}
|
, textured_multiply_program{textured_vs, textured_multiply_fs}
|
||||||
{
|
{
|
||||||
bitmap_text_program.bind();
|
textured_mix_program.bind();
|
||||||
bitmap_text_program["u_atlas"] = 0;
|
textured_mix_program["u_texture"] = 0;
|
||||||
|
|
||||||
textured_program.bind();
|
textured_multiply_program.bind();
|
||||||
textured_program["u_texture"] = 0;
|
textured_multiply_program["u_texture"] = 0;
|
||||||
|
|
||||||
colored_mesh.setup<geom::point<float, 2>, std::uint32_t, gfx::normalized<gfx::color_rgba>>();
|
colored_mesh.setup<geom::point<float, 2>, std::uint32_t, gfx::normalized<gfx::color_rgba>>();
|
||||||
bitmap_text_mesh.setup<geom::point<float, 2>, std::uint32_t, gfx::normalized<gfx::color_rgba>, geom::vector<std::uint16_t, 2>>();
|
|
||||||
textured_mesh.setup<geom::point<float, 2>, std::uint32_t, gfx::normalized<gfx::color_rgba>, geom::vector<float, 2>>();
|
textured_mesh.setup<geom::point<float, 2>, std::uint32_t, gfx::normalized<gfx::color_rgba>, geom::vector<float, 2>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -304,47 +259,9 @@ void main()
|
||||||
impl().draw_bbox |= tri[2];
|
impl().draw_bbox |= tri[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
void painter_impl::draw_glyph(font const & f, char32_t c, geom::box<float, 2> const & rect, gfx::color_rgba const & color)
|
|
||||||
{
|
|
||||||
auto tbox = f.texcoords(c);
|
|
||||||
if (!tbox) return;
|
|
||||||
|
|
||||||
auto size = f.atlas().size();
|
|
||||||
|
|
||||||
auto const tc = [&](float x, float y)
|
|
||||||
{
|
|
||||||
auto t = tbox->corner(x, y);
|
|
||||||
geom::vector<std::uint16_t, 2> r;
|
|
||||||
r[0] = geom::clamp(t[0], {0, size[0]});
|
|
||||||
r[1] = geom::clamp(t[1], {0, size[1]});
|
|
||||||
return r;
|
|
||||||
};
|
|
||||||
|
|
||||||
auto & batch = impl().batch<bitmap_text_batch>(bitmap_text_batch{&f.atlas()});
|
|
||||||
|
|
||||||
std::uint32_t const depth = impl().depth++;
|
|
||||||
std::uint32_t const base = batch.vertices.size();
|
|
||||||
|
|
||||||
auto round = [](geom::point<float, 2> p)
|
|
||||||
{
|
|
||||||
p[0] = std::round(p[0]);
|
|
||||||
p[1] = std::round(p[1]);
|
|
||||||
return p;
|
|
||||||
};
|
|
||||||
|
|
||||||
batch.vertices.push_back({round(rect.corner(0.f, 0.f)), depth, color, tc(0.f, 0.f)});
|
|
||||||
batch.vertices.push_back({round(rect.corner(1.f, 0.f)), depth, color, tc(1.f, 0.f)});
|
|
||||||
batch.vertices.push_back({round(rect.corner(0.f, 1.f)), depth, color, tc(0.f, 1.f)});
|
|
||||||
batch.vertices.push_back({round(rect.corner(1.f, 1.f)), depth, color, tc(1.f, 1.f)});
|
|
||||||
|
|
||||||
batch.indices.insert(batch.indices.end(), {base + 0, base + 1, base + 2, base + 2, base + 1, base + 3});
|
|
||||||
|
|
||||||
impl().draw_bbox |= rect;
|
|
||||||
}
|
|
||||||
|
|
||||||
void painter_impl::draw_image(geom::box<float, 2> const & rect, gfx::texture_view_2d const & tex, image_options const & options)
|
void painter_impl::draw_image(geom::box<float, 2> const & rect, gfx::texture_view_2d const & tex, image_options const & options)
|
||||||
{
|
{
|
||||||
auto & batch = impl().batch<textured_batch>(textured_batch{tex.texture});
|
auto & batch = impl().batch<textured_batch>(textured_batch{tex.texture, options.mode});
|
||||||
|
|
||||||
std::uint32_t const depth = impl().depth++;
|
std::uint32_t const depth = impl().depth++;
|
||||||
std::uint32_t const base = batch.vertices.size();
|
std::uint32_t const base = batch.vertices.size();
|
||||||
|
|
@ -462,10 +379,10 @@ void main()
|
||||||
{
|
{
|
||||||
impl().colored_program.bind();
|
impl().colored_program.bind();
|
||||||
impl().colored_program["u_transform"] = transform;
|
impl().colored_program["u_transform"] = transform;
|
||||||
impl().bitmap_text_program.bind();
|
impl().textured_mix_program.bind();
|
||||||
impl().bitmap_text_program["u_transform"] = transform;
|
impl().textured_mix_program["u_transform"] = transform;
|
||||||
impl().textured_program.bind();
|
impl().textured_multiply_program.bind();
|
||||||
impl().textured_program["u_transform"] = transform;
|
impl().textured_multiply_program["u_transform"] = transform;
|
||||||
|
|
||||||
gl::ActiveTexture(gl::TEXTURE0);
|
gl::ActiveTexture(gl::TEXTURE0);
|
||||||
|
|
||||||
|
|
@ -475,18 +392,11 @@ void main()
|
||||||
impl().colored_mesh.load(b.vertices, b.indices, gl::TRIANGLES);
|
impl().colored_mesh.load(b.vertices, b.indices, gl::TRIANGLES);
|
||||||
impl().colored_mesh.draw();
|
impl().colored_mesh.draw();
|
||||||
},
|
},
|
||||||
[&](bitmap_text_batch const & b){
|
|
||||||
if (!b.atlas) return;
|
|
||||||
impl().bitmap_text_program.bind();
|
|
||||||
impl().bitmap_text_program["u_atlas_size"] = geom::cast<float>(b.atlas->size());
|
|
||||||
b.atlas->bind();
|
|
||||||
impl().bitmap_text_mesh.load(b.vertices, b.indices, gl::TRIANGLES);
|
|
||||||
impl().bitmap_text_mesh.draw();
|
|
||||||
},
|
|
||||||
[&](textured_batch const & b){
|
[&](textured_batch const & b){
|
||||||
if (!b.texture) return;
|
if (!b.texture) return;
|
||||||
impl().textured_program.bind();
|
gfx::program & program = (b.mode == ui::painter::color_mode::mix) ? impl().textured_mix_program : impl().textured_multiply_program;
|
||||||
impl().textured_program["u_texture_size"] = geom::cast<float>(b.texture->size());
|
program.bind();
|
||||||
|
program["u_texture_size"] = geom::cast<float>(b.texture->size());
|
||||||
b.texture->bind();
|
b.texture->bind();
|
||||||
impl().textured_mesh.load(b.vertices, b.indices, gl::TRIANGLES);
|
impl().textured_mesh.load(b.vertices, b.indices, gl::TRIANGLES);
|
||||||
impl().textured_mesh.draw();
|
impl().textured_mesh.draw();
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue