psemek/libs/ui/source/painter_impl.cpp

126 lines
3.1 KiB
C++

#include <psemek/ui/painter_impl.hpp>
#include <psemek/gfx/program.hpp>
#include <psemek/gfx/array.hpp>
#include <psemek/gfx/buffer.hpp>
namespace psemek::ui
{
static char const colored_vs[] =
R"(#version 330
uniform mat4 u_transform;
layout (location = 0) in vec2 in_position;
layout (location = 1) in uint in_depth;
layout (location = 2) in vec4 in_color;
out vec4 color;
void main()
{
gl_Position = u_transform * vec4(in_position, float(in_depth) / 16777216.0 * 2.0 - 1.0, 1.0);
color = in_color;
}
)";
static char const colored_fs[] =
R"(#version 330
in vec4 color;
out vec4 out_color;
void main()
{
out_color = color;
}
)";
struct colored_vertex
{
geom::point<float, 2> position;
std::uint32_t depth;
gfx::color_rgba color;
};
static_assert(sizeof(colored_vertex) == 16);
struct painter_impl::impl
{
std::shared_ptr<struct font> font;
std::uint32_t depth = 0;
gfx::program colored_program;
gfx::array colored_vao;
gfx::buffer colored_vbo;
gfx::buffer colored_ebo;
std::vector<colored_vertex> colored_vertices;
std::vector<std::uint32_t> colored_indices;
impl();
};
painter_impl::impl::impl()
: colored_program{colored_vs, colored_fs}
{
colored_vao.bind();
colored_vbo.bind();
gl::EnableVertexAttribArray(0);
gl::VertexAttribPointer(0, 2, gl::FLOAT, gl::FALSE, sizeof(colored_vertex), reinterpret_cast<void const *>(0));
gl::EnableVertexAttribArray(1);
gl::VertexAttribIPointer(1, 1, gl::UNSIGNED_INT, sizeof(colored_vertex), reinterpret_cast<void const *>(8));
gl::EnableVertexAttribArray(2);
gl::VertexAttribPointer(2, 4, gl::UNSIGNED_BYTE, gl::TRUE, sizeof(colored_vertex), reinterpret_cast<void const *>(12));
gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, colored_ebo.id());
}
painter_impl::painter_impl()
: pimpl_{make_impl()}
{}
painter_impl::~painter_impl() = default;
void painter_impl::set_font(std::shared_ptr<struct font> font)
{
impl().font = font;
}
font const * painter_impl::font() const
{
return impl().font.get();
}
void painter_impl::draw_rect(geom::box<float, 2> const & rect, gfx::color_rgba const & color)
{
std::uint32_t const depth = impl().depth++;
std::uint32_t const base = impl().colored_vertices.size();
impl().colored_vertices.push_back({rect.corner(0.f, 0.f), depth, color});
impl().colored_vertices.push_back({rect.corner(1.f, 0.f), depth, color});
impl().colored_vertices.push_back({rect.corner(0.f, 1.f), depth, color});
impl().colored_vertices.push_back({rect.corner(1.f, 1.f), depth, color});
impl().colored_indices.insert(impl().colored_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)
{
impl().colored_vbo.load(impl().colored_vertices);
impl().colored_ebo.load(impl().colored_indices);
int const colored_count = impl().colored_indices.size();
impl().colored_vertices.clear();
impl().colored_indices.clear();
impl().depth = 0;
impl().colored_program.bind();
impl().colored_program["u_transform"] = transform;
impl().colored_vao.bind();
gl::DrawElements(gl::TRIANGLES, colored_count, gl::UNSIGNED_INT, nullptr);
}
}