#include #include #include #include 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, 1.0 - float(in_depth) / 16777216.0 * 2.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 position; std::uint32_t depth; gfx::color_rgba color; }; static_assert(sizeof(colored_vertex) == 16); struct painter_impl::impl { std::uint32_t depth = 0; gfx::program colored_program; gfx::array colored_vao; gfx::buffer colored_vbo; gfx::buffer colored_ebo; std::vector colored_vertices; std::vector 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(0)); gl::EnableVertexAttribArray(1); gl::VertexAttribIPointer(1, 1, gl::UNSIGNED_INT, sizeof(colored_vertex), reinterpret_cast(8)); gl::EnableVertexAttribArray(2); gl::VertexAttribPointer(2, 4, gl::UNSIGNED_BYTE, gl::TRUE, sizeof(colored_vertex), reinterpret_cast(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::draw_rect(geom::box 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 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); } }