diff --git a/examples/ExampleApps/BillboardExampleApp.cpp b/examples/ExampleApps/BillboardExampleApp.cpp index 068f812..dd7088f 100644 --- a/examples/ExampleApps/BillboardExampleApp.cpp +++ b/examples/ExampleApps/BillboardExampleApp.cpp @@ -31,10 +31,9 @@ namespace OpenVulkano class BillboardExampleAppImpl final : public BillboardExampleApp { public: - void Init() override { - auto engineConfig = OpenVulkano::EngineConfiguration::GetEngineConfiguration(); + auto engineConfig = EngineConfiguration::GetEngineConfiguration(); engineConfig->SetPreferFramebufferFormatSRGB(false); engineConfig->SetFpsCap(0); // monitor's refresh rate engineConfig->SetVSync(true); @@ -44,17 +43,17 @@ namespace OpenVulkano m_cam.Init(70, 16, 9, 0.1f, 100); m_scene.SetCamera(&m_cam); - m_quadBillboardShader.AddShaderProgram(OpenVulkano::ShaderProgramType::VERTEX, "Shader/billboardFromSinglePoint"); - m_quadBillboardShader.AddShaderProgram(OpenVulkano::ShaderProgramType::GEOMETRY, "Shader/billboardFromSinglePoint"); - m_quadBillboardShader.AddShaderProgram(OpenVulkano::ShaderProgramType::FRAGMENT, "Shader/basic"); - m_quadBillboardShader.AddVertexInputDescription(OpenVulkano::Vertex::GetVertexInputDescription()); + m_quadBillboardShader.AddShaderProgram(ShaderProgramType::VERTEX, "Shader/billboardFromSinglePoint"); + m_quadBillboardShader.AddShaderProgram(ShaderProgramType::GEOMETRY, "Shader/billboardFromSinglePoint"); + m_quadBillboardShader.AddShaderProgram(ShaderProgramType::FRAGMENT, "Shader/basic"); + m_quadBillboardShader.AddVertexInputDescription(Vertex::GetVertexInputDescription()); m_quadBillboardShader.AddDescriptorSetLayoutBinding(Texture::DESCRIPTOR_SET_LAYOUT_BINDING); m_quadBillboardShader.AddDescriptorSetLayoutBinding(UniformBuffer::DESCRIPTOR_SET_LAYOUT_BINDING, 4); m_quadBillboardShader.topology = Topology::POINT_LIST; - m_shader.AddShaderProgram(OpenVulkano::ShaderProgramType::VERTEX, "Shader/billboard"); - m_shader.AddShaderProgram(OpenVulkano::ShaderProgramType::FRAGMENT, "Shader/basic"); - m_shader.AddVertexInputDescription(OpenVulkano::Vertex::GetVertexInputDescription()); + m_shader.AddShaderProgram(ShaderProgramType::VERTEX, "Shader/billboard"); + m_shader.AddShaderProgram(ShaderProgramType::FRAGMENT, "Shader/basic"); + m_shader.AddVertexInputDescription(Vertex::GetVertexInputDescription()); m_shader.AddDescriptorSetLayoutBinding(Texture::DESCRIPTOR_SET_LAYOUT_BINDING); m_shader.AddDescriptorSetLayoutBinding(UniformBuffer::DESCRIPTOR_SET_LAYOUT_BINDING, 4); m_shader.cullMode = CullMode::NONE; @@ -85,13 +84,13 @@ namespace OpenVulkano geo->vertices[0].color = glm::vec4(1, 1, 1, 1); else geo->vertices[0].color = glm::vec4(1, 0, 0, 1); - m_nodesPool[i].SetMatrix(Math::Utils::translate(glm::mat4x4(1.f), Vector3f(-5 + std::rand() % 5, -5 + std::rand() % 5, std::rand() % 5))); + m_nodesPool[i].SetMatrix(translate(glm::mat4x4(1.f), Vector3f(-5 + std::rand() % 5, -5 + std::rand() % 5, std::rand() % 5))); m_drawablesPool[i].Init(&m_quadBillboardShader, geo, &m_texturedMat, &m_uniBuffer); } else { *geo = GeometryFactory::MakePyramid(1, 1, glm::vec4(0, 1, 0, 1)); - m_nodesPool[i].SetMatrix(Math::Utils::translate(glm::mat4x4(1.f), Vector3f(-5 + std::rand() % 5, -5 + std::rand() % 5, -std::rand() % 10))); + m_nodesPool[i].SetMatrix(translate(glm::mat4x4(1.f), Vector3f(-5 + std::rand() % 5, -5 + std::rand() % 5, -std::rand() % 10))); m_drawablesPool[i].Init(&m_shader, geo, &m_mat, &m_uniBuffer); } m_scene.GetRoot()->AddChild(&m_nodesPool[i]); @@ -105,8 +104,8 @@ namespace OpenVulkano m_camController.SetPosition({ 0, 0, 5 }); m_camController.SetBoostFactor(5); - std::shared_ptr m_perfInfo = - std::make_shared(); + std::shared_ptr m_perfInfo = + std::make_shared(); m_ui.AddElement(m_perfInfo); GetGraphicsAppManager()->GetRenderer()->SetActiveUi(&m_ui); } @@ -125,7 +124,7 @@ namespace OpenVulkano BillboardControlBlock m_bbContolBlock; PerspectiveCamera m_cam; UniformBuffer m_uniBuffer; - OpenVulkano::FreeCamCameraController m_camController; + FreeCamCameraController m_camController; Material m_mat; Material m_texturedMat; Shader m_shader; @@ -133,9 +132,9 @@ namespace OpenVulkano std::vector m_drawablesPool; std::vector m_nodesPool; Vector3f_SIMD m_position = { 0, 0, -10 }; - OpenVulkano::Scene::UI::SimpleUi m_ui; + UI::SimpleUi m_ui; std::vector m_geo; - std::shared_ptr m_perfInfo; + std::shared_ptr m_perfInfo; }; IGraphicsApp* BillboardExampleApp::Create() { return new BillboardExampleAppImpl(); } diff --git a/examples/ExampleApps/CubesExampleApp.cpp b/examples/ExampleApps/CubesExampleApp.cpp index 391f548..d77ad3e 100644 --- a/examples/ExampleApps/CubesExampleApp.cpp +++ b/examples/ExampleApps/CubesExampleApp.cpp @@ -36,7 +36,7 @@ namespace OpenVulkano { OpenVulkano::Scene::Scene scene; PerspectiveCamera cam; - OpenVulkano::FreeCamCameraController camController; + FreeCamCameraController camController; Material mat; Shader shader; std::vector drawablesPool; @@ -44,13 +44,13 @@ namespace OpenVulkano Vector3f_SIMD position = {0, 0, -10}; std::vector m_geos; - OpenVulkano::Scene::UI::SimpleUi m_ui; - std::shared_ptr m_perfInfo; + UI::SimpleUi m_ui; + std::shared_ptr m_perfInfo; public: void Init() override { - auto engineConfig = OpenVulkano::EngineConfiguration::GetEngineConfiguration(); + auto engineConfig = EngineConfiguration::GetEngineConfiguration(); //engineConfig->SetNumThreads(4); engineConfig->SetPreferFramebufferFormatSRGB(false); @@ -58,9 +58,9 @@ namespace OpenVulkano scene.Init(); cam.Init(70, 16, 9, 0.1f, 100); scene.SetCamera(&cam); - shader.AddShaderProgram(OpenVulkano::ShaderProgramType::VERTEX, "Shader/basic"); - shader.AddShaderProgram(OpenVulkano::ShaderProgramType::FRAGMENT, "Shader/basic"); - shader.AddVertexInputDescription(OpenVulkano::Vertex::GetVertexInputDescription()); + shader.AddShaderProgram(ShaderProgramType::VERTEX, "Shader/basic"); + shader.AddShaderProgram(ShaderProgramType::FRAGMENT, "Shader/basic"); + shader.AddVertexInputDescription(Vertex::GetVertexInputDescription()); drawablesPool.resize(GEOS); m_geos.reserve(GEOS); for (uint32_t i = 0; i < GEOS; i++) @@ -78,7 +78,7 @@ namespace OpenVulkano scene.GetRoot()->AddChild(&nodesPool[i]); if (i < DYNAMIC) nodesPool[i].SetUpdateFrequency(UpdateFrequency::Always); nodesPool[i].AddDrawable(&drawablesPool[std::rand() % GEOS]); - nodesPool[i].SetMatrix(Math::Utils::translate(glm::mat4x4(1), Vector3f((std::rand() % 10000) / 1000.0f - 5, (std::rand() % 10000) / 1000.0f - 5, (std::rand() % 10000) / 1000.0f - 5))); + nodesPool[i].SetMatrix(translate(glm::mat4x4(1), Vector3f((std::rand() % 10000) / 1000.0f - 5, (std::rand() % 10000) / 1000.0f - 5, (std::rand() % 10000) / 1000.0f - 5))); } GetGraphicsAppManager()->GetRenderer()->SetScene(&scene); @@ -87,7 +87,7 @@ namespace OpenVulkano camController.SetDefaultKeybindings(); camController.SetPosition({0, 0, 10}); - std::shared_ptr m_perfInfo = std::make_shared(); + std::shared_ptr m_perfInfo = std::make_shared(); m_ui.AddElement(m_perfInfo); GetGraphicsAppManager()->GetRenderer()->SetActiveUi(&m_ui); } @@ -96,7 +96,7 @@ namespace OpenVulkano { for (uint32_t i = 0; i < DYNAMIC; i++) { - nodesPool[i].SetMatrix(glm::translate(glm::mat4x4(1), glm::vec3((std::rand() % 10000) / 1000.0f - 5, (std::rand() % 10000) / 1000.0f - 5, (std::rand() % 10000) / 1000.0f - 5))); + nodesPool[i].SetMatrix(translate(glm::mat4x4(1), glm::vec3((std::rand() % 10000) / 1000.0f - 5, (std::rand() % 10000) / 1000.0f - 5, (std::rand() % 10000) / 1000.0f - 5))); } camController.Tick(); diff --git a/examples/ExampleApps/LabelDrawableExampleApp.cpp b/examples/ExampleApps/LabelDrawableExampleApp.cpp index a076eaf..cfe0566 100644 --- a/examples/ExampleApps/LabelDrawableExampleApp.cpp +++ b/examples/ExampleApps/LabelDrawableExampleApp.cpp @@ -7,14 +7,8 @@ #include "LabelDrawableExampleApp.hpp" #include "Scene/Scene.hpp" #include "Scene/Shader/Shader.hpp" -#include "Scene/Geometry.hpp" #include "Scene/TextDrawable.hpp" -#include "Scene/GeometryFactory.hpp" -#include "Scene/Material.hpp" -#include "Scene/Vertex.hpp" -#include "Scene/SimpleDrawable.hpp" #include "Scene/UI/PerformanceInfo.hpp" -#include "Scene/UniformBuffer.hpp" #include "Scene/Prefabs/LabelDrawable.hpp" #include "Input/InputManager.hpp" #include "Host/GraphicsAppManager.hpp" @@ -23,9 +17,7 @@ #include "Math/Math.hpp" #include "Base/EngineConfiguration.hpp" #include "Controller/FreeCamCameraController.hpp" -#include "Image/ImageLoaderPng.hpp" #include "Scene/SdfFontAtlasGenerator.hpp" -#include "Scene/IFontAtlasGenerator.hpp" #include #ifdef _WIN32 @@ -45,9 +37,7 @@ namespace OpenVulkano void Init() override { - auto engineConfig = OpenVulkano::EngineConfiguration::GetEngineConfiguration(); - engineConfig->SetNumThreads(1); - engineConfig->SetPreferFramebufferFormatSRGB(false); + EngineConfiguration::GetEngineConfiguration()->SetPreferFramebufferFormatSRGB(false); std::srand(1); // Fix seed for random numbers m_scene.Init(); @@ -63,7 +53,6 @@ namespace OpenVulkano m_nodesPool.resize(N); m_drawablesPool.reserve(N); - BillboardControlBlock billboardSettings; LabelDrawableSettings labelSettings; for (int i = 0; i < N; i++) @@ -74,12 +63,11 @@ namespace OpenVulkano } else { - labelSettings.hasRoundedCorners = (i % 2 == 0 ? 0 : 1); - labelSettings.hasArrow = (i % 2 == 0 ? 1 : 0); + labelSettings.hasRoundedCorners = i & 1; + labelSettings.hasArrow = i % 2 == 0; } - bool isBillboard = (i % 2 == 0 ? 1 : 0); - LabelDrawable& label = m_drawablesPool.emplace_back(textDrawable.GetAtlasData(), labelSettings, isBillboard); - label.SetBillboardSettings(billboardSettings); + labelSettings.isBillboard = i % 2 == 0; + LabelDrawable& label = m_drawablesPool.emplace_back(textDrawable.GetAtlasData(), labelSettings); label.AddText(texts[i]); if (i == 2) { @@ -90,7 +78,7 @@ namespace OpenVulkano } m_drawablesPool[i].SetIsHittable(true); m_scene.GetRoot()->AddChild(&m_nodesPool[i]); - m_nodesPool[i].SetMatrix(Math::Utils::translate(glm::mat4x4(1.f), Vector3f(-5 + std::rand() % 5, -5 + std::rand() % 5, -std::rand() % 10))); + m_nodesPool[i].SetMatrix(Math::Utils::translate(glm::mat4x4(1.f), Vector3f(5 - std::rand() % 10, 5 - std::rand() % 10, 5 - std::rand() % 10))); m_nodesPool[i].AddDrawable(&m_drawablesPool[i]); } @@ -100,8 +88,7 @@ namespace OpenVulkano m_camController.SetPosition({ 0, 0, 10 }); m_camController.SetBoostFactor(5); - std::shared_ptr m_perfInfo = - std::make_shared(); + std::shared_ptr m_perfInfo = std::make_shared(); m_ui.AddElement(m_perfInfo); GetGraphicsAppManager()->GetRenderer()->SetActiveUi(&m_ui); } @@ -116,12 +103,12 @@ namespace OpenVulkano private: OpenVulkano::Scene::Scene m_scene; PerspectiveCamera m_cam; - OpenVulkano::FreeCamCameraController m_camController; + FreeCamCameraController m_camController; std::vector m_drawablesPool; std::vector m_nodesPool; Vector3f_SIMD m_position = { 0, 0, -10 }; - OpenVulkano::Scene::UI::SimpleUi m_ui; - std::shared_ptr m_perfInfo; + UI::SimpleUi m_ui; + std::shared_ptr m_perfInfo; }; IGraphicsApp* LabelDrawableExampleApp::Create() { return new LabelDrawableExampleAppImpl(); } diff --git a/examples/ExampleApps/MovingCubeApp.cpp b/examples/ExampleApps/MovingCubeApp.cpp index d33dcd8..2fa39e3 100644 --- a/examples/ExampleApps/MovingCubeApp.cpp +++ b/examples/ExampleApps/MovingCubeApp.cpp @@ -17,16 +17,12 @@ #include "Scene/SimpleAnimationController.hpp" #include "Scene/SequenceAnimationController.hpp" #include "Scene/MorphableCameraController.hpp" -#include "Scene/PlaneCameraController.hpp" #include "Scene/UI/PerformanceInfo.hpp" #include "Scene/SceneIntersectionTestController.hpp" -#include "Input/InputManager.hpp" #include "Host/GraphicsAppManager.hpp" -#include "Base/EngineConfiguration.hpp" #include "Base/Logger.hpp" #include "Controller/FreeCamCameraController.hpp" #include "Scene/Prefabs/LabelDrawable.hpp" -#include "Scene/SimpleDrawable.hpp" #include "Scene/Ray.hpp" #define USE_PLANE_CAM_CONTROL 0 diff --git a/examples/ExampleApps/TextExampleApp.cpp b/examples/ExampleApps/TextExampleApp.cpp index 9ed0549..f5b11ee 100644 --- a/examples/ExampleApps/TextExampleApp.cpp +++ b/examples/ExampleApps/TextExampleApp.cpp @@ -9,12 +9,8 @@ #include "Scene/Shader/Shader.hpp" #include "Scene/Geometry.hpp" #include "Scene/TextDrawable.hpp" -#include "Scene/GeometryFactory.hpp" -#include "Scene/Material.hpp" #include "Scene/Vertex.hpp" -#include "Scene/SimpleDrawable.hpp" #include "Scene/UI/PerformanceInfo.hpp" -#include "Scene/UniformBuffer.hpp" #include "Input/InputManager.hpp" #include "Host/GraphicsAppManager.hpp" #include "Host/GLFW/WindowGLFW.hpp" @@ -22,9 +18,7 @@ #include "Math/Math.hpp" #include "Base/EngineConfiguration.hpp" #include "Controller/FreeCamCameraController.hpp" -#include "Image/ImageLoaderPng.hpp" #include "Scene/SdfFontAtlasGenerator.hpp" -#include "Scene/IFontAtlasGenerator.hpp" #include "Scene/BitmapFontAtlasGenerator.hpp" #include @@ -45,11 +39,9 @@ namespace OpenVulkano class TextExampleAppImpl final : public TextExampleApp { public: - void Init() override { - auto engineConfig = OpenVulkano::EngineConfiguration::GetEngineConfiguration(); - engineConfig->SetPreferFramebufferFormatSRGB(false); + EngineConfiguration::GetEngineConfiguration()->SetPreferFramebufferFormatSRGB(false); std::srand(1); // Fix seed for random numbers m_scene.Init(); @@ -62,8 +54,7 @@ namespace OpenVulkano texts.push_back(std::make_pair("\u0410\u0411\u0412\u041F", TextConfig())); texts.push_back(std::make_pair("Unsupported glyphs \u1E30\u1E31 are coming", TextConfig())); texts.push_back(std::make_pair("This is first line\nSecond gg line\nThird G line", TextConfig())); - texts[0].second.applyBorder = true; - texts[1].second.backgroundColor.a = 1; + texts[1].second.backgroundColor.a = 255; const int N = texts.size(); auto& resourceLoader = ResourceLoader::GetInstance(); @@ -73,6 +64,7 @@ namespace OpenVulkano if constexpr (CREATE_BITMAP_ATLAS) { + // ReSharper disable once CppDFAUnreachableCode std::set s = BitmapFontAtlasGenerator::LoadAllGlyphs(fontPath); BitmapFontAtlasGenerator generator; generator.GenerateAtlas(fontPath, s); @@ -98,32 +90,27 @@ namespace OpenVulkano #if defined(MSDFGEN_AVAILABLE) && CREATE_NEW_ATLAS if (i < texts.size()) { - t = new TextDrawable(m_atlasGenerator.GetAtlasData(), texts[textIdx].second); - t->SetShader(&TextDrawable::GetSdfDefaultShader()); + t = new TextDrawable(m_atlasGenerator.GetAtlasData(), texts[textIdx].second); } else { - t = new TextDrawable(m_msdfAtlasGenerator.GetAtlasData(), texts[textIdx].second); - t->SetShader(&TextDrawable::GetMsdfDefaultShader()); + t = new TextDrawable(m_msdfAtlasGenerator.GetAtlasData(), texts[textIdx].second); } #else int xOffset = 0; if (i < N) { - t = new TextDrawable(sdfMetadataInfo, texts[textIdx].second); - t->SetShader(&TextDrawable::GetSdfDefaultShader()); + t = new TextDrawable(sdfMetadataInfo, texts[textIdx].second); xOffset = -5; } else if (i >= N && i < N * 2) { - t = new TextDrawable(msdfMetadataInfo, texts[textIdx].second); - t->SetShader(&TextDrawable::GetMsdfDefaultShader()); + t = new TextDrawable(msdfMetadataInfo, texts[textIdx].second); xOffset = 15; } else { - t = new TextDrawable(bitmapMetadataInfo, texts[textIdx].second); - t->SetShader(&TextDrawable::GetBitmapDefaultShader()); + t = new TextDrawable(bitmapMetadataInfo, texts[textIdx].second); xOffset = 35; } // OR use separate texture + metadata file @@ -139,10 +126,10 @@ namespace OpenVulkano //TextDrawable* t = new TextDrawable(metadataInfo, &tex, texts[i].second); #endif // MSDFGEN_AVAILABLE t->GenerateText(texts[textIdx].first); - m_drawablesPool[i] = t; + m_drawablesPool[i].reset(t); m_nodesPool[i].Init(); m_nodesPool[i].SetMatrix(Math::Utils::translate(glm::mat4x4(1.f), Vector3f(xOffset, 2 - textIdx * 2, 0))); - m_nodesPool[i].AddDrawable(m_drawablesPool[i]); + m_nodesPool[i].AddDrawable(m_drawablesPool[i].get()); m_scene.GetRoot()->AddChild(&m_nodesPool[i]); } GetGraphicsAppManager()->GetRenderer()->SetScene(&m_scene); @@ -151,8 +138,8 @@ namespace OpenVulkano m_camController.SetPosition({ 10, 0, 15 }); m_camController.SetBoostFactor(5); - std::shared_ptr m_perfInfo = - std::make_shared(); + std::shared_ptr m_perfInfo = + std::make_shared(); m_ui.AddElement(m_perfInfo); GetGraphicsAppManager()->GetRenderer()->SetActiveUi(&m_ui); } @@ -164,26 +151,22 @@ namespace OpenVulkano void Close() override { - for (SimpleDrawable* d: m_drawablesPool) - { - d->Close(); - delete d; - } + m_drawablesPool.clear(); } private: OpenVulkano::Scene::Scene m_scene; PerspectiveCamera m_cam; - OpenVulkano::FreeCamCameraController m_camController; + FreeCamCameraController m_camController; #ifdef MSDFGEN_AVAILABLE SdfFontAtlasGenerator m_atlasGenerator; MsdfFontAtlasGenerator m_msdfAtlasGenerator; #endif - std::vector m_drawablesPool; + std::vector> m_drawablesPool; std::vector m_nodesPool; Vector3f_SIMD m_position = { 0, 0, -10 }; - OpenVulkano::Scene::UI::SimpleUi m_ui; - std::shared_ptr m_perfInfo; + UI::SimpleUi m_ui; + std::shared_ptr m_perfInfo; }; IGraphicsApp* TextExampleApp::Create() { return new TextExampleAppImpl(); } diff --git a/examples/ExampleApps/TexturedCubeExampleApp.cpp b/examples/ExampleApps/TexturedCubeExampleApp.cpp index af3ba7d..396b49f 100644 --- a/examples/ExampleApps/TexturedCubeExampleApp.cpp +++ b/examples/ExampleApps/TexturedCubeExampleApp.cpp @@ -16,7 +16,6 @@ #include "Input/InputManager.hpp" #include "Host/GraphicsAppManager.hpp" #include "Math/Math.hpp" -#include "Base/EngineConfiguration.hpp" #include "Controller/FreeCamCameraController.hpp" #include "Base/FrameMetadata.hpp" @@ -30,14 +29,14 @@ namespace OpenVulkano { OpenVulkano::Scene::Scene scene; PerspectiveCamera cam; - OpenVulkano::FreeCamCameraController camController; + FreeCamCameraController camController; Material mat; Shader shader; SimpleDrawable drawable; Node node; - OpenVulkano::Scene::UI::SimpleUi m_ui; - std::shared_ptr m_perfInfo; + UI::SimpleUi m_ui; + std::shared_ptr m_perfInfo; public: void Init() override @@ -45,9 +44,9 @@ namespace OpenVulkano scene.Init(); cam.Init(70, 16, 9, 0.1f, 100); scene.SetCamera(&cam); - shader.AddShaderProgram(OpenVulkano::ShaderProgramType::VERTEX, "Shader/basic"); - shader.AddShaderProgram(OpenVulkano::ShaderProgramType::FRAGMENT, "Shader/basicTexture"); - shader.AddVertexInputDescription(OpenVulkano::Vertex::GetVertexInputDescription()); + shader.AddShaderProgram(ShaderProgramType::VERTEX, "Shader/basic"); + shader.AddShaderProgram(ShaderProgramType::FRAGMENT, "Shader/basicTexture"); + shader.AddVertexInputDescription(Vertex::GetVertexInputDescription()); shader.AddDescriptorSetLayoutBinding(Texture::DESCRIPTOR_SET_LAYOUT_BINDING); static Geometry geo = GeometryFactory::MakeCube(); mat.texture = &Texture::PLACEHOLDER; @@ -63,7 +62,7 @@ namespace OpenVulkano //camController.SetDefaultKeybindings(); camController.SetPosition({0, 0, 2}); - m_perfInfo = std::make_shared(); + m_perfInfo = std::make_shared(); m_ui.AddElement(m_perfInfo); GetGraphicsAppManager()->GetRenderer()->SetActiveUi(&m_ui); } @@ -73,9 +72,9 @@ namespace OpenVulkano { t += CURRENT_FRAME.frameTime * 0.25; - Math::Matrix4f rotation = Math::Utils::rotate(t, Math::Vector3f_SIMD{1.0f, 0.0f, 0.0f}); - rotation *= Math::Utils::rotate(t, Math::Vector3f_SIMD{0.0f, 1.0f, 0.0f}); - rotation *= Math::Utils::rotate(t, Math::Vector3f_SIMD{0.0f, 0.0f, 1.0f}); + Matrix4f rotation = Math::Utils::rotate(t, Vector3f_SIMD{1.0f, 0.0f, 0.0f}); + rotation *= Math::Utils::rotate(t, Vector3f_SIMD{0.0f, 1.0f, 0.0f}); + rotation *= Math::Utils::rotate(t, Vector3f_SIMD{0.0f, 0.0f, 1.0f}); node.SetMatrix(rotation); camController.Tick(); diff --git a/examples/main.cpp b/examples/main.cpp index f10b998..263c96f 100644 --- a/examples/main.cpp +++ b/examples/main.cpp @@ -20,40 +20,32 @@ using namespace OpenVulkano; int main(int argc, char** argv) { - std::vector examples; - for (const auto& e : EXAMPLE_APPS) + int selectedExample = -1; + if (argc == 2) { - examples.emplace_back(e.first); + selectedExample = strtol(argv[1], nullptr, 10); } - - int selectedExample = 0; - ftxui::MenuOption option; - auto screen = ftxui::ScreenInteractive::TerminalOutput(); - screen.ForceHandleCtrlC(true); - //screen.ForceHandleCtrlZ(true); - option.on_enter = screen.ExitLoopClosure(); - auto menu = ftxui::Menu(&examples, &selectedExample, option); - bool shouldExit = false; - menu |= ftxui::CatchEvent( - [&](ftxui::Event event) + if (selectedExample < 0) { - if (event == ftxui::Event::CtrlC || event == ftxui::Event::CtrlZ) + std::vector examples; + for (const auto& e : EXAMPLE_APPS) { - screen.ExitLoopClosure()(); - shouldExit = true; + examples.emplace_back(e.first); } - return false; - }); - screen.Loop(menu); - if (shouldExit) - { - return 0; - } + ftxui::MenuOption option; + auto screen = ftxui::ScreenInteractive::TerminalOutput(); + bool shouldExit = true; + option.on_enter = [&]() { shouldExit = false; screen.ExitLoopClosure()(); }; + auto menu = ftxui::Menu(&examples, &selectedExample, option); + screen.Loop(menu); - if (selectedExample >= examples.size()) - { - throw std::runtime_error("Invalid menu selection!"); + if (shouldExit) return 0; + + if (selectedExample >= examples.size()) + { + throw std::runtime_error("Invalid menu selection!"); + } } std::unique_ptr app(EXAMPLE_APPS[selectedExample].second()); diff --git a/openVulkanoCpp/Base/ICloseable.hpp b/openVulkanoCpp/Base/ICloseable.hpp deleted file mode 100644 index 07f143a..0000000 --- a/openVulkanoCpp/Base/ICloseable.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -namespace OpenVulkano -{ - class ICloseable - { - public: - virtual ~ICloseable() = default; - - virtual void Close() = 0; - }; -} \ No newline at end of file diff --git a/openVulkanoCpp/Base/IGraphicsApp.hpp b/openVulkanoCpp/Base/IGraphicsApp.hpp index c282416..4055b5e 100644 --- a/openVulkanoCpp/Base/IGraphicsApp.hpp +++ b/openVulkanoCpp/Base/IGraphicsApp.hpp @@ -7,7 +7,6 @@ #pragma once #include "ITickable.hpp" -#include "ICloseable.hpp" #include "Version.hpp" #include @@ -15,7 +14,7 @@ namespace OpenVulkano { class IGraphicsAppManager; - class IGraphicsApp : public ITickable, public ICloseable + class IGraphicsApp : public ITickable { private: IGraphicsAppManager* m_manager = nullptr; @@ -25,6 +24,7 @@ namespace OpenVulkano virtual void Init() = 0; virtual void InitPostGraphics() {} + virtual void Close() {} virtual void CloseFinalize() {} [[nodiscard]] IGraphicsAppManager* GetGraphicsAppManager() const { return m_manager; } void SetGraphicsAppManager(IGraphicsAppManager* manager) { m_manager = manager; } diff --git a/openVulkanoCpp/Base/IPlatform.hpp b/openVulkanoCpp/Base/IPlatform.hpp index d6c99d4..65fc847 100644 --- a/openVulkanoCpp/Base/IPlatform.hpp +++ b/openVulkanoCpp/Base/IPlatform.hpp @@ -1,7 +1,6 @@ #pragma once #include "ITickable.hpp" -#include "ICloseable.hpp" #include "UI/IWindow.hpp" namespace OpenVulkano @@ -12,11 +11,11 @@ namespace OpenVulkano PlatformInitFailedException(char const* const message) : runtime_error(message) {} }; - class IPlatform : public ITickable, public ICloseable + class IPlatform : public ITickable { public: virtual void Init() = 0; - + virtual void Close() = 0; virtual IWindow* MakeWindow() = 0; }; } diff --git a/openVulkanoCpp/Base/Render/IRenderer.hpp b/openVulkanoCpp/Base/Render/IRenderer.hpp index 59d8dd7..63cce17 100644 --- a/openVulkanoCpp/Base/Render/IRenderer.hpp +++ b/openVulkanoCpp/Base/Render/IRenderer.hpp @@ -8,7 +8,6 @@ #include "IResourceManager.hpp" #include "Base/ITickable.hpp" -#include "Base/ICloseable.hpp" #include "Scene/Scene.hpp" #include "Scene/UI/UI.hpp" #include @@ -18,12 +17,13 @@ namespace OpenVulkano class IWindow; class IGraphicsAppManager; - class IRenderer : public ITickable, public ICloseable + class IRenderer : public ITickable { public: virtual ~IRenderer() = default; virtual void Init(IGraphicsAppManager* graphicsAppManager, IWindow* window) = 0; + virtual void Close() = 0; virtual std::string GetMainRenderDeviceName() = 0; virtual void Resize(uint32_t newWidth, uint32_t newHeight) = 0; diff --git a/openVulkanoCpp/Base/UI/IWindow.hpp b/openVulkanoCpp/Base/UI/IWindow.hpp index 876cd19..4b7c868 100644 --- a/openVulkanoCpp/Base/UI/IWindow.hpp +++ b/openVulkanoCpp/Base/UI/IWindow.hpp @@ -8,7 +8,6 @@ #include "Math/Math.hpp" #include "Base/PlatformEnums.hpp" -#include "Base/ICloseable.hpp" #include #include @@ -36,12 +35,13 @@ namespace OpenVulkano bool resizeable = true; }; - class IWindow : public ICloseable + class IWindow { public: - ~IWindow() override = default; + virtual ~IWindow() = default; virtual void Init(RenderAPI::RenderApi renderApi) = 0; + virtual void Close() = 0; virtual bool WindowHasBeenDestroyed() const = 0; virtual void SetWindowHasBeenDestroyed() = 0; diff --git a/openVulkanoCpp/Controller/CameraController.hpp b/openVulkanoCpp/Controller/CameraController.hpp index 80bfa2d..171e140 100644 --- a/openVulkanoCpp/Controller/CameraController.hpp +++ b/openVulkanoCpp/Controller/CameraController.hpp @@ -7,7 +7,6 @@ #pragma once #include "Base/ITickable.hpp" -#include "Base/ICloseable.hpp" namespace OpenVulkano { @@ -16,7 +15,7 @@ namespace OpenVulkano class Camera; } - class CameraController : public ITickable, ICloseable + class CameraController : public ITickable { Scene::Camera* m_camera; @@ -30,7 +29,7 @@ namespace OpenVulkano virtual void Init(Scene::Camera* camera) { m_camera = camera; } - void Close() override { m_camera = nullptr; } + virtual void Close() { m_camera = nullptr; } void SetCamera(Scene::Camera* camera) { m_camera = camera; } diff --git a/openVulkanoCpp/Data/Containers/String.hpp b/openVulkanoCpp/Data/Containers/String.hpp index 9e69c3f..4233df0 100644 --- a/openVulkanoCpp/Data/Containers/String.hpp +++ b/openVulkanoCpp/Data/Containers/String.hpp @@ -105,7 +105,14 @@ namespace OpenVulkano String& Trim() noexcept { return TrimBack().TrimFront(); } - [[nodiscard]] String Trim() const { return Trim(); } + [[nodiscard]] String Trim() const + { + size_t start = m_string.find_first_not_of(" \t\n\r"); + if (start == std::string::npos) start = 0; + size_t end = m_string.find_last_not_of(" \t\n\r"); + if (end == std::string::npos) end = m_string.size(); + return { m_string.substr(start, end - start + 1) }; + } String& TrimFront() noexcept { diff --git a/openVulkanoCpp/Scene/FreetypeHelper.hpp b/openVulkanoCpp/Extensions/FreetypeHelper.hpp similarity index 100% rename from openVulkanoCpp/Scene/FreetypeHelper.hpp rename to openVulkanoCpp/Extensions/FreetypeHelper.hpp diff --git a/openVulkanoCpp/Host/GLFW/InputProviderGLFW.hpp b/openVulkanoCpp/Host/GLFW/InputProviderGLFW.hpp index 2e9a2b9..3ca8fe2 100644 --- a/openVulkanoCpp/Host/GLFW/InputProviderGLFW.hpp +++ b/openVulkanoCpp/Host/GLFW/InputProviderGLFW.hpp @@ -7,7 +7,6 @@ #pragma once #include "Base/ITickable.hpp" -#include "Base/ICloseable.hpp" #include "Base/IPlatform.hpp" #include "InputDeviceGLFW.hpp" #include @@ -18,7 +17,7 @@ namespace OpenVulkano { class WindowGLFW; - class InputProviderGLFW final : public ITickable, public ICloseable + class InputProviderGLFW final : public ITickable { friend WindowGLFW; static InputProviderGLFW* INSTANCE; @@ -32,7 +31,7 @@ namespace OpenVulkano public: void Init(); - void Close() override; + virtual void Close(); void PreTick(); diff --git a/openVulkanoCpp/Input/InputDevice.hpp b/openVulkanoCpp/Input/InputDevice.hpp index 9649a67..ff50491 100644 --- a/openVulkanoCpp/Input/InputDevice.hpp +++ b/openVulkanoCpp/Input/InputDevice.hpp @@ -6,12 +6,11 @@ #pragma once -#include "Base/ICloseable.hpp" #include "InputKey.hpp" namespace OpenVulkano::Input { - class InputDevice : public ICloseable + class InputDevice { InputDeviceType deviceType = InputDeviceType::UNKNOWN; int index = -1; @@ -38,11 +37,11 @@ namespace OpenVulkano::Input [[nodiscard]] virtual bool ReadButtonDown(int16_t key) const = 0; public: - ~InputDevice() override = default; + virtual ~InputDevice() = default; virtual void Tick() {} - void Close() override + virtual void Close() { this->deviceType = InputDeviceType::UNKNOWN; this->index = -1; diff --git a/openVulkanoCpp/Math/AABB.hpp b/openVulkanoCpp/Math/AABB.hpp index 9fddbdb..9c68237 100644 --- a/openVulkanoCpp/Math/AABB.hpp +++ b/openVulkanoCpp/Math/AABB.hpp @@ -14,101 +14,111 @@ namespace OpenVulkano::Math /** * \brief A class that represents an axis aligned bounding box */ - class AABB final : public Range + template + class AABB_T final : public Range { public: - AABB() : Range(Math::Vector3f(INFINITY), Math::Vector3f(-INFINITY)) {} + AABB_T() : Range(T(INFINITY), T(-INFINITY)) {} - AABB(const Math::Vector3f& min, const Math::Vector3f& max) : Range(min, max) {} + AABB_T(const T& min, const T& max) : Range(min, max) {} - AABB(const Vector3f& point) : Range(point, point) + AABB_T(const T& point) : Range(point, point) {} - AABB(const Vector3f& point, float radius) : Range(point - radius, point + radius) + AABB_T(const T& point, float radius) : Range(point - radius, point + radius) {} /** * \brief Initiates the AABB to a single point (min=max=point) * \param point The point that should be used as min and max of the AABB */ - void Init(const Math::Vector3f& point) + void Init(const T& point) { - min = max = point; + Range::min = Range::max = point; } - void Init(const Math::Vector3f& min, const Math::Vector3f& max) + void Init(const T& min, const T& max) { this->min = min; this->max = max; } - void Init(const Math::Vector3f& point, float radius) + void Init(const T& point, float radius) { - min = point - radius; - max = point + radius; + Range::min = point - radius; + Range::max = point + radius; } /** * \brief Initiates the AABB from some other AABB * \param other The other AABB that should be copied */ - void Init(const AABB& other) + void Init(const AABB_T& other) { - min = other.GetMin(); - max = other.GetMax(); + Range::min = other.GetMin(); + Range::max = other.GetMax(); } - void Grow(const Math::Vector3f& point) + void Grow(const T& point) { - min = Math::Utils::min(min, point); - max = Math::Utils::max(max, point); + Range::min = Math::Utils::min(Range::min, point); + Range::max = Math::Utils::max(Range::max, point); } - void Grow(const AABB& otherAABB) + void Grow(const AABB_T& otherAABB) { - min = Math::Utils::min(min, otherAABB.GetMin()); - max = Math::Utils::max(max, otherAABB.GetMax()); + Range::min = Math::Utils::min(Range::min, otherAABB.GetMin()); + Range::max = Math::Utils::max(Range::max, otherAABB.GetMax()); } - void Grow(const AABB& otherAABB, Math::Matrix4f transformation) + void Grow(const AABB_T& otherAABB, Math::Matrix4f transformation) { //TODO } - [[nodiscard]] Math::Vector3f GetDiagonal() const + [[nodiscard]] T GetDiagonal() const { - return GetSize(); + return Range::GetSize(); } - [[nodiscard]] Math::Vector3f GetCenter() const + [[nodiscard]] T GetCenter() const { - return min + (GetDiagonal() * 0.5f); + return Range::min + (GetDiagonal() * 0.5f); + } + + [[nodiscard]] bool Covers(const AABB_T& other) const + { + return other.IsCovered(*this); + } + + [[nodiscard]] bool IsCovered(const AABB_T& other) const + { + return Math::Utils::all(Math::Utils::greaterThanEqual(other.GetMax(), Range::max)) && Math::Utils::all(Math::Utils::greaterThanEqual(Range::min, other.GetMin())); } /** - * \brief Checks if the AABB overlaps with an other AABB + * \brief Checks if the AABB overlaps with another AABB * \param other The other AABB that should be checked * \return true if the AABB overlaps with the other, false if not */ - [[nodiscard]] bool IsOverlapping(const AABB& other) const + [[nodiscard]] bool IsOverlapping(const AABB_T& other) const { - return !(other.min.x > max.x || other.max.x < min.x || other.min.y > max.y || - other.max.y < min.y || other.min.z > max.z || other.max.z < min.z); + return Math::Utils::all(Math::Utils::lessThanEqual(Range::min, other.GetMax())) && Math::Utils::all(Math::Utils::greaterThanEqual(Range::max, other.GetMin())); } - [[nodiscard]] bool InBounds(const Math::Vector3f& position) const + [[nodiscard]] bool InBounds(const T& position) const { - return Math::Utils::all(Math::Utils::lessThanEqual(min, position)) && Math::Utils::all(Math::Utils::lessThanEqual(position, max)); + return Math::Utils::all(Math::Utils::lessThanEqual(Range::min, position)) && Math::Utils::all(Math::Utils::lessThanEqual(position, Range::max)); } - [[nodiscard]] bool Inside(const Math::Vector3f& position) const + [[nodiscard]] bool Inside(const T& position) const { - return Math::Utils::all(Math::Utils::lessThan(min, position)) && Math::Utils::all(Math::Utils::lessThan(position, max)); + return Math::Utils::all(Math::Utils::lessThan(Range::min, position)) && Math::Utils::all(Math::Utils::lessThan(position, Range::max)); } [[nodiscard]] bool IsEmpty() const { - return min == Math::Vector3f(INFINITY) && max == Math::Vector3f(-INFINITY); + return Range::min == T(INFINITY) && Range::max == T(-INFINITY); } /** @@ -116,8 +126,13 @@ namespace OpenVulkano::Math */ void Reset() { - min = Math::Vector3f(INFINITY); - max = Math::Vector3f(-INFINITY); + Range::min = T(INFINITY); + Range::max = T(-INFINITY); } + + AABB_T& operator +=(const AABB_T& other) { Grow(other); return *this; } }; + + typedef AABB_T AABB; + typedef AABB_T AABB2f; } diff --git a/openVulkanoCpp/Math/Math.hpp b/openVulkanoCpp/Math/Math.hpp index a6f0f03..7f0f9ce 100644 --- a/openVulkanoCpp/Math/Math.hpp +++ b/openVulkanoCpp/Math/Math.hpp @@ -52,6 +52,12 @@ namespace OpenVulkano::Math } return angle; } + + template + constexpr void SortPair(T& e1, T& e2) + { + if (e1 > e2) std::swap(e1, e2); + } } template using Matrix2_SIMD = glm::tmat2x2; @@ -177,3 +183,15 @@ glm::vec operator / (const float lhs, const glm::vec& rhs) { return lhs / glm::vec(rhs); } + +template>> +glm::vec operator * (const float lhs, const glm::vec& rhs) +{ + return lhs * glm::vec(rhs); +} + +template>> +glm::vec operator * (const glm::vec& lhs, const T rhs) +{ + return lhs * static_cast(rhs); +} diff --git a/openVulkanoCpp/Scene/AtlasData.hpp b/openVulkanoCpp/Scene/AtlasData.hpp index ed75309..be784ec 100644 --- a/openVulkanoCpp/Scene/AtlasData.hpp +++ b/openVulkanoCpp/Scene/AtlasData.hpp @@ -12,6 +12,7 @@ #include "Scene/Texture.hpp" #include #include +#include namespace OpenVulkano::Scene { @@ -34,15 +35,22 @@ namespace OpenVulkano::Scene BITMAP, UNKNOWN }; - static constexpr std::string_view DEFAULT_FG_SHADERS[] = { "Shader/text", "Shader/msdfText" }; - public: - FontAtlasType(Type type) : m_type(type) {} - Type GetType() const { return m_type; } - const std::string_view& GetDefaultFragmentShader() const + static constexpr std::string_view DEFAULT_FG_SHADERS[] = { "Shader/sdfText", "Shader/msdfText", "Shader/text" }; + + constexpr FontAtlasType(Type type) : m_type(type) {} + + [[nodiscard]] constexpr Type GetType() const { return m_type; } + + [[nodiscard]] constexpr auto GetName() const { return magic_enum::enum_name(m_type); } + + [[nodiscard]] constexpr const std::string_view& GetDefaultFragmentShader() const { return DEFAULT_FG_SHADERS[static_cast(m_type)]; } + + [[nodiscard]] constexpr operator Type() const { return m_type; } + private: Type m_type; }; @@ -51,7 +59,7 @@ namespace OpenVulkano::Scene { // vertical difference between baselines double lineHeight = 0; - int16_t atlasType = FontAtlasType::UNKNOWN; + FontAtlasType atlasType = FontAtlasType::UNKNOWN; }; struct AtlasData @@ -60,6 +68,8 @@ namespace OpenVulkano::Scene AtlasMetadata meta; Unique img; Texture texture; + + operator bool() const { return !glyphs.empty() && texture.textureBuffer; } }; } \ No newline at end of file diff --git a/openVulkanoCpp/Scene/Drawable.hpp b/openVulkanoCpp/Scene/Drawable.hpp index 2c24b0d..42c9bdb 100644 --- a/openVulkanoCpp/Scene/Drawable.hpp +++ b/openVulkanoCpp/Scene/Drawable.hpp @@ -6,7 +6,6 @@ #pragma once -#include "Base/ICloseable.hpp" #include "Scene/IRayIntersectable.hpp" #include "DrawEncoder.hpp" #include @@ -27,7 +26,7 @@ namespace OpenVulkano::Scene BACKGROUND = 0, MAIN, TRANSPARENT, POST }; - class Drawable : public ICloseable, public IRayIntersectable + class Drawable : public IRayIntersectable { std::vector m_nodes; Scene* m_scene = nullptr; @@ -43,7 +42,7 @@ namespace OpenVulkano::Scene ~Drawable() override {/* if (m_scene) Drawable::Close();*/ } - void Close() override; + virtual void Close(); void SetShader(Shader* shader) { m_shader = shader; } diff --git a/openVulkanoCpp/Scene/FontAtlasGeneratorBase.hpp b/openVulkanoCpp/Scene/FontAtlasGeneratorBase.hpp index c4eae22..0c4ff78 100644 --- a/openVulkanoCpp/Scene/FontAtlasGeneratorBase.hpp +++ b/openVulkanoCpp/Scene/FontAtlasGeneratorBase.hpp @@ -7,30 +7,31 @@ #pragma once #include "IFontAtlasGenerator.hpp" +#include "AtlasData.hpp" #include "Math/AABB.hpp" -#include "FreetypeHelper.hpp" +#include "Extensions/FreetypeHelper.hpp" #include -#include namespace OpenVulkano::Scene { class FontAtlasGeneratorBase : public IFontAtlasGenerator { + protected: + int m_channelsCount; + std::shared_ptr m_atlasData; + public: - FontAtlasGeneratorBase(int channelsCount) : m_channelsCount(channelsCount) {} + FontAtlasGeneratorBase(const int channelsCount) : m_channelsCount(channelsCount) {} void SaveAtlasMetadataInfo(const std::string& outputFile, bool packIntoSingleFile = true) const override; - std::shared_ptr GetAtlasData() const { return m_atlasData; } - int GetAtlasChannelsCount() const { return m_channelsCount; } - static std::set LoadAllGlyphs(const std::variant>& data); + [[nodiscard]] const std::shared_ptr& GetAtlasData() const override { return m_atlasData; } + [[nodiscard]] int GetAtlasChannelsCount() const { return m_channelsCount; } + [[nodiscard]] static std::set LoadAllGlyphs(const std::variant>& data); protected: void SavePng(std::string output) const; void SetupAtlasData(Math::Vector2ui textureResolution, double lineHeight, FontAtlasType::Type atlasType); void SetGlyphData(GlyphInfo& info, Math::Vector2d bearing, Math::Vector2d size, const Math::AABB& aabb, double advance); - static std::string GetFreetypeErrorDescription(FT_Error error); - static std::pair InitFreetype(const std::variant>& source); - protected: - int m_channelsCount; - std::shared_ptr m_atlasData; + [[nodiscard]] static std::string GetFreetypeErrorDescription(FT_Error error); + [[nodiscard]] static std::pair InitFreetype(const std::variant>& source); }; } \ No newline at end of file diff --git a/openVulkanoCpp/Scene/Geometry.hpp b/openVulkanoCpp/Scene/Geometry.hpp index 5522ac5..cd62b18 100644 --- a/openVulkanoCpp/Scene/Geometry.hpp +++ b/openVulkanoCpp/Scene/Geometry.hpp @@ -6,7 +6,6 @@ #pragma once -#include "Base/ICloseable.hpp" #include "Base/Render/RenderResource.hpp" #include "Math/AABB.hpp" #include "Base/Utils.hpp" @@ -22,7 +21,7 @@ namespace OpenVulkano UINT16 = sizeof(uint16_t), UINT32 = sizeof(uint32_t) }; - class Geometry : public RenderResourceHolder, public ICloseable + class Geometry : public RenderResourceHolder { friend class MeshLoader; public: @@ -51,7 +50,7 @@ namespace OpenVulkano void SetIndices(const uint32_t* data, uint32_t size, uint32_t dstOffset = 0) const; - void Close() override; + virtual void Close(); void Free(); diff --git a/openVulkanoCpp/Scene/IFontAtlasGenerator.hpp b/openVulkanoCpp/Scene/IFontAtlasGenerator.hpp index cdb4094..979f723 100644 --- a/openVulkanoCpp/Scene/IFontAtlasGenerator.hpp +++ b/openVulkanoCpp/Scene/IFontAtlasGenerator.hpp @@ -6,24 +6,25 @@ #pragma once -#include "Scene/AtlasData.hpp" +#include #include #include -#include -#include #include #include namespace OpenVulkano::Scene { + struct AtlasData; + class IFontAtlasGenerator { public: + virtual ~IFontAtlasGenerator() = default; virtual void GenerateAtlas(const std::string& fontFile, const std::set& charset, const std::optional& pngOutput = std::nullopt) = 0; virtual void GenerateAtlas(const Array& fontData, const std::set& charset, const std::optional& pngOutput = std::nullopt) = 0; virtual void SaveAtlasMetadataInfo(const std::string& outputFile, bool packIntoSingleFile = true) const = 0; - virtual std::shared_ptr GetAtlasData() const = 0; + virtual const std::shared_ptr& GetAtlasData() const = 0; }; } diff --git a/openVulkanoCpp/Scene/IRayIntersectable.hpp b/openVulkanoCpp/Scene/IRayIntersectable.hpp index 0deaf91..1e4d741 100644 --- a/openVulkanoCpp/Scene/IRayIntersectable.hpp +++ b/openVulkanoCpp/Scene/IRayIntersectable.hpp @@ -13,6 +13,7 @@ namespace OpenVulkano::Scene class IRayIntersectable { public: + virtual ~IRayIntersectable() = default; virtual std::optional Intersect(const Ray& ray) const = 0; }; } diff --git a/openVulkanoCpp/Scene/Node.hpp b/openVulkanoCpp/Scene/Node.hpp index abcdcff..fb0886d 100644 --- a/openVulkanoCpp/Scene/Node.hpp +++ b/openVulkanoCpp/Scene/Node.hpp @@ -6,7 +6,6 @@ #pragma once -#include "Base/ICloseable.hpp" #include "Base/Render/RenderResource.hpp" #include "Math/Math.hpp" #include "Math/Pose.hpp" @@ -20,7 +19,7 @@ namespace OpenVulkano::Scene { class Scene; - class Node : public RenderResourceHolder, public ICloseable + class Node : public RenderResourceHolder { friend Scene; @@ -41,11 +40,11 @@ namespace OpenVulkano::Scene Node(const Math::Matrix4f& pose); - ~Node() noexcept override; + virtual ~Node() noexcept; void Init(); - void Close() override; + virtual void Close(); void AddChild(Node* node); diff --git a/openVulkanoCpp/Scene/Prefabs/LabelDrawable.cpp b/openVulkanoCpp/Scene/Prefabs/LabelDrawable.cpp index e1ddfef..16040bd 100644 --- a/openVulkanoCpp/Scene/Prefabs/LabelDrawable.cpp +++ b/openVulkanoCpp/Scene/Prefabs/LabelDrawable.cpp @@ -7,27 +7,77 @@ #include "LabelDrawable.hpp" #include "Scene/TextDrawable.hpp" #include "Scene/DrawEncoder.hpp" +#include "Scene/Vertex.hpp" +#include "Scene/Shader/Shader.hpp" #include "Scene/IFontAtlasGenerator.hpp" #include "Base/Logger.hpp" #include namespace OpenVulkano::Scene { - using namespace Math; + namespace + { + Shader MakeLabelBgShader(const bool billboard) + { + Shader backgroundShader; + backgroundShader.AddShaderProgram(ShaderProgramType::VERTEX, billboard ? "Shader/labelBillboard" : "Shader/label"); + backgroundShader.AddShaderProgram(ShaderProgramType::FRAGMENT, "Shader/label"); + backgroundShader.AddDescriptorSetLayoutBinding(Texture::DESCRIPTOR_SET_LAYOUT_BINDING, 2); + backgroundShader.AddDescriptorSetLayoutBinding(UniformBuffer::DESCRIPTOR_SET_LAYOUT_BINDING, 4); + backgroundShader.topology = Topology::TRIANGLE_STRIP; + backgroundShader.cullMode = CullMode::NONE; + return backgroundShader; + } - LabelDrawable::LabelDrawable(const std::shared_ptr& atlasData, const LabelDrawableSettings& settings, - bool isBillboard) - : Drawable(DrawEncoder::GetDrawEncoder(), DrawPhase::MAIN) + Shader MakeLabelTextShader(const FontAtlasType type, const bool billboard) + { + Shader shader = TextDrawable::MakeDefaultShader(type); + shader.depthCompareOp = CompareOp::LESS_OR_EQUAL; + shader.EnableDepthBias(); + if (billboard) + { + for (auto& program : shader.shaderPrograms) + { + if (program.type == ShaderProgramType::VERTEX) + { + program.name = "Shader/textBillboard"; + break; + } + } + DescriptorSetLayoutBinding billboardUniformBinding = UniformBuffer::DESCRIPTOR_SET_LAYOUT_BINDING; + shader.AddDescriptorSetLayoutBinding(billboardUniformBinding, 4); + shader.depthBiasConstant = 0.01f; + } + return shader; + } + + Shader BACKGROUND_SHADER = MakeLabelBgShader(false); + Shader BACKGROUND_BILLBOARD_SHADER = MakeLabelBgShader(true); + std::array TEXT_SHADERS = { + MakeLabelTextShader(FontAtlasType::SDF, false), + MakeLabelTextShader(FontAtlasType::SDF, true), + MakeLabelTextShader(FontAtlasType::MSDF, false), + MakeLabelTextShader(FontAtlasType::MSDF, true), + MakeLabelTextShader(FontAtlasType::BITMAP, false), + MakeLabelTextShader(FontAtlasType::BITMAP, true), + }; + + Shader* GetTextShader(const FontAtlasType type, const bool billboard) + { + return &TEXT_SHADERS[static_cast(type) << 1 | billboard]; + } + } + + LabelDrawable::LabelDrawable(const std::shared_ptr& atlasData, const LabelDrawableSettings& settings) + : Drawable(DrawEncoder::GetDrawEncoder(), DrawPhase::MAIN), m_atlasData(atlasData) + , m_labelBuffer(sizeof(LabelUniformData), &m_labelData, 4) { if (atlasData->glyphs.empty() || !atlasData->texture.size) { throw std::runtime_error("Can't create label drawable. Either glyphs or texture is empty"); } - m_atlasData = atlasData; - m_isBillboard = isBillboard; SetLabelSettings(settings); - SetupShaders(); - SetupBuffers(); + SetShader(IsBillboard() ? &BACKGROUND_BILLBOARD_SHADER : &BACKGROUND_SHADER); } void LabelDrawable::SetLabelSettings(const LabelDrawableSettings& settings) @@ -43,124 +93,27 @@ namespace OpenVulkano::Scene void LabelDrawable::AddText(const std::string& text, const TextConfig& config) { - if (text.empty()) - { - return; - } + if (text.empty()) return; TextDrawable& textDrawable = m_texts.emplace_back(m_atlasData, config); - // do not render glyph's background - textDrawable.GetConfig().backgroundColor.a = 0; - textDrawable.SetShader(&m_textShader); + textDrawable.GetConfig().backgroundColor.a = 0; // do not render glyph's background double lineHeight = m_atlasData->meta.lineHeight; - textDrawable.GenerateText(text, m_position); - RecalculateBbox(textDrawable.GetBoundingBox()); + textDrawable.SetShader(GetTextShader(m_atlasData->meta.atlasType, IsBillboard())); + m_bbox.Grow(textDrawable.GetBoundingBox()); // update position for next text entry m_position.y = m_bbox.GetMin().y - lineHeight; - const auto& min = m_bbox.GetMin(); - const auto& max = m_bbox.GetMax(); - Vertex v, v2, v3, v4; - const float offset = 0.001; - const float yOffset = m_settings.hasArrow ? m_settings.arrowLength : 0; - v.position = Vector3f(min.x - m_settings.horizontalOffset, min.y - m_settings.verticalOffset - yOffset, min.z - offset); - v2.position = Vector3f(max.x + m_settings.horizontalOffset, min.y - m_settings.verticalOffset - yOffset, min.z - offset); - v3.position = Vector3f(max.x + m_settings.horizontalOffset, max.y + m_settings.verticalOffset, min.z - offset); - v4.position = Vector3f(min.x - m_settings.horizontalOffset, max.y + m_settings.verticalOffset, min.z - offset); + Math::Vector2f padding = m_settings.padding * 2; + if (m_settings.hasArrow) padding.y += m_settings.arrowLength; - m_labelData.textSize.x = v2.position.x - v.position.x; - m_labelData.textSize.y = v3.position.y - v.position.y; - m_labelData.bboxCenter.x = (v2.position.x + v.position.x) / 2; - m_labelData.bboxCenter.y = (v3.position.y + v.position.y) / 2; - } - - void LabelDrawable::SetBillboardSettings(const BillboardControlBlock& settings) - { - m_billboardSettings = settings; + m_labelData.textSize = Math::Vector2f(m_bbox.GetSize()) + padding * 2; + m_labelData.bboxCenter = { m_bbox.GetCenter() }; + if (m_settings.hasArrow) m_labelData.bboxCenter.y -= m_settings.arrowLength; } std::optional LabelDrawable::Intersect(const Ray& ray) const { return ray.IntersectAABB(m_bbox); } - - void LabelDrawable::RecalculateBbox(const Math::AABB& other) - { - if (m_bbox.IsEmpty()) - { - m_bbox = other; - } - else - { - auto& currentMin = m_bbox.GetMin(); - auto& currentMax = m_bbox.GetMax(); - currentMin.x = std::min(currentMin.x, other.min.x); - currentMin.y = std::min(currentMin.y, other.min.y); - currentMax.x = std::max(currentMax.x, other.max.x); - currentMax.y = std::max(currentMax.y, other.max.y); - } - } - - void LabelDrawable::SetupShaders() - { - if (!m_isBillboard) - { - m_backgroundShader.AddShaderProgram(OpenVulkano::ShaderProgramType::VERTEX, "Shader/label"); - } - else - { - m_backgroundShader.AddShaderProgram(OpenVulkano::ShaderProgramType::VERTEX, "Shader/labelBillboard"); - // binding for billboard's buffer - DescriptorSetLayoutBinding binding = UniformBuffer::DESCRIPTOR_SET_LAYOUT_BINDING; - binding.stageFlags = ShaderProgramType::Type::VERTEX; - m_backgroundShader.AddDescriptorSetLayoutBinding(binding, 4); - } - m_backgroundShader.AddShaderProgram(OpenVulkano::ShaderProgramType::FRAGMENT, "Shader/label"); - m_backgroundShader.AddDescriptorSetLayoutBinding(Texture::DESCRIPTOR_SET_LAYOUT_BINDING, 2); - m_backgroundShader.AddDescriptorSetLayoutBinding(UniformBuffer::DESCRIPTOR_SET_LAYOUT_BINDING, 5); - m_backgroundShader.topology = Topology::TRIANGLE_STRIP; - m_backgroundShader.cullMode = CullMode::NONE; - SetShader(&m_backgroundShader); - - FontAtlasType fontAtlasType(static_cast(m_atlasData->meta.atlasType)); - if (!m_isBillboard) - { - m_textShader.AddShaderProgram(OpenVulkano::ShaderProgramType::VERTEX, "Shader/text"); - } - else - { - m_textShader.AddShaderProgram(OpenVulkano::ShaderProgramType::VERTEX, "Shader/billboard"); - DescriptorSetLayoutBinding billboardUniformBinding = UniformBuffer::DESCRIPTOR_SET_LAYOUT_BINDING; - billboardUniformBinding.stageFlags = ShaderProgramType::Type::VERTEX; - m_textShader.AddDescriptorSetLayoutBinding(billboardUniformBinding, 4); - } - - DescriptorSetLayoutBinding textUniformBinding = UniformBuffer::DESCRIPTOR_SET_LAYOUT_BINDING; - textUniformBinding.stageFlags = ShaderProgramType::FRAGMENT; - m_textShader.AddDescriptorSetLayoutBinding(textUniformBinding, 3); - m_textShader.AddShaderProgram(OpenVulkano::ShaderProgramType::FRAGMENT, - std::string(fontAtlasType.GetDefaultFragmentShader())); - m_textShader.AddVertexInputDescription(OpenVulkano::Vertex::GetVertexInputDescription()); - m_textShader.AddDescriptorSetLayoutBinding(Texture::DESCRIPTOR_SET_LAYOUT_BINDING, 2); - m_textShader.alphaBlend = true; - m_textShader.cullMode = CullMode::NONE; - m_textShader.depthWrite = false; - m_textShader.depthCompareOp = CompareOp::LESS_OR_EQUAL; - } - - void LabelDrawable::SetupBuffers() - { - m_billboardBuffer.size = sizeof(BillboardControlBlock); - m_billboardBuffer.data = &m_billboardSettings; - m_billboardBuffer.setId = 4; - DescriptorSetLayoutBinding binding = UniformBuffer::DESCRIPTOR_SET_LAYOUT_BINDING; - binding.stageFlags = ShaderProgramType::Type::VERTEX; - m_billboardBuffer.binding = binding; - - m_labelBuffer.size = sizeof(LabelUniformData); - m_labelBuffer.data = &m_labelData; - m_labelBuffer.setId = 5; - m_labelBuffer.binding = UniformBuffer::DESCRIPTOR_SET_LAYOUT_BINDING; - } } diff --git a/openVulkanoCpp/Scene/Prefabs/LabelDrawable.hpp b/openVulkanoCpp/Scene/Prefabs/LabelDrawable.hpp index ce29ae7..03eff25 100644 --- a/openVulkanoCpp/Scene/Prefabs/LabelDrawable.hpp +++ b/openVulkanoCpp/Scene/Prefabs/LabelDrawable.hpp @@ -6,79 +6,66 @@ #pragma once -#include "Base/Wrapper.hpp" #include "Scene/Drawable.hpp" -#include "Scene/Shader/Shader.hpp" -#include "Scene/Texture.hpp" #include "Scene/UniformBuffer.hpp" -#include "Scene/Vertex.hpp" -#include "Scene/BillboardControlBlock.hpp" #include "Math/AABB.hpp" #include "Scene/TextDrawable.hpp" #include namespace OpenVulkano::Scene { + class Shader; struct LabelDrawableSettings { Math::Vector4f backgroundColor = { 1, 0, 0, 1 }; - float horizontalOffset = 0.05f; - float verticalOffset = 0.05f; + Math::Vector2f padding = { 0.2f, 0.2f }; float cornerRadius = 0.05f; float arrowLength = 0.5f; float arrowWidth = 0.2f; - int32_t hasRoundedCorners = false; - int32_t hasArrow = false; + bool hasRoundedCorners = false; + bool hasArrow = false; + bool isBillboard = false; }; struct LabelUniformData { - Math::Vector4f textSize = { 0, 0, 0, 0 }; Math::Vector4f color = { 0, 0, 0, 0 }; - Math::Vector4f bboxCenter = { 0, 0, 0, 0 }; + Math::Vector2f textSize = {}; + Math::Vector2f bboxCenter = {}; float cornerRadius = 0.f; float arrowLength = 0.f; float arrowWidth = 0.f; int32_t hasRoundedCorners = false; int32_t hasArrow = false; + int32_t isBillboardFixedSize = false; }; class LabelDrawable final : public Drawable { public: - LabelDrawable(const std::shared_ptr& atlasData, - const LabelDrawableSettings& settings = LabelDrawableSettings(), bool isBillboard = false); + LabelDrawable(const std::shared_ptr& atlasData, const LabelDrawableSettings& settings = LabelDrawableSettings()); + void AddText(const std::string& text, const TextConfig& config = TextConfig()); void SetLabelSettings(const LabelDrawableSettings& settings); - void SetBillboardSettings(const BillboardControlBlock& settings); - void SetPosition(const Math::Vector3f& pos) { m_position = pos; } - std::list& GetTexts() { return m_texts; } - LabelDrawableSettings& GetSettings() { return m_settings; } - UniformBuffer* GetBillboardBuffer() { return &m_billboardBuffer; } - UniformBuffer* GetLabelBuffer() { return &m_labelBuffer; } - BillboardControlBlock& GetBillboardSettings() { return m_billboardSettings; } - Math::Vector3f& GetPosition() { return m_position; } - bool IsBillboard() const { return m_isBillboard; } - const Math::AABB& GetBoundingBox() const { return m_bbox; } - std::optional Intersect(const Ray& ray) const override; + void SetPosition(const Math::Vector2f& pos) { m_position = pos; } + + [[nodiscard]] std::list& GetTexts() { return m_texts; } + [[nodiscard]] LabelDrawableSettings& GetSettings() { return m_settings; } + [[nodiscard]] UniformBuffer* GetLabelBuffer() { return &m_labelBuffer; } + [[nodiscard]] Math::Vector2f& GetPosition() { return m_position; } + [[nodiscard]] bool IsBillboard() const { return m_settings.isBillboard; } + [[nodiscard]] const Math::AABB2f& GetBoundingBox() const { return m_bbox; } + + [[nodiscard]] std::optional Intersect(const Ray& ray) const override; + private: - void RecalculateBbox(const Math::AABB& other); - void SetupShaders(); - void SetupBuffers(); - private: - Shader m_backgroundShader; - UniformBuffer m_billboardBuffer; - UniformBuffer m_labelBuffer; - // list over vector to prevent memory reallocation and crash - std::list m_texts; - Shader m_textShader; LabelDrawableSettings m_settings; - LabelUniformData m_labelData; std::shared_ptr m_atlasData; - BillboardControlBlock m_billboardSettings; - Math::Vector3f m_position = { 0, 0, 0 }; - Math::AABB m_bbox; - bool m_isBillboard; + UniformBuffer m_labelBuffer; + LabelUniformData m_labelData; + std::list m_texts; // Using list instead of vector for stable iterators + Math::Vector2f m_position = { 0, 0 }; + Math::AABB2f m_bbox; }; } diff --git a/openVulkanoCpp/Scene/Ray.cpp b/openVulkanoCpp/Scene/Ray.cpp index 7e2a30c..49d9679 100644 --- a/openVulkanoCpp/Scene/Ray.cpp +++ b/openVulkanoCpp/Scene/Ray.cpp @@ -10,12 +10,9 @@ namespace { int SolveQuadraticEquation(float a, float b, float c, float& x0, float& x1) - { - float discr = b * b - 4 * a * c; - if (discr < 0) - { - return 0; - } + { + const float discr = b * b - 4 * a * c; + if (discr < 0) return 0; if (discr == 0) { x0 = x1 = (-b) / (2 * a); @@ -24,10 +21,7 @@ namespace float q = (b > 0) ? -0.5 * (b + std::sqrt(discr)) : -0.5 * (b - std::sqrt(discr)); x0 = q / a; x1 = c / q; - if (x0 > x1) - { - std::swap(x0, x1); - } + OpenVulkano::Math::Utils::SortPair(x0, x1); return 2; } }; @@ -50,10 +44,10 @@ namespace OpenVulkano::Scene std::optional Ray::IntersectTriangle(const Math::Vector3f& v0, const Math::Vector3f& v1, const Math::Vector3f& v2) const { - RayHit hitRes; float d; if (intersectRayTriangle(m_origin, m_dir, v0, v1, v2, m_baryPos, d) && d >= 0) { + RayHit hitRes; hitRes.point = (1.f - m_baryPos.x - m_baryPos.y) * v0 + m_baryPos.x * v1 + m_baryPos.y * v2; Math::Vector3f e = v1 - v0; Math::Vector3f e2 = v2 - v0; @@ -81,96 +75,73 @@ namespace OpenVulkano::Scene std::optional Ray::IntersectQuad(const Math::Vector3f& v0, const Math::Vector3f& v1, const Math::Vector3f& v2, const Math::Vector3f& v3) const { - if (auto hitRes = IntersectTriangle(v0, v1, v2)) + if (const auto hitRes = IntersectTriangle(v0, v1, v2)) { return hitRes; } - if (auto hitRes = IntersectTriangle(v0, v2, v3)) + if (const auto hitRes = IntersectTriangle(v0, v2, v3)) { return hitRes; } return {}; } + std::optional Ray::IntersectAABB(const Math::AABB2f& bbox) const + { + //TODO impl that skips z checks + return IntersectAABB(Math::AABB({bbox.GetMin(), 0}, {bbox.GetMax(), 0})); + } + std::optional Ray::IntersectAABB(const Math::AABB& bbox) const { RayHit h1, h2; const int intersections = this->IntersectAABB(bbox, h1, h2); - switch (intersections) - { - case 1: - return h1; - case 2: - return (h1.distance2 < h2.distance2) ? h1 : h2; - } + if (intersections == 1) return h1; + if (intersections == 2) return (h1.distance2 < h2.distance2) ? h1 : h2; return {}; } int Ray::IntersectAABB(const Math::AABB& bbox, RayHit& p1, RayHit& p2) const { - const auto tmin = (bbox.min - m_origin) / m_dir; - const auto tmax = (bbox.max - m_origin) / m_dir; - float txmin = tmin.x; - float txmax = tmax.x; - float tymin = tmin.y; - float tymax = tmax.y; - float tzmin = tmin.z; - float tzmax = tmax.z; + auto tmin = (bbox.min - m_origin) / m_dir; + auto tmax = (bbox.max - m_origin) / m_dir; - if (txmin > txmax) + SortPair(tmin.x, tmax.x); + SortPair(tmin.y, tmax.y); + SortPair(tmin.z, tmax.z); + + if ((tmin.x > tmax.y) || (tmin.y > tmax.x)) return 0; + + if (tmin.y > tmin.x) { - std::swap(txmin, txmax); + tmin.x = tmin.y; } - if (tymin > tymax) + if (tmax.y < tmax.x) { - std::swap(tymin, tymax); - } - if ((txmin > tymax) || (tymin > txmax)) - { - return 0; + tmax.x = tmax.y; } - if (tymin > txmin) - { - txmin = tymin; - } - if (tymax < txmax) - { - txmax = tymax; - } - - if (tzmin > tzmax) - { - std::swap(tzmin, tzmax); - } + if ((tmin.x > tmax.z) || (tmin.z > tmax.x)) return 0; - if ((txmin > tzmax) || (tzmin > txmax)) + if (tmin.z > tmin.x) { - return 0; + tmin.x = tmin.z; } - - if (tzmin > txmin) + if (tmax.z < tmax.x) { - txmin = tzmin; - } - if (tzmax < txmax) - { - txmax = tzmax; + tmax.x = tmax.z; } int intersections = 2; - if (txmin < 0) + if (tmin.x < 0) { - if (txmax < 0) - { - return 0; - } + if (tmax.x < 0) return 0; intersections--; - txmin = txmax; + tmin.x = tmax.x; } - p1.point = m_origin + txmin * m_dir; - p2.point = m_origin + txmax * m_dir; + p1.point = m_origin + tmin.x * m_dir; + p2.point = m_origin + tmax.x * m_dir; p1.distance2 = distance2(m_origin, p1.point); p2.distance2 = distance2(m_origin, p2.point); p1.normal = p2.normal = Math::Vector3f(0); @@ -179,15 +150,11 @@ namespace OpenVulkano::Scene std::optional Ray::IntersectPlane(const Math::Vector3f& pOrigin, const Math::Vector3f& pNorm) const { - RayHit hit; Math::Vector3f norm = normalize(pNorm); float d; if (intersectRayPlane(m_origin, m_dir, pOrigin, pNorm, d)) { - hit.SetDistance(d); - hit.point = m_origin + m_dir * d; - hit.normal = norm; - return hit; + return {{ m_origin + m_dir * d, norm, d, d * d }}; } return {}; } @@ -201,56 +168,36 @@ namespace OpenVulkano::Scene float x1, x2; int roots = ::SolveQuadraticEquation(a, b, c, x1, x2); - if (roots == 0) - { - return 0; - } - if (x1 > x2) - { - std::swap(x1, x2); - } - + if (roots == 0) return 0; + SortPair(x1, x2); + bool calcP2 = false; if (roots == 1) { - // ray intersects sphere behind the origin - if (x1 < 0) - { - return 0; - } - p1.point = m_origin + x1 * m_dir; - p1.distance2 = distance2(m_origin, p1.point); - p1.normal = normalize(p1.point - center); - p2 = p1; + if (x1 < 0) return 0; // ray intersects sphere behind the origin } - else if (roots == 2) + else { - // ray intersects sphere behind the origin - if (x1 < 0 && x2 < 0) - { - return 0; - } + if (x1 < 0 && x2 < 0) return 0; // ray intersects sphere behind the origin if (x1 >= 0 && x2 >= 0) { - p1.point = m_origin + x1 * m_dir; - p1.distance2 = distance2(m_origin, p1.point); - p1.normal = normalize(p1.point - center); - p2.point = m_origin + x2 * m_dir; - p2.distance2 = distance2(m_origin, p2.point); - p2.normal = normalize(p2.point - center); + calcP2 = true; } else { --roots; - if (x1 < 0) - { - x1 = x2; - } - p1.point = m_origin + x1 * m_dir; - p1.distance2 = distance2(m_origin, p1.point); - p1.normal = normalize(p1.point - center); - p2 = p1; + if (x1 < 0) x1 = x2; } } + p1.point = m_origin + x1 * m_dir; + p1.distance2 = distance2(m_origin, p1.point); + p1.normal = normalize(p1.point - center); + if (calcP2) + { + p2.point = m_origin + x2 * m_dir; + p2.distance2 = distance2(m_origin, p2.point); + p2.normal = normalize(p2.point - center); + } + else p2 = p1; return roots; } diff --git a/openVulkanoCpp/Scene/Ray.hpp b/openVulkanoCpp/Scene/Ray.hpp index 999888b..38b1f32 100644 --- a/openVulkanoCpp/Scene/Ray.hpp +++ b/openVulkanoCpp/Scene/Ray.hpp @@ -20,21 +20,32 @@ namespace OpenVulkano::Scene Math::Vector3f point; Math::Vector3f normal; float distance2; + + RayHit() : distance2(0), distance(-1) {} + + RayHit(Math::Vector3f point, Math::Vector3f normal, float distance2) + : point(point), normal(normal), distance2(distance2) + {} + + RayHit(Math::Vector3f point, Math::Vector3f normal, float distance, float distance2) + : point(point), normal(normal), distance2(distance2), distance(distance) + {} + [[nodiscard]] float GetDistance() const { - if (distance == -1) - { - distance = std::sqrt(distance2); - } + if (distance == -1) distance = std::sqrt(distance2); return distance; } + void SetDistance(float d) { this->distance = d; this->distance2 = d * d; } + bool operator==(const RayHit& other) const; bool operator!=(const RayHit& other) const; + private: mutable float distance = -1; }; @@ -66,6 +77,7 @@ namespace OpenVulkano::Scene const Math::Vector3f& n1, const Math::Vector3f& n2) const; [[nodiscard]] std::optional IntersectQuad(const Math::Vector3f& v0, const Math::Vector3f& v1, const Math::Vector3f& v2, const Math::Vector3f& v3) const; + [[nodiscard]] std::optional IntersectAABB(const Math::AABB2f& bbox) const; [[nodiscard]] std::optional IntersectAABB(const Math::AABB& bbox) const; int IntersectAABB(const Math::AABB& bbox, RayHit& p1, RayHit& p2) const; [[nodiscard]] std::optional IntersectPlane(const Math::Vector3f& pOrigin, diff --git a/openVulkanoCpp/Scene/Scene.hpp b/openVulkanoCpp/Scene/Scene.hpp index a3dc720..e83e910 100644 --- a/openVulkanoCpp/Scene/Scene.hpp +++ b/openVulkanoCpp/Scene/Scene.hpp @@ -15,7 +15,7 @@ namespace OpenVulkano { namespace Scene { - class Scene : public ICloseable + class Scene { public: Node* root; @@ -46,7 +46,7 @@ namespace OpenVulkano this->root = root; } - void Close() override + virtual void Close() { //TODO } diff --git a/openVulkanoCpp/Scene/Shader/Shader.hpp b/openVulkanoCpp/Scene/Shader/Shader.hpp index 1ff0a54..53c2594 100644 --- a/openVulkanoCpp/Scene/Shader/Shader.hpp +++ b/openVulkanoCpp/Scene/Shader/Shader.hpp @@ -6,7 +6,6 @@ #pragma once -#include "Base/ICloseable.hpp" #include "Base/Utils.hpp" #include "Base/Render/RenderResource.hpp" #include "VertexInputDescription.hpp" @@ -81,8 +80,7 @@ namespace OpenVulkano::Scene }; - - class Shader final : public RenderResourceHolder, public ICloseable + class Shader final : public RenderResourceHolder { public: std::vector shaderPrograms{}; @@ -96,9 +94,11 @@ namespace OpenVulkano::Scene bool depthTest = true; bool depthWrite = true; bool dynamicViewport = true; // If disabled the swapchains fullscreen viewport will always be used, regardless of framebuffer or viewport + bool depthBias = false; + float depthBiasClamp = 0.0f, depthBiasSlope = 0.0f, depthBiasConstant = 0.0f; Shader() = default; - ~Shader() override { Shader::Close(); } + ~Shader() { Shader::Close(); } Shader& AddShaderProgram(const ShaderProgram& shaderProgram) { @@ -128,6 +128,7 @@ namespace OpenVulkano::Scene { CheckShaderInitState(); if (bindingId < 0) bindingId = static_cast(vertexInputDescriptions.size()); + // ReSharper disable once CppDFALoopConditionNotUpdated while (bindingId > static_cast(vertexInputDescriptions.size())) { vertexInputDescriptions.emplace_back(0, 0); @@ -149,6 +150,7 @@ namespace OpenVulkano::Scene if (setId < 0) setId = static_cast(descriptorSets.size() + 2); if (setId < 2) throw std::runtime_error("Cant bind set id 0 or 1! They are used for node and camera!"); setId -= 2; + // ReSharper disable once CppDFALoopConditionNotUpdated while (setId >= static_cast(descriptorSets.size())) { descriptorSets.emplace_back(); @@ -163,7 +165,14 @@ namespace OpenVulkano::Scene pushConstantRanges.push_back(pushConstantRange); } - void Close() override + void EnableDepthBias(const float slope = -1.0, const float constant = 0.001f) + { + depthBias = true; + depthBiasSlope = slope; + depthBiasConstant = constant; + } + + void Close() { if (HasRenderResource()) GetRenderResource().Release(); diff --git a/openVulkanoCpp/Scene/Shader/VertexInputDescription.hpp b/openVulkanoCpp/Scene/Shader/VertexInputDescription.hpp index 03cb00f..1908ce7 100644 --- a/openVulkanoCpp/Scene/Shader/VertexInputDescription.hpp +++ b/openVulkanoCpp/Scene/Shader/VertexInputDescription.hpp @@ -12,6 +12,8 @@ namespace OpenVulkano { + enum class VertexStepMode : uint32_t { VERTEX = 0, INSTANCE }; + struct VertexInputParameter { uint32_t location; @@ -32,13 +34,16 @@ namespace OpenVulkano { uint32_t bindingId; uint32_t vertexSize; + VertexStepMode stepMode = VertexStepMode::VERTEX; std::vector inputParameters; VertexInputDescription(uint32_t bindingId, uint32_t vertexSize) : bindingId(bindingId), vertexSize(vertexSize) {} VertexInputDescription(uint32_t bindingId, const VertexInputDescription& vertexDescription) - : bindingId(bindingId), vertexSize(vertexDescription.vertexSize), inputParameters(vertexDescription.inputParameters) + : bindingId(bindingId), vertexSize(vertexDescription.vertexSize) + , stepMode(vertexDescription.stepMode) + , inputParameters(vertexDescription.inputParameters) { for (auto& param : inputParameters) { diff --git a/openVulkanoCpp/Scene/TextDrawable.cpp b/openVulkanoCpp/Scene/TextDrawable.cpp index adffe2b..88acca2 100644 --- a/openVulkanoCpp/Scene/TextDrawable.cpp +++ b/openVulkanoCpp/Scene/TextDrawable.cpp @@ -6,9 +6,7 @@ #include "TextDrawable.hpp" #include "Scene/Geometry.hpp" -#include "Scene/Material.hpp" -#include "Scene/Vertex.hpp" -#include "Scene/UniformBuffer.hpp" +#include "Shader/Shader.hpp" #include "Scene/IFontAtlasGenerator.hpp" #include "Base/Logger.hpp" #include "Host/ResourceLoader.hpp" @@ -20,89 +18,58 @@ namespace OpenVulkano::Scene { - Shader& TextDrawable::GetSdfDefaultShader() + namespace { - static bool once = true; - static Shader sdfDefaultShader; - if (once) - { - sdfDefaultShader.AddShaderProgram(OpenVulkano::ShaderProgramType::VERTEX, "Shader/sdfText"); - sdfDefaultShader.AddShaderProgram(OpenVulkano::ShaderProgramType::FRAGMENT, "Shader/sdfText"); - sdfDefaultShader.AddVertexInputDescription(OpenVulkano::Vertex::GetVertexInputDescription()); - sdfDefaultShader.AddDescriptorSetLayoutBinding(Texture::DESCRIPTOR_SET_LAYOUT_BINDING); - DescriptorSetLayoutBinding desc = UniformBuffer::DESCRIPTOR_SET_LAYOUT_BINDING; - desc.stageFlags = ShaderProgramType::FRAGMENT; - sdfDefaultShader.AddDescriptorSetLayoutBinding(desc); - sdfDefaultShader.alphaBlend = true; - sdfDefaultShader.cullMode = CullMode::NONE; - once = false; - } - return sdfDefaultShader; + constexpr uint32_t MISSING_GLYPH_SYMBOL = '?'; + + Shader DEFAULT_SHADER_BITMAP = TextDrawable::MakeDefaultShader(FontAtlasType::BITMAP); + Shader DEFAULT_SHADER_SDF = TextDrawable::MakeDefaultShader(FontAtlasType::SDF); + Shader DEFAULT_SHADER_MSDF = TextDrawable::MakeDefaultShader(FontAtlasType::MSDF); } - Shader& TextDrawable::GetMsdfDefaultShader() + Shader TextDrawable::MakeDefaultShader(const FontAtlasType type) { - static bool once = true; - static Shader msdfDefaultShader; - if (once) - { - msdfDefaultShader.AddShaderProgram(OpenVulkano::ShaderProgramType::VERTEX, "Shader/sdfText"); - msdfDefaultShader.AddShaderProgram(OpenVulkano::ShaderProgramType::FRAGMENT, "Shader/msdfText"); - msdfDefaultShader.AddVertexInputDescription(OpenVulkano::Vertex::GetVertexInputDescription()); - msdfDefaultShader.AddDescriptorSetLayoutBinding(Texture::DESCRIPTOR_SET_LAYOUT_BINDING); - DescriptorSetLayoutBinding desc = UniformBuffer::DESCRIPTOR_SET_LAYOUT_BINDING; - desc.stageFlags = ShaderProgramType::FRAGMENT; - msdfDefaultShader.AddDescriptorSetLayoutBinding(desc); - msdfDefaultShader.alphaBlend = true; - msdfDefaultShader.cullMode = CullMode::NONE; - once = false; - } - return msdfDefaultShader; - } - - Shader& TextDrawable::GetBitmapDefaultShader() - { - static bool once = true; - static Shader bitmapDefaultShader; - if (once) - { - bitmapDefaultShader.AddShaderProgram(OpenVulkano::ShaderProgramType::VERTEX, "Shader/text"); - bitmapDefaultShader.AddShaderProgram(OpenVulkano::ShaderProgramType::FRAGMENT, "Shader/text"); - bitmapDefaultShader.AddVertexInputDescription(OpenVulkano::Vertex::GetVertexInputDescription()); - bitmapDefaultShader.AddDescriptorSetLayoutBinding(Texture::DESCRIPTOR_SET_LAYOUT_BINDING); - DescriptorSetLayoutBinding desc = UniformBuffer::DESCRIPTOR_SET_LAYOUT_BINDING; - desc.stageFlags = ShaderProgramType::FRAGMENT; - bitmapDefaultShader.AddDescriptorSetLayoutBinding(desc); - bitmapDefaultShader.alphaBlend = true; - bitmapDefaultShader.cullMode = CullMode::NONE; - once = false; - } - return bitmapDefaultShader; + Shader shader; + shader.AddShaderProgram(ShaderProgramType::VERTEX, "Shader/text"); + shader.AddShaderProgram(ShaderProgramType::FRAGMENT, std::string(type.GetDefaultFragmentShader())); + VertexInputDescription inputDesc(0, sizeof(TextGlyphVertex)); + inputDesc.AddInputParameter(DataFormat::R32G32_SFLOAT, offsetof(TextGlyphVertex, position)); + inputDesc.AddInputParameter(DataFormat::R32G32_SFLOAT, offsetof(TextGlyphVertex, position)+8); + inputDesc.AddInputParameter(DataFormat::R32G32_SFLOAT, offsetof(TextGlyphVertex, position)+16); + inputDesc.AddInputParameter(DataFormat::R32G32_SFLOAT, offsetof(TextGlyphVertex, position)+24); + inputDesc.AddInputParameter(DataFormat::R32G32_SFLOAT, offsetof(TextGlyphVertex, uv)); + inputDesc.AddInputParameter(DataFormat::R32G32_SFLOAT, offsetof(TextGlyphVertex, uv)+8); + inputDesc.AddInputParameter(DataFormat::R32G32_SFLOAT, offsetof(TextGlyphVertex, uv)+16); + inputDesc.AddInputParameter(DataFormat::R32G32_SFLOAT, offsetof(TextGlyphVertex, uv)+24); + inputDesc.AddInputParameter(DataFormat::R8G8B8A8_UNORM, offsetof(TextGlyphVertex, color)); + inputDesc.AddInputParameter(DataFormat::R8G8B8A8_UNORM, offsetof(TextGlyphVertex, background)); + inputDesc.stepMode = VertexStepMode::INSTANCE; + shader.AddVertexInputDescription(inputDesc); + shader.AddDescriptorSetLayoutBinding(Texture::DESCRIPTOR_SET_LAYOUT_BINDING); + shader.alphaBlend = true; + shader.cullMode = CullMode::NONE; + shader.topology = Topology::TRIANGLE_FAN; + return shader; } TextDrawable::TextDrawable(const TextConfig& config) - { - m_cfg = config; - m_uniBuffer.Init(sizeof(TextConfig), &m_cfg, 3); - m_uniBuffer.binding.stageFlags = ShaderProgramType::FRAGMENT; - } + : Drawable(DrawEncoder::GetDrawEncoder()), m_cfg(config) + {} TextDrawable::TextDrawable(const Array& atlasMetadata, const TextConfig& config) : TextDrawable(atlasMetadata, nullptr, config) - { - } + {} TextDrawable::TextDrawable(const std::string& atlasMetadataFile, const TextConfig& config) - : TextDrawable(OpenVulkano::Utils::ReadFile(atlasMetadataFile), nullptr, config) - { - } + : TextDrawable(Utils::ReadFile(atlasMetadataFile), nullptr, config) + {} TextDrawable::TextDrawable(const std::string& atlasMetadataFile, Texture* atlasTex, const TextConfig& config) - : TextDrawable(OpenVulkano::Utils::ReadFile(atlasMetadataFile), atlasTex, config) - { - } + : TextDrawable(Utils::ReadFile(atlasMetadataFile), atlasTex, config) + {} TextDrawable::TextDrawable(const Array& atlasMetadata, Texture* atlasTex, const TextConfig& config) + : Drawable(DrawEncoder::GetDrawEncoder()), m_cfg(config) { uint32_t isPacked; std::memcpy(&isPacked, atlasMetadata.Data() + (atlasMetadata.Size() - sizeof(uint32_t)), sizeof(uint32_t)); @@ -113,19 +80,17 @@ namespace OpenVulkano::Scene m_atlasData = std::make_shared(); if (isPacked) { - m_material.texture = &m_atlasData->texture; - m_atlasData->img = Image::IImageLoader::loadData((const uint8_t*) atlasMetadata.Data(), - offsetToMetadata); - m_material.texture->format = m_atlasData->img->dataFormat; - m_material.texture->resolution = m_atlasData->img->resolution; - m_material.texture->size = m_atlasData->img->data.Size(); - m_material.texture->textureBuffer = m_atlasData->img->data.Data(); + Texture* texture = &m_atlasData->texture; + m_atlasData->img = Image::IImageLoader::loadData(reinterpret_cast(atlasMetadata.Data()), offsetToMetadata); + texture->format = m_atlasData->img->dataFormat; + texture->resolution = m_atlasData->img->resolution; + texture->size = m_atlasData->img->data.Size(); + texture->textureBuffer = m_atlasData->img->data.Data(); } else { if (atlasTex == nullptr) { throw std::runtime_error("Atlas texture cannot be null with non-packed atlas metadata"); } m_atlasData->texture = *atlasTex; - m_material.texture = atlasTex; } // metadata info @@ -146,67 +111,47 @@ namespace OpenVulkano::Scene read_bytes += sizeof(GlyphInfo); readMetadataBytes += sizeof(GlyphInfo); } - m_cfg = config; - m_uniBuffer.Init(sizeof(TextConfig), &m_cfg, 3); - m_uniBuffer.binding.stageFlags = ShaderProgramType::FRAGMENT; if (m_atlasData->meta.atlasType == FontAtlasType::BITMAP) { - m_material.texture->m_samplerConfig = &SamplerConfig::NEAREST; + m_atlasData->texture.m_samplerConfig = &SamplerConfig::NEAREST; } } TextDrawable::TextDrawable(const std::shared_ptr& atlasData, const TextConfig& config) + : Drawable(DrawEncoder::GetDrawEncoder()), m_atlasData(atlasData), m_cfg(config) { - if (!atlasData || atlasData->glyphs.empty() || !atlasData->texture.textureBuffer) - { - throw std::runtime_error("Cannot initialize text drawable with empty atlas data"); - } - m_atlasData = atlasData; - m_cfg = config; - m_uniBuffer.Init(sizeof(TextConfig), &m_cfg, 3); - m_uniBuffer.binding.stageFlags = ShaderProgramType::FRAGMENT; + if (!atlasData || !*atlasData) throw std::runtime_error("Cannot initialize text drawable with empty atlas data"); } - void TextDrawable::GenerateText(const std::string& text, const Math::Vector3f& pos) + uint32_t TextDrawable::GetFallbackGlyph() const { - if (text.empty()) + if (m_atlasData->glyphs.find(MISSING_GLYPH_SYMBOL) != m_atlasData->glyphs.end()) { - return; + return MISSING_GLYPH_SYMBOL; } + Logger::RENDER->warn("Could not find glyph for character ? to use as fallback. Using first glyph instead"); + return m_atlasData->glyphs.begin()->first; + } + + void TextDrawable::GenerateText(const std::string& text, const Math::Vector2f& pos) + { + if (text.empty()) return; + if (m_vertexBuffer.data) throw std::runtime_error("Text has already been initialized"); + const uint32_t fallbackGlyph = GetFallbackGlyph(); m_text = text; - auto GetActualLength = [&]() - { - auto begin = text.begin(); - auto end = text.end(); - size_t len = 0; - while (begin != end) - { - uint32_t c = utf8::next(begin, end); - if (c == '\n') continue; - ++len; - } - return len; - }; - - size_t len = GetActualLength(); - m_geometry.Close(); - m_geometry.Init(len * 4, len * 6); - AtlasMetadata* meta; - std::map* symbols; - m_material.texture = &m_atlasData->texture; - symbols = &m_atlasData->glyphs; - meta = &m_atlasData->meta; + m_symbolCount = 0; + const size_t len = utf8::distance(text.begin(), text.end()); + m_vertexBuffer.Close(); + TextGlyphVertex* vertices = m_vertexBuffer.Init(len); + std::map* symbols = &m_atlasData->glyphs; + AtlasMetadata* meta = &m_atlasData->meta; double cursorX = pos.x; - auto begin = text.begin(); - auto end = text.end(); const double lineHeight = meta->lineHeight; double posY = pos.y; - int i = 0; - Math::Vector3f bmin(pos), bmax(pos); - bool firstGlyph = true; - while (begin != end) + Math::Vector3f bmin(pos, 0), bmax(pos, 0); + for (auto begin = text.begin(), end = text.end(); begin != end;) { uint32_t c = utf8::next(begin, end); if (c == '\n') @@ -215,72 +160,56 @@ namespace OpenVulkano::Scene cursorX = pos.x; continue; } + // TODO handle special chars - if (symbols->find(c) == symbols->end()) + if (!symbols->contains(c)) { - Logger::RENDER->error("Could not find glyph for character {}", c); - if (symbols->find(static_cast('?')) != symbols->end()) - { - c = static_cast('?'); - } - else - { - Logger::RENDER->error("Could not find glyph for character ? to replace glyph {}", c); - continue; - } + Logger::RENDER->warn("Could not find glyph for character {}, using fallback", c); + c = fallbackGlyph; } - uint32_t vIdx = i * 4; - uint32_t indices[] = { 1 + vIdx, 2 + vIdx, 3 + vIdx, 1 + vIdx, 3 + vIdx, 0 + vIdx }; GlyphInfo& info = symbols->at(c); - // left bottom - m_geometry.vertices[vIdx].position.x = info.xyz[0].x + cursorX; - m_geometry.vertices[vIdx].position.y = posY - info.xyz[0].y; - m_geometry.vertices[vIdx].position.z = info.xyz[0].z; - m_geometry.vertices[vIdx].textureCoordinates = Math::Vector3f(info.uv[0], 0); + for (int i = 0; i < 4; i++) + { + vertices->position[i].x = info.xyz[i].x + cursorX; + vertices->uv[i] = info.uv[i]; + if (i < 2) vertices->position[i].y = posY - info.xyz[i].y; + else vertices->position[i].y = posY + info.xyz[i].y; + vertices->color = m_cfg.textColor; + vertices->background = m_cfg.backgroundColor; + } - // right bottom - m_geometry.vertices[vIdx + 1].position.x = info.xyz[1].x + cursorX; - m_geometry.vertices[vIdx + 1].position.y = posY - info.xyz[1].y; - m_geometry.vertices[vIdx + 1].position.z = info.xyz[1].z; - m_geometry.vertices[vIdx + 1].textureCoordinates = Math::Vector3f(info.uv[1], 0); - - // top right - m_geometry.vertices[vIdx + 2].position.x = info.xyz[2].x + cursorX; - m_geometry.vertices[vIdx + 2].position.y = posY + info.xyz[2].y; - m_geometry.vertices[vIdx + 2].position.z = info.xyz[2].z; - m_geometry.vertices[vIdx + 2].textureCoordinates = Math::Vector3f(info.uv[2], 0); - - // top left - m_geometry.vertices[vIdx + 3].position.x = info.xyz[3].x + cursorX; - m_geometry.vertices[vIdx + 3].position.y = posY + info.xyz[3].y; - m_geometry.vertices[vIdx + 3].position.z = info.xyz[3].z; - m_geometry.vertices[vIdx + 3].textureCoordinates = Math::Vector3f(info.uv[3], 0); - m_geometry.SetIndices(indices, 6, 6 * i); // TODO: change to lower value(or ideally remove completely) to avoid overlapping and make less space between symbols // when setting for depth comparison operator will be available( <= ) cursorX += info.advance + 0.08; - if (firstGlyph) - { - bmin.x = m_geometry.vertices[vIdx].position.x; - firstGlyph = false; - } - bmax.x = std::max(bmax.x, m_geometry.vertices[vIdx + 1].position.x); - bmax.y = std::max(bmax.y, m_geometry.vertices[vIdx + 2].position.y); - bmin.y = std::min(bmin.y, m_geometry.vertices[vIdx + 1].position.y); - ++i; + + bmax.x = std::max(bmax.x, vertices->position[1].x); + bmax.y = std::max(bmax.y, vertices->position[2].y); + bmin.y = std::min(bmin.y, vertices->position[1].y); + vertices++; + m_symbolCount++; } + bmin.x = vertices->position[0].x; m_bbox.Init(bmin, bmax); - SimpleDrawable::Init(m_shader, &m_geometry, &m_material, &m_uniBuffer); + + if (!GetShader()) SetShader(GetDefaultShader(m_atlasData->meta.atlasType)); } void TextDrawable::SetAtlasData(const std::shared_ptr& atlasData) { - if (!atlasData || atlasData->glyphs.empty() || !atlasData->texture.textureBuffer) - { - throw std::runtime_error("Cannot initialize text drawable with empty atlas data"); - } + if (!atlasData || !*atlasData) throw std::runtime_error("Cannot initialize text drawable with empty atlas data"); m_atlasData = atlasData; } + + Shader* TextDrawable::GetDefaultShader(const FontAtlasType type) + { + switch (type) + { + case FontAtlasType::SDF: return &DEFAULT_SHADER_SDF; + case FontAtlasType::MSDF: return &DEFAULT_SHADER_MSDF; + default: Logger::RENDER->warn("No default shader for atlas type: {}", type.GetName()); + case FontAtlasType::BITMAP: return &DEFAULT_SHADER_BITMAP; + } + } } \ No newline at end of file diff --git a/openVulkanoCpp/Scene/TextDrawable.hpp b/openVulkanoCpp/Scene/TextDrawable.hpp index f8d6e3f..2dac8d8 100644 --- a/openVulkanoCpp/Scene/TextDrawable.hpp +++ b/openVulkanoCpp/Scene/TextDrawable.hpp @@ -6,62 +6,63 @@ #pragma once -#include "SimpleDrawable.hpp" +#include "Drawable.hpp" #include "Texture.hpp" -#include "Material.hpp" -#include "Geometry.hpp" -#include "UniformBuffer.hpp" +#include "VertexBuffer.hpp" #include "AtlasData.hpp" #include "Image/Image.hpp" -#include -#include namespace OpenVulkano::Scene { - class IFontAtlasGenerator; struct TextConfig { - Math::Vector4f textColor = { 1, 1, 1, 1 }; - Math::Vector4f borderColor = { 1, 0, 0, 1 }; - Math::Vector4f backgroundColor = { 0, 1, 0, 0 }; - float threshold = 0.4f; - float borderSize = 0.05f; - float smoothing = 1.f/32.f; - uint32_t applyBorder = false; - //bool sdfMultiChannel = false; + Math::Vector4uc textColor = { 255, 255, 255, 255 }; + Math::Vector4uc backgroundColor = { 0, 255, 0, 0 }; }; - class TextDrawable : public SimpleDrawable + struct TextGlyphVertex { + std::array position; + std::array uv; + Math::Vector4uc color = { 255, 255, 255, 255 }; + Math::Vector4uc background = {}; + }; + + class TextDrawable : public Drawable + { + VertexBuffer m_vertexBuffer; + std::shared_ptr m_atlasData; + Math::AABB2f m_bbox; + std::string m_text; + size_t m_symbolCount = 0; + TextConfig m_cfg; + + uint32_t GetFallbackGlyph() const; + public: - static Shader& GetSdfDefaultShader(); - static Shader& GetMsdfDefaultShader(); - static Shader& GetBitmapDefaultShader(); TextDrawable(const TextConfig& config = TextConfig()); TextDrawable(const Array& atlasMetadata, const TextConfig& config = TextConfig()); TextDrawable(const std::string& atlasMetadataFile, const TextConfig& config = TextConfig()); TextDrawable(const std::string& atlasMetadataFile, Texture* atlasTex, const TextConfig& config = TextConfig()); TextDrawable(const Array& atlasMetadata, Texture* atlasTex, const TextConfig& config = TextConfig()); TextDrawable(const std::shared_ptr& atlasData, const TextConfig& config = TextConfig()); - void GenerateText(const std::string& text, const Math::Vector3f& pos = Math::Vector3f(0.f)); + + void GenerateText(const std::string& text, const Math::Vector2f& pos = Math::Vector2f(0.f)); void SetConfig(const TextConfig& cfg) { m_cfg = cfg; } - void SetShader(Shader* shader) { m_shader = shader; } void SetAtlasData(const std::shared_ptr& atlasData); - Math::AABB& GetBoundingBox() { return m_bbox; } - TextConfig& GetConfig() { return m_cfg; } - Shader* GetShader() { return m_shader; } + + [[nodiscard]] Math::AABB2f& GetBoundingBox() { return m_bbox; } + [[nodiscard]] TextConfig& GetConfig() { return m_cfg; } [[nodiscard]] const std::string& GetText() const { return m_text; } - std::shared_ptr GetAtlasData() { return m_atlasData; } - private: - Geometry m_geometry; - Material m_material; - UniformBuffer m_uniBuffer; - std::shared_ptr m_atlasData; - Math::AABB m_bbox; - Shader* m_shader = nullptr; - std::string m_text; - TextConfig m_cfg; + [[nodiscard]] const std::shared_ptr& GetAtlasData() { return m_atlasData; } + + [[nodiscard]] VertexBuffer* GetVertexBuffer() { return &m_vertexBuffer; } + [[nodiscard]] Texture* GetTexture() { return &m_atlasData->texture; } + [[nodiscard]] size_t GetSymbolCount() const { return m_symbolCount; } + + [[nodiscard]] static Shader MakeDefaultShader(FontAtlasType type); + [[nodiscard]] static Shader* GetDefaultShader(FontAtlasType type); }; } diff --git a/openVulkanoCpp/Scene/UniformBuffer.hpp b/openVulkanoCpp/Scene/UniformBuffer.hpp index ec6370a..f975e53 100644 --- a/openVulkanoCpp/Scene/UniformBuffer.hpp +++ b/openVulkanoCpp/Scene/UniformBuffer.hpp @@ -19,11 +19,15 @@ namespace OpenVulkano::Scene DescriptorSetLayoutBinding binding; uint32_t setId; - size_t size = 0; - const void* data = nullptr; + size_t size; + const void* data; UpdateFrequency updateFrequency = UpdateFrequency::Never; bool updated = true; + UniformBuffer(size_t size = 0, const void* data = nullptr, uint32_t setId = 2, const DescriptorSetLayoutBinding& binding = DESCRIPTOR_SET_LAYOUT_BINDING) + : binding(binding), setId(setId), size(size), data(data) + {} + void Init(size_t size, const void* data, uint32_t setId = 2, const DescriptorSetLayoutBinding& binding = DESCRIPTOR_SET_LAYOUT_BINDING) { this->size = size; diff --git a/openVulkanoCpp/Scene/VertexBuffer.hpp b/openVulkanoCpp/Scene/VertexBuffer.hpp new file mode 100644 index 0000000..3655881 --- /dev/null +++ b/openVulkanoCpp/Scene/VertexBuffer.hpp @@ -0,0 +1,54 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include "Base/Render/RenderResource.hpp" +#include "Scene/UpdateFrequency.hpp" + +namespace OpenVulkano::Scene +{ + class VertexBuffer final : public RenderResourceHolder + { + public: + size_t size = 0; + const void* data = nullptr; + UpdateFrequency updateFrequency = UpdateFrequency::Never; + bool updated = true; + bool ownsMemory = true; + + ~VertexBuffer() { Close(); } + + void Init(size_t size, const void* data) + { + this->size = size; + this->data = data; + this->ownsMemory = false; + } + + void Init(size_t size) + { + this->size = size; + this->data = malloc(size); + this->ownsMemory = true; + } + + template + T* Init(size_t count) + { + Init(count * sizeof(T)); + return static_cast(const_cast(data)); + } + + void Close() + { + if (ownsMemory && data) free(const_cast(data)); + data = nullptr; + } + + UpdateFrequency GetUpdateFrequency() const { return updateFrequency; } + }; +} \ No newline at end of file diff --git a/openVulkanoCpp/Shader/label.frag b/openVulkanoCpp/Shader/label.frag index 33c8fc5..2d702d5 100644 --- a/openVulkanoCpp/Shader/label.frag +++ b/openVulkanoCpp/Shader/label.frag @@ -3,71 +3,71 @@ layout(location = 1) in vec2 texCoord; layout(location = 0) out vec4 outColor; -layout(set = 5, binding = 0) uniform LabelData +layout(set = 4, binding = 0) uniform LabelData { - vec4 textSize; - vec4 color; - vec4 bboxCenter; - float radius; - float arrowLength; - float arrowWidth; - bool hasRoundedCorners; - bool hasArrow; + vec4 color; + vec2 textSize; + vec2 bboxCenter; + float radius; + float arrowLength; + float arrowWidth; + bool hasRoundedCorners; + bool hasArrow; } labelInfo; void main() -{ - if (labelInfo.hasRoundedCorners || labelInfo.hasArrow) - { - vec2 bbox = vec2(labelInfo.textSize); - const float arrowLength = int(labelInfo.hasArrow) * labelInfo.arrowLength; - float arrowWidth = labelInfo.arrowWidth; - vec2 uvScaled = texCoord; +{ + if (labelInfo.hasRoundedCorners || labelInfo.hasArrow) + { + vec2 bbox = vec2(labelInfo.textSize); + const float arrowLength = int(labelInfo.hasArrow) * labelInfo.arrowLength; + float arrowWidth = labelInfo.arrowWidth; + vec2 uvScaled = texCoord; - float distX = min(uvScaled.x, bbox.x - uvScaled.x); - float distY = min(uvScaled.y - arrowLength, bbox.y - uvScaled.y); - float distanceFromCorner = distX * distY; + float distX = min(uvScaled.x, bbox.x - uvScaled.x); + float distY = min(uvScaled.y - arrowLength, bbox.y - uvScaled.y); + float distanceFromCorner = distX * distY; - if (distanceFromCorner < labelInfo.radius) - { - // plain arrow - if (labelInfo.hasArrow && !labelInfo.hasRoundedCorners) - { - // Some bias to prevent line between arrow and label + - // check that we are dealing with lower parts of the label where arrow should be drawn, - // to prevent discarding fragments from upper corners - if (distY <= 0.01 && uvScaled.y < (bbox.y - arrowWidth) && arrowLength != 0.0f) - { - arrowWidth = arrowWidth * ((arrowLength + distY) / arrowLength); - if (distX < (bbox.x - arrowWidth) * 0.5) - { - discard; - } - } - } - // TODO: rounded corners + rounded arrow. - // now renders rounded corners and sharp arrow - else if (labelInfo.hasArrow && labelInfo.hasRoundedCorners) - { - if (distY <= 0.05 && uvScaled.y < (bbox.y - arrowWidth) && arrowLength != 0.0f) - { - arrowWidth = arrowWidth * ((arrowLength + distY) / arrowLength); - if (distX < (bbox.x - arrowWidth) * 0.5) - { - discard; - } - } - else - { - discard; - } - } - // no arrow, rounded corners - else - { - discard; - } - } - } - outColor = labelInfo.color; + if (distanceFromCorner < labelInfo.radius) + { + // plain arrow + if (labelInfo.hasArrow && !labelInfo.hasRoundedCorners) + { + // Some bias to prevent line between arrow and label + + // check that we are dealing with lower parts of the label where arrow should be drawn, + // to prevent discarding fragments from upper corners + if (distY <= 0.01 && uvScaled.y < (bbox.y - arrowWidth) && arrowLength != 0.0f) + { + arrowWidth = arrowWidth * ((arrowLength + distY) / arrowLength); + if (distX < (bbox.x - arrowWidth) * 0.5) + { + discard; + } + } + } + // TODO: rounded corners + rounded arrow. + // now renders rounded corners and sharp arrow + else if (labelInfo.hasArrow && labelInfo.hasRoundedCorners) + { + if (distY <= 0.05 && uvScaled.y < (bbox.y - arrowWidth) && arrowLength != 0.0f) + { + arrowWidth = arrowWidth * ((arrowLength + distY) / arrowLength); + if (distX < (bbox.x - arrowWidth) * 0.5) + { + discard; + } + } + else + { + discard; + } + } + // no arrow, rounded corners + else + { + discard; + } + } + } + outColor = labelInfo.color; } \ No newline at end of file diff --git a/openVulkanoCpp/Shader/label.vert b/openVulkanoCpp/Shader/label.vert index ca0380d..2d23910 100644 --- a/openVulkanoCpp/Shader/label.vert +++ b/openVulkanoCpp/Shader/label.vert @@ -8,18 +8,19 @@ layout(set = 0, binding = 0) uniform NodeData layout(set = 1, binding = 0) uniform CameraData { - mat4 viewProjection; + mat4 viewProjection; } cam; -layout(set = 5, binding = 0) uniform LabelData +layout(set = 4, binding = 0) uniform LabelData { - vec4 textSize; - vec4 color; - vec4 bboxCenter; - float radius; - float arrowLength; - bool hasRoundedCorners; - bool hasArrow; + vec4 color; + vec2 textSize; + vec2 bboxCenter; + float radius; + float arrowLength; + float arrowWidth; + bool hasRoundedCorners; + bool hasArrow; } labelInfo; layout(location = 0) out vec4 color; @@ -28,18 +29,18 @@ layout(location = 1) out vec2 textureCoordinates; // Background plane positions are in clipped space const vec4 PLANE[4] = vec4[]( vec4(-0.5, -0.5, 0, 1), vec4(0.5, -0.5, 0, 1), vec4(-0.5, 0.5, 0, 1), vec4(0.5, 0.5, 0, 1) - ); + const vec2 TEX_COORDS[4] = vec2[]( vec2(0, 0), vec2(1, 0), vec2(0, 1), vec2(1, 1) ); -void main() { - vec4 position = PLANE[gl_VertexIndex]; - vec2 bbox = labelInfo.textSize.xy; - position.xy *= bbox; - position.xy += vec2(labelInfo.bboxCenter); - position.z = -0.001; - gl_Position = cam.viewProjection * node.world * position; - textureCoordinates = TEX_COORDS[gl_VertexIndex] * bbox; +void main() +{ + vec4 position = PLANE[gl_VertexIndex]; + position.xy *= labelInfo.textSize; + position.xy += labelInfo.bboxCenter; + //position.z = -0.001; + gl_Position = cam.viewProjection * node.world * position; + textureCoordinates = TEX_COORDS[gl_VertexIndex] * labelInfo.textSize; } diff --git a/openVulkanoCpp/Shader/labelBillboard.vert b/openVulkanoCpp/Shader/labelBillboard.vert index 00e1d02..ab4e610 100644 --- a/openVulkanoCpp/Shader/labelBillboard.vert +++ b/openVulkanoCpp/Shader/labelBillboard.vert @@ -8,35 +8,31 @@ layout(set = 0, binding = 0) uniform NodeData layout(set = 1, binding = 0) uniform CameraData { - mat4 viewProjection; - mat4 view; - mat4 projection; - vec4 camPos; - float nearPlane; - float farPlane; - float width; - float height; - float fov; - float aspect; - float scaleFactor; - float pixelScaleFactor; + mat4 viewProjection; + mat4 view; + mat4 projection; + vec4 camPos; + float nearPlane; + float farPlane; + float width; + float height; + float fov; + float aspect; + float scaleFactor; + float pixelScaleFactor; } cam; -layout(set = 4, binding = 0) uniform BillboardData +layout(set = 4, binding = 0) uniform LabelData { - vec2 size; - bool isFixedSize; -} billboardInfo; - -layout(set = 5, binding = 0) uniform LabelData -{ - vec4 textSize; - vec4 color; - vec4 bboxCenter; - float radius; - float arrowLength; - bool hasRoundedCorners; - bool hasArrow; + vec4 color; + vec2 textSize; + vec2 bboxCenter; + float radius; + float arrowLength; + float arrowWidth; + bool hasRoundedCorners; + bool hasArrow; + bool isBillboardFixedSize; } labelInfo; layout(location = 0) out vec4 color; @@ -45,43 +41,41 @@ layout(location = 1) out vec2 textureCoordinates; // Background plane positions are in clipped space const vec4 PLANE[4] = vec4[]( vec4(-0.5, -0.5, 0, 1), vec4(0.5, -0.5, 0, 1), vec4(-0.5, 0.5, 0, 1), vec4(0.5, 0.5, 0, 1) - - ); -const vec2 TEX_COORDS[4] = vec2[]( - vec2(0, 0), vec2(1, 0), vec2(0, 1), vec2(1, 1) ); -void main() { - vec4 position = PLANE[gl_VertexIndex]; - vec2 bbox = labelInfo.textSize.xy; - position.xy *= bbox; - position.xy += vec2(labelInfo.bboxCenter); - position.z = -0.001; - textureCoordinates = TEX_COORDS[gl_VertexIndex] * bbox; +const vec2 TEX_COORDS[4] = vec2[](vec2(0, 0), vec2(1, 0), vec2(0, 1), vec2(1, 1)); - if (!billboardInfo.isFixedSize) - { - mat4 mv = cam.view * node.world; +void main() +{ + vec4 position = PLANE[gl_VertexIndex]; + position.xy *= labelInfo.textSize; + position.xy += labelInfo.bboxCenter; + position.z = - 0.001; + textureCoordinates = TEX_COORDS[gl_VertexIndex] * labelInfo.textSize; - mv[0][0] = 1; - mv[0][1] = 0; - mv[0][2] = 0; - - mv[1][0] = 0; - mv[1][1] = 1; - mv[1][2] = 0; - - mv[2][0] = 0; - mv[2][1] = 0; - mv[2][2] = 1; - - gl_Position = cam.projection * mv * vec4(position.xyz, 1); - } - else - { - vec4 billboardPos = vec4(0.5, 0.5, 0.5, 1); - vec4 viewPos = cam.view * node.world * billboardPos; - float dist = -viewPos.z; - gl_Position = cam.projection * (viewPos + vec4(position.xy*dist*0.2,0,0)); - } + if (!labelInfo.isBillboardFixedSize) + { + mat4 mv = cam.view * node.world; + + mv[0][0] = 1; + mv[0][1] = 0; + mv[0][2] = 0; + + mv[1][0] = 0; + mv[1][1] = 1; + mv[1][2] = 0; + + mv[2][0] = 0; + mv[2][1] = 0; + mv[2][2] = 1; + + gl_Position = cam.projection * mv * vec4(position.xyz, 1); + } + else + { + vec4 billboardPos = vec4(0.5, 0.5, 0, 1); + vec4 viewPos = cam.view * node.world * billboardPos; + float dist = - viewPos.z; + gl_Position = cam.projection * (viewPos + vec4(position.xy *dist * 0.2, 0, 0)); + } } diff --git a/openVulkanoCpp/Shader/msdfText.frag b/openVulkanoCpp/Shader/msdfText.frag index 2878e2e..ad08fbd 100644 --- a/openVulkanoCpp/Shader/msdfText.frag +++ b/openVulkanoCpp/Shader/msdfText.frag @@ -1,47 +1,40 @@ #version 450 -layout(location = 1) in vec2 texCoord; +layout(location = 0) in vec4 color; +layout(location = 1) in vec4 bgColor; +layout(location = 2) in vec2 texCoord; layout(location = 0) out vec4 outColor; layout(set = 2, binding = 0) uniform sampler2D texSampler; -layout(set = 3, binding = 0) uniform TextConfig +float median(float r, float g, float b) { - vec4 textColor; - vec4 borderColor; - vec4 backgroundColor; - float threshold; - float borderSize; - float smoothing; - bool applyBorder; -} textConfig; - -float median(float r, float g, float b) { return max(min(r, g), min(max(r, g), b)); } // this parameter should be same as FontAtlasGeneratorConfig::pixelRange const float pxRange = 3; -float screenPxRange() { - vec2 unitRange = vec2(pxRange)/vec2(textureSize(texSampler, 0)); - vec2 screenTexSize = vec2(1.0)/fwidth(texCoord); - return max(0.5*dot(unitRange, screenTexSize), 1.0); +float screenPxRange() +{ + vec2 unitRange = vec2(pxRange) / vec2(textureSize(texSampler, 0)); + vec2 screenTexSize = vec2(1.0) / fwidth(texCoord); + return max(0.5 * dot(unitRange, screenTexSize), 1.0); } void main() { vec3 msd = texture(texSampler, texCoord).rgb; float sd = median(msd.r, msd.g, msd.b); - float screenPxDistance = screenPxRange()*(sd - 0.5); + float screenPxDistance = screenPxRange() * (sd - 0.5); float opacity = clamp(screenPxDistance + 0.5, 0.0, 1.0); - if (textConfig.backgroundColor.a != 0) + if (bgColor.a != 0) { - outColor = mix(textConfig.backgroundColor, textConfig.textColor, opacity); + outColor = mix(bgColor, color, opacity); } else { - outColor = vec4(vec3(textConfig.textColor), opacity); + outColor = vec4(vec3(color), opacity); } } diff --git a/openVulkanoCpp/Shader/sdfText.frag b/openVulkanoCpp/Shader/sdfText.frag index 579d9c7..c5e17fa 100644 --- a/openVulkanoCpp/Shader/sdfText.frag +++ b/openVulkanoCpp/Shader/sdfText.frag @@ -1,39 +1,24 @@ #version 450 -layout(location = 1) in vec2 texCoord; +layout(location = 0) in vec4 color; +layout(location = 1) in vec4 bgColor; +layout(location = 2) in vec2 texCoord; layout(location = 0) out vec4 outColor; layout(set = 2, binding = 0) uniform sampler2D texSampler; -layout(set = 3, binding = 0) uniform TextConfig -{ - vec4 textColor; - vec4 borderColor; - vec4 backgroundColor; - float threshold; - float borderSize; - float smoothing; - bool applyBorder; -} textConfig; +const float threshold = 0.4f; +const float smoothing = 1.f/32.f; void main() { float distance = texture(texSampler, texCoord).r; - float alpha = smoothstep(textConfig.threshold - textConfig.smoothing, textConfig.threshold + textConfig.smoothing, distance); - if (textConfig.applyBorder) - { - float border = smoothstep(textConfig.threshold + textConfig.borderSize - textConfig.smoothing, - textConfig.threshold + textConfig.borderSize + textConfig.smoothing, distance); - outColor = mix(textConfig.borderColor, textConfig.textColor, border) * alpha; - } - else - { - outColor = vec4(textConfig.textColor) * alpha; - } + float alpha = smoothstep(threshold - smoothing, threshold + smoothing, distance); + outColor = vec4(color) * alpha; - if (textConfig.backgroundColor.a != 0) + if (bgColor.a != 0) { - outColor = mix(textConfig.backgroundColor, outColor, alpha); + outColor = mix(bgColor, outColor, alpha); } } diff --git a/openVulkanoCpp/Shader/sdfText.vert b/openVulkanoCpp/Shader/sdfText.vert deleted file mode 100644 index c259c65..0000000 --- a/openVulkanoCpp/Shader/sdfText.vert +++ /dev/null @@ -1,26 +0,0 @@ -#version 450 -layout(location = 0) in vec3 position; -layout(location = 1) in vec3 normal; -layout(location = 2) in vec3 tangent; -layout(location = 3) in vec3 biTangent; -layout(location = 4) in vec3 textureCoordinates; -layout(location = 5) in vec4 color; -layout(location = 1) out vec2 fragTextureCoordinates; - -layout(set = 0, binding = 0) uniform NodeData -{ - mat4 world; -} node; - -layout(set = 1, binding = 0) uniform CameraData -{ - mat4 viewProjection; - mat4 view; - mat4 projection; - vec4 camPos; -} cam; - -void main() { - gl_Position = cam.viewProjection * node.world * vec4(position, 1.0); - fragTextureCoordinates.xy = textureCoordinates.xy; -} diff --git a/openVulkanoCpp/Shader/sdfTextWithBorder.frag b/openVulkanoCpp/Shader/sdfTextWithBorder.frag new file mode 100644 index 0000000..6960a33 --- /dev/null +++ b/openVulkanoCpp/Shader/sdfTextWithBorder.frag @@ -0,0 +1,32 @@ +#version 450 + +layout(location = 1) in vec2 texCoord; + +layout(location = 0) out vec4 outColor; + +layout(set = 2, binding = 0) uniform sampler2D texSampler; + +layout(set = 3, binding = 0) uniform TextConfig +{ + vec4 textColor; + vec4 borderColor; + vec4 backgroundColor; + float threshold; + float borderSize; + float smoothing; +} textConfig; + +void main() +{ + float distance = texture(texSampler, texCoord).r; + float alpha = smoothstep(textConfig.threshold - textConfig.smoothing, textConfig.threshold + textConfig.smoothing, distance); + + float border = smoothstep(textConfig.threshold + textConfig.borderSize - textConfig.smoothing, + textConfig.threshold + textConfig.borderSize + textConfig.smoothing, distance); + outColor = mix(textConfig.borderColor, textConfig.textColor, border) * alpha; + + if (textConfig.backgroundColor.a != 0) + { + outColor = mix(textConfig.backgroundColor, outColor, alpha); + } +} diff --git a/openVulkanoCpp/Shader/text.frag b/openVulkanoCpp/Shader/text.frag index b906e40..47a7164 100644 --- a/openVulkanoCpp/Shader/text.frag +++ b/openVulkanoCpp/Shader/text.frag @@ -1,25 +1,15 @@ #version 450 layout(location = 0) in vec4 color; -layout(location = 1) in vec2 texCoord; +layout(location = 1) in vec4 bgColor; +layout(location = 2) in vec2 texCoord; layout(location = 0) out vec4 outColor; layout(set = 2, binding = 0) uniform sampler2D texSampler; -layout(set = 3, binding = 0) uniform TextConfig -{ - vec4 textColor; - vec4 borderColor; - vec4 backgroundColor; - float threshold; - float borderSize; - float smoothing; - bool applyBorder; -} textConfig; - void main() { vec4 sampled = vec4(1.0, 1.0, 1.0, texture(texSampler, texCoord).r); - outColor = vec4(textConfig.textColor) * sampled; + outColor = vec4(color) * sampled; } diff --git a/openVulkanoCpp/Shader/text.vert b/openVulkanoCpp/Shader/text.vert index 47f4b61..bc4012c 100644 --- a/openVulkanoCpp/Shader/text.vert +++ b/openVulkanoCpp/Shader/text.vert @@ -1,13 +1,13 @@ #version 450 -layout(location = 0) in vec3 position; -layout(location = 1) in vec3 normal; -layout(location = 2) in vec3 tangent; -layout(location = 3) in vec3 biTangent; -layout(location = 4) in vec3 textureCoordinates; -layout(location = 5) in vec4 color; + +layout(location = 0) in vec2 position[4]; +layout(location = 4) in vec2 textureCoordinates[4]; +layout(location = 8) in vec4 color; +layout(location = 9) in vec4 bgColor; layout(location = 0) out vec4 outColor; -layout(location = 1) out vec2 fragTextureCoordinates; +layout(location = 1) out vec4 outBgColor; +layout(location = 2) out vec2 fragTextureCoordinates; layout(set = 0, binding = 0) uniform NodeData { @@ -16,14 +16,12 @@ layout(set = 0, binding = 0) uniform NodeData layout(set = 1, binding = 0) uniform CameraData { - mat4 viewProjection; - mat4 view; - mat4 projection; - vec4 camPos; + mat4 viewProjection; } cam; void main() { - gl_Position = cam.viewProjection * node.world * vec4(position, 1.0); - fragTextureCoordinates.xy = textureCoordinates.xy; - outColor = color; + gl_Position = cam.viewProjection * node.world * vec4(position[gl_VertexIndex], 0.0, 1.0); + fragTextureCoordinates = textureCoordinates[gl_VertexIndex]; + outColor = color; + outBgColor = bgColor; } diff --git a/openVulkanoCpp/Shader/textBillboard.vert b/openVulkanoCpp/Shader/textBillboard.vert new file mode 100644 index 0000000..dfe9de1 --- /dev/null +++ b/openVulkanoCpp/Shader/textBillboard.vert @@ -0,0 +1,71 @@ +#version 450 + +#extension GL_ARB_separate_shader_objects : enable + +layout(location = 0) in vec2 position[4]; +layout(location = 4) in vec2 textureCoordinates[4]; +layout(location = 8) in vec4 color; +layout(location = 9) in vec4 bgColor; + +layout(location = 0) out vec4 outColor; +layout(location = 1) out vec4 outBgColor; +layout(location = 2) out vec2 outTexture; + +layout(set = 0, binding = 0) uniform NodeData +{ + mat4 world; +} node; + +layout(set = 1, binding = 0) uniform CameraData +{ + mat4 viewProjection; + mat4 view; + mat4 projection; + vec4 camPos; +} cam; + +layout(set = 4, binding = 0) uniform BillboardData +{ + vec4 color; + vec2 textSize; + vec2 bboxCenter; + float radius; + float arrowLength; + float arrowWidth; + bool hasRoundedCorners; + bool hasArrow; + bool isBillboardFixedSize; +} billboardInfo; + +void main() +{ + vec4 pos = vec4(position[gl_VertexIndex], 0, 1); + if (!billboardInfo.isBillboardFixedSize) + { + mat4 mv = cam.view * node.world; + + mv[0][0] = 1; + mv[0][1] = 0; + mv[0][2] = 0; + + mv[1][0] = 0; + mv[1][1] = 1; + mv[1][2] = 0; + + mv[2][0] = 0; + mv[2][1] = 0; + mv[2][2] = 1; + + gl_Position = cam.projection * mv * pos; + } + else + { + vec4 billboardPos = vec4(0.5, 0.5, 0, 1); + vec4 viewPos = cam.view * node.world * billboardPos; + float dist = -viewPos.z; + gl_Position = cam.projection * (viewPos + vec4(pos.xy * dist * 0.2, 0, 0)); + } + outTexture = textureCoordinates[gl_VertexIndex]; + outColor = color; + outBgColor = bgColor; +} diff --git a/openVulkanoCpp/Vulkan/Buffer.hpp b/openVulkanoCpp/Vulkan/Buffer.hpp index 373497c..e737f23 100644 --- a/openVulkanoCpp/Vulkan/Buffer.hpp +++ b/openVulkanoCpp/Vulkan/Buffer.hpp @@ -1,5 +1,5 @@ #pragma once -#include "Base/ICloseable.hpp" + #include "Device.hpp" namespace OpenVulkano @@ -9,7 +9,7 @@ namespace OpenVulkano /** * \brief A not managed buffer. This should be used rarely. */ - struct Buffer : public ICloseable + struct Buffer { vk::Device device; vk::DeviceMemory memory; @@ -94,7 +94,7 @@ namespace OpenVulkano device.invalidateMappedMemoryRanges(vk::MappedMemoryRange(memory, offset, size)); } - void Close() override + void Close() { if (mapped) UnMap(); if(memory) diff --git a/openVulkanoCpp/Vulkan/CommandHelper.hpp b/openVulkanoCpp/Vulkan/CommandHelper.hpp index f109db3..2dcaf78 100644 --- a/openVulkanoCpp/Vulkan/CommandHelper.hpp +++ b/openVulkanoCpp/Vulkan/CommandHelper.hpp @@ -6,14 +6,13 @@ #pragma once -#include "Base/ICloseable.hpp" #include namespace OpenVulkano { namespace Vulkan { - struct CommandHelper : virtual ICloseable + struct CommandHelper final { vk::Device device; vk::CommandPool cmdPool; @@ -42,7 +41,7 @@ namespace OpenVulkano return level; } - void Close() override + void Close() { device.freeCommandBuffers(cmdPool, 1, &cmdBuffer); device.destroyCommandPool(cmdPool); diff --git a/openVulkanoCpp/Vulkan/Context.hpp b/openVulkanoCpp/Vulkan/Context.hpp index 18d4765..644b2cb 100644 --- a/openVulkanoCpp/Vulkan/Context.hpp +++ b/openVulkanoCpp/Vulkan/Context.hpp @@ -21,7 +21,7 @@ namespace OpenVulkano { class Device; - class Context final : public ICloseable + class Context final { bool enableValidationLayer, initialized; std::set requiredExtensions; @@ -45,14 +45,14 @@ namespace OpenVulkano #endif } - ~Context() override + ~Context() { if (initialized) Close(); } void Init(IGraphicsAppManager* graphicsAppManager, IVulkanWindow* window); - void Close() override; + void Close(); void Resize(uint32_t newWidth, uint32_t newHeight); diff --git a/openVulkanoCpp/Vulkan/Device.hpp b/openVulkanoCpp/Vulkan/Device.hpp index 6a26226..a6c99b0 100644 --- a/openVulkanoCpp/Vulkan/Device.hpp +++ b/openVulkanoCpp/Vulkan/Device.hpp @@ -10,13 +10,12 @@ #include #include #include -#include "Base/ICloseable.hpp" namespace OpenVulkano { namespace Vulkan { - class Device : public ICloseable + class Device final { public: vk::PhysicalDevice physicalDevice; @@ -106,7 +105,7 @@ namespace OpenVulkano return memoryProperties.memoryTypes[memoryType].propertyFlags; } - void Close() override; + void Close(); }; } } diff --git a/openVulkanoCpp/Vulkan/FrameBuffer.hpp b/openVulkanoCpp/Vulkan/FrameBuffer.hpp index e9d68ca..757d9f9 100644 --- a/openVulkanoCpp/Vulkan/FrameBuffer.hpp +++ b/openVulkanoCpp/Vulkan/FrameBuffer.hpp @@ -6,7 +6,6 @@ #pragma once -#include "Base/ICloseable.hpp" #include "Image.hpp" #include "Device.hpp" #include @@ -17,7 +16,7 @@ namespace OpenVulkano::Vulkan { class RenderPass; - class FrameBuffer : ICloseable + class FrameBuffer { Image depthBuffer; std::vector frameBuffers; @@ -50,7 +49,7 @@ namespace OpenVulkano::Vulkan protected: void Resize(vk::Extent3D size); - void Close() override + virtual void Close() { DestroyFrameBuffer(); if(depthBuffer) depthBuffer.Close(); diff --git a/openVulkanoCpp/Vulkan/Image.hpp b/openVulkanoCpp/Vulkan/Image.hpp index 40d8ad1..7b820b4 100644 --- a/openVulkanoCpp/Vulkan/Image.hpp +++ b/openVulkanoCpp/Vulkan/Image.hpp @@ -47,7 +47,7 @@ namespace OpenVulkano::Vulkan SetLayout(cmdBuffer, vk::ImageSubresourceRange(aspectMask, 0, 1, 0, 1), newLayout, oldLayout); } - void Close() override; + virtual void Close(); operator bool() const { return image.operator bool(); } diff --git a/openVulkanoCpp/Vulkan/Metal/MetalTextureCache.h b/openVulkanoCpp/Vulkan/Metal/MetalTextureCache.h index 7a4c226..14dbc9c 100644 --- a/openVulkanoCpp/Vulkan/Metal/MetalTextureCache.h +++ b/openVulkanoCpp/Vulkan/Metal/MetalTextureCache.h @@ -6,7 +6,6 @@ #pragma once -#include "Base/ICloseable.hpp" #include "MetalBackedTexture.h" #import @@ -16,19 +15,20 @@ namespace OpenVulkano::Vulkan { class Renderer; - class MetalTextureCache : public ICloseable + class MetalTextureCache final { CVMetalTextureCacheRef m_textureCache = nullptr; Vulkan::ResourceManager* m_resourceManager = nullptr; std::map m_mtlToVkTextureMap; Renderer* m_renderer; + IEventHandler* m_eventHandler = nullptr; public: ~MetalTextureCache() { if (m_resourceManager) Close(); } void Init(IRenderer* renderer); - void Close() override; + void Close(); Scene::Texture* Get(CVPixelBufferRef pixelBuffer, MTLPixelFormat pixelFormat); diff --git a/openVulkanoCpp/Vulkan/Metal/MetalTextureCache.mm b/openVulkanoCpp/Vulkan/Metal/MetalTextureCache.mm index 29a68d8..46b36cc 100644 --- a/openVulkanoCpp/Vulkan/Metal/MetalTextureCache.mm +++ b/openVulkanoCpp/Vulkan/Metal/MetalTextureCache.mm @@ -28,7 +28,7 @@ namespace OpenVulkano::Vulkan Logger::AR->error("Failed to create metal texture cache! Status code: {}", result); } m_resourceManager = &m_renderer->GetResourceManager(); - m_renderer->RegisterCloseable(this); + m_renderer->OnClose += EventHandler(this, &MetalTextureCache::Close); } Scene::Texture* MetalTextureCache::Get(CVPixelBufferRef pixelBuffer, MTLPixelFormat pixelFormat) @@ -57,7 +57,7 @@ namespace OpenVulkano::Vulkan void MetalTextureCache::Close() { m_mtlToVkTextureMap.clear(); - m_renderer->UnregisterCloseable(this); + m_eventHandler->SetInvalid(); m_renderer = nullptr; m_resourceManager = nullptr; //TODO delete the texture cache object? diff --git a/openVulkanoCpp/Vulkan/RenderPass.hpp b/openVulkanoCpp/Vulkan/RenderPass.hpp index 71a7f3f..fbedfab 100644 --- a/openVulkanoCpp/Vulkan/RenderPass.hpp +++ b/openVulkanoCpp/Vulkan/RenderPass.hpp @@ -13,7 +13,7 @@ namespace OpenVulkano::Vulkan { class FrameBuffer; - class RenderPass : public ICloseable + class RenderPass { //TODO allow to control the render rect size protected: vk::Device m_device; @@ -27,14 +27,14 @@ namespace OpenVulkano::Vulkan RenderPass() = default; - ~RenderPass() override + virtual ~RenderPass() { if (m_frameBuffer) RenderPass::Close(); } void Init(Device* device, FrameBuffer* frameBuffer, bool clearColor = false, bool clearDepth = false); - void Close() override; + virtual void Close(); void SetClearColor(vk::ClearColorValue clearColor = vk::ClearColorValue(std::array{ 0.39f, 0.58f, 0.93f, 1.0f })) { diff --git a/openVulkanoCpp/Vulkan/Renderer.cpp b/openVulkanoCpp/Vulkan/Renderer.cpp index 30390b8..4aa56f1 100644 --- a/openVulkanoCpp/Vulkan/Renderer.cpp +++ b/openVulkanoCpp/Vulkan/Renderer.cpp @@ -89,12 +89,7 @@ namespace OpenVulkano::Vulkan { context.device->device.destroySemaphore(sema); } - while (!closeables.empty()) - { - ICloseable* closeable = closeables.back(); - closeables.pop_back(); - closeable->Close(); - } + OnClose(); depthBufferQuery.Close(); uiRenderer.Close(); resourceManager.Close(); diff --git a/openVulkanoCpp/Vulkan/Renderer.hpp b/openVulkanoCpp/Vulkan/Renderer.hpp index 567e3ea..fb7ccc3 100644 --- a/openVulkanoCpp/Vulkan/Renderer.hpp +++ b/openVulkanoCpp/Vulkan/Renderer.hpp @@ -40,7 +40,6 @@ namespace OpenVulkano::Vulkan std::vector> commands; std::vector> submitBuffers; UiRenderer uiRenderer; - std::vector closeables; DepthBufferQuery depthBufferQuery; public: @@ -83,14 +82,12 @@ namespace OpenVulkano::Vulkan Context& GetContext() { return context; } - void RegisterCloseable(ICloseable* closeable) { closeables.push_back(closeable); } - - void UnregisterCloseable(ICloseable* closeable) { Utils::Remove(closeables, closeable); } - IResourceManager* GetIResourceManager() override { return &resourceManager; } float GetLastQueriedDepthValue() override { return depthBufferQuery.GetQueriedValue(); } void SetQueryDepthValue(const Math::Vector2f& depthCoordinates) override { depthBufferQuery.SetQueryCoordinates(depthCoordinates); } + + Event<> OnClose; }; } diff --git a/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp b/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp index 452e907..bd88819 100644 --- a/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp +++ b/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp @@ -5,6 +5,9 @@ */ #include "ResourceManager.hpp" + +#include + #include "ManagedBuffer.hpp" #include "MemoryAllocation.hpp" #include "Scene/Vertex.hpp" @@ -21,6 +24,7 @@ #include "Vulkan/Scene/VulkanTexture.hpp" #include "Vulkan/Scene/VulkanCamera.hpp" #include "Vulkan/Scene/VulkanUniformBuffer.hpp" +#include "Vulkan/Scene/VulkanVertexBuffer.hpp" namespace OpenVulkano::Vulkan { @@ -173,6 +177,21 @@ namespace OpenVulkano::Vulkan return geometry->GetRenderResource(); } + VulkanVertexBuffer* ResourceManager::PrepareVertexBuffer(Scene::VertexBuffer* vbo) + { + const std::unique_lock lock(mutex); + if(!vbo->HasRenderResource()) + { + ManagedBuffer::Ptr vertexBuffer = + CreateDeviceOnlyBufferWithData(vbo->size, vk::BufferUsageFlagBits::eVertexBuffer, vbo->data); + ManagedBuffer::Ptr indexBuffer; + VulkanVertexBuffer* vkVbo = new VulkanVertexBuffer(vbo, vertexBuffer); + vertexBuffers.emplace_back(vkVbo); + return vkVbo; + } + return vbo->GetRenderResource(); + } + void ResourceManager::PrepareMaterial(Scene::Material* material) { if (material->texture && !material->texture->HasRenderResource()) diff --git a/openVulkanoCpp/Vulkan/Resources/ResourceManager.hpp b/openVulkanoCpp/Vulkan/Resources/ResourceManager.hpp index 9274a32..100c767 100644 --- a/openVulkanoCpp/Vulkan/Resources/ResourceManager.hpp +++ b/openVulkanoCpp/Vulkan/Resources/ResourceManager.hpp @@ -34,6 +34,7 @@ namespace OpenVulkano class Shader; class Camera; class UniformBuffer; + class VertexBuffer; } namespace Vulkan @@ -45,11 +46,12 @@ namespace OpenVulkano class VulkanNode; class VulkanShader; class VulkanUniformBuffer; + class VulkanVertexBuffer; class UniformBuffer; class ManagedBuffer; class MemoryAllocation; - class ResourceManager : public IShaderOwner, public IResourceManager + class ResourceManager final : public IShaderOwner, public IResourceManager { friend UniformBuffer; friend VulkanTexture; @@ -63,6 +65,7 @@ namespace OpenVulkano MemoryPool memPool; std::vector> shaders; std::vector> geometries; + std::vector> vertexBuffers; std::vector> nodes; std::vector> textures; std::vector> cameras; @@ -100,6 +103,8 @@ namespace OpenVulkano VulkanUniformBuffer* PrepareUniformBuffer(Scene::UniformBuffer* buffer); + VulkanVertexBuffer* PrepareVertexBuffer(Scene::VertexBuffer* vbo); + VulkanNode* PrepareNode(Scene::Node* node); VulkanTexture* PrepareTexture(Scene::Texture* texture); diff --git a/openVulkanoCpp/Vulkan/Resources/UniformBuffer.hpp b/openVulkanoCpp/Vulkan/Resources/UniformBuffer.hpp index 656ae61..a9feeb9 100644 --- a/openVulkanoCpp/Vulkan/Resources/UniformBuffer.hpp +++ b/openVulkanoCpp/Vulkan/Resources/UniformBuffer.hpp @@ -6,7 +6,6 @@ #pragma once -#include "Base/ICloseable.hpp" #include "Vulkan/Resources/ManagedBuffer.hpp" #include "Vulkan/Scene/IRecordable.hpp" @@ -14,7 +13,7 @@ namespace OpenVulkano::Vulkan { class ManagedBuffer; - class UniformBuffer final : public IRecordable, public ICloseable + class UniformBuffer final : public IRecordable { ManagedBuffer::Ptr m_buffer = nullptr; vk::DescriptorSet m_descriptorSet; @@ -30,7 +29,7 @@ namespace OpenVulkano::Vulkan void Init(ManagedBuffer::Ptr buffer, uint32_t frameOffset, uint32_t frameSize, vk::DescriptorSetLayout* descriptorSetLayout, const DescriptorSetLayoutBinding& binding, uint32_t setId); - void Close() override; + virtual void Close(); void Record(VulkanDrawContext* drawContext) override; diff --git a/openVulkanoCpp/Vulkan/Scene/LabelDrawableVulkanEncoder.cpp b/openVulkanoCpp/Vulkan/Scene/LabelDrawableVulkanEncoder.cpp index 7371174..2dd0ef4 100644 --- a/openVulkanoCpp/Vulkan/Scene/LabelDrawableVulkanEncoder.cpp +++ b/openVulkanoCpp/Vulkan/Scene/LabelDrawableVulkanEncoder.cpp @@ -12,107 +12,61 @@ #include "Vulkan/VulkanDrawContext.hpp" #include "Vulkan/Scene/VulkanTexture.hpp" #include "Vulkan/Scene/VulkanUniformBuffer.hpp" +#include "Vulkan/Scene/VulkanVertexBuffer.hpp" using namespace OpenVulkano::Scene; namespace OpenVulkano::Vulkan { - void EncodeBackground(LabelDrawable* labelDrawable, Vulkan::VulkanDrawContext* drawContext) + void EncodeBackground(LabelDrawable* labelDrawable, VulkanDrawContext* drawContext) { - if (labelDrawable->IsBillboard()) - { - OpenVulkano::Scene::UniformBuffer* buffer = labelDrawable->GetBillboardBuffer(); - VulkanUniformBuffer* vkBuffer = buffer->GetRenderResource(); - if (!vkBuffer) - { - vkBuffer = drawContext->renderer->GetResourceManager().PrepareUniformBuffer(buffer); - } - vkBuffer->Record(drawContext); - } - - OpenVulkano::Scene::UniformBuffer* labelBuffer = labelDrawable->GetLabelBuffer(); - VulkanUniformBuffer* vkBuffer = labelBuffer->GetRenderResource(); - if (!vkBuffer) - { - vkBuffer = drawContext->renderer->GetResourceManager().PrepareUniformBuffer(labelBuffer); - } + VulkanUniformBuffer* vkBuffer = labelDrawable->GetLabelBuffer()->GetRenderResource(); + if (!vkBuffer) vkBuffer = drawContext->renderer->GetResourceManager().PrepareUniformBuffer(labelDrawable->GetLabelBuffer()); vkBuffer->Record(drawContext); for (Node* node: labelDrawable->GetNodes()) { - if (!node->IsEnabled()) [[unlikely]] - { - continue; - } + if (!node->IsEnabled()) [[unlikely]] continue; drawContext->EncodeNode(node); } drawContext->commandBuffer.draw(4, 1, 0, 0); } - void EncodeTextDrawable(LabelDrawable* labelDrawable, Vulkan::VulkanDrawContext* drawContext) + void EncodeTextDrawable(LabelDrawable* labelDrawable, VulkanDrawContext* drawContext) { for (TextDrawable& entry : labelDrawable->GetTexts()) { - OpenVulkano::Scene::Shader* shader = entry.GetShader(); - drawContext->EncodeShader(shader); - Geometry* mesh = entry.GetMesh(); - VulkanGeometry* renderGeo = mesh->GetRenderResource(); - if (!renderGeo) - { - renderGeo = drawContext->renderer->GetResourceManager().PrepareGeometry(mesh); - } - renderGeo->RecordBind(drawContext->commandBuffer); - - std::array uniforms = { nullptr, nullptr }; - // fragment shader buffer - uniforms[0] = entry.GetBuffer(); + drawContext->EncodeShader(entry.GetShader()); + VertexBuffer* vbo = entry.GetVertexBuffer(); + VulkanVertexBuffer* renderVbo = vbo->GetRenderResource(); + if (!renderVbo) renderVbo = drawContext->renderer->GetResourceManager().PrepareVertexBuffer(vbo); + renderVbo->RecordBind(drawContext->commandBuffer); + if (labelDrawable->IsBillboard()) { - // vertex shader buffer - uniforms[1] = labelDrawable->GetBillboardBuffer(); + VulkanUniformBuffer* vkBuffer = labelDrawable->GetLabelBuffer()->GetRenderResource(); + if (!vkBuffer) vkBuffer = drawContext->renderer->GetResourceManager().PrepareUniformBuffer(labelDrawable->GetLabelBuffer()); + vkBuffer->Record(drawContext); } - for (OpenVulkano::Scene::UniformBuffer* buffer : uniforms) + VulkanTexture* renderTexture = entry.GetTexture()->GetRenderResource(); + if (!renderTexture) { - if (buffer) - { - VulkanUniformBuffer* vkBuffer = buffer->GetRenderResource(); - if (!vkBuffer) - { - vkBuffer = drawContext->renderer->GetResourceManager().PrepareUniformBuffer(buffer); - } - vkBuffer->Record(drawContext); - } - } - - if (Material* material = entry.GetMaterial()) - { - if (Texture* texture = material->texture) - { - VulkanTexture* renderTexture = texture->GetRenderResource(); - if (!renderTexture) - { - drawContext->renderer->GetResourceManager().PrepareMaterial(entry.GetMaterial()); - renderTexture = texture->GetRenderResource(); - } - renderTexture->Record(drawContext); - } + renderTexture = drawContext->renderer->GetResourceManager().PrepareTexture(entry.GetTexture()); } + renderTexture->Record(drawContext); for (Node* node: labelDrawable->GetNodes()) { - if (!node->IsEnabled()) [[unlikely]] - { - continue; - } + if (!node->IsEnabled()) [[unlikely]] continue; drawContext->EncodeNode(node); - renderGeo->RecordDraw(drawContext->commandBuffer); + drawContext->commandBuffer.draw(4, entry.GetSymbolCount(), 0, 0); } } } - void EncodeLabelDrawable(Drawable* instance, Vulkan::VulkanDrawContext* drawContext) + void EncodeLabelDrawable(Drawable* instance, VulkanDrawContext* drawContext) { LabelDrawable* labelDrawable = static_cast(instance); EncodeBackground(labelDrawable, drawContext); @@ -122,5 +76,5 @@ namespace OpenVulkano::Vulkan namespace { - void* labelDrawableVulkanEncoderReg = DrawEncoder::RegisterVulkanEncodeFunction(&OpenVulkano::Vulkan::EncodeLabelDrawable); + [[maybe_unused]] void* labelDrawableVulkanEncoderReg = DrawEncoder::RegisterVulkanEncodeFunction(&OpenVulkano::Vulkan::EncodeLabelDrawable); } \ No newline at end of file diff --git a/openVulkanoCpp/Vulkan/Scene/TextDrawableVulkanEncoder.cpp b/openVulkanoCpp/Vulkan/Scene/TextDrawableVulkanEncoder.cpp new file mode 100644 index 0000000..445a4c6 --- /dev/null +++ b/openVulkanoCpp/Vulkan/Scene/TextDrawableVulkanEncoder.cpp @@ -0,0 +1,45 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#include "Scene/TextDrawable.hpp" +#include "VulkanNode.hpp" +#include "Vulkan/VulkanDrawContext.hpp" +#include "Vulkan/Scene/VulkanUniformBuffer.hpp" +#include "Vulkan/Scene/VulkanVertexBuffer.hpp" +#include "VulkanTexture.hpp" + +using namespace OpenVulkano::Scene; + +namespace OpenVulkano::Vulkan +{ + void EncodeTextDrawable(Drawable* instance, VulkanDrawContext* drawContext) + { + TextDrawable* drawable = static_cast(instance); + VertexBuffer* vbo = drawable->GetVertexBuffer(); + VulkanVertexBuffer* renderVbo = vbo->GetRenderResource(); + if (!renderVbo) renderVbo = drawContext->renderer->GetResourceManager().PrepareVertexBuffer(vbo); + renderVbo->RecordBind(drawContext->commandBuffer); + + VulkanTexture* renderTexture = drawable->GetTexture()->GetRenderResource(); + if (!renderTexture) + { + renderTexture = drawContext->renderer->GetResourceManager().PrepareTexture(drawable->GetTexture()); + } + renderTexture->Record(drawContext); + + for(Node* node : instance->GetNodes()) + { + if (!node->IsEnabled()) [[unlikely]] continue; + drawContext->EncodeNode(node); + drawContext->commandBuffer.draw(4, drawable->GetSymbolCount(), 0, 0); + } + } +} + +namespace +{ + [[maybe_unused]] void* textDrawableVulkanEncoderReg = DrawEncoder::RegisterVulkanEncodeFunction(&OpenVulkano::Vulkan::EncodeTextDrawable); +} \ No newline at end of file diff --git a/openVulkanoCpp/Vulkan/Scene/VulkanShader.cpp b/openVulkanoCpp/Vulkan/Scene/VulkanShader.cpp index e7bc334..db0542b 100644 --- a/openVulkanoCpp/Vulkan/Scene/VulkanShader.cpp +++ b/openVulkanoCpp/Vulkan/Scene/VulkanShader.cpp @@ -54,7 +54,7 @@ namespace OpenVulkano::Vulkan for(const auto& description : shader->vertexInputDescriptions) { - vertexBindDesc.emplace_back(description.bindingId, description.vertexSize, vk::VertexInputRate::eVertex); + vertexBindDesc.emplace_back(description.bindingId, description.vertexSize, static_cast(description.stepMode)); if (shader->vertexInputDescriptions.size() > 1) { for(const auto& param : description.inputParameters) @@ -84,6 +84,13 @@ namespace OpenVulkano::Vulkan vk::PipelineInputAssemblyStateCreateInfo inputAssembly = { {}, static_cast(shader->topology), 0 }; vk::PipelineRasterizationStateCreateInfo rasterizer = {}; rasterizer.cullMode = static_cast(shader->cullMode); + if (shader->depthBias) + { + rasterizer.depthBiasEnable = VK_TRUE; + rasterizer.depthBiasClamp = shader->depthBiasClamp; + rasterizer.depthBiasConstantFactor = shader->depthBiasConstant; + rasterizer.depthBiasSlopeFactor = shader->depthBiasSlope; + } vk::PipelineMultisampleStateCreateInfo msaa = {}; vk::PipelineDepthStencilStateCreateInfo depth = { {}, shader->depthTest, shader->depthWrite, static_cast(shader->depthCompareOp) }; depth.maxDepthBounds = 1; diff --git a/openVulkanoCpp/Vulkan/Scene/VulkanShader.hpp b/openVulkanoCpp/Vulkan/Scene/VulkanShader.hpp index 738e0c2..8ece2c3 100644 --- a/openVulkanoCpp/Vulkan/Scene/VulkanShader.hpp +++ b/openVulkanoCpp/Vulkan/Scene/VulkanShader.hpp @@ -11,39 +11,36 @@ #include #include -namespace OpenVulkano +namespace OpenVulkano::Vulkan { - namespace Vulkan - { - class Context; - class IShaderOwner; + class Context; + class IShaderOwner; class VulkanShader final : public IRenderResource, public IRecordable - { - public: - vk::Device device; - std::vector shaderModules; // TODO manage live time somewhere else to allow sharing of shader programs - std::vector shaderStageCreateInfo; - vk::Pipeline pipeline; // TODO pipeline and shader config should be split - std::vector descriptorSetLayouts; - vk::PipelineLayout pipelineLayout; - IShaderOwner* owner = nullptr; - Context* context = nullptr; + { + public: + vk::Device device; + std::vector shaderModules; // TODO manage live time somewhere else to allow sharing of shader programs + std::vector shaderStageCreateInfo; + vk::Pipeline pipeline; // TODO pipeline and shader config should be split + std::vector descriptorSetLayouts; + vk::PipelineLayout pipelineLayout; + IShaderOwner* owner = nullptr; + Context* context = nullptr; - VulkanShader(Context* context, Scene::Shader* shader, IShaderOwner* owner); + VulkanShader(Context* context, Scene::Shader* shader, IShaderOwner* owner); - ~VulkanShader() override; + ~VulkanShader() override; - void Resize(); + void Resize(); - void Record(VulkanDrawContext* context) override; + void Record(VulkanDrawContext* context) override; - void Release() override; + void Release() override; - private: - void BuildPipeline(); + private: + void BuildPipeline(); - void CreatePipelineLayout(); - }; - } + void CreatePipelineLayout(); + }; } \ No newline at end of file diff --git a/openVulkanoCpp/Vulkan/Scene/VulkanVertexBuffer.hpp b/openVulkanoCpp/Vulkan/Scene/VulkanVertexBuffer.hpp new file mode 100644 index 0000000..f774ab9 --- /dev/null +++ b/openVulkanoCpp/Vulkan/Scene/VulkanVertexBuffer.hpp @@ -0,0 +1,43 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include "IRecordable.hpp" +#include "Scene/Scene.hpp" +#include "Scene/VertexBuffer.hpp" +#include "Vulkan/Resources/ManagedBuffer.hpp" + +namespace OpenVulkano::Vulkan +{ + class VulkanVertexBuffer final : public IRenderResource + { + ManagedBuffer::Ptr m_vertexBuffer; + + public: + VulkanVertexBuffer(Scene::VertexBuffer* vbo, ManagedBuffer::Ptr& vertexBuffer) + : IRenderResource(vbo) , m_vertexBuffer(std::move(vertexBuffer)) + {} + + ~VulkanVertexBuffer() override = default; + + void RecordBind(vk::CommandBuffer& cmdBuffer) + { + const vk::DeviceSize m_offsets = 0; + cmdBuffer.bindVertexBuffers(0, 1, &m_vertexBuffer->buffer, &m_offsets); + } + + void RecordDraw(vk::CommandBuffer& cmdBuffer, uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex = 0, uint32_t firstInstance = 0) + { + cmdBuffer.draw(vertexCount, instanceCount, firstVertex, firstInstance); + } + + void Release() override + { + //TODO + } + }; +}