From 73132bbec5ce65510f05a99e432deec11bf5aaae Mon Sep 17 00:00:00 2001 From: Andrew Golovashevich Date: Wed, 11 Dec 2024 09:42:03 +0300 Subject: [PATCH] Drawing square to screen (almost) --- CMakeLists.txt | 2 +- programs/lab1/CMakeLists.txt | 16 +- programs/lab1/src/keyboard_catcher_widget.hpp | 5 + programs/lab1/src/main.cpp | 29 +- programs/lab1/src/pixel_grid_sprite.hpp | 10 +- programs/lab1/src/sprite_data.hpp | 48 +++- programs/lab1/src/variants.hpp | 83 ++++++ programs/lab1/src/variants/variant1.cpp | 29 ++ programs/lab1/src/variants/variant2.cpp | 0 programs/lab1/src/variants/variant3.cpp | 0 programs/lab1/src/variants/variant4.cpp | 0 programs/lab1/src/variants/variant5.cpp | 0 programs/lab1/src/variants/variant6.cpp | 0 programs/lab1/src/variants/variant8.cpp | 0 programs/lab1/src/variants/variant9.cpp | 0 programs/lab1/src/zoomed_scene_sprite.hpp | 25 ++ .../_separate_threaded_renderer.hpp | 2 +- .../separate_threaded_renderer.hpp | 6 +- .../renderer_api/point.hpp | 17 +- .../utilities/color.hpp | 145 +++++++++- .../utilities/{ => shapes}/brezenham.hpp | 41 +-- .../utilities/shapes/polygon.hpp | 69 +++++ .../utilities/shapes/polyline.hpp | 62 ++++ .../utilities/shapes/rectangle.hpp | 272 ++++++++++++++++++ .../utilities/triangle_fill_iterable.hpp | 2 +- ...voxel_painter_exporter_to_packed_array.hpp | 2 +- .../utilities/zoomed_voxel_painter.hpp | 66 +++++ utilities/src/color.asm | 53 ++-- 28 files changed, 910 insertions(+), 74 deletions(-) create mode 100644 programs/lab1/src/variants.hpp create mode 100644 programs/lab1/src/variants/variant1.cpp create mode 100644 programs/lab1/src/variants/variant2.cpp create mode 100644 programs/lab1/src/variants/variant3.cpp create mode 100644 programs/lab1/src/variants/variant4.cpp create mode 100644 programs/lab1/src/variants/variant5.cpp create mode 100644 programs/lab1/src/variants/variant6.cpp create mode 100644 programs/lab1/src/variants/variant8.cpp create mode 100644 programs/lab1/src/variants/variant9.cpp create mode 100644 programs/lab1/src/zoomed_scene_sprite.hpp rename utilities/include/bgtu/computer_graphics_lab_work/utilities/{ => shapes}/brezenham.hpp (67%) create mode 100644 utilities/include/bgtu/computer_graphics_lab_work/utilities/shapes/polygon.hpp create mode 100644 utilities/include/bgtu/computer_graphics_lab_work/utilities/shapes/polyline.hpp create mode 100644 utilities/include/bgtu/computer_graphics_lab_work/utilities/shapes/rectangle.hpp create mode 100644 utilities/include/bgtu/computer_graphics_lab_work/utilities/zoomed_voxel_painter.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 1cc2189..17eff28 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.25) project(cg1) -set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD 23) find_package(Qt5 REQUIRED COMPONENTS Core Widgets Gui) set(CMAKE_AUTOMOC ON) diff --git a/programs/lab1/CMakeLists.txt b/programs/lab1/CMakeLists.txt index d9a9612..8c79bd4 100644 --- a/programs/lab1/CMakeLists.txt +++ b/programs/lab1/CMakeLists.txt @@ -1,2 +1,16 @@ -add_executable(lab1 src/main.cpp src/sprite_data.hpp src/keyboard_catcher_widget.hpp) +add_executable( + lab1 + src/main.cpp + src/sprite_data.hpp + src/keyboard_catcher_widget.hpp + + src/variants/variant1.cpp + src/variants/variant2.cpp + src/variants/variant3.cpp + src/variants/variant4.cpp + src/variants/variant5.cpp + src/variants/variant6.cpp + src/variants/variant8.cpp + src/variants/variant9.cpp +) target_link_libraries(lab1 PRIVATE Qt5::Core Qt5::Widgets renderer_api utilities qt_utilities) diff --git a/programs/lab1/src/keyboard_catcher_widget.hpp b/programs/lab1/src/keyboard_catcher_widget.hpp index 53d7201..5c21c8b 100644 --- a/programs/lab1/src/keyboard_catcher_widget.hpp +++ b/programs/lab1/src/keyboard_catcher_widget.hpp @@ -18,6 +18,8 @@ namespace BGTU::ComputerGraphicsLabWork::Lab1 { void key_pressed_PageDown(); + void key_pressed_G(); + protected: void keyPressEvent(QKeyEvent *event) override { switch (event->key()) { @@ -27,6 +29,9 @@ namespace BGTU::ComputerGraphicsLabWork::Lab1 { case Qt::Key_PageDown: emit this->key_pressed_PageDown(); return; + case Qt::Key_G: + emit this->key_pressed_G(); + return; } } diff --git a/programs/lab1/src/main.cpp b/programs/lab1/src/main.cpp index a30ecd0..c324533 100644 --- a/programs/lab1/src/main.cpp +++ b/programs/lab1/src/main.cpp @@ -1,7 +1,8 @@ +#include +#include #include #include #include -#include #include #include #include @@ -11,27 +12,38 @@ #include "sprite_data.hpp" #include "keyboard_catcher_widget.hpp" #include "pixel_grid_sprite.hpp" +#include "variants.hpp" +#include "zoomed_scene_sprite.hpp" namespace BGTU::ComputerGraphicsLabWork::Lab1 { + + volatile RendererApi::Color bg{0, 0, 0}; + RendererApi::Color::Transparent fg{255, 255, 255, 127}; + int main(int argc, char **argv) { +#if 1 QApplication qApplication{argc, argv}; - PixelGridSprite pixels_grid_sprite{RendererApi::Color{0, 0, 0}, RendererApi::Color{32, 32, 32}}; + PixelGridSprite pixels_grid_sprite{RendererApi::Color{0, 0, 0}, RendererApi::Color{16, 16, 16}}; + ZoomedSceneSprite zoomed_scene_sprite{}; auto sprites = std::to_array *const>({ - &pixels_grid_sprite - }); + &pixels_grid_sprite, + &zoomed_scene_sprite + }); Lab1SpriteData::Provider sprites_data{1}; sprites_data.set_pixel_size(16); + sprites_data.set_sub_sprites(variant1.sprites, variant1.count); QMainWindow w{}; KeyboardCatcherWidget kbd{&w}; QObject::connect(&kbd, &KeyboardCatcherWidget::key_pressed_PageDown, &sprites_data, &Lab1SpriteData::Provider::decrease_pixel_size); QObject::connect(&kbd, &KeyboardCatcherWidget::key_pressed_PageUp, &sprites_data, &Lab1SpriteData::Provider::increase_pixel_size); + QObject::connect(&kbd, &KeyboardCatcherWidget::key_pressed_G, &sprites_data, &Lab1SpriteData::Provider::invert_show_grid); QtUtilities::SeparateThreadedDefaultRendererLinear renderer{}; renderer.set_sprite_data_provider(&sprites_data); @@ -46,6 +58,15 @@ namespace BGTU::ComputerGraphicsLabWork::Lab1 { QApplication::exec(); return 0; +#else + + + + auto c = Utilities::apply_transparent_color(*(RendererApi::Color*)&bg, fg); + std::cout << c.red << c.green << c.blue << std::endl; + + return 0; +#endif } } diff --git a/programs/lab1/src/pixel_grid_sprite.hpp b/programs/lab1/src/pixel_grid_sprite.hpp index 56e357e..8b35441 100644 --- a/programs/lab1/src/pixel_grid_sprite.hpp +++ b/programs/lab1/src/pixel_grid_sprite.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "sprite_data.hpp" @@ -15,6 +16,9 @@ namespace BGTU::ComputerGraphicsLabWork::Lab1 { PixelGridSprite(RendererApi::Color bg, RendererApi::Color fg) : bg{bg}, fg{fg} {}; void draw(Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl *frame, const Lab1SpriteData *data) const override { + if (!data->show_grid) + return; + long long start_x = data->central_pixel_tl.x - ((data->central_pixel_tl.x + data->pixel_size - 1) / data->pixel_size * data->pixel_size); long long start_y = data->central_pixel_tl.y - ((data->central_pixel_tl.y + data->pixel_size - 1) / data->pixel_size * data->pixel_size); long long w = frame->width(); @@ -26,11 +30,7 @@ namespace BGTU::ComputerGraphicsLabWork::Lab1 { for (long long x = start_x; x < w; x += data->pixel_size, x_flag = !x_flag) { auto c = x_flag ? this->bg : this->fg; - for (long long yy = y + data->pixel_size; yy-- > y;) { - for (long long xx = x + data->pixel_size; xx-- > x;) { - frame->add_voxel(xx, yy, std::numeric_limits::max(), c); - } - } + Utilities::Shapes::fill_rectangle_wh(frame, x, y, data->pixel_size, data->pixel_size, std::numeric_limits::max(), c, c); } } } diff --git a/programs/lab1/src/sprite_data.hpp b/programs/lab1/src/sprite_data.hpp index aa8a3ee..c29c65e 100644 --- a/programs/lab1/src/sprite_data.hpp +++ b/programs/lab1/src/sprite_data.hpp @@ -4,12 +4,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include namespace BGTU::ComputerGraphicsLabWork::Lab1 { @@ -19,17 +21,37 @@ namespace BGTU::ComputerGraphicsLabWork::Lab1 { struct Lab1SpriteData { public: struct ShapeData { + public: double rotation_radians; + RendererApi::PointI<2>::component_t radius; + RendererApi::PointI<2>::component_t diameter; + + [[nodiscard]] inline RendererApi::PointI<2> pos_rotated(RendererApi::PointI<2>::component_t custom_radius, double angle_degrees) const { + double angle_radians = angle_degrees * (std::numbers::pi_v / 180); + return { + (RendererApi::PointI<2>::component_t) (std::cos(this->rotation_radians + angle_radians) * custom_radius), + (RendererApi::PointI<2>::component_t) (std::sin(this->rotation_radians + angle_radians) * custom_radius), + }; + } + + [[nodiscard]] inline RendererApi::PointI<2> neg_rotated(RendererApi::PointI<2>::component_t custom_radius, double angle_degrees) const { + double angle_radians = angle_degrees * (std::numbers::pi_v / 180); + return { + (RendererApi::PointI<2>::component_t) (std::cos(-this->rotation_radians + angle_radians) * custom_radius), + (RendererApi::PointI<2>::component_t) (std::sin(-this->rotation_radians + angle_radians) * custom_radius), + }; + } }; RendererApi::PointI<2> central_pixel_tl; std::size_t pixel_size; bool show_grid; ShapeData shape_data; - RendererApi::Sprite **sub_sprites; + RendererApi::Sprite> *const *sub_sprites; std::size_t sub_sprites_count; using Provider = _Lab1SpriteData_Provider; + }; class _Lab1SpriteData_Provider : public QObject, public RendererApi::Sprite::SpriteDataProvider { @@ -42,7 +64,7 @@ namespace BGTU::ComputerGraphicsLabWork::Lab1 { double radians_per_second; bool show_grid; RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t w, h; - RendererApi::Sprite **sub_sprites; + RendererApi::Sprite> *const *sub_sprites; std::size_t sub_sprites_count; public: @@ -54,15 +76,18 @@ namespace BGTU::ComputerGraphicsLabWork::Lab1 { Lab1SpriteData get_sprite_data() override { this->sync.lock(); + RendererApi::PointI<2>::component_t radius = (((this->w < this->h) ? this->w : this->h) * 7 / 16) / this->pixel_size; Lab1SpriteData cached{ .central_pixel_tl = (RendererApi::PointI<2>) (RendererApi::PointF<2>(this->w, this->h) / 2.0 - RendererApi::PointF<2>(this->pixel_size, this->pixel_size) / 2.0), .pixel_size = this->pixel_size, .show_grid = this->show_grid, .shape_data = { - .rotation_radians = std::fmod(this->time.elapsed() / 1000.0 * radians_per_second, std::numbers::pi) + .rotation_radians = std::fmod(this->time.elapsed() / 1000.0 * radians_per_second, std::numbers::pi), + .radius = radius, + .diameter = radius * 2 }, - .sub_sprites = nullptr, - .sub_sprites_count = 0 + .sub_sprites = this->sub_sprites, + .sub_sprites_count = this->sub_sprites_count, }; this->sync.unlock(); return cached; @@ -101,5 +126,18 @@ namespace BGTU::ComputerGraphicsLabWork::Lab1 { this->show_grid = f; this->sync.unlock(); } + + void invert_show_grid() { + this->sync.lock(); + this->show_grid = !this->show_grid; + this->sync.unlock(); + } + + void set_sub_sprites(RendererApi::Sprite> *const *s, std::size_t c) { + this->sync.lock(); + this->sub_sprites = s; + this->sub_sprites_count = c; + this->sync.unlock(); + } }; } \ No newline at end of file diff --git a/programs/lab1/src/variants.hpp b/programs/lab1/src/variants.hpp new file mode 100644 index 0000000..e0ccd8a --- /dev/null +++ b/programs/lab1/src/variants.hpp @@ -0,0 +1,83 @@ +#pragma once + +#include +#include +#include +#include +#include "sprite_data.hpp" + +namespace BGTU::ComputerGraphicsLabWork::Lab1 { + struct variant_sprites { + private : + using sprite_t = RendererApi::Sprite>; + public: + + + sprite_t *const *const sprites; + std::size_t const count; + + + constexpr variant_sprites(sprite_t *const *const _sprites, std::size_t _count) : sprites{_sprites}, count{_count}{ + + } + private: + template + struct _make { + }; + + template<> + struct _make<> { + public: + constexpr _make() {}; + + constexpr void export_pointers(sprite_t **dst, std::size_t pos) { + } + }; + + template + struct _make { + public: + e0 value; + + constexpr _make(e0 v) : value{std::move(v)} {}; + + constexpr void export_pointers(sprite_t **dst, std::size_t pos) { + dst[pos] = &this->value; + } + }; + + template + struct _make { + public: + e0 value; + _make next; + + constexpr _make(e0 v, en...nv) : value{std::move(v)}, next{nv...} {}; + + constexpr void export_pointers(sprite_t **dst, std::size_t pos) { + dst[pos] = &this->value; + this->next.export_pointers(dst, pos + 1); + } + }; + + public: + + template + constexpr static variant_sprites make(sprites_t...sprites) { + static _make i{sprites...}; + static sprite_t *p[sizeof...(sprites)]; + + i.export_pointers(p, 0); + return variant_sprites{p, sizeof...(sprites)}; + } + }; + + extern variant_sprites variant1; + extern variant_sprites variant2; + extern variant_sprites variant3; + extern variant_sprites variant4; + extern variant_sprites variant5; + extern variant_sprites variant6; + extern variant_sprites variant8; + extern variant_sprites variant9; +} \ No newline at end of file diff --git a/programs/lab1/src/variants/variant1.cpp b/programs/lab1/src/variants/variant1.cpp new file mode 100644 index 0000000..1e46557 --- /dev/null +++ b/programs/lab1/src/variants/variant1.cpp @@ -0,0 +1,29 @@ +#include +#include +#include +#include "../variants.hpp" +#include "../sprite_data.hpp" + +namespace BGTU::ComputerGraphicsLabWork::Lab1{ + namespace Variant1 { + class S1 : public RendererApi::Sprite> { + public: + void draw( + BGTU::ComputerGraphicsLabWork::Utilities::ZoomedVoxelPainter *frame, + const BGTU::ComputerGraphicsLabWork::Lab1::Lab1SpriteData::ShapeData *data + ) const final { + Utilities::Shapes::draw_polygon_edge( + frame, + {data->neg_rotated(data->radius / 2, 0), data->neg_rotated(data->radius / 2, 90), data->neg_rotated(data->radius / 2, 180), data->neg_rotated(data->radius / 2, 270),}, + 1, + {255, 0, 0} + ); + } + }; + + + + } + + variant_sprites variant1 = variant_sprites::make(Variant1::S1{}); +} \ No newline at end of file diff --git a/programs/lab1/src/variants/variant2.cpp b/programs/lab1/src/variants/variant2.cpp new file mode 100644 index 0000000..e69de29 diff --git a/programs/lab1/src/variants/variant3.cpp b/programs/lab1/src/variants/variant3.cpp new file mode 100644 index 0000000..e69de29 diff --git a/programs/lab1/src/variants/variant4.cpp b/programs/lab1/src/variants/variant4.cpp new file mode 100644 index 0000000..e69de29 diff --git a/programs/lab1/src/variants/variant5.cpp b/programs/lab1/src/variants/variant5.cpp new file mode 100644 index 0000000..e69de29 diff --git a/programs/lab1/src/variants/variant6.cpp b/programs/lab1/src/variants/variant6.cpp new file mode 100644 index 0000000..e69de29 diff --git a/programs/lab1/src/variants/variant8.cpp b/programs/lab1/src/variants/variant8.cpp new file mode 100644 index 0000000..e69de29 diff --git a/programs/lab1/src/variants/variant9.cpp b/programs/lab1/src/variants/variant9.cpp new file mode 100644 index 0000000..e69de29 diff --git a/programs/lab1/src/zoomed_scene_sprite.hpp b/programs/lab1/src/zoomed_scene_sprite.hpp new file mode 100644 index 0000000..a246d4f --- /dev/null +++ b/programs/lab1/src/zoomed_scene_sprite.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include +#include +#include +#include +#include +#include "sprite_data.hpp" + + +namespace BGTU::ComputerGraphicsLabWork::Lab1 { + class ZoomedSceneSprite : public RendererApi::Sprite { + private: + public: + ZoomedSceneSprite() = default; + + void draw(Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl *frame, const Lab1SpriteData *data) const override { + Utilities::ZoomedVoxelPainter zoomed_painter{frame, data->central_pixel_tl, data->pixel_size}; + + for (std::size_t i = 0; i < data->sub_sprites_count; i++) { + data->sub_sprites[i]->draw(&zoomed_painter, &data->shape_data); + } + } + }; +} \ No newline at end of file diff --git a/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/_separate_threaded_renderer.hpp b/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/_separate_threaded_renderer.hpp index 749c78f..ab6d9d1 100644 --- a/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/_separate_threaded_renderer.hpp +++ b/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/_separate_threaded_renderer.hpp @@ -18,7 +18,7 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities { using _SeparateThreadedRenderer_RenderProcedureType = void (renderer_context_t::*)( RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t, RendererApi::VirtualVoxelPainter::visible_pixel_coordinate_fast_t, - Utilities::VoxelPainterExporterToRgb32Array *, + Utilities::VoxelPainterExporterToBgr32Array *, RendererApi::Color, RendererApi::Sprite *const *, std::size_t, diff --git a/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/separate_threaded_renderer.hpp b/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/separate_threaded_renderer.hpp index 200706e..685c8eb 100644 --- a/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/separate_threaded_renderer.hpp +++ b/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/separate_threaded_renderer.hpp @@ -158,7 +158,7 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities { data_t cached = *const_cast(&this->owner->next_data); this->owner->sync.unlock(); - Utilities::VoxelPainterExporterToRgb32Array img{ + Utilities::VoxelPainterExporterToBgr32Array img{ cached.width, cached.height, new unsigned char[cached.width * cached.height * 4], new RendererApi::SpriteMetadata *[cached.width * cached.height] @@ -206,12 +206,12 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities { template - class SeparateThreadedDefaultRendererLinear : public SeparateThreadedRenderer> { + class SeparateThreadedDefaultRendererLinear : public SeparateThreadedRenderer> { private: Utilities::DefaultVoxelDrawerCache context; public: explicit SeparateThreadedDefaultRendererLinear(QObject *owner = nullptr) : - SeparateThreadedRenderer>{&this->context, owner}, context{} {}; + SeparateThreadedRenderer>{&this->context, owner}, context{} {}; ~SeparateThreadedDefaultRendererLinear() { this->shutdown_thread_blocking(); diff --git a/renderer-api/include/bgtu/computer_graphics_lab_work/renderer_api/point.hpp b/renderer-api/include/bgtu/computer_graphics_lab_work/renderer_api/point.hpp index ede8036..d3c6f86 100644 --- a/renderer-api/include/bgtu/computer_graphics_lab_work/renderer_api/point.hpp +++ b/renderer-api/include/bgtu/computer_graphics_lab_work/renderer_api/point.hpp @@ -19,23 +19,22 @@ namespace BGTU::ComputerGraphicsLabWork::RendererApi { constexpr Point(component_t x, component_t y) : x{x}, y{y} {} - [[nodiscard]] constexpr Point<2, _component_t> operator+(Point<2, _component_t> const &other) const noexcept { + [[nodiscard]] constexpr Point<2, _component_t> operator+(Point<2, _component_t> const &other) const noexcept { return Point<2, _component_t>{this->x + other.x, this->y + other.y}; } - [[nodiscard]] constexpr Point<2, _component_t> operator-(Point<2, _component_t> const &other) const noexcept { + [[nodiscard]] constexpr Point<2, _component_t> operator-(Point<2, _component_t> const &other) const noexcept { return Point<2, _component_t>{this->x - other.x, this->y - other.y}; } - [[nodiscard]] constexpr Point<2, _component_t> operator*(_component_t const &other) const noexcept { + [[nodiscard]] constexpr Point<2, _component_t> operator*(_component_t const &other) const noexcept { return Point<2, _component_t>{this->x * other, this->y * other}; } - [[nodiscard]] constexpr Point<2, _component_t> operator/(_component_t const &other) const noexcept { + [[nodiscard]] constexpr Point<2, _component_t> operator/(_component_t const &other) const noexcept { return Point<2, _component_t>{this->x / other, this->y / other}; } - template, void>::type> [[nodiscard]] constexpr explicit operator Point<2, double>() const noexcept { return Point<2, double>{(double) this->x, (double) this->y}; @@ -45,6 +44,14 @@ namespace BGTU::ComputerGraphicsLabWork::RendererApi { [[nodiscard]] constexpr explicit operator Point<2, long long>() const noexcept { return Point<2, long long>{(long long) this->x, (long long) this->y}; } + + [[nodiscard]] constexpr bool operator==(Point<2, _component_t> const &other) const noexcept { + return this->x == other.x && this->y == other.y; + } + + [[nodiscard]] constexpr bool operator!=(Point<2, _component_t> const &other) const noexcept { + return this->x != other.x || this->y != other.y; + } }; template diff --git a/utilities/include/bgtu/computer_graphics_lab_work/utilities/color.hpp b/utilities/include/bgtu/computer_graphics_lab_work/utilities/color.hpp index 7a6e491..4bcb344 100644 --- a/utilities/include/bgtu/computer_graphics_lab_work/utilities/color.hpp +++ b/utilities/include/bgtu/computer_graphics_lab_work/utilities/color.hpp @@ -1,24 +1,139 @@ #pragma once #include -#include #include namespace BGTU::ComputerGraphicsLabWork::Utilities { - inline RendererApi::Color apply_transparent_color(RendererApi::Color bg, RendererApi::Color::Transparent fg) { -#if defined(__AVX512F__) - return _apply_transparent_color_avx512(bg, fg); -#elif 0 && defined(__AVX2__) - return _apply_transparent_color_avx2(bg, fg); -#else + constexpr RendererApi::Color _apply_transparent_color_pure(RendererApi::Color bg, RendererApi::Color::Transparent fg) { #if 1 + if (fg.alpha == 255) + return {fg.red, fg.green, fg.blue}; + + // pmovzxbd + const std::uint_fast32_t bg_i32[4]{bg.red, bg.green, bg.blue}; + const std::uint_fast32_t fg_i32[4]{fg.red, fg.green, fg.blue}; + + // cvtdq2pd + const float bg_f[4]{(float) bg_i32[0], (float) bg_i32[1], (float) bg_i32[2]}; + const float fg_f[4]{(float) fg_i32[0], (float) fg_i32[1], (float) fg_i32[2]}; + + const float alpha_f = fg.alpha; + const float neg_alpha_f = 255.f - alpha_f; + + // mulps + const float bg_alpha[4]{bg_f[0] * neg_alpha_f, bg_f[1] * neg_alpha_f, bg_f[1] * neg_alpha_f}; + const float fg_alpha[4]{fg_f[0] * alpha_f, fg_f[1] * alpha_f, fg_f[1] * alpha_f}; + + // addps + const float sum_f[4]{bg_alpha[0] + fg_alpha[0], bg_alpha[1] + fg_alpha[1], bg_alpha[2] + fg_alpha[2]}; + + // divps + const float sum_fixed_f[4]{sum_f[0] / 255.f, sum_f[2] / 255.f, sum_f[2] / 255.f}; + + return {(RendererApi::Color::component_compact_t) sum_fixed_f[0], (RendererApi::Color::component_compact_t) sum_fixed_f[1], (RendererApi::Color::component_compact_t) sum_fixed_f[2]}; + +#else return RendererApi::Color{ - static_cast(((static_cast(fg.red) * static_cast(fg.alpha) + static_cast(bg.red) * (static_cast(255) - static_cast(fg.alpha))) / 255)), + static_cast(((static_cast(fg.red) * static_cast(fg.alpha) + static_cast(bg.red) * (static_cast(255) - static_cast(fg.alpha))) / 255)), static_cast(((static_cast(fg.green) * static_cast(fg.alpha) + static_cast(bg.green) * (static_cast(255) - static_cast(fg.alpha))) / 255)), static_cast(((static_cast(fg.blue) * static_cast(fg.alpha) + static_cast(bg.blue) * (static_cast(255) - static_cast(fg.alpha))) / 255)), }; -#elif 1 +#endif + } + +#if defined(_MSC_VER) +# if defined(__AVX512F__) + + extern RendererApi::Color _apply_transparent_color_avx512f(RendererApi::Color bg, RendererApi::Color::Transparent fg); + + inline RendererApi::Color apply_transparent_color(RendererApi::Color bg, RendererApi::Color::Transparent fg) { + return _apply_transparent_color_avx512f(bg, fg); + } + +# pragma comment(linker, "/alternatename:?_apply_transparent_color_avx512f@Utilities@ComputerGraphicsLabWork@BGTU@@YA?AVColor@RendererApi@23@V4523@VTransparent@4523@@Z=?_apply_transparent_color_pure@Utilities@ComputerGraphicsLabWork@BGTU@@YA?AVColor@RendererApi@23@V4523@VTransparent@4523@@Z") + +# elif defined(__AVX2__) + + extern RendererApi::Color _apply_transparent_color_avx2(RendererApi::Color bg, RendererApi::Color::Transparent fg); + + inline RendererApi::Color apply_transparent_color(RendererApi::Color bg, RendererApi::Color::Transparent fg) { + return _apply_transparent_color_avx2(bg, fg); + } + +# pragma comment(linker, "/alternatename:?_apply_transparent_color_avx2@Utilities@ComputerGraphicsLabWork@BGTU@@YA?AVColor@RendererApi@23@V4523@VTransparent@4523@@Z=?_apply_transparent_color_pure@Utilities@ComputerGraphicsLabWork@BGTU@@YA?AVColor@RendererApi@23@V4523@VTransparent@4523@@Z") + +# else + + inline RendererApi::Color apply_transparent_color(RendererApi::Color bg, RendererApi::Color::Transparent fg) { + return _apply_transparent_color_pure(bg, fg); + } + +# endif +#endif + + //?_apply_transparent_color_avx2@Utilities@ComputerGraphicsLabWork@BGTU@@YA?AVColor@RendererApi@23@V4523@VTransparent@4523@@Z + // ?apply_transparent_color@Utilities@ComputerGraphicsLabWork@BGTU@@YA?AVColor@RendererApi@23@V4523@VTransparent@4523@@Z +#if 0 +#if 0 + RendererApi::Color apply_transparent_color(RendererApi::Color bg, RendererApi::Color::Transparent fg) { + return _apply_transparent_color_avx2(bg, fg); + + if (fg.alpha == 255) + return {fg.red, fg.green, fg.blue}; + + // pmovzxbd + const std::uint_fast32_t bg_i32[4]{bg.red, bg.green, bg.blue}; + const std::uint_fast32_t fg_i32[4]{fg.red, fg.green, fg.blue}; + + // cvtdq2pd + const float bg_f[4]{(float) bg_i32[0], (float) bg_i32[1], (float) bg_i32[2]}; + const float fg_f[4]{(float) fg_i32[0], (float) fg_i32[1], (float) fg_i32[2]}; + + const float alpha_f = fg.alpha; + const float neg_alpha_f = 255.f - alpha_f; + + // mulps + const float bg_alpha[4]{bg_f[0] * neg_alpha_f, bg_f[1] * neg_alpha_f, bg_f[1] * neg_alpha_f}; + const float fg_alpha[4]{fg_f[0] * alpha_f, fg_f[1] * alpha_f, fg_f[1] * alpha_f}; + + // addps + const float sum_f[4]{bg_alpha[0] + fg_alpha[0], bg_alpha[1] + fg_alpha[1], bg_alpha[2] + fg_alpha[2]}; + + // divps + const float sum_fixed_f[4]{sum_f[0] / 255.f, sum_f[2] / 255.f, sum_f[2] / 255.f}; + + return {(RendererApi::Color::component_compact_t) sum_fixed_f[0], (RendererApi::Color::component_compact_t) sum_fixed_f[1], (RendererApi::Color::component_compact_t) sum_fixed_f[2]}; + +#else + return RendererApi::Color{ + static_cast(((static_cast(fg.red) * static_cast(fg.alpha) + static_cast(bg.red) * (static_cast(255) - static_cast(fg.alpha))) / 255)), + static_cast(((static_cast(fg.green) * static_cast(fg.alpha) + static_cast(bg.green) * (static_cast(255) - static_cast(fg.alpha))) / 255)), + static_cast(((static_cast(fg.blue) * static_cast(fg.alpha) + static_cast(bg.blue) * (static_cast(255) - static_cast(fg.alpha))) / 255)), + }; + + + /*__m128i bg_vec = _mm_cvtsi32_si128(*(std::int32_t *) &bg); + __m128i fg_vec = _mm_cvtsi32_si128(*(std::int32_t *) &fg); + + bg_vec = _mm_cvtepu8_epi16(bg_vec); + fg_vec = _mm_cvtepu8_epi16(fg_vec); + +// bg_vec = _mm_cvtepi16_ph(bg_vec); +// fg_vec = _mm_cvtepi16_ph(fg_vec);*/ + +#if defined(__AVX512F__) + return _apply_transparent_color_avx512(bg, fg); +#elif defined(__AVX2__) + return _apply_transparent_color_avx2(bg, fg); +#else +#if 0 + return RendererApi::Color{ + static_cast(((static_cast(fg.red) * static_cast(fg.alpha) + static_cast(bg.red) * (static_cast(255) - static_cast(fg.alpha))) / 255)), + static_cast(((static_cast(fg.green) * static_cast(fg.alpha) + static_cast(bg.green) * (static_cast(255) - static_cast(fg.alpha))) / 255)), + static_cast(((static_cast(fg.blue) * static_cast(fg.alpha) + static_cast(bg.blue) * (static_cast(255) - static_cast(fg.alpha))) / 255)), + }; +#elif 0 static auto calc = [&](RendererApi::Color::component_fast_t s, RendererApi::Color::component_fast_t o) { auto oo = static_cast(o) * static_cast(fg.alpha); auto ss = static_cast(s) * (static_cast(255) - static_cast(fg.alpha)); @@ -29,7 +144,7 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities { calc(bg.green, fg.green), calc(bg.blue, fg.blue) }; -#else +#elif 0 static __m128i vec_256 = _mm_set_epi16(256, 256, 256, 0, 0, 0, 0, 0); __m128i vec_bg = _mm_set_epi16(bg.red, bg.green, bg.blue, 0, 0, 0, 0, 0); __m128i vec_fg = _mm_set_epi16(fg.red, fg.green, fg.blue, 0, 0, 0, 0, 0); @@ -49,12 +164,18 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities { #endif } - +#endif +#endif namespace PackColor { - inline void color_to_rgb32(unsigned char *buffer, std::size_t offset, RendererApi::Color color) noexcept{ + inline void color_to_rgb32(unsigned char *buffer, std::size_t offset, RendererApi::Color color) noexcept { buffer[offset] = color.red; buffer[offset + 1] = color.green; buffer[offset + 2] = color.blue; } + inline void color_to_bgr32(unsigned char *buffer, std::size_t offset, RendererApi::Color color) noexcept { + buffer[offset] = color.blue; + buffer[offset + 1] = color.green; + buffer[offset + 2] = color.red; + } } } \ No newline at end of file diff --git a/utilities/include/bgtu/computer_graphics_lab_work/utilities/brezenham.hpp b/utilities/include/bgtu/computer_graphics_lab_work/utilities/shapes/brezenham.hpp similarity index 67% rename from utilities/include/bgtu/computer_graphics_lab_work/utilities/brezenham.hpp rename to utilities/include/bgtu/computer_graphics_lab_work/utilities/shapes/brezenham.hpp index 470adb2..62a5c81 100644 --- a/utilities/include/bgtu/computer_graphics_lab_work/utilities/brezenham.hpp +++ b/utilities/include/bgtu/computer_graphics_lab_work/utilities/shapes/brezenham.hpp @@ -3,7 +3,7 @@ #include #include -namespace BGTU::ComputerGraphicsLabWork::Utilities { +namespace BGTU::ComputerGraphicsLabWork::Utilities::Shapes { class brezenham_line_iterable { private: RendererApi::PointI<2>::component_t start_arg, start_ret, end_arg; @@ -11,7 +11,12 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities { RendererApi::PointI<2>::component_t delta_error, error_threshold; bool swap_flag; public: - inline brezenham_line_iterable(RendererApi::PointI<2>::component_t x1, RendererApi::PointI<2>::component_t y1, RendererApi::PointI<2>::component_t x2, RendererApi::PointI<2>::component_t y2) { + constexpr brezenham_line_iterable( + RendererApi::PointI<2>::component_t x1, + RendererApi::PointI<2>::component_t y1, + RendererApi::PointI<2>::component_t x2, + RendererApi::PointI<2>::component_t y2 + ) noexcept { RendererApi::PointI<2>::component_t delta_x = (x1 > x2) ? (x1 - x2) : (x2 - x1); RendererApi::PointI<2>::component_t delta_y = (y1 > y2) ? (y1 - y2) : (y2 - y1); if (delta_x > delta_y) { @@ -33,12 +38,10 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities { } } - struct point { - public: - RendererApi::PointI<2>::component_t x, y; - - inline point(RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y) : x{x}, y{y} {} - }; + constexpr brezenham_line_iterable( + RendererApi::PointI<2> start, + RendererApi::PointI<2> end + ) noexcept: brezenham_line_iterable{start.x, start.y, end.x, end.y} {} class iterator { private: @@ -47,17 +50,17 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities { RendererApi::PointI<2>::component_t error, delta_error, error_threshold; bool swap_flag; - inline iterator( + constexpr iterator( RendererApi::PointI<2>::component_t arg, RendererApi::PointI<2>::component_t ret, RendererApi::PointI<2>::component_t end_arg, RendererApi::PointI<2>::component_t delta_ret, RendererApi::PointI<2>::component_t delta_error, RendererApi::PointI<2>::component_t error_threshold, bool swap_flag - ) : arg{arg}, ret{ret}, end_arg{end_arg}, delta_ret{delta_ret}, error{0}, delta_error{delta_error}, swap_flag{swap_flag}, error_threshold{error_threshold} {} + ) noexcept: arg{arg}, ret{ret}, end_arg{end_arg}, delta_ret{delta_ret}, error{0}, delta_error{delta_error}, swap_flag{swap_flag}, error_threshold{error_threshold} {} friend class brezenham_line_iterable; public: - inline iterator &operator++() { + constexpr iterator &operator++() noexcept { this->arg++; this->error += this->delta_error; if (this->error >= this->error_threshold) { @@ -67,29 +70,29 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities { return *this; } - inline iterator operator++(int) { + constexpr iterator operator++(int) noexcept { iterator next = *this; ++(*this); return next; } - inline point operator*() const { + constexpr RendererApi::PointI<2> operator*() const noexcept { if (this->swap_flag) - return point{this->ret, this->arg}; + return {this->ret, this->arg}; else - return point{this->arg, this->ret}; + return {this->arg, this->ret}; } - inline bool operator==(std::nullptr_t) const { + constexpr bool operator==(std::nullptr_t) const noexcept { return this->arg > this->end_arg; } - inline bool operator!=(std::nullptr_t) const { + constexpr bool operator!=(std::nullptr_t) const noexcept { return this->arg <= this->end_arg; } }; - [[nodiscard]] inline iterator begin() const { + [[nodiscard]] constexpr iterator begin() const noexcept { return iterator{ this->start_arg, this->start_ret, this->end_arg, this->delta_ret, @@ -98,7 +101,7 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities { }; } - [[nodiscard]] inline std::nullptr_t end() const { + [[nodiscard]] constexpr std::nullptr_t end() const noexcept { return nullptr; } }; diff --git a/utilities/include/bgtu/computer_graphics_lab_work/utilities/shapes/polygon.hpp b/utilities/include/bgtu/computer_graphics_lab_work/utilities/shapes/polygon.hpp new file mode 100644 index 0000000..df4e5b0 --- /dev/null +++ b/utilities/include/bgtu/computer_graphics_lab_work/utilities/shapes/polygon.hpp @@ -0,0 +1,69 @@ +#pragma once + +#include +#include +#include +#include +#include +#include "../color.hpp" +#include "brezenham.hpp" + +namespace BGTU::ComputerGraphicsLabWork::Utilities::Shapes { + template + void iterate_polygon_edge( + RendererApi::PointI<2> (&&points)[points_count], + receiver_t receiver + ) { + if constexpr (points_count == 0) { + return; + } else if constexpr (points_count == 1) { + receiver(points[0].x, points[0].y); + return; + } else { + receiver(points[0].x, points[0].y); + for (std::size_t i = 1; i < points_count; i++) { + if (points[i - 1] == points[i]) + continue; + auto it = brezenham_line_iterable{points[i - 1], points[i]}.begin(); + it++; + for (; it != nullptr; it++) { + receiver((*it).x, (*it).y); + } + } + if (points[0] != points[points_count - 1]) { + auto it = brezenham_line_iterable{points[points_count - 1], points[0]}.begin(); + it++; + for (; it != nullptr; it++) { + receiver((*it).x, (*it).y); + } + } + } + } + + template + void draw_polygon_edge( + voxel_painter_t *painter, + RendererApi::PointI<2> (&&points)[points_count], + double z, + RendererApi::Color::Transparent outline + ) { + iterate_polygon_edge( + std::move(points), + [=](RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y) { painter->add_voxel(x, y, z, outline); } + ); + } + + template + void draw_polygon_edge( + voxel_painter_t *painter, + RendererApi::PointI<2> (&&points)[points_count], + double z, + RendererApi::Color::Transparent outline, + RendererApi::SpriteMetadata *owner + ) { + iterate_polygon_edge( + std::move(points), + [=](RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y) { painter->add_voxel(x, y, z, outline, owner); } + ); + } +} \ No newline at end of file diff --git a/utilities/include/bgtu/computer_graphics_lab_work/utilities/shapes/polyline.hpp b/utilities/include/bgtu/computer_graphics_lab_work/utilities/shapes/polyline.hpp new file mode 100644 index 0000000..d1aa6c1 --- /dev/null +++ b/utilities/include/bgtu/computer_graphics_lab_work/utilities/shapes/polyline.hpp @@ -0,0 +1,62 @@ +#pragma once + +#include +#include +#include +#include +#include "../color.hpp" +#include "brezenham.hpp" + +namespace BGTU::ComputerGraphicsLabWork::Utilities::Shapes { + template + void iterate_polyline( + RendererApi::PointI<2> (&&points)[points_count], + receiver_t receiver + ) { + if constexpr (points_count == 0) { + return; + } else if constexpr (points_count == 1) { + receiver(points[0].x, points[0].y); + return; + } else { + receiver(points[0].x, points[0].y); + for (std::size_t i = 1; i < points_count; i++) { + if (points[i - 1] == points[i]) + continue; + auto it = brezenham_line_iterable{points[i - 1], points[i]}.begin(); + it++; + for (; it != nullptr; it++) { + receiver((*it).x, (*it).y); + } + } + } + } + + + template + void draw_polyline_edge( + voxel_painter_t *painter, + RendererApi::PointI<2> (&&points)[points_count], + double z, + RendererApi::Color::Transparent outline + ) { + iterate_polyline( + points, + [=](RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y) { painter->add_voxel(x, y, z, outline); } + ); + } + + template + void draw_polyline_edge( + voxel_painter_t *painter, + RendererApi::PointI<2> (&&points)[points_count], + double z, + RendererApi::Color::Transparent outline, + RendererApi::SpriteMetadata *owner + ) { + iterate_polyline( + points, + [=](RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y) { painter->add_voxel(x, y, z, outline, owner); } + ); + } +} \ No newline at end of file diff --git a/utilities/include/bgtu/computer_graphics_lab_work/utilities/shapes/rectangle.hpp b/utilities/include/bgtu/computer_graphics_lab_work/utilities/shapes/rectangle.hpp new file mode 100644 index 0000000..761f184 --- /dev/null +++ b/utilities/include/bgtu/computer_graphics_lab_work/utilities/shapes/rectangle.hpp @@ -0,0 +1,272 @@ +#pragma once + +#include +#include +#include +#include +#include + +namespace BGTU::ComputerGraphicsLabWork::Utilities::Shapes { + class rectangle_fill_iterable { + private: + RendererApi::PointI<2>::component_t x_start, y_start, x_end, y_end; + + constexpr rectangle_fill_iterable( + RendererApi::PointI<2>::component_t x0, + RendererApi::PointI<2>::component_t y0, + RendererApi::PointI<2>::component_t x1, + RendererApi::PointI<2>::component_t y1 + ) noexcept: x_start{x0}, y_start{y0}, x_end{x1}, y_end{y1} {} + + public: + static constexpr rectangle_fill_iterable from_wh( + RendererApi::PointI<2>::component_t x, + RendererApi::PointI<2>::component_t y, + RendererApi::PointI<2>::component_t w, + RendererApi::PointI<2>::component_t h + ) noexcept { + return {x, y, x + w, y + h}; + } + + static constexpr rectangle_fill_iterable from_edges( + RendererApi::PointI<2>::component_t left, + RendererApi::PointI<2>::component_t top, + RendererApi::PointI<2>::component_t right, + RendererApi::PointI<2>::component_t bottom + ) noexcept { + return {left, top, right, bottom}; + } + + class iterator { + private: + RendererApi::PointI<2>::component_t x_start, x_end, y_end; + RendererApi::PointI<2>::component_t x, y; + + constexpr iterator( + RendererApi::PointI<2>::component_t x0, + RendererApi::PointI<2>::component_t y0, + RendererApi::PointI<2>::component_t x1, + RendererApi::PointI<2>::component_t y1 + ) noexcept: x_start{x0}, x_end{x1}, y_end{y1}, x{x0}, y{y0} {} + + friend class rectangle_fill_iterable; + + public: + constexpr iterator &operator++() noexcept { + if (++this->x > this->x_end) { + if (this->y < this->y_end) { + this->y++; + } + this->x = x_start; + } + + return *this; + } + + constexpr iterator operator++(int) noexcept { + iterator next = *this; + ++(*this); + return next; + } + + constexpr RendererApi::PointI<2> operator*() const noexcept { + return {this->x, this->y}; + } + + constexpr bool operator==(std::nullptr_t) const noexcept { + return this->y >= this->y_end; + } + + constexpr bool operator!=(std::nullptr_t) const noexcept { + return this->y < this->y_end; + } + }; + + [[nodiscard]] constexpr iterator begin() const noexcept { + return iterator{ + this->x_start, this->y_start, + this->x_end, this->y_end + }; + } + + [[nodiscard]] constexpr std::nullptr_t end() const noexcept { + return nullptr; + } + }; + + template + void iterate_rectangle_fill_edges( + RendererApi::PointI<2>::component_t left, + RendererApi::PointI<2>::component_t top, + RendererApi::PointI<2>::component_t right, + RendererApi::PointI<2>::component_t bottom, + receiver_t receiver + ) { + for (RendererApi::PointI<2>::component_t x = left; x < right; x++) { + receiver(true, x, top); + } + + right--; + bottom--; + for (RendererApi::PointI<2>::component_t y = top; y < bottom; y++) { + RendererApi::PointI<2>::component_t x = left; + receiver(true, x, y); + for (x++; x < right; x++) { + receiver(false, x, y); + } + receiver(true, x, y); + } + bottom++; + + for (RendererApi::PointI<2>::component_t x = left; x <= right; x++) { + receiver(true, x, bottom); + } + } + + template + void iterate_rectangle_fill_wh( + RendererApi::PointI<2>::component_t x, + RendererApi::PointI<2>::component_t y, + RendererApi::PointI<2>::component_t width, + RendererApi::PointI<2>::component_t height, + receiver_t receiver + ) { + return iterate_rectangle_fill_edges(x, y, x + width, y + height, receiver); + } + + template + void draw_rectangle_edges( + voxel_painter_t *painter, + RendererApi::PointI<2>::component_t left, + RendererApi::PointI<2>::component_t top, + RendererApi::PointI<2>::component_t right, + RendererApi::PointI<2>::component_t bottom, + double z, + RendererApi::Color::Transparent outline + ) { + iterate_rectangle_fill_edges( + left, top, right, bottom, + [=](bool is_edge, RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y) { if (is_edge) painter->add_voxel(x, y, z, outline); } + ); + } + + template + void draw_rectangle_wh( + voxel_painter_t *painter, + RendererApi::PointI<2>::component_t x, + RendererApi::PointI<2>::component_t y, + RendererApi::PointI<2>::component_t width, + RendererApi::PointI<2>::component_t height, + double z, + RendererApi::Color::Transparent outline + ) { + iterate_rectangle_fill_wh( + x, y, width, height, + [=](bool is_edge, RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y) { if (is_edge) painter->add_voxel(x, y, z, outline); } + ); + } + + template + void fill_rectangle_edges( + voxel_painter_t *painter, + RendererApi::PointI<2>::component_t left, + RendererApi::PointI<2>::component_t top, + RendererApi::PointI<2>::component_t right, + RendererApi::PointI<2>::component_t bottom, + double z, + RendererApi::Color::Transparent outline, + RendererApi::Color::Transparent fill + ) { + iterate_rectangle_fill_edges( + left, top, right, bottom, + [=](bool is_edge, RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y) { painter->add_voxel(x, y, z, is_edge ? outline : fill); } + ); + } + + template + void fill_rectangle_wh( + voxel_painter_t *painter, + RendererApi::PointI<2>::component_t x, + RendererApi::PointI<2>::component_t y, + RendererApi::PointI<2>::component_t width, + RendererApi::PointI<2>::component_t height, + double z, + RendererApi::Color::Transparent outline, + RendererApi::Color::Transparent fill + ) { + iterate_rectangle_fill_wh( + x, y, width, height, + [=](bool is_edge, RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y) { painter->add_voxel(x, y, z, is_edge ? outline : fill); } + ); + } + + template + void draw_rectangle_edges( + voxel_painter_t *painter, + RendererApi::PointI<2>::component_t left, + RendererApi::PointI<2>::component_t top, + RendererApi::PointI<2>::component_t right, + RendererApi::PointI<2>::component_t bottom, + double z, + RendererApi::Color::Transparent outline, + RendererApi::SpriteMetadata *owner + ) { + iterate_rectangle_fill_edges( + left, top, right, bottom, + [=](bool is_edge, RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y) { if (is_edge) painter->add_voxel(x, y, z, outline, owner); } + ); + } + + template + void draw_rectangle_wh( + voxel_painter_t *painter, + RendererApi::PointI<2>::component_t x, + RendererApi::PointI<2>::component_t y, + RendererApi::PointI<2>::component_t width, + RendererApi::PointI<2>::component_t height, + double z, + RendererApi::Color::Transparent outline, + RendererApi::SpriteMetadata *owner + ) { + iterate_rectangle_fill_wh( + x, y, width, height, + [=](bool is_edge, RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y) { if (is_edge) painter->add_voxel(x, y, z, outline, owner); } + ); + } + + template + void fill_rectangle_edges( + voxel_painter_t *painter, + RendererApi::PointI<2>::component_t left, + RendererApi::PointI<2>::component_t top, + RendererApi::PointI<2>::component_t right, + RendererApi::PointI<2>::component_t bottom, + double z, + RendererApi::Color::Transparent outline, + RendererApi::Color::Transparent fill, + RendererApi::SpriteMetadata *owner + ) { + iterate_rectangle_fill_edges( + left, top, right, bottom, + [=](bool is_edge, RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y) { painter->add_voxel(x, y, z, (is_edge ? outline : fill), owner); } + ); + } + + template + void fill_rectangle_wh( + voxel_painter_t *painter, + RendererApi::PointI<2>::component_t x, + RendererApi::PointI<2>::component_t y, + RendererApi::PointI<2>::component_t width, + RendererApi::PointI<2>::component_t height, + double z, + RendererApi::Color::Transparent outline, + RendererApi::Color::Transparent fill, + RendererApi::SpriteMetadata *owner + ) { + iterate_rectangle_fill_wh( + x, y, width, height, + [=](bool is_edge, RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y) { painter->add_voxel(x, y, z, (is_edge ? outline : fill), owner); } + ); + } +} \ No newline at end of file diff --git a/utilities/include/bgtu/computer_graphics_lab_work/utilities/triangle_fill_iterable.hpp b/utilities/include/bgtu/computer_graphics_lab_work/utilities/triangle_fill_iterable.hpp index 23c58e9..bc0f2fb 100644 --- a/utilities/include/bgtu/computer_graphics_lab_work/utilities/triangle_fill_iterable.hpp +++ b/utilities/include/bgtu/computer_graphics_lab_work/utilities/triangle_fill_iterable.hpp @@ -4,7 +4,7 @@ #include #include #include -#include "brezenham.hpp" +#include "bgtu/computer_graphics_lab_work/utilities/shapes/brezenham.hpp" namespace BGTU::ComputerGraphicsLabWork::Utilities { diff --git a/utilities/include/bgtu/computer_graphics_lab_work/utilities/voxel_painter_exporter_to_packed_array.hpp b/utilities/include/bgtu/computer_graphics_lab_work/utilities/voxel_painter_exporter_to_packed_array.hpp index 7f15eba..00884b2 100644 --- a/utilities/include/bgtu/computer_graphics_lab_work/utilities/voxel_painter_exporter_to_packed_array.hpp +++ b/utilities/include/bgtu/computer_graphics_lab_work/utilities/voxel_painter_exporter_to_packed_array.hpp @@ -29,5 +29,5 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities { }; }; - using VoxelPainterExporterToRgb32Array = VoxelPainterExporterToPackedArray<4, PackColor::color_to_rgb32>; + using VoxelPainterExporterToBgr32Array = VoxelPainterExporterToPackedArray<4, PackColor::color_to_bgr32>; } \ No newline at end of file diff --git a/utilities/include/bgtu/computer_graphics_lab_work/utilities/zoomed_voxel_painter.hpp b/utilities/include/bgtu/computer_graphics_lab_work/utilities/zoomed_voxel_painter.hpp new file mode 100644 index 0000000..95ba4b5 --- /dev/null +++ b/utilities/include/bgtu/computer_graphics_lab_work/utilities/zoomed_voxel_painter.hpp @@ -0,0 +1,66 @@ +#pragma once + +#include +#include +#include +#include +#include +#include "shapes/rectangle.hpp" + +namespace BGTU::ComputerGraphicsLabWork::Utilities { + template + class ZoomedVoxelPainter : public RendererApi::VirtualVoxelPainter { + private: + unzoomed_painter_t *dst; + RendererApi::PointI<2>::component_t cx, cy; + std::size_t pixel_size; + public: + constexpr ZoomedVoxelPainter( + unzoomed_painter_t *dst, + RendererApi::PointI<2>::component_t cx, + RendererApi::PointI<2>::component_t cy, + std::size_t pixel_size + ) noexcept: dst{dst}, cx{cx}, cy{cy}, pixel_size{pixel_size} {} + + constexpr ZoomedVoxelPainter( + unzoomed_painter_t *dst, + RendererApi::PointI<2> center_tl, + std::size_t pixel_size + ) noexcept: dst{dst}, cx{center_tl.x}, cy{center_tl.y}, pixel_size{pixel_size} {} + + void add_voxel(long long x, long long y, double z, RendererApi::Color::Transparent c) final { + Shapes::fill_rectangle_wh( + this->dst, + this->cx + x * this->pixel_size, + this->cy + y * this->pixel_size, + this->pixel_size, + this->pixel_size, + z, + c, c + ); + } + + void add_voxel(long long x, long long y, double z, RendererApi::Color::Transparent c, RendererApi::SpriteMetadata *owner) final { + Shapes::fill_rectangle_wh( + this->dst, + this->cx + x * this->pixel_size, + this->cy + y * this->pixel_size, + this->pixel_size, + this->pixel_size, + z, + c, c, + owner + ); + } + + [[nodiscard]] constexpr visible_pixel_coordinate_fast_t width() const override { + throw std::exception{"This wrapper doesn't provides such information"}; + return 0; + } + + [[nodiscard]] constexpr visible_pixel_coordinate_fast_t height() const override { + throw std::exception{"This wrapper doesn't provides such information"}; + return 0; + } + }; +} \ No newline at end of file diff --git a/utilities/src/color.asm b/utilities/src/color.asm index 009f917..37efdbf 100644 --- a/utilities/src/color.asm +++ b/utilities/src/color.asm @@ -14,23 +14,24 @@ %macro impl_body 1 %ifidn __OUTPUT_FORMAT__, elf64 - movd xmm0, edi movd xmm1, esi + shr esi, 24 + cmp r8d, 255 + je %%not_opaque + movd xmm0, edi mov r8d, esi %elifidn __OUTPUT_FORMAT__, win64 -; movzx r9d, WORD [rdx] -; movzx r10d, BYTE [rdx+2] -; shl r10d, 16 -; or r9d, r10d - movd xmm0, DWORD [rdx] movd xmm1, r8d + shr r8d, 24 + cmp r8d, 255 + je %%not_opaque + movd xmm0, DWORD [rdx] %else %error "Unsupported output format" %endif - pmovzxbd xmm0, xmm0 ; 0-extend 8bit->32bit - pmovzxbd xmm1, xmm1 ; 0-extend 8bit->32bit - shr r8d, 24 + pmovzxbd xmm0, xmm0 ; 0-extend 8bit->32bit SSE4.1 + pmovzxbd xmm1, xmm1 ; 0-extend 8bit->32bit SSE4.1 %if %1 >= __AVX512F__ vpbroadcastd xmm2, r8d ; fill vector with 32bit values %elif %1 >= __AVX2__ @@ -44,12 +45,19 @@ movd xmm3, r8d vpbroadcastd xmm3, xmm3 %endif + cvtdq2ps xmm0, xmm0 ; i32 -> float SSE2 + cvtdq2ps xmm1, xmm1 ; i32 -> float SSE2 + cvtdq2ps xmm2, xmm2 ; i32 -> float SSE2 + cvtdq2ps xmm3, xmm3 ; i32 -> float SSE2 + movups xmm4, xmm3 - psubd xmm3, xmm2 ; sub 32bit integers - pmuludq xmm0, xmm3 ; mul unsigned 32bit integers - pmuludq xmm1, xmm2 ; mul unsigned 32bit integers - paddd xmm0, xmm1 ; add 32bit integers - psrld xmm0, 8 ; 0-shift 32bit integers right + subps xmm3, xmm2 + mulps xmm0, xmm3 + mulps xmm1, xmm2 + addps xmm0, xmm1 + divps xmm0, xmm4 + + cvttps2dq xmm0, xmm0 pextrd r9d, xmm0, 0 ; extracts 32 bit integer pextrd r10d, xmm0, 1 ; extracts 32 bit integer @@ -60,11 +68,21 @@ or r9d, r11d %ifidn __OUTPUT_FORMAT__, elf64 - mov eax, r9d + movd eax, r9d %elifidn __OUTPUT_FORMAT__, win64 mov DWORD [rcx], r9d %else %error "Unsupported output format" +%endif + ret + +%%not_opaque: +%ifidn __OUTPUT_FORMAT__, elf64 + movd eax, xmm1 +%elifidn __OUTPUT_FORMAT__, win64 + movd DWORD [rcx], xmm1 +%else +%error "Unsupported output format" %endif ret %endmacro @@ -75,7 +93,10 @@ section .text ; avx2 -global ?_apply_transparent_color_avx2@Utilities@ComputerGraphicsLabWork@BGTU@@YA?AVColor@RendererApi@23@V4523@VTransparent@4523@@Z ; msvc +global ?_apply_transparent_color_avx512f@Utilities@ComputerGraphicsLabWork@BGTU@@YA?AVColor@RendererApi@23@V4523@VTransparent@4523@@Z ; msvc +?_apply_transparent_color_avx512f@Utilities@ComputerGraphicsLabWork@BGTU@@YA?AVColor@RendererApi@23@V4523@VTransparent@4523@@Z: +impl_body __AVX512F__ +global ?_apply_transparent_color_avx2@Utilities@ComputerGraphicsLabWork@BGTU@@YA?AVColor@RendererApi@23@V4523@VTransparent@4523@@Z ; msvc ?_apply_transparent_color_avx2@Utilities@ComputerGraphicsLabWork@BGTU@@YA?AVColor@RendererApi@23@V4523@VTransparent@4523@@Z: impl_body __AVX2__ \ No newline at end of file