diff --git a/assets/renderer_logo.png b/assets/renderer_logo.png new file mode 100644 index 0000000..802488e Binary files /dev/null and b/assets/renderer_logo.png differ diff --git a/src/demo/menu.cc b/src/demo/menu.cc index 2bfd91c..83f98cf 100644 --- a/src/demo/menu.cc +++ b/src/demo/menu.cc @@ -11,6 +11,7 @@ #include "engine/font.h" #include "engine/image.h" #include "engine/input_event.h" +#include "engine/renderer/renderer.h" #include "engine/sound.h" #include "demo/demo.h" @@ -33,9 +34,10 @@ const Vector4f kColorNormal = {1, 1, 1, 1}; const Vector4f kColorHighlight = {20, 20, 20, 1}; constexpr float kBlendingSpeed = 0.12f; -const Vector4f kColorSwitch[2] = {{0.003f, 0.91f, 0.99f, 1}, - {0.33f, 0.47, 0.51f, 1}}; +const std::array kColorSwitch = {Vector4f{0.003f, 0.91f, 0.99f, 1}, + Vector4f{0.33f, 0.47, 0.51f, 1}}; +const Vector4f kColorFadeIn = {1, 1, 1, 1}; const Vector4f kColorFadeOut = {1, 1, 1, 0}; constexpr float kFadeSpeed = 0.2f; @@ -150,7 +152,8 @@ bool Menu::Initialize() { } game->saved_data().root()["audio"] = toggle_audio_.enabled(); }, - true, game->saved_data().root().get("audio", Json::Value(true)).asBool()); + true, game->saved_data().root().get("audio", Json::Value(true)).asBool(), + kColorFadeOut, kColorSwitch); toggle_audio_.image().SetPosition(Engine::Get().GetScreenSize() * Vector2f(0, -0.25f)); toggle_audio_.image().Scale(0.7f); @@ -162,7 +165,8 @@ bool Menu::Initialize() { game->SetEnableMusic(toggle_music_.enabled()); game->saved_data().root()["music"] = toggle_music_.enabled(); }, - true, game->saved_data().root().get("music", Json::Value(true)).asBool()); + true, game->saved_data().root().get("music", Json::Value(true)).asBool(), + kColorFadeOut, kColorSwitch); toggle_music_.image().SetPosition(Engine::Get().GetScreenSize() * Vector2f(0, -0.25f)); toggle_music_.image().Scale(0.7f); @@ -177,7 +181,8 @@ bool Menu::Initialize() { game->saved_data().root()["vibration"] = toggle_vibration_.enabled(); }, true, - game->saved_data().root().get("vibration", Json::Value(true)).asBool()); + game->saved_data().root().get("vibration", Json::Value(true)).asBool(), + kColorFadeOut, kColorSwitch); toggle_vibration_.image().SetPosition(Engine::Get().GetScreenSize() * Vector2f(0, -0.25f)); toggle_vibration_.image().Scale(0.7f); @@ -188,6 +193,21 @@ bool Menu::Initialize() { toggle_vibration_.image().Translate( {toggle_music_.image().GetSize().x / 2, 0}); + renderer_type_.Create( + "renderer_logo", {2, 1}, 0, 1, + [&] { + Engine::Get().CreateRenderer(renderer_type_.enabled() + ? RendererType::kVulkan + : RendererType::kOpenGL); + renderer_type_.SetEnabled( + (Engine::Get().GetRendererType() == RendererType::kVulkan)); + }, + true, Engine::Get().GetRendererType() == RendererType::kVulkan, + kColorFadeOut, {Vector4f{1, 1, 1, 1}, Vector4f{1, 1, 1, 1}}); + renderer_type_.image().PlaceToBottomOf(toggle_music_.image()); + renderer_type_.image().Translate(toggle_music_.image().GetPosition() * + Vector2f(0, 1.1f)); + high_score_value_ = game->GetHighScore(); high_score_.Create("high_score_tex"); @@ -226,7 +246,7 @@ bool Menu::Initialize() { starting_wave_.image().SetFrame(start_from_wave_ / 3); click_.Play(false); }, - false, true); + false, true, kColorFadeOut, kColorSwitch); wave_up_.image().Scale(1.5f); return true; @@ -236,6 +256,7 @@ void Menu::OnInputEvent(std::unique_ptr event) { if (toggle_audio_.OnInputEvent(event.get()) || toggle_music_.OnInputEvent(event.get()) || toggle_vibration_.OnInputEvent(event.get()) || + renderer_type_.OnInputEvent(event.get()) || (wave_up_.image().IsVisible() && wave_up_.OnInputEvent(event.get()))) return; @@ -350,6 +371,7 @@ void Menu::Show() { toggle_audio_.Show(); toggle_music_.Show(); toggle_vibration_.Show(); + renderer_type_.Show(); Demo* game = static_cast(Engine::Get().GetGame()); @@ -410,6 +432,7 @@ void Menu::Hide(Closure cb) { toggle_audio_.Hide(); toggle_music_.Hide(); toggle_vibration_.Hide(); + renderer_type_.Hide(); if (starting_wave_.image().IsVisible()) { starting_wave_.Hide(); @@ -425,6 +448,7 @@ bool Menu::CreateRenderResources() { Engine::Get().SetImageSource("buttons_tex", "menu_icons.png"); Engine::Get().SetImageSource("high_score_tex", std::bind(&Menu::CreateHighScoreImage, this)); + Engine::Get().SetImageSource("renderer_logo", "renderer_logo.png"); Engine::Get().SetImageSource("wave_up_tex", []() -> std::unique_ptr { const Font& font = static_cast(Engine::Get().GetGame())->GetFont(); @@ -520,16 +544,20 @@ void Menu::Button::Create(const std::string& asset_name, int frame2, Closure pressed_cb, bool switch_control, - bool enabled) { + bool enabled, + const Vector4f& fade_out_color, + const std::array& switch_color) { frame1_ = frame1; frame2_ = frame2; pressed_cb_ = std::move(pressed_cb); switch_control_ = switch_control; enabled_ = enabled; + fade_out_color_ = fade_out_color; + switch_color_ = switch_color; image_.Create(asset_name, num_frames); image_.SetFrame(enabled ? frame1 : frame2); - image_.SetColor(kColorFadeOut); + image_.SetColor(fade_out_color_); image_.SetZOrder(41); image_.SetVisible(false); @@ -562,14 +590,14 @@ bool Menu::Button::OnInputEvent(eng::InputEvent* event) { void Menu::Button::Show() { animator_.SetVisible(true); - animator_.SetBlending(enabled_ ? kColorSwitch[0] : kColorSwitch[1], + animator_.SetBlending(enabled_ ? switch_color_[0] : switch_color_[1], kBlendingSpeed); animator_.Play(Animator::kBlending, false); animator_.SetEndCallback(Animator::kBlending, nullptr); } void Menu::Button::Hide() { - animator_.SetBlending(kColorFadeOut, kBlendingSpeed); + animator_.SetBlending(fade_out_color_, kBlendingSpeed); animator_.Play(Animator::kBlending, false); animator_.SetEndCallback(Animator::kBlending, [&]() -> void { animator_.SetVisible(false); }); @@ -579,7 +607,7 @@ void Menu::Button::SetEnabled(bool enable) { if (switch_control_) { enabled_ = enable; image_.SetFrame(enabled_ ? frame1_ : frame2_); - image_.SetColor(enabled_ ? kColorSwitch[0] : kColorSwitch[1]); + image_.SetColor(enabled_ ? switch_color_[0] : switch_color_[1]); } } diff --git a/src/demo/menu.h b/src/demo/menu.h index 894490c..9a42216 100644 --- a/src/demo/menu.h +++ b/src/demo/menu.h @@ -55,13 +55,17 @@ class Menu { int frame2, base::Closure pressed_cb, bool switch_control, - bool enabled); + bool enabled, + const base::Vector4f& fade_out_color, + const std::array& switch_color); bool OnInputEvent(eng::InputEvent* event); void Show(); void Hide(); + void SetEnabled(bool enable); + eng::ImageQuad& image() { return image_; }; bool enabled() const { return enabled_; } @@ -77,7 +81,8 @@ class Menu { bool enabled_ = false; base::Vector2f tap_pos_[2] = {{0, 0}, {0, 0}}; - void SetEnabled(bool enable); + base::Vector4f fade_out_color_; + std::array switch_color_; }; class Radio { @@ -126,6 +131,7 @@ class Menu { Button toggle_audio_; Button toggle_music_; Button toggle_vibration_; + Button renderer_type_; size_t high_score_value_ = 0; diff --git a/src/engine/engine.cc b/src/engine/engine.cc index fc7e0e8..3622287 100644 --- a/src/engine/engine.cc +++ b/src/engine/engine.cc @@ -106,7 +106,7 @@ void Engine::Initialize() { thread_pool_.Initialize(); - CreateRenderer(true); + CreateRenderer(RendererType::kVulkan); // Normalize viewport. if (GetScreenWidth() > GetScreenHeight()) { @@ -201,23 +201,27 @@ void Engine::RemoveAnimator(Animator* animator) { } } -void Engine::CreateRenderer(bool vulkan) { - if ((dynamic_cast(renderer_.get()) && vulkan) || - (dynamic_cast(renderer_.get()) && !vulkan)) +void Engine::CreateRenderer(RendererType type) { + if ((dynamic_cast(renderer_.get()) && + type == RendererType::kVulkan) || + (dynamic_cast(renderer_.get()) && + type == RendererType::kOpenGL)) return; - if (vulkan) + if (type == RendererType::kVulkan) renderer_ = std::make_unique(std::bind(&Engine::ContextLost, this)); - else + else if (type == RendererType::kOpenGL) renderer_ = std::make_unique(std::bind(&Engine::ContextLost, this)); + else + NOTREACHED; bool result = renderer_->Initialize(platform_); - if (!result && vulkan) { + if (!result && type == RendererType::kVulkan) { LOG << "Failed to initialize " << renderer_->GetDebugName() << " renderer."; LOG << "Fallback to OpenGL renderer."; - CreateRenderer(false); + CreateRenderer(RendererType::kOpenGL); return; } CHECK(result) << "Failed to initialize " << renderer_->GetDebugName() @@ -227,6 +231,12 @@ void Engine::CreateRenderer(bool vulkan) { ContextLost(); } +RendererType Engine::GetRendererType() { + if (renderer_) + return renderer_->GetRendererType(); + return RendererType::kUnknown; +} + void Engine::Exit() { platform_->Exit(); } diff --git a/src/engine/engine.h b/src/engine/engine.h index d694e00..bbbe77f 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -20,17 +20,18 @@ namespace eng { class Animator; class AudioMixer; +class Drawable; class Font; class Game; -class Drawable; -class InputEvent; +class Geometry; class Image; class ImageQuad; +class InputEvent; +class Platform; class Renderer; -class Geometry; class Shader; class Texture; -class Platform; +enum class RendererType; class Engine : public PlatformObserver { public: @@ -49,7 +50,8 @@ class Engine : public PlatformObserver { void AddAnimator(Animator* animator); void RemoveAnimator(Animator* animator); - void CreateRenderer(bool vulkan); + void CreateRenderer(RendererType type); + RendererType GetRendererType(); void Exit(); diff --git a/src/engine/renderer/opengl/renderer_opengl.h b/src/engine/renderer/opengl/renderer_opengl.h index bf7c798..be582be 100644 --- a/src/engine/renderer/opengl/renderer_opengl.h +++ b/src/engine/renderer/opengl/renderer_opengl.h @@ -86,6 +86,8 @@ class RendererOpenGL final : public Renderer { const char* GetDebugName() final { return "OpenGL"; } + RendererType GetRendererType() final { return RendererType::kOpenGL; } + private: struct GeometryOpenGL { struct Element { diff --git a/src/engine/renderer/renderer.h b/src/engine/renderer/renderer.h index 352852f..a539ee0 100644 --- a/src/engine/renderer/renderer.h +++ b/src/engine/renderer/renderer.h @@ -15,6 +15,8 @@ class ShaderSource; class Mesh; class Platform; +enum class RendererType { kUnknown, kVulkan, kOpenGL }; + class Renderer { public: const unsigned kInvalidId = 0; @@ -82,6 +84,8 @@ class Renderer { virtual const char* GetDebugName() = 0; + virtual RendererType GetRendererType() { return RendererType::kUnknown; } + protected: struct TextureCompression { unsigned etc1 : 1; diff --git a/src/engine/renderer/vulkan/renderer_vulkan.h b/src/engine/renderer/vulkan/renderer_vulkan.h index 3412053..6addbef 100644 --- a/src/engine/renderer/vulkan/renderer_vulkan.h +++ b/src/engine/renderer/vulkan/renderer_vulkan.h @@ -69,6 +69,8 @@ class RendererVulkan final : public Renderer { const char* GetDebugName() final { return "Vulkan"; } + RendererType GetRendererType() final { return RendererType::kVulkan; } + private: // VkBuffer or VkImage with allocator. template