Lab5 impl without sorting

This commit is contained in:
Andrew Golovashevich 2025-03-10 17:53:08 +03:00
parent 9e58b48034
commit 737cb2a23c
13 changed files with 483 additions and 29 deletions

View File

@ -22,3 +22,4 @@ add_subdirectory(qt-utilities)
add_subdirectory(programs/labs1_2) add_subdirectory(programs/labs1_2)
add_subdirectory(programs/lab3) add_subdirectory(programs/lab3)
add_subdirectory(programs/lab4) add_subdirectory(programs/lab4)
add_subdirectory(programs/lab5)

View File

@ -15,7 +15,7 @@
namespace BGTU::ComputerGraphicsLabWork::Impl { namespace BGTU::ComputerGraphicsLabWork::Impl {
class _Lab3SpriteData_Provider; class _Lab5SpriteData_Provider;
struct SpriteData { struct SpriteData {
@ -25,11 +25,11 @@ namespace BGTU::ComputerGraphicsLabWork::Impl {
Utilities::Matrix3d planets_transform[9]; Utilities::Matrix3d planets_transform[9];
Utilities::Matrix3d stars_transform; Utilities::Matrix3d stars_transform;
double time_ms; double time_ms;
using Provider = _Lab3SpriteData_Provider; using Provider = _Lab5SpriteData_Provider;
}; };
class _Lab3SpriteData_Provider : public QObject, public RendererApi::Sprite<SpriteData, Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl>::SpriteDataProvider { class _Lab5SpriteData_Provider : public QObject, public RendererApi::Sprite<SpriteData, Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl>::SpriteDataProvider {
Q_OBJECT Q_OBJECT
private: private:
QMutex sync; QMutex sync;
@ -37,7 +37,7 @@ namespace BGTU::ComputerGraphicsLabWork::Impl {
RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t w, h; RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t w, h;
public: public:
explicit _Lab3SpriteData_Provider(double radians_per_second) : explicit _Lab5SpriteData_Provider(double radians_per_second) :
sync{}, time{}, sync{}, time{},
w{0}, h{0} {} w{0}, h{0} {}

View File

@ -0,0 +1,10 @@
add_executable(
lab5
src/main.cpp
src/sprite_data.hpp
src/model.cpp
src/triangle.hpp
)
target_link_libraries(lab5 PRIVATE Qt5::Core Qt5::Widgets renderer_api utilities qt_utilities)

View File

@ -0,0 +1,82 @@
#include <cmath>
#include <array>
#include <iostream>
#include <numbers>
#include <QApplication>
#include <QMainWindow>
#include <QTimer>
#include <QGridLayout>
#include <bgtu/computer_graphics_lab_work/renderer_api/color.hpp>
#include <bgtu/computer_graphics_lab_work/utilities/default_renderer_linear.hpp>
#include <bgtu/computer_graphics_lab_work/utilities/voxel_painter_exporter_to_packed_array.hpp>
#include <bgtu/computer_graphics_lab_work/utilities/matrix.hpp>
#include <bgtu/computer_graphics_lab_work/qt_utilities/separate_threaded_renderer.hpp>
#include <bgtu/computer_graphics_lab_work/qt_utilities/renderer_widget.hpp>
#include <bgtu/computer_graphics_lab_work/qt_utilities/keyboard_catcher_widget.hpp>
#include "sprite_data.hpp"
#include "model.hpp"
namespace BGTU::ComputerGraphicsLabWork::Impl {
int main(int argc, char **argv) {
#if 1
QApplication qApplication{argc, argv};
SpriteData::Provider sprites_data_custom{0.1, 0.1, 10};
QMainWindow w{};
QtUtilities::KeyboardCatcherWidget kbd{&w};
QObject::connect(&kbd, &QtUtilities::KeyboardCatcherWidget::key_pressed_Left, &sprites_data_custom, &SpriteData::Provider::dec_y_angle);
QObject::connect(&kbd, &QtUtilities::KeyboardCatcherWidget::key_pressed_Right, &sprites_data_custom, &SpriteData::Provider::inc_y_angle);
QObject::connect(&kbd, &QtUtilities::KeyboardCatcherWidget::key_pressed_Down, &sprites_data_custom, &SpriteData::Provider::dec_x_angle);
QObject::connect(&kbd, &QtUtilities::KeyboardCatcherWidget::key_pressed_Up, &sprites_data_custom, &SpriteData::Provider::inc_x_angle);
QObject::connect(&kbd, &QtUtilities::KeyboardCatcherWidget::key_pressed_A, &sprites_data_custom, &SpriteData::Provider::dec_y_angle);
QObject::connect(&kbd, &QtUtilities::KeyboardCatcherWidget::key_pressed_D, &sprites_data_custom, &SpriteData::Provider::inc_y_angle);
QObject::connect(&kbd, &QtUtilities::KeyboardCatcherWidget::key_pressed_S, &sprites_data_custom, &SpriteData::Provider::dec_x_angle);
QObject::connect(&kbd, &QtUtilities::KeyboardCatcherWidget::key_pressed_W, &sprites_data_custom, &SpriteData::Provider::inc_x_angle);
QObject::connect(&kbd, &QtUtilities::KeyboardCatcherWidget::key_pressed_PageDown, &sprites_data_custom, &SpriteData::Provider::dec_scale);
QObject::connect(&kbd, &QtUtilities::KeyboardCatcherWidget::key_pressed_PageUp, &sprites_data_custom, &SpriteData::Provider::inc_scale);
QObject::connect(&kbd, &QtUtilities::KeyboardCatcherWidget::key_pressed_P, &sprites_data_custom, &SpriteData::Provider::switch_projection);
QtUtilities::SeparateThreadedDefaultRendererLinear<SpriteData> renderer_custom{};
renderer_custom.set_sprite_data_provider(&sprites_data_custom);
renderer_custom.set_sprites(reinterpret_cast<RendererApi::Sprite <SpriteData, Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> *const *>(sprites), sprites_count);
renderer_custom.set_background(BGTU::ComputerGraphicsLabWork::RendererApi::Color{0, 0, 0});
QGridLayout layout{&kbd};
kbd.setLayout(&layout);
QtUtilities::RendererWidget<SpriteData> canvas_custom{&renderer_custom, &kbd};
layout.addWidget(&canvas_custom, 0, 0);
QObject::connect(&canvas_custom, &QtUtilities::_RendererWidget_SignalSlots::resized, &sprites_data_custom, &SpriteData::Provider::set_frame_size);
w.setCentralWidget(&kbd);
w.show();
QApplication::exec();
return 0;
#else
auto x = Utilities::Matrix4d{5, 0, 0, 0,
0, 5, 0, 0,
0, 0, 0, 1,
0, 0, -1, 0};
RendererApi::PointF<3> a{1, 1, 6};
RendererApi::PointF<3> b = x * a;
return 0;
#endif
}
}
int main(int argc, char **argv) {
return BGTU::ComputerGraphicsLabWork::Impl::main(argc, argv);
}

View File

@ -0,0 +1,95 @@
#include <utility>
#include <numbers>
#include <cmath>
#include <bgtu/computer_graphics_lab_work/utilities/shader.hpp>
#include <bgtu/computer_graphics_lab_work/utilities/shapes/triangle.hpp>
#include "triangle.hpp"
#include "sprite_data.hpp"
#include "model.hpp"
namespace BGTU::ComputerGraphicsLabWork::Impl {
namespace {
Utilities::hsv_sector_shader hsv_shader{0, 0, 0};
Utilities::MonoShader transparent_shader{{255, 255, 255, 127}};
class ChessBoardShader : public Utilities::Shader {
private:
double w, h;
public:
ChessBoardShader(double w, double h) : w{w}, h{h} {}
[[nodiscard]] RendererApi::Color::Transparent get_color(double x, double y) const override {
if (static_cast<long long>(std::floor(x / this->w) + std::floor(y / this->h)) % 2 == 0)
return {0, 0, 0, 255};
else
return {255, 255, 255, 255};
}
} chess_board_shader{0.125000000000, 0.125000000000};
RendererApi::PointF<2> rot_n(double degrees, unsigned len) {
auto radians = degrees * std::numbers::pi_v<double> / 180;
return {std::cos(radians) * len, std::sin(radians) * len};
}
Utilities::Shapes::triangle_barycentric_shader tri_shader_1{
{0, 0}, RendererApi::Color{0, 0, 255},
{1, 0}, RendererApi::Color{0, 255, 255},
{0, 1}, RendererApi::Color{0, 255, 0}
};
Utilities::Shapes::triangle_barycentric_shader tri_shader_2{
{1, 1}, RendererApi::Color{255, 255, 0},
{1, 0}, RendererApi::Color{0, 255, 255},
{0, 1}, RendererApi::Color{0, 255, 0}
};
Triangle triangles[] = {
{{0, 1, 1}, {1, 1, 0}, {1, 0, 1}, rot_n(0, 1), rot_n(240, 1), rot_n(120, 1), &hsv_shader},
{{-1, -1, 1}, {-1, 1, 1}, {0, 1, 1}, rot_n(60, 2), rot_n(0, 2), rot_n(0, 1), &hsv_shader},
{{-1, -1, 1}, {1, 0, 1}, {0, 1, 1}, rot_n(60, 2), rot_n(120, 1), rot_n(0, 1), &hsv_shader},
{{-1, -1, 1}, {1, 0, 1}, {1, -1, 1}, rot_n(60, 2), rot_n(120, 1), rot_n(120, 1), &hsv_shader},
{{1, -1, -1}, {1, 1, -1}, {1, 1, 0}, rot_n(180, 2), rot_n(240, 2), rot_n(240, 1), &hsv_shader},
{{1, -1, -1}, {1, 0, 1}, {1, 1, 0}, rot_n(180, 2), rot_n(120, 1), rot_n(240, 1), &hsv_shader},
{{1, -1, -1}, {1, 0, 1}, {1, -1, 1}, rot_n(180, 2), rot_n(120, 1), rot_n(120, 2), &hsv_shader},
{{-1, 1, -1}, {1, 1, -1}, {1, 1, 0}, rot_n(300, 2), rot_n(240, 2), rot_n(240, 1), &hsv_shader},
{{-1, 1, -1}, {0, 1, 1}, {1, 1, 0}, rot_n(300, 2), rot_n(0, 1), rot_n(240, 1), &hsv_shader},
{{-1, 1, -1}, {0, 1, 1}, {-1, 1, 1}, rot_n(300, 2), rot_n(0, 1), rot_n(0, 2), &hsv_shader},
{{-1, -1, 1}, {-1, -1, -1}, {-1, 1, 1}, {0, 0}, {0, 1}, {1, 0}, &chess_board_shader, false},
{{-1, 1, -1}, {-1, -1, -1}, {-1, 1, 1}, {1, 1}, {0, 1}, {1, 0}, &chess_board_shader, false},
{{-1, -1, -1}, {-1, 1, -1}, {1, 1, -1}, {0, 0}, {0, 1}, {1, 1}, &transparent_shader},
{{-1, -1, -1}, {1, -1, -1}, {1, 1, -1}, {0, 0}, {1, 0}, {1, 1}, &transparent_shader},
{{1, -1, 1}, {-1, -1, 1}, {1, -1, -1}, {0, 0}, {0, 1}, {1, 0}, &tri_shader_1},
{{-1, -1, -1}, {-1, -1, 1}, {1, -1, -1}, {1, 1}, {0, 1}, {1, 0}, &tri_shader_2},
};
Triangle *const _sprites[]{
&triangles[0],
&triangles[1],
&triangles[2],
&triangles[3],
&triangles[4],
&triangles[5],
&triangles[6],
&triangles[7],
&triangles[8],
&triangles[9],
&triangles[10],
&triangles[11],
&triangles[12],
&triangles[13],
&triangles[14],
&triangles[15],
&triangles[16],
&triangles[17],
&triangles[18],
&triangles[19],
};
}
Triangle *const *const sprites = _sprites;
std::size_t sprites_count = 16;
}

View File

@ -0,0 +1,11 @@
#pragma once
#include <bgtu/computer_graphics_lab_work/renderer_api/sprite.hpp>
#include <bgtu/computer_graphics_lab_work/utilities/default_renderer_linear.hpp>
#include "sprite_data.hpp"
#include "triangle.hpp"
namespace BGTU::ComputerGraphicsLabWork::Impl {
extern Triangle *const *const sprites;
extern std::size_t sprites_count;
}

View File

@ -0,0 +1,127 @@
#pragma once
#include <cstdlib>
#include <cmath>
#include <numbers>
#include <QObject>
#include <QMutex>
#include <QElapsedTimer>
#include <bgtu/computer_graphics_lab_work/renderer_api/point.hpp>
#include <bgtu/computer_graphics_lab_work/renderer_api/sprite.hpp>
#include <bgtu/computer_graphics_lab_work/utilities/matrix.hpp>
#include <bgtu/computer_graphics_lab_work/utilities/default_renderer_linear.hpp>
#include <bgtu/computer_graphics_lab_work/utilities/zoomed_voxel_painter.hpp>
namespace BGTU::ComputerGraphicsLabWork::Impl {
class _Lab5SpriteData_Provider;
struct SpriteData {
public:
using Provider = _Lab5SpriteData_Provider;
Utilities::Matrix4d transform;
bool is_projection_enabled;
double x_radius;
double y_radius;
explicit SpriteData(Utilities::Matrix4d transform, bool is_projection_enabled, double x_radius, double y_radius) :
transform{transform}, is_projection_enabled{is_projection_enabled}, x_radius{x_radius}, y_radius{y_radius} {}
[[nodiscard]] inline RendererApi::PointI<2> project_point(RendererApi::PointF<3> p) const {
if (this->is_projection_enabled)
return {static_cast<RendererApi::PointI<2>::component_t>((p.x - this->x_radius) / (p.z * (1 / this->x_radius) + 1) + this->x_radius), static_cast<RendererApi::PointI<2>::component_t>((p.y - this->y_radius) / (p.z * (1 / this->y_radius) + 1) + this->y_radius)};
else
return RendererApi::PointI<2>{static_cast<RendererApi::PointI<2>::component_t>(p.x), static_cast<RendererApi::PointI<2>::component_t>(p.y)};
};
};
class _Lab5SpriteData_Provider : public QObject, public RendererApi::Sprite<SpriteData, Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl>::SpriteDataProvider {
Q_OBJECT
private:
QMutex sync;
double x_angle;
double y_angle;
double scale;
double x_angle_step;
double y_angle_step;
double scale_step;
bool is_projection_enabled;
RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t w, h;
public:
explicit _Lab5SpriteData_Provider(
double x_angle_step,
double y_angle_step,
double scale_step
) : x_angle{0}, y_angle{0}, scale{1}, x_angle_step{x_angle_step}, y_angle_step{y_angle_step}, scale_step{scale_step},
w{0}, h{0}, is_projection_enabled{false} {}
SpriteData get_sprite_data() override {
this->sync.lock();
double radius = (((this->w < this->h) ? this->w : this->h) * 7 / 16.0);
SpriteData cached{
Utilities::Matrix4d::shift(0, 0, this->scale) * Utilities::Matrix4d::shift(this->w / 2, this->h / 2, radius * 2) * Utilities::Matrix4d::rotate_x(this->x_angle) * Utilities::Matrix4d::rotate_y(this->y_angle) * Utilities::Matrix4d::scale(radius),
this->is_projection_enabled, this->w * 7 / 16.0, this->h * 7 / 16.0,
};
this->sync.unlock();
return cached;
}
public slots:
void set_frame_size(RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t ww, RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t hh) {
this->sync.lock();
this->w = ww;
this->h = hh;
this->sync.unlock();
}
void inc_x_angle() {
this->sync.lock();
this->x_angle += this->x_angle_step;
this->sync.unlock();
}
void dec_x_angle() {
this->sync.lock();
this->x_angle -= this->x_angle_step;
this->sync.unlock();
}
void inc_y_angle() {
this->sync.lock();
this->y_angle += this->y_angle_step;
this->sync.unlock();
}
void dec_y_angle() {
this->sync.lock();
this->y_angle -= this->y_angle_step;
this->sync.unlock();
}
void inc_scale() {
this->sync.lock();
this->scale += this->scale_step;
this->sync.unlock();
}
void dec_scale() {
this->sync.lock();
this->scale -= this->scale_step;
this->sync.unlock();
}
void switch_projection() {
this->sync.lock();
this->is_projection_enabled = !this->is_projection_enabled;
this->sync.unlock();
}
};
}

View File

@ -0,0 +1,83 @@
#pragma once
#include <bgtu/computer_graphics_lab_work/renderer_api/point.hpp>
#include <bgtu/computer_graphics_lab_work/renderer_api/sprite.hpp>
#include <bgtu/computer_graphics_lab_work/utilities/matrix.hpp>
#include <bgtu/computer_graphics_lab_work/utilities/shader.hpp>
#include <bgtu/computer_graphics_lab_work/utilities/shapes/triangle.hpp>
#include "sprite_data.hpp"
namespace BGTU::ComputerGraphicsLabWork::Impl {
class Triangle : public RendererApi::Sprite<SpriteData> {
public:
const RendererApi::PointF<3> triangle_p0;
const RendererApi::PointF<3> triangle_p1;
const RendererApi::PointF<3> triangle_p2;
private:
const RendererApi::PointF<2> shader_p0;
const RendererApi::PointF<2> shader_p1;
const RendererApi::PointF<2> shader_p2;
Utilities::Shader const *const shader;
bool apply_projection_to_shader;
public:
Triangle(
RendererApi::PointF<3> triangle_p0,
RendererApi::PointF<3> triangle_p1,
RendererApi::PointF<3> triangle_p2,
RendererApi::PointF<2> shader_p0,
RendererApi::PointF<2> shader_p1,
RendererApi::PointF<2> shader_p2,
Utilities::Shader const *shader,
bool apply_projection_to_shader = true
) : triangle_p0{triangle_p0}, triangle_p1{triangle_p1}, triangle_p2{triangle_p2},
shader_p0{shader_p0}, shader_p1{shader_p1}, shader_p2{shader_p2}, shader{shader}, apply_projection_to_shader{apply_projection_to_shader} {}
void draw(BGTU::ComputerGraphicsLabWork::RendererApi::VirtualVoxelPainter *frame, SpriteData const *data) const override {
auto ta = data->transform * this->triangle_p0;
auto tb = data->transform * this->triangle_p1;
auto tc = data->transform * this->triangle_p2;
RendererApi::PointI<2> pa = data->project_point(ta);
RendererApi::PointI<2> pb = data->project_point(tb);
RendererApi::PointI<2> pc = data->project_point(tc);
if (this->apply_projection_to_shader) {
Utilities::Shapes::triangle_barycentric_interpolator<RendererApi::PointF<3>> interpolator{
static_cast<RendererApi::PointF<2>>(pa), {this->shader_p0.x, this->shader_p0.y, ta.z},
static_cast<RendererApi::PointF<2>>(pb), {this->shader_p1.x, this->shader_p1.y, tb.z},
static_cast<RendererApi::PointF<2>>(pc), {this->shader_p2.x, this->shader_p2.y, tc.z},
};
Utilities::Shapes::iterate_triangle_fill(
pa, pb, pc,
[&, this](bool is_edge, RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y) {
RendererApi::PointF<3> _tmp = interpolator.interpolate_point(x, y);
frame->add_voxel(x, y, _tmp.z, this->shader->get_color(_tmp.x, _tmp.y));
}
);
} else {
Utilities::Shapes::triangle_barycentric_interpolator<double> z_interpolator{
static_cast<RendererApi::PointF<2>>(pa), ta.z,
static_cast<RendererApi::PointF<2>>(pb), tb.z,
static_cast<RendererApi::PointF<2>>(pc), tc.z,
};
Utilities::Shapes::triangle_barycentric_interpolator<RendererApi::PointF<2>> shader_interpolator{
{ta.x, ta.y}, this->shader_p0,
{tb.x, tb.y}, this->shader_p1,
{tc.x, tc.y}, this->shader_p2,
};
Utilities::Shapes::iterate_triangle_fill(
pa, pb, pc,
[&, this](bool is_edge, RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y) {
frame->add_voxel(x, y, z_interpolator.interpolate_point(x, y), this->shader->get_color(shader_interpolator.interpolate_point(x, y)));
}
);
}
}
};
}

View File

@ -286,24 +286,18 @@ namespace BGTU::ComputerGraphicsLabWork::Impl::Variants::Lab2 {
} }
case ShaderType::BARYCENTRIC: { case ShaderType::BARYCENTRIC: {
Utilities::Shapes::triangle_barycentric_shader s{ Utilities::Shapes::triangle_barycentric_shader s{
data->pos_rotated_f(data->radius * radius_multiplier, -120.0), data->pos_rotated_f(data->radius * radius_multiplier, -120.0), RendererApi::Color{255, 0, 0},
data->pos_rotated_f(data->radius * radius_multiplier, 0.0), data->pos_rotated_f(data->radius * radius_multiplier, 0.0), RendererApi::Color{0, 255, 0},
data->pos_rotated_f(data->radius * radius_multiplier, 120.0), data->pos_rotated_f(data->radius * radius_multiplier, 120.0), RendererApi::Color{0, 0, 255}
RendererApi::Color{255, 0, 0},
RendererApi::Color{0, 255, 0},
RendererApi::Color{0, 0, 255}
}; };
receiver(s); receiver(s);
return; return;
} }
case ShaderType::BARYCENTRIC_SEMI_TRANSPARENT: { case ShaderType::BARYCENTRIC_SEMI_TRANSPARENT: {
Utilities::Shapes::triangle_barycentric_shader s{ Utilities::Shapes::triangle_barycentric_shader s{
data->pos_rotated_f(data->radius * radius_multiplier, -120.0), data->pos_rotated_f(data->radius * radius_multiplier, -120.0), RendererApi::Color::Transparent{255, 0, 0, 127},
data->pos_rotated_f(data->radius * radius_multiplier, 0.0), data->pos_rotated_f(data->radius * radius_multiplier, 0.0), RendererApi::Color::Transparent{0, 255, 0, 127},
data->pos_rotated_f(data->radius * radius_multiplier, 120.0), data->pos_rotated_f(data->radius * radius_multiplier, 120.0), RendererApi::Color::Transparent{0, 0, 255, 127}
RendererApi::Color::Transparent{255, 0, 0, 127},
RendererApi::Color::Transparent{0, 255, 0, 127},
RendererApi::Color::Transparent{0, 0, 255, 127}
}; };
receiver(s); receiver(s);
return; return;

View File

@ -83,6 +83,7 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
void key_pressed_S(); void key_pressed_S();
void key_pressed_D(); void key_pressed_D();
void key_pressed_P();
protected: protected:
void keyPressEvent(QKeyEvent *event) override { void keyPressEvent(QKeyEvent *event) override {
@ -186,6 +187,9 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities {
case Qt::Key_S: case Qt::Key_S:
emit this->key_pressed_S(); emit this->key_pressed_S();
return; return;
case Qt::Key_P:
emit this->key_pressed_P();
return;
} }
} }

View File

@ -32,7 +32,7 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities {
const float sum_f[4]{bg_alpha[0] + fg_alpha[0], bg_alpha[1] + fg_alpha[1], bg_alpha[2] + fg_alpha[2]}; const float sum_f[4]{bg_alpha[0] + fg_alpha[0], bg_alpha[1] + fg_alpha[1], bg_alpha[2] + fg_alpha[2]};
// divps // divps
const float sum_fixed_f[4]{sum_f[0] / 255.f, sum_f[2] / 255.f, sum_f[2] / 255.f}; const float sum_fixed_f[4]{sum_f[0] / 255.f, sum_f[1] / 255.f, sum_f[2] / 255.f};
return { return {
(RendererApi::Color::component_compact_t) sum_fixed_f[0], (RendererApi::Color::component_compact_t) sum_fixed_f[0],

View File

@ -3,6 +3,7 @@
#include <bgtu/computer_graphics_lab_work/renderer_api/color.hpp> #include <bgtu/computer_graphics_lab_work/renderer_api/color.hpp>
#include <bgtu/computer_graphics_lab_work/renderer_api/point.hpp> #include <bgtu/computer_graphics_lab_work/renderer_api/point.hpp>
#include "color.hpp"
#include "matrix.hpp" #include "matrix.hpp"
@ -134,6 +135,51 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities {
template<RendererApi::Color::Transparent color> template<RendererApi::Color::Transparent color>
constexpr MonoShader::Static<color> const MonoShader::static_{}; constexpr MonoShader::Static<color> const MonoShader::static_{};
template<RendererApi::Color::Transparent c1, RendererApi::Color::Transparent c2>
class RadialShader : public Utilities::Shader {
private:
RendererApi::PointF<2>::component_t cx, cy;
RendererApi::PointF<2>::component_t radius;
public:
RadialShader(RendererApi::PointF<2>::component_t cx, RendererApi::PointF<2>::component_t cy, RendererApi::PointF<2>::component_t radius) : cx{cx}, cy{cy}, radius{radius} {}
RadialShader(RendererApi::PointF<2> c, RendererApi::PointF<2>::component_t radius) : cx{c.x}, cy{c.y}, radius{radius} {}
RadialShader(RendererApi::PointI<2> c, RendererApi::PointF<2>::component_t radius) : cx{(double) c.x}, cy{(double) c.y}, radius{radius} {}
[[nodiscard]] RendererApi::Color::Transparent get_color(RendererApi::PointF<2>::component_t x, RendererApi::PointF<2>::component_t y) const final {
RendererApi::PointF<2>::component_t distance = std::hypot(x - this->cx, y - this->cy);
double ratio = distance / this->radius;
float c1v;
if (ratio < 0.5) {
c1v = (float) (std::fabs(ratio - 0.25) * 4);
} else if (ratio < 1.0) {
c1v = (float) (std::fabs(ratio - 0.75) * 4);
} else {
return c1;
}
return Utilities::colors_gradient(c1, c1v, c2);
}
};
class hsv_sector_shader : public Utilities::Shader {
private:
RendererApi::PointF<2>::component_t cx, cy;
double angle_offset_radians;
public:
hsv_sector_shader(RendererApi::PointF<2>::component_t cx, RendererApi::PointF<2>::component_t cy, double angle_offset_radians) : cx{cx}, cy{cy}, angle_offset_radians{angle_offset_radians} {}
hsv_sector_shader(RendererApi::PointF<2> c, double angle_offset_radians) : cx{c.x}, cy{c.y}, angle_offset_radians{angle_offset_radians} {}
hsv_sector_shader(RendererApi::PointI<2> c, double angle_offset_radians) : cx{(double) c.x}, cy{(double) c.y}, angle_offset_radians{angle_offset_radians} {}
[[nodiscard]] RendererApi::Color::Transparent get_color(RendererApi::PointF<2>::component_t x, RendererApi::PointF<2>::component_t y) const final {
double angle = std::atan2(static_cast<double>(y - this->cy), static_cast<double>(x - this->cx)) + this->angle_offset_radians;
return Utilities::hsv_to_rgb_360_1_1(std::fmod(std::fmod(angle / std::numbers::pi_v<double> * 180, 360.0) + 360, 360.0), 1.0, 1.0);
}
};
class TransformedShader : public Shader { class TransformedShader : public Shader {
private: private:

View File

@ -391,17 +391,17 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities::Shapes {
private: private:
using point_t = RendererApi::Point<DIMENSIONS, component_t>; using point_t = RendererApi::Point<DIMENSIONS, component_t>;
_triangle_barycentric_interpolator<RendererApi::Color, []<class interpolator_t>(interpolator_t interpolator) { _triangle_barycentric_interpolator<point_t, []<class interpolator_t>(interpolator_t interpolator) {
if constexpr (DIMENSIONS == 2) if constexpr (DIMENSIONS == 2)
return point_t{ return point_t{
static_cast<point_t::component_fast_t>(interpolator([](point_t const &p) { return p.x; })), static_cast<point_t::component_t>(interpolator([](point_t const &p) { return p.x; })),
static_cast<point_t::component_fast_t>(interpolator([](point_t const &p) { return p.y; })) static_cast<point_t::component_t>(interpolator([](point_t const &p) { return p.y; }))
}; };
else else
return RendererApi::Point<3, component_t>{ return point_t{
static_cast<point_t::component_fast_t>(interpolator([](point_t const &p) { return p.x; })), static_cast<point_t::component_t>(interpolator([](point_t const &p) { return p.x; })),
static_cast<point_t::component_fast_t>(interpolator([](point_t const &p) { return p.y; })), static_cast<point_t::component_t>(interpolator([](point_t const &p) { return p.y; })),
static_cast<point_t::component_fast_t>(interpolator([](point_t const &p) { return p.z; })) static_cast<point_t::component_t>(interpolator([](point_t const &p) { return p.z; }))
}; };
}> impl; }> impl;
public: public:
@ -413,11 +413,11 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities::Shapes {
} }
[[nodiscard]] RendererApi::Color interpolate_point(RendererApi::PointF<2> p) const { [[nodiscard]] point_t interpolate_point(RendererApi::PointF<2> p) const {
return this->impl.interpolate_point(p); return this->impl.interpolate_point(p);
} }
[[nodiscard]] RendererApi::Color interpolate_point(RendererApi::PointF<2>::component_t x, RendererApi::PointF<2>::component_t y) const { [[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); return this->impl.interpolate_point(x, y);
} }
}; };
@ -427,8 +427,9 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities::Shapes {
triangle_barycentric_interpolator<RendererApi::Color::Transparent> interpolator; triangle_barycentric_interpolator<RendererApi::Color::Transparent> interpolator;
public: public:
inline triangle_barycentric_shader( inline triangle_barycentric_shader(
RendererApi::PointF<2> p0, RendererApi::PointF<2> p1, RendererApi::PointF<2> p2, RendererApi::PointF<2> p0, RendererApi::Color::Transparent c0,
RendererApi::Color::Transparent c0, RendererApi::Color::Transparent c1, RendererApi::Color::Transparent c2 RendererApi::PointF<2> p1, RendererApi::Color::Transparent c1,
RendererApi::PointF<2> p2, RendererApi::Color::Transparent c2
) noexcept: interpolator{p0, c0, p1, c1, p2, c2} {} ) noexcept: interpolator{p0, c0, p1, c1, p2, c2} {}