3 #include <BLIB/Cameras/2D/Camera2D.hpp>
4 #include <BLIB/Util/Random.hpp>
15 constexpr
float AlphaRate = 0.1f;
16 const glm::vec2 FogVelocity(64.f, 25.f);
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;
41 ,
rotation(
bl::util::Random::get<float>(0.f, 2.f *
bl::math::Pi))
43 ,
scale(
bl::util::Random::get<float>(0.8f, 1.8f)) {}
84 static constexpr
bool ContainsTransparency =
true;
86 static constexpr
bool CreateRenderPipeline =
true;
88 static constexpr std::initializer_list<std::uint32_t> RenderPassIds =
89 bl::pcl::RenderConfigDefaults<Particle>::RenderPassIds;
93 bl::pcl::RenderConfigDescriptorList<bl::rc::ds::TexturePoolFactory,
94 bl::rc::ds::Scene2DFactory,
95 bl::pcl::DescriptorSetFactory<Particle, GpuParticle>>;
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;
114 class FogSink :
public bl::pcl::Sink<fog::Particle> {
121 virtual void update(Proxy& proxy, std::span<Particle> particles,
float,
float)
override {
124 for (
Particle& p : particles) { proxy.destroy(p); }
134 class FogUpdater :
public bl::pcl::MetaUpdater<fog::Particle> {
139 , prevArea(1.f, 1.f, 1.f, 1.f) {}
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();
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) {
156 else { prevArea = area; }
160 bl::rc::RenderTarget& observer;
162 sf::FloatRect prevArea;
171 : observer(observer) {}
175 virtual void update(Proxy& proxy,
float dt,
float)
override {
176 bl::cam::Camera2D* cam = observer.getCurrentCamera<bl::cam::Camera2D>();
177 if (!cam) {
return; }
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;
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; }
196 bl::rc::RenderTarget& observer;
201 FogEmitter(bl::rc::RenderTarget& observer, glm::vec2 txtrSize)
203 , txtrHalfSize(txtrSize * 0.4f) {}
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();
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);
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);
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);
231 bl::rc::RenderTarget& observer;
232 const glm::vec2 txtrHalfSize;
239 , maxOpacity(static_cast<float>(thick ?
Properties::ThickFogAlpha() :
Properties::ThinFogAlpha()) /
242 , particles(nullptr) {}
245 if (engine) { engine->particleSystem().removeUniqueSystem<
fog::Particle>(); }
252 void Fog::start(bl::engine::Engine& e, bl::rc::RenderTarget& renderTarget,
Map& map) {
254 targetOpacity = maxOpacity;
256 const auto sampler = e.renderer().vulkanState().samplerCache.noFilterBorderClamped();
259 particles = &e.particleSystem().getUniqueSystem<
fog::Particle>();
261 particles->addUpdater<
fog::FogUpdater>(std::ref(renderTarget), std::ref(*sink));
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;
271 particles->addToScene(renderTarget.getCurrentScene());
272 particles->getRenderer().getComponent()->vertexBuffer.vertices()[0].pos.z = map.
getMinDepth();
278 return particles && particles->getRenderer().getGlobals().alpha <= 0.01f;
283 if (particles->getRenderer().getGlobals().alpha != targetOpacity) {
284 particles->getRenderer().getGlobals().alpha =
285 computeAlpha(particles->getRenderer().getGlobals().alpha, targetOpacity, dt);
Core classes and functionality for both the editor and game.
core::map::weather::fog::GlobalShaderInfo GlobalShaderInfo
core::map::weather::fog::GpuParticle GpuParticle
core::map::weather::fog::Particle Particle
The primary map class that represents a usable map in the game.
float getMinDepth() const
Returns the maximum depth possible for this map. Maximum is always 0.f. Minimum is negative,...
@ ThinFog
Thin fog covers the area.
@ ThickFog
Thick fog obscures everything.
Wrapper around bl::engine::Configuration. Provides application configuration in variables that may be...
static const std::string & FogFile()
static constexpr std::uint32_t FogPipelineId
static unsigned int ThickFogAlpha()
Particle(const glm::vec2 &pos)
GpuParticle & operator=(const Particle &p)
bl::pcl::RenderConfigDescriptorList< bl::rc::ds::TexturePoolFactory, bl::rc::ds::Scene2DFactory, bl::pcl::DescriptorSetFactory< Particle, GpuParticle > > DescriptorSets
virtual void update(Proxy &proxy, std::span< Particle > particles, float, float) override
virtual ~FogSink()=default
FogUpdater(bl::rc::RenderTarget &observer, FogSink &sink)
virtual void update(Proxy &proxy, float, float) override
virtual ~FogUpdater()=default
virtual ~FogAffector()=default
virtual void update(Proxy &proxy, float dt, float) override
FogAffector(bl::rc::RenderTarget &observer)
virtual ~FogEmitter()=default
FogEmitter(bl::rc::RenderTarget &observer, glm::vec2 txtrSize)
virtual void update(Proxy &proxy, float, float) override
virtual void stop() override
Stops the fog.
virtual Weather::Type type() const override
Returns ThinFog or ThickFog.
Fog(bool thick)
Creates foggy weather.
virtual void update(float dt) override
Updates the fog.
virtual void start(bl::engine::Engine &engine, bl::rc::RenderTarget &renderTarget, Map &map) override
Starts the fog.
virtual bool stopped() const override
Returns true when the fog is fully dissipated, false if not.
virtual ~Fog()
No more fog.