Peoplemon  0.1.0
Peoplemon 3 game source documentation
Fog.cpp
Go to the documentation of this file.
1 #include "Fog.hpp"
2 
3 #include <BLIB/Cameras/2D/Camera2D.hpp>
4 #include <BLIB/Util/Random.hpp>
5 #include <Core/Properties.hpp>
6 
7 namespace core
8 {
9 namespace map
10 {
11 namespace weather
12 {
13 namespace
14 {
15 constexpr float AlphaRate = 0.1f;
16 const glm::vec2 FogVelocity(64.f, 25.f);
17 
18 float computeAlpha(float current, float target, float step) {
19  const float rate = target > current ? AlphaRate : -AlphaRate;
20  const float na = current + rate * step;
21  if (na < 0.f) return 0.f;
22  if (na > 1.f) return 1.f;
23  if (current < target && na > target) return target;
24  return na;
25 }
26 
27 } // namespace
28 
29 namespace fog
30 {
31 struct Particle {
32  glm::vec2 pos;
33  float rotation;
35  float scale;
36 
37  Particle() = default;
38 
39  Particle(const glm::vec2& pos)
40  : pos(pos)
41  , rotation(bl::util::Random::get<float>(0.f, 2.f * bl::math::Pi))
42  , angularVelocity(bl::util::Random::get<float>(-bl::math::Pi, bl::math::Pi))
43  , scale(bl::util::Random::get<float>(0.8f, 1.8f)) {}
44 };
45 
46 struct GpuParticle {
47  glm::vec2 pos;
48  float rotation;
49  float scale;
50 
51  GpuParticle() = default;
52 
54  pos = p.pos;
55  rotation = p.rotation;
56  scale = p.scale;
57  return *this;
58  }
59 };
60 
62  std::uint32_t textureId;
63  glm::vec2 textureCenter;
64  float alpha;
65  float radius;
66 };
67 
68 } // namespace fog
69 } // namespace weather
70 } // namespace map
71 } // namespace core
72 
73 namespace bl
74 {
75 namespace pcl
76 {
80 
81 template<>
82 struct RenderConfigMap<Particle> {
83  static constexpr std::uint32_t PipelineId = core::Properties::FogPipelineId;
84  static constexpr bool ContainsTransparency = true;
85 
86  static constexpr bool CreateRenderPipeline = true;
87 
88  static constexpr std::initializer_list<std::uint32_t> RenderPassIds =
89  bl::pcl::RenderConfigDefaults<Particle>::RenderPassIds;
90 
93  bl::pcl::RenderConfigDescriptorList<bl::rc::ds::TexturePoolFactory,
94  bl::rc::ds::Scene2DFactory,
95  bl::pcl::DescriptorSetFactory<Particle, GpuParticle>>;
96 
97  static constexpr bool EnableDepthTesting = true;
98  static constexpr VkPrimitiveTopology Topology = VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
99  static constexpr const char* VertexShader = "Resources/Shaders/Particles/fog.vert.spv";
100  static constexpr const char* FragmentShader =
101  bl::rc::Config::ShaderIds::Fragment2DRotatedParticle;
102 };
103 } // namespace pcl
104 } // namespace bl
105 
106 namespace core
107 {
108 namespace map
109 {
110 namespace weather
111 {
112 namespace fog
113 {
114 class FogSink : public bl::pcl::Sink<fog::Particle> {
115 public:
117  : clear(false) {}
118 
119  virtual ~FogSink() = default;
120 
121  virtual void update(Proxy& proxy, std::span<Particle> particles, float, float) override {
122  if (clear) {
123  clear = false;
124  for (Particle& p : particles) { proxy.destroy(p); }
125  }
126  }
127 
128  void clearAll() { clear = true; }
129 
130 private:
131  bool clear;
132 };
133 
134 class FogUpdater : public bl::pcl::MetaUpdater<fog::Particle> {
135 public:
136  FogUpdater(bl::rc::RenderTarget& observer, FogSink& sink)
137  : observer(observer)
138  , sink(sink)
139  , prevArea(1.f, 1.f, 1.f, 1.f) {}
140 
141  virtual ~FogUpdater() = default;
142 
143  virtual void update(Proxy& proxy, float, float) override {
144  bl::cam::Camera2D* cam = observer.getCurrentCamera<bl::cam::Camera2D>();
145  if (!cam) { return; }
146  const sf::FloatRect area = cam->getVisibleArea();
147 
148  if (proxy.getManager().getParticleCount() > 0) {
149  const float dx = area.width / prevArea.width;
150  const float dy = area.height / prevArea.height;
151  if (dx >= 1.25f || dy >= 1.25f) {
152  sink.clearAll();
153  prevArea = area;
154  }
155  }
156  else { prevArea = area; }
157  }
158 
159 private:
160  bl::rc::RenderTarget& observer;
161  FogSink& sink;
162  sf::FloatRect prevArea;
163 };
164 
165 float wrapWidth = 800.f;
166 float wrapHeight = 600.f;
167 
168 class FogAffector : public bl::pcl::Affector<fog::Particle> {
169 public:
170  FogAffector(bl::rc::RenderTarget& observer)
171  : observer(observer) {}
172 
173  virtual ~FogAffector() = default;
174 
175  virtual void update(Proxy& proxy, float dt, float) override {
176  bl::cam::Camera2D* cam = observer.getCurrentCamera<bl::cam::Camera2D>();
177  if (!cam) { return; }
178 
179  const sf::FloatRect area = cam->getVisibleArea();
180  const float leftBound = area.left + area.width * 0.5f - wrapWidth * 0.5f;
181  const float rightBound = leftBound + wrapWidth;
182  const float topBound = area.top + area.height * 0.5f - wrapHeight * 0.5f;
183  const float bottomBound = topBound + wrapHeight;
184 
185  for (Particle& p : proxy.particles()) {
186  p.pos += FogVelocity * dt;
187  p.rotation += p.angularVelocity * dt;
188  if (p.pos.x < leftBound) { p.pos.x += wrapWidth; }
189  else if (p.pos.x > rightBound) { p.pos.x -= wrapWidth; }
190  if (p.pos.y < topBound) { p.pos.y += wrapHeight; }
191  else if (p.pos.y > bottomBound) { p.pos.y -= wrapHeight; }
192  }
193  }
194 
195 private:
196  bl::rc::RenderTarget& observer;
197 };
198 
199 class FogEmitter : public bl::pcl::Emitter<fog::Particle> {
200 public:
201  FogEmitter(bl::rc::RenderTarget& observer, glm::vec2 txtrSize)
202  : observer(observer)
203  , txtrHalfSize(txtrSize * 0.4f) {}
204 
205  virtual ~FogEmitter() = default;
206 
207  virtual void update(Proxy& proxy, float, float) override {
208  if (proxy.getManager().getParticleCount() == 0) {
209  bl::cam::Camera2D* cam = observer.getCurrentCamera<bl::cam::Camera2D>();
210  if (!cam) { return; }
211  const sf::FloatRect area = cam->getVisibleArea();
212 
213  const unsigned int width = std::ceil(area.width * 2.f / txtrHalfSize.x);
214  const unsigned int height = std::ceil(area.height * 2.f / txtrHalfSize.y);
215 
216  wrapWidth = static_cast<float>(width) * txtrHalfSize.x;
217  wrapHeight = static_cast<float>(height) * txtrHalfSize.y;
218  const glm::vec2 corner(area.left + area.width * 0.5f - wrapWidth * 0.5f,
219  area.top + area.height * 0.5f - wrapHeight * 0.5f);
220 
221  for (unsigned int x = 0; x < width; ++x) {
222  for (unsigned int y = 0; y < height; ++y) {
223  const glm::vec2 pos{static_cast<float>(x), static_cast<float>(y)};
224  proxy.emit(pos * txtrHalfSize + corner);
225  }
226  }
227  }
228  }
229 
230 private:
231  bl::rc::RenderTarget& observer;
232  const glm::vec2 txtrHalfSize;
233 };
234 
235 } // namespace fog
236 
237 Fog::Fog(bool thick)
238 : engine(nullptr)
239 , maxOpacity(static_cast<float>(thick ? Properties::ThickFogAlpha() : Properties::ThinFogAlpha()) /
240  255.f)
241 , targetOpacity(0.f)
242 , particles(nullptr) {}
243 
245  if (engine) { engine->particleSystem().removeUniqueSystem<fog::Particle>(); }
246 }
247 
250 }
251 
252 void Fog::start(bl::engine::Engine& e, bl::rc::RenderTarget& renderTarget, Map& map) {
253  engine = &e;
254  targetOpacity = maxOpacity;
255 
256  const auto sampler = e.renderer().vulkanState().samplerCache.noFilterBorderClamped();
257  fogTxtr = e.renderer().texturePool().getOrLoadTexture(Properties::FogFile(), sampler);
258 
259  particles = &e.particleSystem().getUniqueSystem<fog::Particle>();
260  fog::FogSink* sink = particles->addSink<fog::FogSink>();
261  particles->addUpdater<fog::FogUpdater>(std::ref(renderTarget), std::ref(*sink));
262  particles->addAffector<fog::FogAffector>(renderTarget);
263  particles->addEmitter<fog::FogEmitter>(renderTarget, fogTxtr->size());
264 
265  particles->getRenderer().getGlobals().alpha = 0.f;
266  particles->getRenderer().getGlobals().textureCenter =
267  fogTxtr->normalizeAndConvertCoord(fogTxtr->size() * 0.5f);
268  particles->getRenderer().getGlobals().textureId = fogTxtr.id();
269  particles->getRenderer().getGlobals().radius = glm::length(fogTxtr->size()) * 0.5f;
270 
271  particles->addToScene(renderTarget.getCurrentScene());
272  particles->getRenderer().getComponent()->vertexBuffer.vertices()[0].pos.z = map.getMinDepth();
273 }
274 
275 void Fog::stop() { targetOpacity = 0.f; }
276 
277 bool Fog::stopped() const {
278  return particles && particles->getRenderer().getGlobals().alpha <= 0.01f;
279 }
280 
281 void Fog::update(float dt) {
282  if (particles) {
283  if (particles->getRenderer().getGlobals().alpha != targetOpacity) {
284  particles->getRenderer().getGlobals().alpha =
285  computeAlpha(particles->getRenderer().getGlobals().alpha, targetOpacity, dt);
286  }
287  }
288 }
289 
290 } // namespace weather
291 } // namespace map
292 } // namespace core
Core classes and functionality for both the editor and game.
core::map::weather::fog::GlobalShaderInfo GlobalShaderInfo
Definition: Fog.cpp:79
core::map::weather::fog::GpuParticle GpuParticle
Definition: Fog.cpp:78
core::map::weather::fog::Particle Particle
Definition: Fog.cpp:77
The primary map class that represents a usable map in the game.
Definition: Map.hpp:49
float getMinDepth() const
Returns the maximum depth possible for this map. Maximum is always 0.f. Minimum is negative,...
Definition: Map.cpp:775
Type
The type of weather.
Definition: Weather.hpp:38
@ ThinFog
Thin fog covers the area.
Definition: Weather.hpp:70
@ ThickFog
Thick fog obscures everything.
Definition: Weather.hpp:73
Wrapper around bl::engine::Configuration. Provides application configuration in variables that may be...
Definition: Properties.hpp:28
static const std::string & FogFile()
Definition: Properties.cpp:407
static constexpr std::uint32_t FogPipelineId
Definition: Properties.hpp:138
static unsigned int ThickFogAlpha()
Definition: Properties.cpp:465
Particle(const glm::vec2 &pos)
Definition: Fog.cpp:39
GpuParticle & operator=(const Particle &p)
Definition: Fog.cpp:53
bl::pcl::RenderConfigDescriptorList< bl::rc::ds::TexturePoolFactory, bl::rc::ds::Scene2DFactory, bl::pcl::DescriptorSetFactory< Particle, GpuParticle > > DescriptorSets
Definition: Fog.cpp:95
virtual void update(Proxy &proxy, std::span< Particle > particles, float, float) override
Definition: Fog.cpp:121
FogUpdater(bl::rc::RenderTarget &observer, FogSink &sink)
Definition: Fog.cpp:136
virtual void update(Proxy &proxy, float, float) override
Definition: Fog.cpp:143
virtual void update(Proxy &proxy, float dt, float) override
Definition: Fog.cpp:175
FogAffector(bl::rc::RenderTarget &observer)
Definition: Fog.cpp:170
FogEmitter(bl::rc::RenderTarget &observer, glm::vec2 txtrSize)
Definition: Fog.cpp:201
virtual void update(Proxy &proxy, float, float) override
Definition: Fog.cpp:207
virtual void stop() override
Stops the fog.
Definition: Fog.cpp:275
virtual Weather::Type type() const override
Returns ThinFog or ThickFog.
Definition: Fog.cpp:248
Fog(bool thick)
Creates foggy weather.
Definition: Fog.cpp:237
virtual void update(float dt) override
Updates the fog.
Definition: Fog.cpp:281
virtual void start(bl::engine::Engine &engine, bl::rc::RenderTarget &renderTarget, Map &map) override
Starts the fog.
Definition: Fog.cpp:252
virtual bool stopped() const override
Returns true when the fog is fully dissipated, false if not.
Definition: Fog.cpp:277
virtual ~Fog()
No more fog.
Definition: Fog.cpp:244