From cda1d750f888363b1a89890f6d197beb189948a7 Mon Sep 17 00:00:00 2001 From: Attila Uygun Date: Wed, 17 May 2023 11:03:04 +0200 Subject: [PATCH] Manage custom shaders in Engine --- src/demo/demo.cc | 9 ++++---- src/demo/demo.h | 2 +- src/demo/enemy.cc | 25 ++++------------------- src/demo/enemy.h | 5 ----- src/demo/sky_quad.cc | 24 +++------------------- src/demo/sky_quad.h | 6 +----- src/engine/engine.cc | 44 ++++++++++++++++++++++++++++++++++++++++ src/engine/engine.h | 14 ++++++++++++- src/engine/image_quad.cc | 4 ++-- src/engine/image_quad.h | 2 +- 10 files changed, 73 insertions(+), 62 deletions(-) diff --git a/src/demo/demo.cc b/src/demo/demo.cc index 2d3747f..2cb3452 100644 --- a/src/demo/demo.cc +++ b/src/demo/demo.cc @@ -50,6 +50,10 @@ Demo::~Demo() { bool Demo::Initialize() { saved_data_.Load(kSaveFileName); + Engine::Get().LoadCustomShader("sky_without_nebula", + "sky_without_nebula.glsl"); + Engine::Get().LoadCustomShader("sky", "sky.glsl"); + if (!font_.Load("PixelCaps!.ttf")) return false; @@ -162,11 +166,6 @@ void Demo::Update(float delta_time) { UpdateGameState(delta_time); } -void Demo::ContextLost() { - sky_.ContextLost(); - enemy_.ContextLost(); -} - void Demo::LostFocus() {} void Demo::GainedFocus(bool from_interstitial_ad) { diff --git a/src/demo/demo.h b/src/demo/demo.h index b3ec1ed..5016861 100644 --- a/src/demo/demo.h +++ b/src/demo/demo.h @@ -27,7 +27,7 @@ class Demo final : public eng::Game { void Update(float delta_time) final; - void ContextLost() final; + void ContextLost() final {} void LostFocus() final; diff --git a/src/demo/enemy.cc b/src/demo/enemy.cc index 5c78220..3ae5cfd 100644 --- a/src/demo/enemy.cc +++ b/src/demo/enemy.cc @@ -13,8 +13,6 @@ #include "engine/font.h" #include "engine/image.h" #include "engine/renderer/geometry.h" -#include "engine/renderer/shader.h" -#include "engine/shader_source.h" #include "engine/sound.h" #include "demo/demo.h" @@ -76,8 +74,7 @@ float SnapSpawnPosX(int col) { } // namespace -Enemy::Enemy() - : chromatic_aberration_(Engine::Get().CreateRenderResource()) {} +Enemy::Enemy() = default; Enemy::~Enemy() = default; @@ -205,10 +202,6 @@ void Enemy::Pause(bool pause) { boss_animator_.PauseOrResumeAll(pause); } -void Enemy::ContextLost() { - CreateShaders(); -} - bool Enemy::HasTarget(DamageType damage_type) { DCHECK(damage_type > kDamageType_Invalid && damage_type < kDamageType_Any); @@ -423,7 +416,7 @@ void Enemy::StopAllEnemyUnits(bool chromatic_aberration_effect) { continue; if (chromatic_aberration_effect) { - e.sprite.SetCustomShader(chromatic_aberration_.get()); + e.sprite.SetCustomShader("chromatic_aberration"); e.chromatic_aberration_active_ = true; } @@ -1193,9 +1186,6 @@ std::unique_ptr Enemy::GetScoreImage(EnemyType enemy_type) { } bool Enemy::CreateRenderResources() { - if (!CreateShaders()) - return false; - Engine::Get().SetImageSource("skull_tex", "enemy_anims_01_frames_ok.png", true); Engine::Get().SetImageSource("bug_tex", "enemy_anims_02_frames_ok.png", true); @@ -1213,16 +1203,9 @@ bool Enemy::CreateRenderResources() { "score_tex"s + std::to_string(i), std::bind(&Enemy::GetScoreImage, this, (EnemyType)i), true); - return true; -} + Engine::Get().LoadCustomShader("chromatic_aberration", + "chromatic_aberration.glsl"); -bool Enemy::CreateShaders() { - auto source = std::make_unique(); - if (!source->Load("chromatic_aberration.glsl")) - return false; - chromatic_aberration_->Create(std::move(source), - Engine::Get().GetQuad()->vertex_description(), - Engine::Get().GetQuad()->primitive(), false); return true; } diff --git a/src/demo/enemy.h b/src/demo/enemy.h index 2172753..f8d4c85 100644 --- a/src/demo/enemy.h +++ b/src/demo/enemy.h @@ -15,7 +15,6 @@ namespace eng { class Image; -class Shader; class Sound; } // namespace eng @@ -30,8 +29,6 @@ class Enemy { void Pause(bool pause); - void ContextLost(); - bool HasTarget(DamageType damage_type); base::Vector2f GetTargetPos(DamageType damage_type); @@ -106,7 +103,6 @@ class Enemy { eng::SoundPlayer hit; }; - std::unique_ptr chromatic_aberration_; float chromatic_aberration_offset_ = 0; eng::ImageQuad boss_; @@ -169,7 +165,6 @@ class Enemy { std::unique_ptr GetScoreImage(EnemyType enemy_type); bool CreateRenderResources(); - bool CreateShaders(); void TranslateEnemyUnit(EnemyUnit& e, const base::Vector2f& delta); }; diff --git a/src/demo/sky_quad.cc b/src/demo/sky_quad.cc index 845d72f..01a1424 100644 --- a/src/demo/sky_quad.cc +++ b/src/demo/sky_quad.cc @@ -6,14 +6,12 @@ #include "engine/engine.h" #include "engine/renderer/geometry.h" #include "engine/renderer/shader.h" -#include "engine/shader_source.h" using namespace base; using namespace eng; SkyQuad::SkyQuad() - : shader_(Engine::Get().CreateRenderResource()), - sky_offset_{ + : sky_offset_{ 0, Lerp(0.0f, 10.0f, Engine::Get().GetRandomGenerator().Rand())} { last_sky_offset_ = sky_offset_; } @@ -22,10 +20,9 @@ SkyQuad::~SkyQuad() = default; bool SkyQuad::Create(bool without_nebula) { without_nebula_ = without_nebula; - if (!CreateShaders()) - return false; - scale_ = Engine::Get().GetScreenSize(); + shader_ = Engine::Get().GetCustomShader( + without_nebula ? "sky_without_nebula" : "sky"); color_animator_.Attach(this); @@ -54,10 +51,6 @@ void SkyQuad::Draw(float frame_frac) { Engine::Get().GetQuad()->Draw(); } -void SkyQuad::ContextLost() { - CreateShaders(); -} - void SkyQuad::SwitchColor(const Vector4f& color) { color_animator_.Pause(Animator::kBlending); color_animator_.SetTime(Animator::kBlending, 0); @@ -66,17 +59,6 @@ void SkyQuad::SwitchColor(const Vector4f& color) { color_animator_.Play(Animator::kBlending, false); } -bool SkyQuad::CreateShaders() { - Engine& engine = Engine::Get(); - - auto source = std::make_unique(); - if (!source->Load(without_nebula_ ? "sky_without_nebula.glsl" : "sky.glsl")) - return false; - shader_->Create(std::move(source), engine.GetQuad()->vertex_description(), - Engine::Get().GetQuad()->primitive(), false); - return true; -} - void SkyQuad::SetSpeed(float speed) { speed_ = speed; } \ No newline at end of file diff --git a/src/demo/sky_quad.h b/src/demo/sky_quad.h index 400cd46..16e146b 100644 --- a/src/demo/sky_quad.h +++ b/src/demo/sky_quad.h @@ -36,8 +36,6 @@ class SkyQuad : public eng::Animatable { // Drawable interface. void Draw(float frame_frac) final; - void ContextLost(); - void SwitchColor(const base::Vector4f& color); void SetSpeed(float speed); @@ -45,7 +43,7 @@ class SkyQuad : public eng::Animatable { const base::Vector4f& nebula_color() { return nebula_color_; } private: - std::unique_ptr shader_; + eng::Shader* shader_; base::Vector2f sky_offset_ = {0, 0}; base::Vector2f last_sky_offset_ = {0, 0}; @@ -57,8 +55,6 @@ class SkyQuad : public eng::Animatable { float speed_ = 0; bool without_nebula_ = false; - - bool CreateShaders(); }; #endif // DEMO_SKY_QUAD_H diff --git a/src/engine/engine.cc b/src/engine/engine.cc index 82233ea..945a0ee 100644 --- a/src/engine/engine.cc +++ b/src/engine/engine.cc @@ -109,6 +109,7 @@ void Engine::Shutdown() { game_.reset(); stats_->Destory(); textures_.clear(); + shaders_.clear(); } void Engine::Update(float delta_time) { @@ -277,6 +278,42 @@ void Engine::ReleaseTexture(const std::string& asset_name) { it->second.texture->Destroy(); } +void Engine::LoadCustomShader(const std::string& asset_name, + const std::string& file_name) { + if (shaders_.contains(asset_name)) { + DLOG << "Shader already exists: " << asset_name; + return; + } + + auto& s = shaders_[asset_name] = {CreateRenderResource(), file_name}; + + auto source = std::make_unique(); + if (!source->Load(file_name)) + return; + s.shader->Create(std::move(source), quad_->vertex_description(), + quad_->primitive(), false); +} + +Shader* Engine::GetCustomShader(const std::string& asset_name) { + auto it = shaders_.find(asset_name); + if (it == shaders_.end()) { + DLOG << "Shader not found: " << asset_name; + return nullptr; + } + + return it->second.shader.get(); +} + +void Engine::RemoveCustomShader(const std::string& asset_name) { + auto it = shaders_.find(asset_name); + if (it == shaders_.end()) { + DLOG << "Shader not found: " << asset_name; + return; + } + + shaders_.erase(it); +} + void Engine::AddInputEvent(std::unique_ptr event) { if (replaying_) return; @@ -452,6 +489,13 @@ void Engine::ContextLost() { RefreshImage(t.first); } + for (auto& s : shaders_) { + auto source = std::make_unique(); + if (source->Load(s.second.file_name)) + s.second.shader->Create(std::move(source), quad_->vertex_description(), + quad_->primitive(), false); + } + game_->ContextLost(); } diff --git a/src/engine/engine.h b/src/engine/engine.h index 75f578d..024c1a5 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -79,6 +79,11 @@ class Engine { Texture* AcquireTexture(const std::string& asset_name); void ReleaseTexture(const std::string& asset_name); + void LoadCustomShader(const std::string& asset_name, + const std::string& file_name); + Shader* GetCustomShader(const std::string& asset_name); + void RemoveCustomShader(const std::string& asset_name); + void AddInputEvent(std::unique_ptr event); std::unique_ptr GetNextInputEvent(); @@ -158,6 +163,12 @@ class Engine { size_t use_count = 0; }; + // Class holding information about shader resources managed by engine. + struct ShaderResource { + std::unique_ptr shader; + std::string file_name; + }; + static Engine* singleton; Platform* platform_ = nullptr; @@ -184,8 +195,9 @@ class Engine { std::list animators_; - // Textures mapped by asset name. + // Managed render resources mapped by asset name. std::unordered_map textures_; + std::unordered_map shaders_; std::unique_ptr stats_; diff --git a/src/engine/image_quad.cc b/src/engine/image_quad.cc index bd6ef9a..ab2e11a 100644 --- a/src/engine/image_quad.cc +++ b/src/engine/image_quad.cc @@ -49,8 +49,8 @@ void ImageQuad::AutoScale() { SetSize(size); } -void ImageQuad::SetCustomShader(Shader* shader) { - custom_shader_ = shader; +void ImageQuad::SetCustomShader(const std::string& asset_name) { + custom_shader_ = Engine::Get().GetCustomShader(asset_name); custom_uniforms_.clear(); } diff --git a/src/engine/image_quad.h b/src/engine/image_quad.h index e735a70..d483774 100644 --- a/src/engine/image_quad.h +++ b/src/engine/image_quad.h @@ -28,7 +28,7 @@ class ImageQuad final : public Animatable { void AutoScale(); - void SetCustomShader(Shader* shader); + void SetCustomShader(const std::string& asset_name); template void SetCustomUniform(const std::string& name, T value) {