Support image rendering in ui::painter
This commit is contained in:
parent
2cedfb0b98
commit
4a8021aa4e
3 changed files with 90 additions and 3 deletions
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <psemek/ui/font.hpp>
|
#include <psemek/ui/font.hpp>
|
||||||
#include <psemek/gfx/color.hpp>
|
#include <psemek/gfx/color.hpp>
|
||||||
|
#include <psemek/gfx/texture.hpp>
|
||||||
#include <psemek/geom/box.hpp>
|
#include <psemek/geom/box.hpp>
|
||||||
|
|
||||||
namespace psemek::ui
|
namespace psemek::ui
|
||||||
|
|
@ -11,6 +12,7 @@ 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_glyph(font const & f, char32_t c, geom::box<float, 2> const & rect, gfx::color_rgba const & color) = 0;
|
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_2d const & tex, gfx::color_rgba const & color = {0, 0, 0, 0}) = 0;
|
||||||
|
|
||||||
virtual ~painter() {}
|
virtual ~painter() {}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ 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_glyph(font const & f, char32_t c, geom::box<float, 2> const & rect, 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_2d const & tex, gfx::color_rgba const & color) override;
|
||||||
|
|
||||||
void render(geom::matrix<float, 4, 4> const & transform);
|
void render(geom::matrix<float, 4, 4> const & transform);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,45 @@ void main()
|
||||||
{
|
{
|
||||||
out_color = color;
|
out_color = color;
|
||||||
}
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
static 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;
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
static 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);
|
||||||
|
}
|
||||||
)";
|
)";
|
||||||
|
|
||||||
static char const textured_vs[] =
|
static char const textured_vs[] =
|
||||||
|
|
@ -76,7 +115,7 @@ out vec4 out_color;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
out_color = texture(u_texture, texcoord) * color;
|
out_color = mix(texture(u_texture, texcoord), color, color.a);
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
|
||||||
|
|
@ -109,6 +148,18 @@ void main()
|
||||||
};
|
};
|
||||||
static_assert(sizeof(textured_vertex) == 20);
|
static_assert(sizeof(textured_vertex) == 20);
|
||||||
|
|
||||||
|
struct bitmap_text_batch
|
||||||
|
{
|
||||||
|
gfx::texture_2d const * atlas = nullptr;
|
||||||
|
std::vector<textured_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_batch
|
struct textured_batch
|
||||||
{
|
{
|
||||||
gfx::texture_2d const * texture = nullptr;
|
gfx::texture_2d const * texture = nullptr;
|
||||||
|
|
@ -128,10 +179,13 @@ void main()
|
||||||
gfx::program colored_program;
|
gfx::program colored_program;
|
||||||
gfx::mesh colored_mesh;
|
gfx::mesh colored_mesh;
|
||||||
|
|
||||||
|
gfx::program bitmap_text_program;
|
||||||
|
gfx::mesh bitmap_text_mesh;
|
||||||
|
|
||||||
gfx::program textured_program;
|
gfx::program textured_program;
|
||||||
gfx::mesh textured_mesh;
|
gfx::mesh textured_mesh;
|
||||||
|
|
||||||
std::vector<std::variant<colored_batch, textured_batch>> batches;
|
std::vector<std::variant<colored_batch, bitmap_text_batch, textured_batch>> batches;
|
||||||
|
|
||||||
template <typename Batch>
|
template <typename Batch>
|
||||||
Batch & batch(Batch && n)
|
Batch & batch(Batch && n)
|
||||||
|
|
@ -151,12 +205,17 @@ 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_program{textured_vs, textured_fs}
|
, textured_program{textured_vs, textured_fs}
|
||||||
{
|
{
|
||||||
|
bitmap_text_program.bind();
|
||||||
|
bitmap_text_program["u_atlas"] = 0;
|
||||||
|
|
||||||
textured_program.bind();
|
textured_program.bind();
|
||||||
textured_program["u_texture"] = 0;
|
textured_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<std::uint16_t, 2>>();
|
textured_mesh.setup<geom::point<float, 2>, std::uint32_t, gfx::normalized<gfx::color_rgba>, geom::vector<std::uint16_t, 2>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -197,7 +256,7 @@ void main()
|
||||||
return r;
|
return r;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto & batch = impl().batch<textured_batch>(textured_batch{&f.atlas()});
|
auto & batch = impl().batch<bitmap_text_batch>(bitmap_text_batch{&f.atlas()});
|
||||||
|
|
||||||
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();
|
||||||
|
|
@ -210,6 +269,23 @@ void main()
|
||||||
batch.indices.insert(batch.indices.end(), {base + 0, base + 1, base + 2, base + 2, base + 1, base + 3});
|
batch.indices.insert(batch.indices.end(), {base + 0, base + 1, base + 2, base + 2, base + 1, base + 3});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void painter_impl::draw_image(geom::box<float, 2> const & rect, gfx::texture_2d const & tex, gfx::color_rgba const & color)
|
||||||
|
{
|
||||||
|
auto & batch = impl().batch<textured_batch>(textured_batch{&tex});
|
||||||
|
|
||||||
|
std::uint32_t const depth = impl().depth++;
|
||||||
|
std::uint32_t const base = batch.vertices.size();
|
||||||
|
|
||||||
|
auto const size = tex.size();
|
||||||
|
|
||||||
|
batch.vertices.push_back({rect.corner(0.f, 0.f), depth, color, {0, 0}});
|
||||||
|
batch.vertices.push_back({rect.corner(1.f, 0.f), depth, color, {size[0], 0}});
|
||||||
|
batch.vertices.push_back({rect.corner(0.f, 1.f), depth, color, {0, size[1]}});
|
||||||
|
batch.vertices.push_back({rect.corner(1.f, 1.f), depth, color, {size[0], size[1]}});
|
||||||
|
|
||||||
|
batch.indices.insert(batch.indices.end(), {base + 0, base + 1, base + 2, base + 2, base + 1, base + 3});
|
||||||
|
}
|
||||||
|
|
||||||
void painter_impl::render(geom::matrix<float, 4, 4> const & transform)
|
void painter_impl::render(geom::matrix<float, 4, 4> const & transform)
|
||||||
{
|
{
|
||||||
impl().colored_program.bind();
|
impl().colored_program.bind();
|
||||||
|
|
@ -224,6 +300,14 @@ 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();
|
impl().textured_program.bind();
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue