Add simple painter helper (wip)
This commit is contained in:
parent
98c3225f86
commit
08ab8c00a7
3 changed files with 178 additions and 1 deletions
36
libs/gfx/include/psemek/gfx/painter.hpp
Normal file
36
libs/gfx/include/psemek/gfx/painter.hpp
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
#pragma once
|
||||
|
||||
#include <psemek/gfx/color.hpp>
|
||||
#include <psemek/geom/vector.hpp>
|
||||
#include <psemek/geom/point.hpp>
|
||||
#include <psemek/geom/matrix.hpp>
|
||||
#include <psemek/geom/simplex.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
namespace psemek::gfx
|
||||
{
|
||||
|
||||
struct painter
|
||||
{
|
||||
using color = color_rgba;
|
||||
|
||||
painter();
|
||||
~painter();
|
||||
|
||||
// 2D
|
||||
void quad(geom::point<float, 2> const & center, float width, color const & c);
|
||||
void circle(geom::point<float, 2> const & center, float radius, color const & c);
|
||||
void line(geom::point<float, 2> const & p0, geom::point<float, 2> const & p1, float width, color const & c, bool smooth = true);
|
||||
|
||||
// Should be called on each frame
|
||||
void render(geom::matrix<float, 4, 4> const & transform);
|
||||
|
||||
private:
|
||||
struct impl;
|
||||
std::unique_ptr<impl> pimpl_;
|
||||
struct impl & impl() { return *pimpl_; }
|
||||
};
|
||||
|
||||
}
|
||||
142
libs/gfx/source/gfx/painter.cpp
Normal file
142
libs/gfx/source/gfx/painter.cpp
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
#include <psemek/gfx/painter.hpp>
|
||||
#include <psemek/gfx/program.hpp>
|
||||
#include <psemek/gfx/mesh.hpp>
|
||||
#include <psemek/geom/constants.hpp>
|
||||
|
||||
static const char vertex_source[] =
|
||||
R"(#version 330
|
||||
|
||||
uniform mat4 u_transform;
|
||||
|
||||
layout (location = 0) in vec4 in_position;
|
||||
layout (location = 1) in vec4 in_color;
|
||||
|
||||
out vec4 color;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = u_transform * in_position;
|
||||
color = in_color;
|
||||
}
|
||||
)";
|
||||
|
||||
static const char fragment_source[] =
|
||||
R"(#version 330
|
||||
|
||||
in vec4 color;
|
||||
|
||||
out vec4 out_color;
|
||||
|
||||
void main()
|
||||
{
|
||||
out_color = color;
|
||||
}
|
||||
)";
|
||||
|
||||
namespace psemek::gfx
|
||||
{
|
||||
|
||||
struct painter::impl
|
||||
{
|
||||
struct vertex
|
||||
{
|
||||
geom::point<float, 3> position;
|
||||
color_rgba color;
|
||||
};
|
||||
|
||||
gfx::program program{vertex_source, fragment_source};
|
||||
gfx::indexed_mesh mesh;
|
||||
|
||||
std::vector<vertex> vertices;
|
||||
std::vector<std::uint32_t> indices;
|
||||
|
||||
impl()
|
||||
{
|
||||
mesh.setup<geom::vector<float, 3>, gfx::normalized<color_rgba>>();
|
||||
}
|
||||
};
|
||||
|
||||
painter::painter()
|
||||
: pimpl_{std::make_unique<struct impl>()}
|
||||
{}
|
||||
|
||||
painter::~painter() = default;
|
||||
|
||||
void painter::quad(geom::point<float, 2> const & p, float width, color const & c)
|
||||
{
|
||||
std::uint32_t const base = impl().vertices.size();
|
||||
float const r = width / 2.f;
|
||||
|
||||
impl().vertices.push_back({{p[0] - r, p[1] - r, 0.f}, c});
|
||||
impl().vertices.push_back({{p[0] + r, p[1] - r, 0.f}, c});
|
||||
impl().vertices.push_back({{p[0] - r, p[1] + r, 0.f}, c});
|
||||
impl().vertices.push_back({{p[0] + r, p[1] + r, 0.f}, c});
|
||||
|
||||
impl().indices.push_back(base + 0);
|
||||
impl().indices.push_back(base + 1);
|
||||
impl().indices.push_back(base + 3);
|
||||
impl().indices.push_back(base + 0);
|
||||
impl().indices.push_back(base + 3);
|
||||
impl().indices.push_back(base + 2);
|
||||
}
|
||||
|
||||
void painter::circle(geom::point<float, 2> const & p, float r, color const & c)
|
||||
{
|
||||
std::uint32_t const base = impl().vertices.size();
|
||||
|
||||
int const quality = 24;
|
||||
|
||||
impl().vertices.push_back({{p[0], p[1], 0.f}, c});
|
||||
for (int i = 0; i < quality; ++i)
|
||||
{
|
||||
float const a = (geom::pi * 2.f * i) / quality;
|
||||
impl().vertices.push_back({{p[0] + r * std::cos(a), p[1] + r * std::sin(a), 0.f}, c});
|
||||
}
|
||||
|
||||
for (int i = 0; i < quality; ++i)
|
||||
{
|
||||
impl().indices.push_back(base);
|
||||
impl().indices.push_back(base + 1 + i);
|
||||
impl().indices.push_back(base + 1 + ((i + 1) % quality));
|
||||
}
|
||||
}
|
||||
|
||||
void painter::line(geom::point<float, 2> const & p0, geom::point<float, 2> const & p1, float width, color const & c, bool smooth)
|
||||
{
|
||||
std::uint32_t const base = impl().vertices.size();
|
||||
float const r = width / 2.f;
|
||||
|
||||
auto const d = geom::normalized(p1 - p0);
|
||||
geom::vector<float, 2> const o { -d[1], d[0] };
|
||||
|
||||
impl().vertices.push_back({{p0[0] + r * o[0], p0[1] + r * o[1], 0.f}, c});
|
||||
impl().vertices.push_back({{p0[0] - r * o[0], p0[1] - r * o[1], 0.f}, c});
|
||||
impl().vertices.push_back({{p1[0] + r * o[0], p1[1] + r * o[1], 0.f}, c});
|
||||
impl().vertices.push_back({{p1[0] - r * o[0], p1[1] - r * o[1], 0.f}, c});
|
||||
|
||||
impl().indices.push_back(base + 0);
|
||||
impl().indices.push_back(base + 1);
|
||||
impl().indices.push_back(base + 3);
|
||||
impl().indices.push_back(base + 0);
|
||||
impl().indices.push_back(base + 3);
|
||||
impl().indices.push_back(base + 2);
|
||||
|
||||
if (smooth)
|
||||
{
|
||||
circle(p0, r, c);
|
||||
circle(p1, r, c);
|
||||
}
|
||||
}
|
||||
|
||||
void painter::render(geom::matrix<float, 4, 4> const & transform)
|
||||
{
|
||||
impl().mesh.load(impl().vertices, impl().indices, gl::STREAM_DRAW);
|
||||
impl().vertices.clear();
|
||||
impl().indices.clear();
|
||||
|
||||
impl().program.bind();
|
||||
impl().program["u_transform"] = transform;
|
||||
impl().mesh.draw(gl::TRIANGLES);
|
||||
}
|
||||
|
||||
}
|
||||
1
todo.md
1
todo.md
|
|
@ -1,6 +1,5 @@
|
|||
* Design affine transforms in geom & use them instead of matrices when appropriate
|
||||
* Implement pixmap font rendering
|
||||
* Create a simple generic primive painter
|
||||
* Design ui system
|
||||
* Add platform deployment tools
|
||||
* Add color utilities
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue