computer-graphics-0/programs/lab3/src/variant1.cpp
2024-12-25 12:50:35 +03:00

76 lines
2.8 KiB
C++

#include <utility>
#include <bgtu/computer_graphics_lab_work/utilities/shader.hpp>
#include <bgtu/computer_graphics_lab_work/utilities/shapes/circle.hpp>
#include "variant1.hpp"
namespace BGTU::ComputerGraphicsLabWork::Impl {
namespace {
template<class real_shader_t>
class TransformedShader : public Utilities::Shader {
private:
Utilities::Matrix3d transform;
real_shader_t real_shader;
public:
TransformedShader(Utilities::Matrix3d transform, real_shader_t real_shader) : transform{transform}, real_shader{real_shader} {};
[[nodiscard]] RendererApi::Color::Transparent get_color(RendererApi::PointF<2>::component_t x, RendererApi::PointF<2>::component_t y) const final {
auto p = this->transform * RendererApi::PointF<2>{x, y};
return this->real_shader.get_color(p.x, p.y);
}
};
template<double radius>
class SunShader : public Utilities::Shader {
private:
public:
SunShader() = default;
[[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;
if (distance > 1)
return RendererApi::Color::Transparent{255, 255, 0, 0};
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});
else
return RendererApi::Color::Transparent{255, 255, 200, 255};
}
};
template<double z, double radius>
class SunSprite : public RendererApi::Sprite<SpriteData, Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> {
private:
public:
SunSprite() = default;
void draw(BGTU::ComputerGraphicsLabWork::Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl *frame, const BGTU::ComputerGraphicsLabWork::Impl::SpriteData *data) const final {
TransformedShader<SunShader<radius>> shader{data->planets_transform[0].inversed(), SunShader<radius>{}};
Utilities::Shapes::iterate_circle_fill(
static_cast< RendererApi::PointI<2>>(data->planets_transform[0] * 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));
}
);
}
};
SunSprite<1.0, 0.1> sun_sprite{};
RendererApi::Sprite<SpriteData, Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> *_sprites[]{
&sun_sprite
};
}
RendererApi::Sprite<SpriteData, Utilities::DefaultVoxelDrawerCache::VoxelPainterImpl> **const sprites = _sprites;
std::size_t sprites_count = 1;
}