diff --git a/programs/lab3/src/main.cpp b/programs/lab3/src/main.cpp index 8649011..536979b 100644 --- a/programs/lab3/src/main.cpp +++ b/programs/lab3/src/main.cpp @@ -39,13 +39,13 @@ namespace BGTU::ComputerGraphicsLabWork::Impl { return 0; #else - Utilities::Matrix3d x = Utilities::Matrix3d::shift(10, 10); - Utilities::Matrix3d y = x.inversed(); + Utilities::Matrix3d x = Utilities::Matrix3d::shift(0, 9); + Utilities::Matrix3d y = Utilities::Matrix3d::rotate(3.14); - RendererApi::PointF<2> a{0, 0}; + RendererApi::PointF<2> a{0, 1}; RendererApi::PointF<2> b = x * a; - RendererApi::PointF<2> c = y * a; - RendererApi::PointF<2> d = y * b; + RendererApi::PointF<2> c = x * y * a; + RendererApi::PointF<2> d = y * x * a; return 0; diff --git a/programs/lab3/src/sprite_data.hpp b/programs/lab3/src/sprite_data.hpp index a8416a5..d7ca829 100644 --- a/programs/lab3/src/sprite_data.hpp +++ b/programs/lab3/src/sprite_data.hpp @@ -43,7 +43,7 @@ namespace BGTU::ComputerGraphicsLabWork::Impl { SpriteData get_sprite_data() override { this->sync.lock(); - double radius = (((this->w < this->h) ? this->w : this->h) * 5 / 16.0); + double radius = (((this->w < this->h) ? this->w : this->h) * 7 / 16.0); Utilities::Matrix3d center_shift = Utilities::Matrix3d::shift(this->w / 2, this->h / 2); Utilities::Matrix3d scale = Utilities::Matrix3d::scale(radius); double current_time = this->time.elapsed(); @@ -52,16 +52,16 @@ namespace BGTU::ComputerGraphicsLabWork::Impl { .radius_multiplier = radius, .planets_transform = { center_shift * Utilities::Matrix3d::scale(radius), - center_shift * scale * Utilities::Matrix3d::rotate(current_time / 1000.0 * 1.5), - center_shift * scale * Utilities::Matrix3d::rotate(current_time / 1000.0 * 1.2), - center_shift * scale * Utilities::Matrix3d::rotate(current_time / 1000.0 * 1), - center_shift * scale * Utilities::Matrix3d::rotate(current_time / 1000.0 * 0.9), - center_shift * scale * Utilities::Matrix3d::rotate(current_time / 1000.0 * 0.5), - center_shift * scale * Utilities::Matrix3d::rotate(current_time / 1000.0 * 0.45), - center_shift * scale * Utilities::Matrix3d::rotate(current_time / 1000.0 * 0.2), - center_shift * scale * Utilities::Matrix3d::rotate(current_time / 1000.0 * 0.17), + center_shift * scale * Utilities::Matrix3d::rotate(current_time / 1000.0 * 0.015), + center_shift * scale * Utilities::Matrix3d::rotate(current_time / 1000.0 * 0.012), + center_shift * scale * Utilities::Matrix3d::rotate(current_time / 1000.0 * 0.01), + center_shift * scale * Utilities::Matrix3d::rotate(current_time / 1000.0 * 0.009), + center_shift * scale * Utilities::Matrix3d::rotate(current_time / 1000.0 * 0.005), + center_shift * scale * Utilities::Matrix3d::rotate(current_time / 1000.0 * 0.0045), + center_shift * scale * Utilities::Matrix3d::rotate(current_time / 1000.0 * 0.002), + center_shift * scale * Utilities::Matrix3d::rotate(current_time / 1000.0 * 0.0017), }, - .stars_transform = Utilities::Matrix3d::rotate(current_time / 1000.0 * 0.02) * scale * center_shift, + .stars_transform = Utilities::Matrix3d::rotate(current_time / 1000.0 * 0.0002) * scale * center_shift, .time_ms = current_time }; diff --git a/programs/lab3/src/variant1.cpp b/programs/lab3/src/variant1.cpp index e6dd185..6877257 100644 --- a/programs/lab3/src/variant1.cpp +++ b/programs/lab3/src/variant1.cpp @@ -31,7 +31,7 @@ namespace BGTU::ComputerGraphicsLabWork::Impl { RendererApi::PointF<2>::component_t distance = std::hypot(x, y) / radius; if (distance > 1) return RendererApi::Color::Transparent{255, 255, 0, 0}; - if (distance > 0.8) + else if (distance > 0.8) return Utilities::colors_gradient(RendererApi::Color::Transparent{255, 255, 0, 0}, (distance - 0.8) * 5, RendererApi::Color::Transparent{255, 255, 0, 255}); else if (distance > 0.3) return Utilities::colors_gradient(RendererApi::Color::Transparent{255, 255, 0, 255}, (distance - 0.3) * 10 / 5, RendererApi::Color::Transparent{255, 255, 200, 255}); @@ -42,8 +42,6 @@ namespace BGTU::ComputerGraphicsLabWork::Impl { template class SunSprite : public RendererApi::Sprite { - - private: public: SunSprite() = default; @@ -60,17 +58,128 @@ namespace BGTU::ComputerGraphicsLabWork::Impl { } }; + template + class SunlightReflectionShaderModifier : public Utilities::Shader { + private: + static_assert(brightness_coefficient >= 0.0); + static_assert(brightness_coefficient <= 1.0); - SunSprite<1.0, 0.1> sun_sprite{}; + static constexpr RendererApi::Color::Transparent light{63, 63, 0, static_cast(55 * brightness_coefficient)}; + static constexpr RendererApi::Color::Transparent darkness{0, 0, 0, 255 - static_cast(55 * brightness_coefficient)}; + static constexpr RendererApi::Color::Transparent middle = Utilities::colors_gradient(light, 0.3, darkness); + + underlying_shader_t underlying_shader; + public: + explicit SunlightReflectionShaderModifier(underlying_shader_t underlying_shader) : underlying_shader{underlying_shader} {} + + [[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, y + radius) / radius; + if (distance > 2) + return underlying_shader.get_color(x, y); + else if (distance > 1) + return Utilities::apply_transparent_color(underlying_shader.get_color(x, y), Utilities::colors_gradient(darkness, (distance - 1), middle)); + else + return Utilities::apply_transparent_color(underlying_shader.get_color(x, y), Utilities::colors_gradient(middle, distance, light)); + } + }; + + + template + class PlanetSprite : public RendererApi::Sprite { + public: + PlanetSprite() = default; + + void draw(BGTU::ComputerGraphicsLabWork::Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl *frame, const BGTU::ComputerGraphicsLabWork::Impl::SpriteData *data) const final { + Utilities::Shapes::iterate_circle_fill( + static_cast< RendererApi::PointI<2>>(data->planets_transform[transform_id] * RendererApi::PointF<2>{0, 0}), + data->radius_multiplier * orbit_radius, + [&](bool is_edge, RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y) { + if (is_edge) + frame->add_voxel(x, y, orbit_z, orbit_color); + } + ); + + auto planet_center = data->planets_transform[transform_id] * Utilities::Matrix3d::shift(0, orbit_radius); + + TransformedShader> shader{ + planet_center.inversed(), + SunlightReflectionShaderModifier{planet_shader} + }; + + Utilities::Shapes::iterate_circle_fill( + static_cast< RendererApi::PointI<2>>(planet_center * RendererApi::PointF<2>{0, 0}), + data->radius_multiplier * planet_radius * atmosphere_radius, + [&](bool, RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y) { + frame->add_voxel(x, y, planet_z, shader.get_color(x, y)); + } + ); + + } + }; + + template{}> + class StartSprite : public RendererApi::Sprite { + public: + StartSprite() = default; + + void draw(BGTU::ComputerGraphicsLabWork::Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl *frame, const BGTU::ComputerGraphicsLabWork::Impl::SpriteData *data) const final { + auto planet_center = data->stars_transform * Utilities::Matrix3d::rotate(angle_offset) * Utilities::Matrix3d::shift(0, orbit_radius); + + TransformedShader shader{ + planet_center.inversed(), + planet_shader + }; + + Utilities::Shapes::iterate_circle_fill( + static_cast< RendererApi::PointI<2>>(planet_center * RendererApi::PointF<2>{0, 0}), + data->radius_multiplier * radius, + [&](bool, RendererApi::PointI<2>::component_t x, RendererApi::PointI<2>::component_t y) { + frame->add_voxel(x, y, z, shader.get_color(x, y)); + } + ); + + } + }; + + constexpr RendererApi::Color::Transparent default_orbit_color{255, 255, 255, 127}; + constexpr double orbit_z = 2.0; + + SunSprite<1.0, 0.25> sun_sprite{}; + + PlanetSprite{}, 0.3> mercury; + PlanetSprite{}, 0.2> venus; + PlanetSprite{}, 0.27> earth; + PlanetSprite{}, 0.25> mars; + PlanetSprite{}, 0.2> jupiter; + PlanetSprite{}, 0.18> saturn; + + StartSprite<1.8-0.4, 0.4, 3.0, 0.0> star1; + StartSprite<1.7-0.4, 0.5, 3.0, 1.0> star2; + StartSprite<1.9-0.4, 0.4, 3.0, 2.0> star3; + StartSprite<1.6-0.4, 0.5, 3.0, 3.0> star4; + StartSprite<2.0-0.4, 0.4, 3.0, 4.0> star5; + StartSprite<2.1-0.4, 0.3, 3.0, 5.0> star6; RendererApi::Sprite *_sprites[]{ - &sun_sprite + &sun_sprite, + &mercury, + &venus, + &earth, + &mars, + &jupiter, + &saturn, + &star1, + &star2, + &star3, + &star4, + &star5, + &star6, }; } RendererApi::Sprite **const sprites = _sprites; - std::size_t sprites_count = 1; + std::size_t sprites_count = 7 + 6; } \ No newline at end of file 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 ff7f3be..c0b7084 100644 --- a/utilities/include/bgtu/computer_graphics_lab_work/utilities/color.hpp +++ b/utilities/include/bgtu/computer_graphics_lab_work/utilities/color.hpp @@ -173,6 +173,53 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities { #endif #endif + + constexpr RendererApi::Color::Transparent apply_transparent_color(RendererApi::Color::Transparent bg, RendererApi::Color::Transparent fg) { +#if 1 + if (fg.alpha == 255) + return fg; + else if (fg.alpha == 0) + return bg; + + // 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 fg_alpha_f = fg.alpha; + const float bg_alpha_f = bg.alpha; + const float neg_fg_alpha_f = bg_alpha_f * (255.f - fg_alpha_f) / 255.f; + const float out_alpha = fg_alpha_f + neg_fg_alpha_f; + + // mulps + const float bg_part[4]{bg_f[0] * neg_fg_alpha_f, bg_f[1] * neg_fg_alpha_f, bg_f[2] * neg_fg_alpha_f}; + const float fg_part[4]{fg_f[0] * fg_alpha_f, fg_f[1] * fg_alpha_f, fg_f[2] * fg_alpha_f}; + + // addps + const float sum_f[4]{bg_part[0] + fg_part[0], bg_part[1] + fg_part[1], bg_part[2] + fg_part[2]}; + + // divps + const float sum_fixed_f[4]{sum_f[0] / out_alpha, sum_f[2] / out_alpha, sum_f[2] / out_alpha}; + + 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], + (RendererApi::Color::component_compact_t) out_alpha + }; + +#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)), + }; +#endif + } + namespace PackColor { inline void color_to_rgb32(unsigned char *buffer, std::size_t offset, RendererApi::Color color) noexcept { buffer[offset] = color.red; diff --git a/utilities/include/bgtu/computer_graphics_lab_work/utilities/matrix.hpp b/utilities/include/bgtu/computer_graphics_lab_work/utilities/matrix.hpp index 5ee6ddd..79aa54c 100644 --- a/utilities/include/bgtu/computer_graphics_lab_work/utilities/matrix.hpp +++ b/utilities/include/bgtu/computer_graphics_lab_work/utilities/matrix.hpp @@ -144,8 +144,8 @@ namespace BGTU::ComputerGraphicsLabWork::Utilities { Matrix3 transposed() const { return Matrix3{ this->data[0][0], this->data[1][0], this->data[2][0], - this->data[0][2], this->data[1][1], this->data[2][1], - this->data[0][1], this->data[1][2], this->data[2][2] + this->data[0][1], this->data[1][1], this->data[2][1], + this->data[0][2], this->data[1][2], this->data[2][2] }; }