Applying perspective interpolation to textures
This commit is contained in:
parent
ff43f035b1
commit
8ec2ea1b58
@ -43,6 +43,16 @@ namespace BGTU::ComputerGraphicsLabWork::Impl {
|
|||||||
RendererApi::PointF<3> tb{tb4[0] / tb4[3], tb4[1] / tb4[3], tb4[2] / tb4[3]};
|
RendererApi::PointF<3> tb{tb4[0] / tb4[3], tb4[1] / tb4[3], tb4[2] / tb4[3]};
|
||||||
RendererApi::PointF<3> tc{tc4[0] / tc4[3], tc4[1] / tc4[3], tc4[2] / tc4[3]};
|
RendererApi::PointF<3> tc{tc4[0] / tc4[3], tc4[1] / tc4[3], tc4[2] / tc4[3]};
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
Utilities::Shapes::triangle_perspective_interpolator<RendererApi::PointF<3>> interpolator{
|
||||||
|
{ta.x, ta.y, ta4[3]},
|
||||||
|
{this->shader_p0.x, this->shader_p0.y, ta.z},
|
||||||
|
{tb.x, tb.y, tb4[3]},
|
||||||
|
{this->shader_p1.x, this->shader_p1.y, tb.z},
|
||||||
|
{tc.x, tc.y, tc4[3]},
|
||||||
|
{this->shader_p2.x, this->shader_p2.y, tc.z},
|
||||||
|
};
|
||||||
|
#else
|
||||||
Utilities::Shapes::triangle_barycentric_interpolator<RendererApi::PointF<3>> interpolator{
|
Utilities::Shapes::triangle_barycentric_interpolator<RendererApi::PointF<3>> interpolator{
|
||||||
{ta.x, ta.y},
|
{ta.x, ta.y},
|
||||||
{this->shader_p0.x, this->shader_p0.y, ta.z},
|
{this->shader_p0.x, this->shader_p0.y, ta.z},
|
||||||
@ -51,6 +61,7 @@ namespace BGTU::ComputerGraphicsLabWork::Impl {
|
|||||||
{tc.x, tc.y},
|
{tc.x, tc.y},
|
||||||
{this->shader_p2.x, this->shader_p2.y, tc.z},
|
{this->shader_p2.x, this->shader_p2.y, tc.z},
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
Utilities::Shapes::iterate_triangle_fill(
|
Utilities::Shapes::iterate_triangle_fill(
|
||||||
{static_cast<RendererApi::PointI<2>::component_t>(ta.x), static_cast<RendererApi::PointI<2>::component_t>(ta.y)},
|
{static_cast<RendererApi::PointI<2>::component_t>(ta.x), static_cast<RendererApi::PointI<2>::component_t>(ta.y)},
|
||||||
|
@ -433,6 +433,197 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities::Shapes {
|
|||||||
) noexcept: interpolator{p0, c0, p1, c1, p2, c2} {}
|
) noexcept: interpolator{p0, c0, p1, c1, p2, c2} {}
|
||||||
|
|
||||||
|
|
||||||
|
[[nodiscard]] inline RendererApi::Color::Transparent get_color(RendererApi::PointF<2>::component_t x, RendererApi::PointF<2>::component_t y) const final {
|
||||||
|
return this->interpolator.interpolate_point(x, y);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class variable_t, auto transform>
|
||||||
|
struct _triangle_perspective_interpolator {
|
||||||
|
private:
|
||||||
|
long double full_square;
|
||||||
|
RendererApi::PointF<3> p0;
|
||||||
|
RendererApi::PointF<3> p1;
|
||||||
|
RendererApi::PointF<3> p2;
|
||||||
|
variable_t v0;
|
||||||
|
variable_t v1;
|
||||||
|
variable_t v2;
|
||||||
|
|
||||||
|
static long double calculate_square_2(
|
||||||
|
RendererApi::PointF<2> p0,
|
||||||
|
RendererApi::PointF<3> p1,
|
||||||
|
RendererApi::PointF<3> p2
|
||||||
|
) noexcept {
|
||||||
|
return (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
_triangle_perspective_interpolator(
|
||||||
|
RendererApi::PointF<3> p0, variable_t v0,
|
||||||
|
RendererApi::PointF<3> p1, variable_t v1,
|
||||||
|
RendererApi::PointF<3> p2, variable_t v2
|
||||||
|
) : p0{p0}, p1{p1}, p2{p2}, v0{v0}, v1{v1}, v2{v2}, full_square{calculate_square_2({p0.x, p0.y}, p1, p2)} {
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] variable_t interpolate_point(RendererApi::PointF<2> p) const {
|
||||||
|
const double k0 = calculate_square_2(p, this->p1, this->p2) / (this->full_square * this->p0.z);
|
||||||
|
const double k1 = calculate_square_2(p, this->p2, this->p0) / (this->full_square * this->p1.z);
|
||||||
|
const double k2 = calculate_square_2(p, this->p0, this->p1) / (this->full_square * this->p2.z);
|
||||||
|
const double divider = k0 + k1 + k2;
|
||||||
|
|
||||||
|
return transform([=, this]<class property_getter_t>(property_getter_t pg) -> auto { return (pg(this->v0) * k0 + pg(this->v1) * k1 + pg(this->v2) * k2) / divider; });
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] variable_t interpolate_point(RendererApi::PointF<2>::component_t x, RendererApi::PointF<2>::component_t y) const {
|
||||||
|
return this->interpolate_point(RendererApi::PointF<2>{x, y});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<class variable_t>
|
||||||
|
struct triangle_perspective_interpolator {
|
||||||
|
private:
|
||||||
|
_triangle_perspective_interpolator<variable_t, []<class interpolator_t>(interpolator_t interpolator) {
|
||||||
|
return static_cast<variable_t>(interpolator([](variable_t v) { return v; }));
|
||||||
|
}> impl;
|
||||||
|
public:
|
||||||
|
triangle_perspective_interpolator(
|
||||||
|
RendererApi::PointF<3> p0, variable_t v0,
|
||||||
|
RendererApi::PointF<3> p1, variable_t v1,
|
||||||
|
RendererApi::PointF<3> p2, variable_t v2
|
||||||
|
) : impl{p0, v0, p1, v1, p2, v2} {};
|
||||||
|
|
||||||
|
[[nodiscard]] variable_t interpolate_point(RendererApi::PointF<2> p) const {
|
||||||
|
return this->impl.interpolate_point(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] variable_t interpolate_point(RendererApi::PointF<2>::component_t x, RendererApi::PointF<2>::component_t y) const {
|
||||||
|
return this->impl.interpolate_point(x, y);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct triangle_perspective_interpolator<RendererApi::Color> {
|
||||||
|
private:
|
||||||
|
_triangle_perspective_interpolator<RendererApi::Color, []<class interpolator_t>(interpolator_t interpolator) {
|
||||||
|
return RendererApi::Color{
|
||||||
|
static_cast<RendererApi::Color::component_fast_t>(interpolator([](RendererApi::Color const &c) { return c.red; })),
|
||||||
|
static_cast<RendererApi::Color::component_fast_t>(interpolator([](RendererApi::Color const &c) { return c.green; })),
|
||||||
|
static_cast<RendererApi::Color::component_fast_t>(interpolator([](RendererApi::Color const &c) { return c.blue; }))
|
||||||
|
};
|
||||||
|
}> impl;
|
||||||
|
public:
|
||||||
|
inline triangle_perspective_interpolator(
|
||||||
|
RendererApi::PointF<3> p0, RendererApi::Color v0,
|
||||||
|
RendererApi::PointF<3> p1, RendererApi::Color v1,
|
||||||
|
RendererApi::PointF<3> p2, RendererApi::Color v2
|
||||||
|
) : impl{p0, v0, p1, v1, p2, v2} {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[[nodiscard]] inline RendererApi::Color interpolate_point(RendererApi::PointF<2> p) const {
|
||||||
|
return this->impl.interpolate_point(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] inline RendererApi::Color interpolate_point(RendererApi::PointF<2>::component_t x, RendererApi::PointF<2>::component_t y) const {
|
||||||
|
return this->impl.interpolate_point(x, y);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct triangle_perspective_interpolator<RendererApi::Color::Transparent> {
|
||||||
|
private:
|
||||||
|
union _interpolators_t {
|
||||||
|
triangle_perspective_interpolator<RendererApi::Color> ignore_alpha;
|
||||||
|
_triangle_perspective_interpolator<RendererApi::Color::Transparent, []<class interpolator_t>(interpolator_t interpolator) {
|
||||||
|
return RendererApi::Color::Transparent{
|
||||||
|
static_cast<RendererApi::Color::component_fast_t>(interpolator([](RendererApi::Color::Transparent const &c) { return c.red; })),
|
||||||
|
static_cast<RendererApi::Color::component_fast_t>(interpolator([](RendererApi::Color::Transparent const &c) { return c.green; })),
|
||||||
|
static_cast<RendererApi::Color::component_fast_t>(interpolator([](RendererApi::Color::Transparent const &c) { return c.blue; })),
|
||||||
|
static_cast<RendererApi::Color::component_fast_t>(interpolator([](RendererApi::Color::Transparent const &c) { return c.alpha; }))
|
||||||
|
};
|
||||||
|
}> transparent;
|
||||||
|
} interpolators;
|
||||||
|
bool is_alpha_const;
|
||||||
|
RendererApi::Color::component_fast_t const_alpha_value;
|
||||||
|
|
||||||
|
inline triangle_perspective_interpolator(
|
||||||
|
bool is_alpha_const,
|
||||||
|
RendererApi::PointF<3> p0, RendererApi::Color::Transparent v0,
|
||||||
|
RendererApi::PointF<3> p1, RendererApi::Color::Transparent v1,
|
||||||
|
RendererApi::PointF<3> p2, RendererApi::Color::Transparent v2
|
||||||
|
) : interpolators{is_alpha_const ? _interpolators_t{.ignore_alpha{p0, v0.without_alpha(), p1, v1.without_alpha(), p2, v2.without_alpha()}} : _interpolators_t{.transparent{p0, v0, p1, v1, p2, v2}}},
|
||||||
|
is_alpha_const{is_alpha_const}, const_alpha_value{v0.alpha} {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
inline triangle_perspective_interpolator(
|
||||||
|
RendererApi::PointF<3> p0, RendererApi::Color::Transparent v0,
|
||||||
|
RendererApi::PointF<3> p1, RendererApi::Color::Transparent v1,
|
||||||
|
RendererApi::PointF<3> p2, RendererApi::Color::Transparent v2
|
||||||
|
) : triangle_perspective_interpolator{
|
||||||
|
v0.alpha == v1.alpha && v0.alpha == v2.alpha,
|
||||||
|
p0, v0, p1, v1, p2, v2
|
||||||
|
} {}
|
||||||
|
|
||||||
|
[[nodiscard]] inline RendererApi::Color::Transparent interpolate_point(RendererApi::PointF<2> p) const {
|
||||||
|
if (this->is_alpha_const)
|
||||||
|
return this->interpolators.ignore_alpha.interpolate_point(p).with_alpha(this->const_alpha_value);
|
||||||
|
else
|
||||||
|
return this->interpolators.transparent.interpolate_point(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] inline RendererApi::Color::Transparent interpolate_point(RendererApi::PointF<2>::component_t x, RendererApi::PointF<2>::component_t y) const {
|
||||||
|
return this->interpolate_point(RendererApi::PointF<2>{x, y});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<unsigned DIMENSIONS, class component_t>
|
||||||
|
struct triangle_perspective_interpolator<RendererApi::Point<DIMENSIONS, component_t>> {
|
||||||
|
private:
|
||||||
|
using point_t = RendererApi::Point<DIMENSIONS, component_t>;
|
||||||
|
|
||||||
|
_triangle_perspective_interpolator<point_t, []<class interpolator_t>(interpolator_t interpolator) {
|
||||||
|
if constexpr (DIMENSIONS == 2)
|
||||||
|
return point_t{
|
||||||
|
static_cast<point_t::component_t>(interpolator([](point_t const &p) { return p.x; })),
|
||||||
|
static_cast<point_t::component_t>(interpolator([](point_t const &p) { return p.y; }))
|
||||||
|
};
|
||||||
|
else
|
||||||
|
return point_t{
|
||||||
|
static_cast<point_t::component_t>(interpolator([](point_t const &p) { return p.x; })),
|
||||||
|
static_cast<point_t::component_t>(interpolator([](point_t const &p) { return p.y; })),
|
||||||
|
static_cast<point_t::component_t>(interpolator([](point_t const &p) { return p.z; }))
|
||||||
|
};
|
||||||
|
}> impl;
|
||||||
|
public:
|
||||||
|
triangle_perspective_interpolator(
|
||||||
|
RendererApi::PointF<3> p0, point_t v0,
|
||||||
|
RendererApi::PointF<3> p1, point_t v1,
|
||||||
|
RendererApi::PointF<3> p2, point_t v2
|
||||||
|
) : impl{p0, v0, p1, v1, p2, v2} {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[[nodiscard]] point_t interpolate_point(RendererApi::PointF<2> p) const {
|
||||||
|
return this->impl.interpolate_point(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] point_t interpolate_point(RendererApi::PointF<2>::component_t x, RendererApi::PointF<2>::component_t y) const {
|
||||||
|
return this->impl.interpolate_point(x, y);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class triangle_perspective_shader : public Shader {
|
||||||
|
private:
|
||||||
|
triangle_perspective_interpolator<RendererApi::Color::Transparent> interpolator;
|
||||||
|
public:
|
||||||
|
inline triangle_perspective_shader(
|
||||||
|
RendererApi::PointF<3> p0, RendererApi::Color::Transparent c0,
|
||||||
|
RendererApi::PointF<3> p1, RendererApi::Color::Transparent c1,
|
||||||
|
RendererApi::PointF<3> p2, RendererApi::Color::Transparent c2
|
||||||
|
) noexcept: interpolator{p0, c0, p1, c1, p2, c2} {}
|
||||||
|
|
||||||
|
|
||||||
[[nodiscard]] inline RendererApi::Color::Transparent get_color(RendererApi::PointF<2>::component_t x, RendererApi::PointF<2>::component_t y) const final {
|
[[nodiscard]] inline RendererApi::Color::Transparent get_color(RendererApi::PointF<2>::component_t x, RendererApi::PointF<2>::component_t y) const final {
|
||||||
return this->interpolator.interpolate_point(x, y);
|
return this->interpolator.interpolate_point(x, y);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user