Optimize vecr::renderer by using primitive's bbox
This commit is contained in:
parent
2e2df09790
commit
f70cdf9d8e
22 changed files with 245 additions and 16 deletions
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <psemek/vecr/invert.hpp>
|
||||
#include <psemek/vecr/intersect.hpp>
|
||||
#include <psemek/geom/box.hpp>
|
||||
|
||||
namespace psemek::vecr
|
||||
{
|
||||
|
|
@ -14,4 +15,6 @@ namespace psemek::vecr
|
|||
|
||||
sdf_sample sdf(add const & s, geom::point<float, 2> const & p);
|
||||
|
||||
geom::box<float, 2> bbox(add const & s);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,12 +2,52 @@
|
|||
|
||||
#include <psemek/vecr/sdf.hpp>
|
||||
#include <psemek/geom/point.hpp>
|
||||
#include <psemek/geom/box.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
namespace psemek::vecr
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
struct any_base
|
||||
{
|
||||
virtual sdf_sample sdf_func(geom::point<float, 2> const & p) const = 0;
|
||||
virtual geom::box<float, 2> bbox_func() const = 0;
|
||||
|
||||
virtual ~any_base() {}
|
||||
};
|
||||
|
||||
template <typename Shape>
|
||||
struct any_impl
|
||||
: any_base
|
||||
{
|
||||
any_impl(Shape && shape)
|
||||
: shape(std::move(shape))
|
||||
{}
|
||||
|
||||
any_impl(Shape const & shape)
|
||||
: shape(shape)
|
||||
{}
|
||||
|
||||
Shape shape;
|
||||
|
||||
sdf_sample sdf_func(geom::point<float, 2> const & p) const override
|
||||
{
|
||||
return sdf(shape, p);
|
||||
}
|
||||
|
||||
geom::box<float, 2> bbox_func() const override
|
||||
{
|
||||
return bbox(shape);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
struct any
|
||||
{
|
||||
any() = default;
|
||||
|
|
@ -26,26 +66,30 @@ namespace psemek::vecr
|
|||
template <typename Shape>
|
||||
any & operator = (Shape && shape)
|
||||
{
|
||||
sdf_ = [shape = std::forward<Shape>(shape)](geom::point<float, 2> const & p){
|
||||
return sdf(shape, p);
|
||||
};
|
||||
impl_ = std::make_shared<detail::any_impl<std::decay_t<Shape>>>(std::move(shape));
|
||||
return *this;
|
||||
}
|
||||
|
||||
explicit operator bool() const
|
||||
{
|
||||
return static_cast<bool>(sdf_);
|
||||
return static_cast<bool>(impl_);
|
||||
}
|
||||
|
||||
friend sdf_sample sdf(any const & s, geom::point<float, 2> const & p);
|
||||
friend geom::box<float, 2> bbox(any const & s);
|
||||
|
||||
private:
|
||||
std::function<sdf_sample(geom::point<float, 2> const &)> sdf_;
|
||||
std::shared_ptr<detail::any_base> impl_;
|
||||
};
|
||||
|
||||
inline sdf_sample sdf(any const & s, geom::point<float, 2> const & p)
|
||||
{
|
||||
return s.sdf_ ? s.sdf_(p) : sdf_sample{};
|
||||
return s.impl_ ? s.impl_->sdf_func(p) : sdf_sample{};
|
||||
}
|
||||
|
||||
inline geom::box<float, 2> bbox(any const & s)
|
||||
{
|
||||
return s.impl_ ? s.impl_->bbox_func() : geom::box<float, 2>{};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <psemek/vecr/sdf.hpp>
|
||||
#include <psemek/geom/point.hpp>
|
||||
#include <psemek/geom/box.hpp>
|
||||
|
||||
namespace psemek::vecr
|
||||
{
|
||||
|
|
@ -24,4 +25,10 @@ namespace psemek::vecr
|
|||
return result;
|
||||
}
|
||||
|
||||
template <typename Shape>
|
||||
geom::box<float, 2> bbox(border<Shape> const & s)
|
||||
{
|
||||
return bbox(s.shape);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <psemek/vecr/sdf.hpp>
|
||||
#include <psemek/geom/point.hpp>
|
||||
#include <psemek/geom/box.hpp>
|
||||
|
||||
namespace psemek::vecr
|
||||
{
|
||||
|
|
@ -14,4 +15,6 @@ namespace psemek::vecr
|
|||
|
||||
sdf_sample sdf(circle const & s, geom::point<float, 2> const & p);
|
||||
|
||||
geom::box<float, 2> bbox(circle const & s);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <psemek/vecr/sdf.hpp>
|
||||
#include <psemek/geom/point.hpp>
|
||||
#include <psemek/geom/box.hpp>
|
||||
|
||||
#include <optional>
|
||||
|
||||
|
|
@ -55,4 +56,10 @@ namespace psemek::vecr
|
|||
return result;
|
||||
}
|
||||
|
||||
template <typename Shape>
|
||||
geom::box<float, 2> bbox(exact<Shape> const & s)
|
||||
{
|
||||
return bbox(s.shape);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <psemek/vecr/path.hpp>
|
||||
#include <psemek/geom/box.hpp>
|
||||
|
||||
namespace psemek::vecr
|
||||
{
|
||||
|
|
@ -12,4 +13,6 @@ namespace psemek::vecr
|
|||
|
||||
sdf_sample sdf(fill const & s, geom::point<float, 2> const & p);
|
||||
|
||||
geom::box<float, 2> bbox(fill const & s);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <psemek/vecr/sdf.hpp>
|
||||
#include <psemek/geom/point.hpp>
|
||||
#include <psemek/geom/box.hpp>
|
||||
|
||||
namespace psemek::vecr
|
||||
{
|
||||
|
|
@ -21,4 +22,10 @@ namespace psemek::vecr
|
|||
return result;
|
||||
}
|
||||
|
||||
template <typename Shape>
|
||||
geom::box<float, 2> bbox(grow<Shape> const & s)
|
||||
{
|
||||
return geom::expand(bbox(s.shape), s.distance);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <psemek/vecr/sdf.hpp>
|
||||
#include <psemek/geom/point.hpp>
|
||||
#include <psemek/geom/box.hpp>
|
||||
|
||||
namespace psemek::vecr
|
||||
{
|
||||
|
|
@ -17,4 +18,10 @@ namespace psemek::vecr
|
|||
return {geom::dot(p - s.origin, s.normal), s.normal};
|
||||
}
|
||||
|
||||
inline geom::box<float, 2> bbox(halfspace const &)
|
||||
{
|
||||
return geom::box<float, 2>::full();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include <psemek/vecr/any.hpp>
|
||||
#include <psemek/geom/point.hpp>
|
||||
#include <psemek/geom/math.hpp>
|
||||
#include <psemek/geom/box.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
|
@ -18,4 +19,6 @@ namespace psemek::vecr
|
|||
|
||||
sdf_sample sdf(intersect const & s, geom::point<float, 2> const & p);
|
||||
|
||||
geom::box<float, 2> bbox(intersect const & s);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <psemek/vecr/sdf.hpp>
|
||||
#include <psemek/geom/point.hpp>
|
||||
#include <psemek/geom/box.hpp>
|
||||
|
||||
namespace psemek::vecr
|
||||
{
|
||||
|
|
@ -21,4 +22,10 @@ namespace psemek::vecr
|
|||
return result;
|
||||
}
|
||||
|
||||
template <typename Shape>
|
||||
geom::box<float, 2> bbox(invert<Shape> const &)
|
||||
{
|
||||
return geom::box<float, 2>::full();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <psemek/vecr/sdf.hpp>
|
||||
#include <psemek/geom/point.hpp>
|
||||
#include <psemek/geom/box.hpp>
|
||||
|
||||
namespace psemek::vecr
|
||||
{
|
||||
|
|
@ -34,4 +35,24 @@ namespace psemek::vecr
|
|||
return result;
|
||||
}
|
||||
|
||||
template <typename Shape>
|
||||
geom::box<float, 2> bbox(mirror<Shape> const & s)
|
||||
{
|
||||
geom::box<float, 2> result;
|
||||
|
||||
auto sbox = bbox(s.shape);
|
||||
|
||||
for (int x = 0; x <= 1; ++x)
|
||||
{
|
||||
for (int y = 0; y <= 1; ++y)
|
||||
{
|
||||
auto p = sbox.corner(x, y);
|
||||
p = p - (2.f * geom::dot(s.axis, p - s.origin)) * s.axis;
|
||||
result |= p;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <psemek/vecr/sdf.hpp>
|
||||
#include <psemek/geom/point.hpp>
|
||||
#include <psemek/geom/box.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
|
@ -15,4 +16,6 @@ namespace psemek::vecr
|
|||
|
||||
sdf_sample sdf(path const & s, geom::point<float, 2> const & p, bool closed = false);
|
||||
|
||||
geom::box<float, 2> bbox(path const & s);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ namespace psemek::vecr
|
|||
geom::vector<std::size_t, 2> size() const;
|
||||
std::size_t samples() const;
|
||||
gfx::pixmap_rgba const & result() const;
|
||||
gfx::pixmap_rgba release();
|
||||
|
||||
void clear(gfx::color_rgba const & color = {0, 0, 0, 0});
|
||||
|
||||
|
|
|
|||
|
|
@ -20,4 +20,10 @@ namespace psemek::vecr
|
|||
return sdf(intersect{{s.shape1, invert{s.shape2}}, s.smooth}, p);
|
||||
}
|
||||
|
||||
template <typename Shape1, typename Shape2>
|
||||
geom::box<float, 2> bbox(subtract<Shape1, Shape2> const & s)
|
||||
{
|
||||
return bbox(s.shape1);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,4 +25,10 @@ namespace psemek::vecr
|
|||
return sdf(s.shape, q);
|
||||
}
|
||||
|
||||
template <typename Shape>
|
||||
geom::box<float, 2> bbox(tile<Shape> const &)
|
||||
{
|
||||
return geom::box<float, 2>::full();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include <psemek/geom/matrix.hpp>
|
||||
#include <psemek/geom/homogeneous.hpp>
|
||||
#include <psemek/geom/gauss.hpp>
|
||||
#include <psemek/geom/box.hpp>
|
||||
|
||||
namespace psemek::vecr
|
||||
{
|
||||
|
|
@ -45,6 +46,12 @@ namespace psemek::vecr
|
|||
return sdf(s.shape, p - s.delta);
|
||||
}
|
||||
|
||||
template <typename Shape>
|
||||
geom::box<float, 2> bbox(translate<Shape> const & s)
|
||||
{
|
||||
return bbox(s.shape) + s.delta;
|
||||
}
|
||||
|
||||
template <typename Shape>
|
||||
sdf_sample sdf(rotate<Shape> const & s, geom::point<float, 2> const & p)
|
||||
{
|
||||
|
|
@ -53,6 +60,20 @@ namespace psemek::vecr
|
|||
return result;
|
||||
}
|
||||
|
||||
template <typename Shape>
|
||||
geom::box<float, 2> bbox(rotate<Shape> const & s)
|
||||
{
|
||||
auto sbox = bbox(s.shape);
|
||||
|
||||
geom::box<float, 2> result;
|
||||
|
||||
for (int y = 0; y <= 1; ++y)
|
||||
for (int x = 0; x <= 1; ++x)
|
||||
result |= s.origin + geom::rotate(sbox.corner(x, y) - s.origin, s.angle);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Shape>
|
||||
sdf_sample sdf(scale<Shape> const & s, geom::point<float, 2> const & p)
|
||||
{
|
||||
|
|
@ -65,6 +86,20 @@ namespace psemek::vecr
|
|||
return result;
|
||||
}
|
||||
|
||||
template <typename Shape>
|
||||
geom::box<float, 2> bbox(scale<Shape> const & s)
|
||||
{
|
||||
auto sbox = bbox(s.shape);
|
||||
|
||||
geom::box<float, 2> result;
|
||||
|
||||
for (int y = 0; y <= 1; ++y)
|
||||
for (int x = 0; x <= 1; ++x)
|
||||
result |= s.origin + (sbox.corner(x, y) - s.origin) * s.factor;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Shape>
|
||||
sdf_sample sdf(transform<Shape> const & s, geom::point<float, 2> const & p)
|
||||
{
|
||||
|
|
@ -89,5 +124,18 @@ namespace psemek::vecr
|
|||
return result;
|
||||
}
|
||||
|
||||
template <typename Shape>
|
||||
geom::box<float, 2> bbox(transform<Shape> const & s)
|
||||
{
|
||||
auto sbox = bbox(s.shape);
|
||||
|
||||
geom::box<float, 2> result;
|
||||
|
||||
for (int y = 0; y <= 1; ++y)
|
||||
for (int x = 0; x <= 1; ++x)
|
||||
result |= geom::as_point(s.matrix * geom::homogeneous(sbox.corner(x, y)));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,4 +38,12 @@ namespace psemek::vecr
|
|||
return result;
|
||||
}
|
||||
|
||||
geom::box<float, 2> bbox(add const & s)
|
||||
{
|
||||
geom::box<float, 2> result;
|
||||
for (auto const & ss : s.shapes)
|
||||
result |= bbox(ss);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,4 +12,9 @@ namespace psemek::vecr
|
|||
return {l - s.radius, {0.f, 0.f}};
|
||||
}
|
||||
|
||||
geom::box<float, 2> bbox(circle const & s)
|
||||
{
|
||||
return geom::expand(geom::box<float, 2>::singleton(s.center), s.radius);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,4 +29,9 @@ namespace psemek::vecr
|
|||
return result;
|
||||
}
|
||||
|
||||
geom::box<float, 2> bbox(fill const & s)
|
||||
{
|
||||
return bbox(s.border);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,4 +39,12 @@ namespace psemek::vecr
|
|||
return result;
|
||||
}
|
||||
|
||||
geom::box<float, 2> bbox(intersect const & s)
|
||||
{
|
||||
auto result = geom::box<float, 2>::full();
|
||||
for (auto const & ss : s.shapes)
|
||||
result &= bbox(ss);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,4 +27,14 @@ namespace psemek::vecr
|
|||
return result;
|
||||
}
|
||||
|
||||
geom::box<float, 2> bbox(path const & s)
|
||||
{
|
||||
geom::box<float, 2> result;
|
||||
|
||||
for (auto const & p : s.points)
|
||||
result |= p;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,13 @@ namespace psemek::vecr
|
|||
return result_;
|
||||
}
|
||||
|
||||
gfx::pixmap_rgba renderer::release()
|
||||
{
|
||||
resolve();
|
||||
canvas_.clear();
|
||||
return std::move(result_);
|
||||
}
|
||||
|
||||
void renderer::clear(gfx::color_rgba const & color)
|
||||
{
|
||||
canvas_.fill(color);
|
||||
|
|
@ -39,22 +46,32 @@ namespace psemek::vecr
|
|||
{
|
||||
float const aa = primitive.blur / 2.f;
|
||||
|
||||
for (auto const & idx : canvas_.indices())
|
||||
auto const box = geom::expand(bbox(primitive.mask), aa);
|
||||
|
||||
int xmin = std::max<int>(0, std::floor(box[0].min) * samples_);
|
||||
int xmax = std::min<int>(canvas_.width() - 1, std::ceil(box[0].max) * samples_);
|
||||
int ymin = std::max<int>(0, std::floor(box[1].min) * samples_);
|
||||
int ymax = std::min<int>(canvas_.height() - 1, std::ceil(box[1].max) * samples_);
|
||||
|
||||
for (int y = ymin; y < ymax; ++y)
|
||||
{
|
||||
geom::point const center{(idx[0] + 0.5f) / samples_, (idx[1] + 0.5f) / samples_};
|
||||
for (int x = xmin; x < xmax; ++x)
|
||||
{
|
||||
geom::point const center{(x + 0.5f) / samples_, (y + 0.5f) / samples_};
|
||||
|
||||
auto const sample = sdf(primitive.mask, center);
|
||||
auto const sample = sdf(primitive.mask, center);
|
||||
|
||||
if (sample.value > aa) continue;
|
||||
if (sample.value > aa) continue;
|
||||
|
||||
float blur = 1.f;
|
||||
if (sample.value > - aa)
|
||||
blur = (aa - sample.value) / (2.f * aa);
|
||||
float blur = 1.f;
|
||||
if (sample.value > - aa)
|
||||
blur = (aa - sample.value) / (2.f * aa);
|
||||
|
||||
auto color = colorize(primitive.colorizer, center, sample);
|
||||
color[3] *= blur;
|
||||
auto color = colorize(primitive.colorizer, center, sample);
|
||||
color[3] *= blur;
|
||||
|
||||
canvas_(idx) = gfx::to_coloru8(primitive.blend(gfx::to_colorf(canvas_(idx)), color));
|
||||
canvas_(x, y) = gfx::to_coloru8(primitive.blend(gfx::to_colorf(canvas_(x, y)), color));
|
||||
}
|
||||
}
|
||||
|
||||
need_resolve_ = true;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue