Last active
January 23, 2020 06:38
-
-
Save falrnd/96b95e5d31488fc0b2b7fe597063edf1 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <Siv3D.hpp> | |
// https://siv3d.github.io/ja-jp/sample/visual/#2d | |
class LightBloom2D | |
{ | |
protected: | |
Size sceneSize; | |
RenderTexture gaussianA1, gaussianB1; | |
RenderTexture gaussianA4, gaussianB4; | |
RenderTexture gaussianA8, gaussianB8; | |
public: | |
explicit LightBloom2D(const Size& sceneSize) | |
: sceneSize(sceneSize), | |
gaussianA1(sceneSize), gaussianB1(sceneSize), | |
gaussianA4(sceneSize / 4), gaussianB4(sceneSize / 4), | |
gaussianA8(sceneSize / 8), gaussianB8(sceneSize / 8) | |
{ | |
init(); | |
} | |
void init() | |
{ | |
gaussianA1.clear(ColorF(0.0)); | |
} | |
void clear() | |
{ | |
gaussianA1.clear(ColorF(0.0)); | |
gaussianA4.clear(ColorF(0.0)); | |
gaussianA8.clear(ColorF(0.0)); | |
} | |
void draw(double a8 = 1, double a4 = 1, double a1 = 1) | |
{ | |
// オリジナルサイズのガウスぼかし (A1) | |
// A1 を 1/4 サイズにしてガウスぼかし (A4) | |
// A4 を 1/2 サイズにしてガウスぼかし (A8) | |
Shader::GaussianBlur(gaussianA1, gaussianB1, gaussianA1); | |
Shader::Downsample(gaussianA1, gaussianA4); | |
Shader::GaussianBlur(gaussianA4, gaussianB4, gaussianA4); | |
Shader::Downsample(gaussianA4, gaussianA8); | |
Shader::GaussianBlur(gaussianA8, gaussianB8, gaussianA8); | |
ScopedRenderStates2D blend(BlendState::Additive); | |
if (a1) | |
gaussianA1.resized(sceneSize).draw(ColorF(a1)); | |
if (a4) | |
gaussianA4.resized(sceneSize).draw(ColorF(a4)); | |
if (a8) | |
gaussianA8.resized(sceneSize).draw(ColorF(a8)); | |
} | |
using RenderScope = std::pair<ScopedRenderTarget2D, ScopedRenderStates2D>; | |
[[nodiscard]] RenderScope makeRenderScope() const | |
{ | |
return std::make_pair(ScopedRenderTarget2D(gaussianA1), ScopedRenderStates2D(BlendState::Additive)); | |
} | |
private: | |
class ScopedLightBloom : Uncopyable | |
{ | |
private: | |
friend class LightBloom2D; | |
Optional<RenderScope> rs; | |
std::reference_wrapper<LightBloom2D> _this; | |
double a8, a4, a1; | |
ScopedLightBloom(Optional<RenderScope>&& rs, LightBloom2D& _this, double a8, double a4, double a1) | |
: rs(std::move(rs)), _this(_this), | |
a8(a8), a4(a4), a1(a1) | |
{ | |
_this.init(); | |
} | |
public: | |
~ScopedLightBloom() | |
{ | |
rs.reset(); | |
_this.get().draw(a8, a4, a1); | |
} | |
}; | |
public: | |
[[nodiscard]] auto makeLightBloomScope(double a8 = 1, double a4 = 1, double a1 = 1) | |
{ | |
return ScopedLightBloom(makeRenderScope(), *this, a8, a4, a1); | |
} | |
}; | |
void DrawScene() | |
{ | |
Circle(680, 40, 20).draw(); | |
Rect(Arg::center(680, 110), 30).draw(); | |
Triangle(680, 180, 40).draw(); | |
Circle(740, 40, 20).draw(HSV(0)); | |
Rect(Arg::center(740, 110), 30).draw(HSV(120)); | |
Triangle(740, 180, 40).draw(HSV(240)); | |
Circle(50, 200, 300).drawFrame(4); | |
Circle(550, 450, 200).drawFrame(4); | |
for (auto i : step(12)) | |
{ | |
const double angle = i * 30_deg + Scene::Time() * 5_deg; | |
const Vec2 pos = OffsetCircular(Scene::Center(), 200, angle); | |
Circle(pos, 8).draw(HSV(i * 30)); | |
} | |
} | |
void GUI(const Vec2& pos, double& a8, double& a4, double& a1) { | |
SimpleGUI::Slider(U"a8: {:.1f}"_fmt(a8), a8, 0.0, 4.0, pos); | |
SimpleGUI::Slider(U"a4: {:.1f}"_fmt(a4), a4, 0.0, 4.0, pos.movedBy(0, 40)); | |
SimpleGUI::Slider(U"a1: {:.1f}"_fmt(a1), a1, 0.0, 4.0, pos.movedBy(0, 80)); | |
if (SimpleGUI::Button(U"0, 0, 0", pos.movedBy(0, 120))) { | |
a8 = a4 = a1 = 0.0; | |
} | |
if (SimpleGUI::Button(U"1, 0, 0", pos.movedBy(0, 160))) { | |
a8 = 1.0; | |
a4 = a1 = 0.0; | |
} | |
if (SimpleGUI::Button(U"1, 1, 0", pos.movedBy(0, 200))) { | |
a8 = a4 = 1.0; | |
a1 = 0.0; | |
} | |
if (SimpleGUI::Button(U"1, 1, 1", pos.movedBy(0, 240))) { | |
a8 = a4 = a1 = 1.0; | |
} | |
} | |
void Main() | |
{ | |
constexpr Size sceneSize(800, 600); | |
LightBloom2D lightbloom(sceneSize); | |
double a8 = 1, a4 = 1, a1 = 1; | |
while (System::Update()) | |
{ | |
DrawScene(); | |
//* | |
lightbloom.init(); | |
{ | |
auto rs = lightbloom.makeRenderScope(); | |
DrawScene(); | |
} | |
lightbloom.draw(a8, a4, a1); | |
//*/ | |
/* | |
{ | |
auto rs = lightbloom.makeLightBloomScope(a8, a4, a1); | |
DrawScene(); | |
} | |
//*/ | |
GUI({ 20,20 }, a8, a4, a1); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment