Merge pull request 'Label Update' (#184) from LabelUpdate into master
Reviewed-on: https://git.madvoxel.net/OpenVulkano/OpenVulkano/pulls/184
This commit is contained in:
@@ -31,10 +31,9 @@ namespace OpenVulkano
|
|||||||
class BillboardExampleAppImpl final : public BillboardExampleApp
|
class BillboardExampleAppImpl final : public BillboardExampleApp
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
void Init() override
|
void Init() override
|
||||||
{
|
{
|
||||||
auto engineConfig = OpenVulkano::EngineConfiguration::GetEngineConfiguration();
|
auto engineConfig = EngineConfiguration::GetEngineConfiguration();
|
||||||
engineConfig->SetPreferFramebufferFormatSRGB(false);
|
engineConfig->SetPreferFramebufferFormatSRGB(false);
|
||||||
engineConfig->SetFpsCap(0); // monitor's refresh rate
|
engineConfig->SetFpsCap(0); // monitor's refresh rate
|
||||||
engineConfig->SetVSync(true);
|
engineConfig->SetVSync(true);
|
||||||
@@ -44,17 +43,17 @@ namespace OpenVulkano
|
|||||||
m_cam.Init(70, 16, 9, 0.1f, 100);
|
m_cam.Init(70, 16, 9, 0.1f, 100);
|
||||||
m_scene.SetCamera(&m_cam);
|
m_scene.SetCamera(&m_cam);
|
||||||
|
|
||||||
m_quadBillboardShader.AddShaderProgram(OpenVulkano::ShaderProgramType::VERTEX, "Shader/billboardFromSinglePoint");
|
m_quadBillboardShader.AddShaderProgram(ShaderProgramType::VERTEX, "Shader/billboardFromSinglePoint");
|
||||||
m_quadBillboardShader.AddShaderProgram(OpenVulkano::ShaderProgramType::GEOMETRY, "Shader/billboardFromSinglePoint");
|
m_quadBillboardShader.AddShaderProgram(ShaderProgramType::GEOMETRY, "Shader/billboardFromSinglePoint");
|
||||||
m_quadBillboardShader.AddShaderProgram(OpenVulkano::ShaderProgramType::FRAGMENT, "Shader/basic");
|
m_quadBillboardShader.AddShaderProgram(ShaderProgramType::FRAGMENT, "Shader/basic");
|
||||||
m_quadBillboardShader.AddVertexInputDescription(OpenVulkano::Vertex::GetVertexInputDescription());
|
m_quadBillboardShader.AddVertexInputDescription(Vertex::GetVertexInputDescription());
|
||||||
m_quadBillboardShader.AddDescriptorSetLayoutBinding(Texture::DESCRIPTOR_SET_LAYOUT_BINDING);
|
m_quadBillboardShader.AddDescriptorSetLayoutBinding(Texture::DESCRIPTOR_SET_LAYOUT_BINDING);
|
||||||
m_quadBillboardShader.AddDescriptorSetLayoutBinding(UniformBuffer::DESCRIPTOR_SET_LAYOUT_BINDING, 4);
|
m_quadBillboardShader.AddDescriptorSetLayoutBinding(UniformBuffer::DESCRIPTOR_SET_LAYOUT_BINDING, 4);
|
||||||
m_quadBillboardShader.topology = Topology::POINT_LIST;
|
m_quadBillboardShader.topology = Topology::POINT_LIST;
|
||||||
|
|
||||||
m_shader.AddShaderProgram(OpenVulkano::ShaderProgramType::VERTEX, "Shader/billboard");
|
m_shader.AddShaderProgram(ShaderProgramType::VERTEX, "Shader/billboard");
|
||||||
m_shader.AddShaderProgram(OpenVulkano::ShaderProgramType::FRAGMENT, "Shader/basic");
|
m_shader.AddShaderProgram(ShaderProgramType::FRAGMENT, "Shader/basic");
|
||||||
m_shader.AddVertexInputDescription(OpenVulkano::Vertex::GetVertexInputDescription());
|
m_shader.AddVertexInputDescription(Vertex::GetVertexInputDescription());
|
||||||
m_shader.AddDescriptorSetLayoutBinding(Texture::DESCRIPTOR_SET_LAYOUT_BINDING);
|
m_shader.AddDescriptorSetLayoutBinding(Texture::DESCRIPTOR_SET_LAYOUT_BINDING);
|
||||||
m_shader.AddDescriptorSetLayoutBinding(UniformBuffer::DESCRIPTOR_SET_LAYOUT_BINDING, 4);
|
m_shader.AddDescriptorSetLayoutBinding(UniformBuffer::DESCRIPTOR_SET_LAYOUT_BINDING, 4);
|
||||||
m_shader.cullMode = CullMode::NONE;
|
m_shader.cullMode = CullMode::NONE;
|
||||||
@@ -85,13 +84,13 @@ namespace OpenVulkano
|
|||||||
geo->vertices[0].color = glm::vec4(1, 1, 1, 1);
|
geo->vertices[0].color = glm::vec4(1, 1, 1, 1);
|
||||||
else
|
else
|
||||||
geo->vertices[0].color = glm::vec4(1, 0, 0, 1);
|
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);
|
m_drawablesPool[i].Init(&m_quadBillboardShader, geo, &m_texturedMat, &m_uniBuffer);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*geo = GeometryFactory::MakePyramid(1, 1, glm::vec4(0, 1, 0, 1));
|
*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_drawablesPool[i].Init(&m_shader, geo, &m_mat, &m_uniBuffer);
|
||||||
}
|
}
|
||||||
m_scene.GetRoot()->AddChild(&m_nodesPool[i]);
|
m_scene.GetRoot()->AddChild(&m_nodesPool[i]);
|
||||||
@@ -105,8 +104,8 @@ namespace OpenVulkano
|
|||||||
m_camController.SetPosition({ 0, 0, 5 });
|
m_camController.SetPosition({ 0, 0, 5 });
|
||||||
m_camController.SetBoostFactor(5);
|
m_camController.SetBoostFactor(5);
|
||||||
|
|
||||||
std::shared_ptr<OpenVulkano::Scene::UI::PerformanceInfo> m_perfInfo =
|
std::shared_ptr<UI::PerformanceInfo> m_perfInfo =
|
||||||
std::make_shared<OpenVulkano::Scene::UI::PerformanceInfo>();
|
std::make_shared<UI::PerformanceInfo>();
|
||||||
m_ui.AddElement(m_perfInfo);
|
m_ui.AddElement(m_perfInfo);
|
||||||
GetGraphicsAppManager()->GetRenderer()->SetActiveUi(&m_ui);
|
GetGraphicsAppManager()->GetRenderer()->SetActiveUi(&m_ui);
|
||||||
}
|
}
|
||||||
@@ -125,7 +124,7 @@ namespace OpenVulkano
|
|||||||
BillboardControlBlock m_bbContolBlock;
|
BillboardControlBlock m_bbContolBlock;
|
||||||
PerspectiveCamera m_cam;
|
PerspectiveCamera m_cam;
|
||||||
UniformBuffer m_uniBuffer;
|
UniformBuffer m_uniBuffer;
|
||||||
OpenVulkano::FreeCamCameraController m_camController;
|
FreeCamCameraController m_camController;
|
||||||
Material m_mat;
|
Material m_mat;
|
||||||
Material m_texturedMat;
|
Material m_texturedMat;
|
||||||
Shader m_shader;
|
Shader m_shader;
|
||||||
@@ -133,9 +132,9 @@ namespace OpenVulkano
|
|||||||
std::vector<SimpleDrawable> m_drawablesPool;
|
std::vector<SimpleDrawable> m_drawablesPool;
|
||||||
std::vector<Node> m_nodesPool;
|
std::vector<Node> m_nodesPool;
|
||||||
Vector3f_SIMD m_position = { 0, 0, -10 };
|
Vector3f_SIMD m_position = { 0, 0, -10 };
|
||||||
OpenVulkano::Scene::UI::SimpleUi m_ui;
|
UI::SimpleUi m_ui;
|
||||||
std::vector<Geometry> m_geo;
|
std::vector<Geometry> m_geo;
|
||||||
std::shared_ptr<OpenVulkano::Scene::UI::PerformanceInfo> m_perfInfo;
|
std::shared_ptr<UI::PerformanceInfo> m_perfInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
IGraphicsApp* BillboardExampleApp::Create() { return new BillboardExampleAppImpl(); }
|
IGraphicsApp* BillboardExampleApp::Create() { return new BillboardExampleAppImpl(); }
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ namespace OpenVulkano
|
|||||||
{
|
{
|
||||||
OpenVulkano::Scene::Scene scene;
|
OpenVulkano::Scene::Scene scene;
|
||||||
PerspectiveCamera cam;
|
PerspectiveCamera cam;
|
||||||
OpenVulkano::FreeCamCameraController camController;
|
FreeCamCameraController camController;
|
||||||
Material mat;
|
Material mat;
|
||||||
Shader shader;
|
Shader shader;
|
||||||
std::vector<SimpleDrawable> drawablesPool;
|
std::vector<SimpleDrawable> drawablesPool;
|
||||||
@@ -44,13 +44,13 @@ namespace OpenVulkano
|
|||||||
Vector3f_SIMD position = {0, 0, -10};
|
Vector3f_SIMD position = {0, 0, -10};
|
||||||
std::vector<Geometry> m_geos;
|
std::vector<Geometry> m_geos;
|
||||||
|
|
||||||
OpenVulkano::Scene::UI::SimpleUi m_ui;
|
UI::SimpleUi m_ui;
|
||||||
std::shared_ptr<OpenVulkano::Scene::UI::PerformanceInfo> m_perfInfo;
|
std::shared_ptr<UI::PerformanceInfo> m_perfInfo;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Init() override
|
void Init() override
|
||||||
{
|
{
|
||||||
auto engineConfig = OpenVulkano::EngineConfiguration::GetEngineConfiguration();
|
auto engineConfig = EngineConfiguration::GetEngineConfiguration();
|
||||||
//engineConfig->SetNumThreads(4);
|
//engineConfig->SetNumThreads(4);
|
||||||
engineConfig->SetPreferFramebufferFormatSRGB(false);
|
engineConfig->SetPreferFramebufferFormatSRGB(false);
|
||||||
|
|
||||||
@@ -58,9 +58,9 @@ namespace OpenVulkano
|
|||||||
scene.Init();
|
scene.Init();
|
||||||
cam.Init(70, 16, 9, 0.1f, 100);
|
cam.Init(70, 16, 9, 0.1f, 100);
|
||||||
scene.SetCamera(&cam);
|
scene.SetCamera(&cam);
|
||||||
shader.AddShaderProgram(OpenVulkano::ShaderProgramType::VERTEX, "Shader/basic");
|
shader.AddShaderProgram(ShaderProgramType::VERTEX, "Shader/basic");
|
||||||
shader.AddShaderProgram(OpenVulkano::ShaderProgramType::FRAGMENT, "Shader/basic");
|
shader.AddShaderProgram(ShaderProgramType::FRAGMENT, "Shader/basic");
|
||||||
shader.AddVertexInputDescription(OpenVulkano::Vertex::GetVertexInputDescription());
|
shader.AddVertexInputDescription(Vertex::GetVertexInputDescription());
|
||||||
drawablesPool.resize(GEOS);
|
drawablesPool.resize(GEOS);
|
||||||
m_geos.reserve(GEOS);
|
m_geos.reserve(GEOS);
|
||||||
for (uint32_t i = 0; i < GEOS; i++)
|
for (uint32_t i = 0; i < GEOS; i++)
|
||||||
@@ -78,7 +78,7 @@ namespace OpenVulkano
|
|||||||
scene.GetRoot()->AddChild(&nodesPool[i]);
|
scene.GetRoot()->AddChild(&nodesPool[i]);
|
||||||
if (i < DYNAMIC) nodesPool[i].SetUpdateFrequency(UpdateFrequency::Always);
|
if (i < DYNAMIC) nodesPool[i].SetUpdateFrequency(UpdateFrequency::Always);
|
||||||
nodesPool[i].AddDrawable(&drawablesPool[std::rand() % GEOS]);
|
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);
|
GetGraphicsAppManager()->GetRenderer()->SetScene(&scene);
|
||||||
@@ -87,7 +87,7 @@ namespace OpenVulkano
|
|||||||
camController.SetDefaultKeybindings();
|
camController.SetDefaultKeybindings();
|
||||||
camController.SetPosition({0, 0, 10});
|
camController.SetPosition({0, 0, 10});
|
||||||
|
|
||||||
std::shared_ptr<OpenVulkano::Scene::UI::PerformanceInfo> m_perfInfo = std::make_shared<OpenVulkano::Scene::UI::PerformanceInfo>();
|
std::shared_ptr<UI::PerformanceInfo> m_perfInfo = std::make_shared<UI::PerformanceInfo>();
|
||||||
m_ui.AddElement(m_perfInfo);
|
m_ui.AddElement(m_perfInfo);
|
||||||
GetGraphicsAppManager()->GetRenderer()->SetActiveUi(&m_ui);
|
GetGraphicsAppManager()->GetRenderer()->SetActiveUi(&m_ui);
|
||||||
}
|
}
|
||||||
@@ -96,7 +96,7 @@ namespace OpenVulkano
|
|||||||
{
|
{
|
||||||
for (uint32_t i = 0; i < DYNAMIC; i++)
|
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();
|
camController.Tick();
|
||||||
|
|||||||
@@ -7,14 +7,8 @@
|
|||||||
#include "LabelDrawableExampleApp.hpp"
|
#include "LabelDrawableExampleApp.hpp"
|
||||||
#include "Scene/Scene.hpp"
|
#include "Scene/Scene.hpp"
|
||||||
#include "Scene/Shader/Shader.hpp"
|
#include "Scene/Shader/Shader.hpp"
|
||||||
#include "Scene/Geometry.hpp"
|
|
||||||
#include "Scene/TextDrawable.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/UI/PerformanceInfo.hpp"
|
||||||
#include "Scene/UniformBuffer.hpp"
|
|
||||||
#include "Scene/Prefabs/LabelDrawable.hpp"
|
#include "Scene/Prefabs/LabelDrawable.hpp"
|
||||||
#include "Input/InputManager.hpp"
|
#include "Input/InputManager.hpp"
|
||||||
#include "Host/GraphicsAppManager.hpp"
|
#include "Host/GraphicsAppManager.hpp"
|
||||||
@@ -23,9 +17,7 @@
|
|||||||
#include "Math/Math.hpp"
|
#include "Math/Math.hpp"
|
||||||
#include "Base/EngineConfiguration.hpp"
|
#include "Base/EngineConfiguration.hpp"
|
||||||
#include "Controller/FreeCamCameraController.hpp"
|
#include "Controller/FreeCamCameraController.hpp"
|
||||||
#include "Image/ImageLoaderPng.hpp"
|
|
||||||
#include "Scene/SdfFontAtlasGenerator.hpp"
|
#include "Scene/SdfFontAtlasGenerator.hpp"
|
||||||
#include "Scene/IFontAtlasGenerator.hpp"
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@@ -45,9 +37,7 @@ namespace OpenVulkano
|
|||||||
|
|
||||||
void Init() override
|
void Init() override
|
||||||
{
|
{
|
||||||
auto engineConfig = OpenVulkano::EngineConfiguration::GetEngineConfiguration();
|
EngineConfiguration::GetEngineConfiguration()->SetPreferFramebufferFormatSRGB(false);
|
||||||
engineConfig->SetNumThreads(1);
|
|
||||||
engineConfig->SetPreferFramebufferFormatSRGB(false);
|
|
||||||
|
|
||||||
std::srand(1); // Fix seed for random numbers
|
std::srand(1); // Fix seed for random numbers
|
||||||
m_scene.Init();
|
m_scene.Init();
|
||||||
@@ -63,7 +53,6 @@ namespace OpenVulkano
|
|||||||
m_nodesPool.resize(N);
|
m_nodesPool.resize(N);
|
||||||
m_drawablesPool.reserve(N);
|
m_drawablesPool.reserve(N);
|
||||||
|
|
||||||
BillboardControlBlock billboardSettings;
|
|
||||||
LabelDrawableSettings labelSettings;
|
LabelDrawableSettings labelSettings;
|
||||||
|
|
||||||
for (int i = 0; i < N; i++)
|
for (int i = 0; i < N; i++)
|
||||||
@@ -74,12 +63,11 @@ namespace OpenVulkano
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
labelSettings.hasRoundedCorners = (i % 2 == 0 ? 0 : 1);
|
labelSettings.hasRoundedCorners = i & 1;
|
||||||
labelSettings.hasArrow = (i % 2 == 0 ? 1 : 0);
|
labelSettings.hasArrow = i % 2 == 0;
|
||||||
}
|
}
|
||||||
bool isBillboard = (i % 2 == 0 ? 1 : 0);
|
labelSettings.isBillboard = i % 2 == 0;
|
||||||
LabelDrawable& label = m_drawablesPool.emplace_back(textDrawable.GetAtlasData(), labelSettings, isBillboard);
|
LabelDrawable& label = m_drawablesPool.emplace_back(textDrawable.GetAtlasData(), labelSettings);
|
||||||
label.SetBillboardSettings(billboardSettings);
|
|
||||||
label.AddText(texts[i]);
|
label.AddText(texts[i]);
|
||||||
if (i == 2)
|
if (i == 2)
|
||||||
{
|
{
|
||||||
@@ -90,7 +78,7 @@ namespace OpenVulkano
|
|||||||
}
|
}
|
||||||
m_drawablesPool[i].SetIsHittable(true);
|
m_drawablesPool[i].SetIsHittable(true);
|
||||||
m_scene.GetRoot()->AddChild(&m_nodesPool[i]);
|
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]);
|
m_nodesPool[i].AddDrawable(&m_drawablesPool[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,8 +88,7 @@ namespace OpenVulkano
|
|||||||
m_camController.SetPosition({ 0, 0, 10 });
|
m_camController.SetPosition({ 0, 0, 10 });
|
||||||
m_camController.SetBoostFactor(5);
|
m_camController.SetBoostFactor(5);
|
||||||
|
|
||||||
std::shared_ptr<OpenVulkano::Scene::UI::PerformanceInfo> m_perfInfo =
|
std::shared_ptr<UI::PerformanceInfo> m_perfInfo = std::make_shared<UI::PerformanceInfo>();
|
||||||
std::make_shared<OpenVulkano::Scene::UI::PerformanceInfo>();
|
|
||||||
m_ui.AddElement(m_perfInfo);
|
m_ui.AddElement(m_perfInfo);
|
||||||
GetGraphicsAppManager()->GetRenderer()->SetActiveUi(&m_ui);
|
GetGraphicsAppManager()->GetRenderer()->SetActiveUi(&m_ui);
|
||||||
}
|
}
|
||||||
@@ -116,12 +103,12 @@ namespace OpenVulkano
|
|||||||
private:
|
private:
|
||||||
OpenVulkano::Scene::Scene m_scene;
|
OpenVulkano::Scene::Scene m_scene;
|
||||||
PerspectiveCamera m_cam;
|
PerspectiveCamera m_cam;
|
||||||
OpenVulkano::FreeCamCameraController m_camController;
|
FreeCamCameraController m_camController;
|
||||||
std::vector<LabelDrawable> m_drawablesPool;
|
std::vector<LabelDrawable> m_drawablesPool;
|
||||||
std::vector<Node> m_nodesPool;
|
std::vector<Node> m_nodesPool;
|
||||||
Vector3f_SIMD m_position = { 0, 0, -10 };
|
Vector3f_SIMD m_position = { 0, 0, -10 };
|
||||||
OpenVulkano::Scene::UI::SimpleUi m_ui;
|
UI::SimpleUi m_ui;
|
||||||
std::shared_ptr<OpenVulkano::Scene::UI::PerformanceInfo> m_perfInfo;
|
std::shared_ptr<UI::PerformanceInfo> m_perfInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
IGraphicsApp* LabelDrawableExampleApp::Create() { return new LabelDrawableExampleAppImpl(); }
|
IGraphicsApp* LabelDrawableExampleApp::Create() { return new LabelDrawableExampleAppImpl(); }
|
||||||
|
|||||||
@@ -17,16 +17,12 @@
|
|||||||
#include "Scene/SimpleAnimationController.hpp"
|
#include "Scene/SimpleAnimationController.hpp"
|
||||||
#include "Scene/SequenceAnimationController.hpp"
|
#include "Scene/SequenceAnimationController.hpp"
|
||||||
#include "Scene/MorphableCameraController.hpp"
|
#include "Scene/MorphableCameraController.hpp"
|
||||||
#include "Scene/PlaneCameraController.hpp"
|
|
||||||
#include "Scene/UI/PerformanceInfo.hpp"
|
#include "Scene/UI/PerformanceInfo.hpp"
|
||||||
#include "Scene/SceneIntersectionTestController.hpp"
|
#include "Scene/SceneIntersectionTestController.hpp"
|
||||||
#include "Input/InputManager.hpp"
|
|
||||||
#include "Host/GraphicsAppManager.hpp"
|
#include "Host/GraphicsAppManager.hpp"
|
||||||
#include "Base/EngineConfiguration.hpp"
|
|
||||||
#include "Base/Logger.hpp"
|
#include "Base/Logger.hpp"
|
||||||
#include "Controller/FreeCamCameraController.hpp"
|
#include "Controller/FreeCamCameraController.hpp"
|
||||||
#include "Scene/Prefabs/LabelDrawable.hpp"
|
#include "Scene/Prefabs/LabelDrawable.hpp"
|
||||||
#include "Scene/SimpleDrawable.hpp"
|
|
||||||
#include "Scene/Ray.hpp"
|
#include "Scene/Ray.hpp"
|
||||||
|
|
||||||
#define USE_PLANE_CAM_CONTROL 0
|
#define USE_PLANE_CAM_CONTROL 0
|
||||||
|
|||||||
@@ -9,12 +9,8 @@
|
|||||||
#include "Scene/Shader/Shader.hpp"
|
#include "Scene/Shader/Shader.hpp"
|
||||||
#include "Scene/Geometry.hpp"
|
#include "Scene/Geometry.hpp"
|
||||||
#include "Scene/TextDrawable.hpp"
|
#include "Scene/TextDrawable.hpp"
|
||||||
#include "Scene/GeometryFactory.hpp"
|
|
||||||
#include "Scene/Material.hpp"
|
|
||||||
#include "Scene/Vertex.hpp"
|
#include "Scene/Vertex.hpp"
|
||||||
#include "Scene/SimpleDrawable.hpp"
|
|
||||||
#include "Scene/UI/PerformanceInfo.hpp"
|
#include "Scene/UI/PerformanceInfo.hpp"
|
||||||
#include "Scene/UniformBuffer.hpp"
|
|
||||||
#include "Input/InputManager.hpp"
|
#include "Input/InputManager.hpp"
|
||||||
#include "Host/GraphicsAppManager.hpp"
|
#include "Host/GraphicsAppManager.hpp"
|
||||||
#include "Host/GLFW/WindowGLFW.hpp"
|
#include "Host/GLFW/WindowGLFW.hpp"
|
||||||
@@ -22,9 +18,7 @@
|
|||||||
#include "Math/Math.hpp"
|
#include "Math/Math.hpp"
|
||||||
#include "Base/EngineConfiguration.hpp"
|
#include "Base/EngineConfiguration.hpp"
|
||||||
#include "Controller/FreeCamCameraController.hpp"
|
#include "Controller/FreeCamCameraController.hpp"
|
||||||
#include "Image/ImageLoaderPng.hpp"
|
|
||||||
#include "Scene/SdfFontAtlasGenerator.hpp"
|
#include "Scene/SdfFontAtlasGenerator.hpp"
|
||||||
#include "Scene/IFontAtlasGenerator.hpp"
|
|
||||||
#include "Scene/BitmapFontAtlasGenerator.hpp"
|
#include "Scene/BitmapFontAtlasGenerator.hpp"
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
@@ -45,11 +39,9 @@ namespace OpenVulkano
|
|||||||
class TextExampleAppImpl final : public TextExampleApp
|
class TextExampleAppImpl final : public TextExampleApp
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
void Init() override
|
void Init() override
|
||||||
{
|
{
|
||||||
auto engineConfig = OpenVulkano::EngineConfiguration::GetEngineConfiguration();
|
EngineConfiguration::GetEngineConfiguration()->SetPreferFramebufferFormatSRGB(false);
|
||||||
engineConfig->SetPreferFramebufferFormatSRGB(false);
|
|
||||||
|
|
||||||
std::srand(1); // Fix seed for random numbers
|
std::srand(1); // Fix seed for random numbers
|
||||||
m_scene.Init();
|
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("\u0410\u0411\u0412\u041F", TextConfig()));
|
||||||
texts.push_back(std::make_pair("Unsupported glyphs \u1E30\u1E31 are coming", 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.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 = 255;
|
||||||
texts[1].second.backgroundColor.a = 1;
|
|
||||||
|
|
||||||
const int N = texts.size();
|
const int N = texts.size();
|
||||||
auto& resourceLoader = ResourceLoader::GetInstance();
|
auto& resourceLoader = ResourceLoader::GetInstance();
|
||||||
@@ -73,6 +64,7 @@ namespace OpenVulkano
|
|||||||
|
|
||||||
if constexpr (CREATE_BITMAP_ATLAS)
|
if constexpr (CREATE_BITMAP_ATLAS)
|
||||||
{
|
{
|
||||||
|
// ReSharper disable once CppDFAUnreachableCode
|
||||||
std::set<uint32_t> s = BitmapFontAtlasGenerator::LoadAllGlyphs(fontPath);
|
std::set<uint32_t> s = BitmapFontAtlasGenerator::LoadAllGlyphs(fontPath);
|
||||||
BitmapFontAtlasGenerator generator;
|
BitmapFontAtlasGenerator generator;
|
||||||
generator.GenerateAtlas(fontPath, s);
|
generator.GenerateAtlas(fontPath, s);
|
||||||
@@ -98,32 +90,27 @@ namespace OpenVulkano
|
|||||||
#if defined(MSDFGEN_AVAILABLE) && CREATE_NEW_ATLAS
|
#if defined(MSDFGEN_AVAILABLE) && CREATE_NEW_ATLAS
|
||||||
if (i < texts.size())
|
if (i < texts.size())
|
||||||
{
|
{
|
||||||
t = new TextDrawable(m_atlasGenerator.GetAtlasData(), texts[textIdx].second);
|
t = new TextDrawable(m_atlasGenerator.GetAtlasData(), texts[textIdx].second);
|
||||||
t->SetShader(&TextDrawable::GetSdfDefaultShader());
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
t = new TextDrawable(m_msdfAtlasGenerator.GetAtlasData(), texts[textIdx].second);
|
t = new TextDrawable(m_msdfAtlasGenerator.GetAtlasData(), texts[textIdx].second);
|
||||||
t->SetShader(&TextDrawable::GetMsdfDefaultShader());
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
int xOffset = 0;
|
int xOffset = 0;
|
||||||
if (i < N)
|
if (i < N)
|
||||||
{
|
{
|
||||||
t = new TextDrawable(sdfMetadataInfo, texts[textIdx].second);
|
t = new TextDrawable(sdfMetadataInfo, texts[textIdx].second);
|
||||||
t->SetShader(&TextDrawable::GetSdfDefaultShader());
|
|
||||||
xOffset = -5;
|
xOffset = -5;
|
||||||
}
|
}
|
||||||
else if (i >= N && i < N * 2)
|
else if (i >= N && i < N * 2)
|
||||||
{
|
{
|
||||||
t = new TextDrawable(msdfMetadataInfo, texts[textIdx].second);
|
t = new TextDrawable(msdfMetadataInfo, texts[textIdx].second);
|
||||||
t->SetShader(&TextDrawable::GetMsdfDefaultShader());
|
|
||||||
xOffset = 15;
|
xOffset = 15;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
t = new TextDrawable(bitmapMetadataInfo, texts[textIdx].second);
|
t = new TextDrawable(bitmapMetadataInfo, texts[textIdx].second);
|
||||||
t->SetShader(&TextDrawable::GetBitmapDefaultShader());
|
|
||||||
xOffset = 35;
|
xOffset = 35;
|
||||||
}
|
}
|
||||||
// OR use separate texture + metadata file
|
// OR use separate texture + metadata file
|
||||||
@@ -139,10 +126,10 @@ namespace OpenVulkano
|
|||||||
//TextDrawable* t = new TextDrawable(metadataInfo, &tex, texts[i].second);
|
//TextDrawable* t = new TextDrawable(metadataInfo, &tex, texts[i].second);
|
||||||
#endif // MSDFGEN_AVAILABLE
|
#endif // MSDFGEN_AVAILABLE
|
||||||
t->GenerateText(texts[textIdx].first);
|
t->GenerateText(texts[textIdx].first);
|
||||||
m_drawablesPool[i] = t;
|
m_drawablesPool[i].reset(t);
|
||||||
m_nodesPool[i].Init();
|
m_nodesPool[i].Init();
|
||||||
m_nodesPool[i].SetMatrix(Math::Utils::translate(glm::mat4x4(1.f), Vector3f(xOffset, 2 - textIdx * 2, 0)));
|
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]);
|
m_scene.GetRoot()->AddChild(&m_nodesPool[i]);
|
||||||
}
|
}
|
||||||
GetGraphicsAppManager()->GetRenderer()->SetScene(&m_scene);
|
GetGraphicsAppManager()->GetRenderer()->SetScene(&m_scene);
|
||||||
@@ -151,8 +138,8 @@ namespace OpenVulkano
|
|||||||
m_camController.SetPosition({ 10, 0, 15 });
|
m_camController.SetPosition({ 10, 0, 15 });
|
||||||
m_camController.SetBoostFactor(5);
|
m_camController.SetBoostFactor(5);
|
||||||
|
|
||||||
std::shared_ptr<OpenVulkano::Scene::UI::PerformanceInfo> m_perfInfo =
|
std::shared_ptr<UI::PerformanceInfo> m_perfInfo =
|
||||||
std::make_shared<OpenVulkano::Scene::UI::PerformanceInfo>();
|
std::make_shared<UI::PerformanceInfo>();
|
||||||
m_ui.AddElement(m_perfInfo);
|
m_ui.AddElement(m_perfInfo);
|
||||||
GetGraphicsAppManager()->GetRenderer()->SetActiveUi(&m_ui);
|
GetGraphicsAppManager()->GetRenderer()->SetActiveUi(&m_ui);
|
||||||
}
|
}
|
||||||
@@ -164,26 +151,22 @@ namespace OpenVulkano
|
|||||||
|
|
||||||
void Close() override
|
void Close() override
|
||||||
{
|
{
|
||||||
for (SimpleDrawable* d: m_drawablesPool)
|
m_drawablesPool.clear();
|
||||||
{
|
|
||||||
d->Close();
|
|
||||||
delete d;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
OpenVulkano::Scene::Scene m_scene;
|
OpenVulkano::Scene::Scene m_scene;
|
||||||
PerspectiveCamera m_cam;
|
PerspectiveCamera m_cam;
|
||||||
OpenVulkano::FreeCamCameraController m_camController;
|
FreeCamCameraController m_camController;
|
||||||
#ifdef MSDFGEN_AVAILABLE
|
#ifdef MSDFGEN_AVAILABLE
|
||||||
SdfFontAtlasGenerator m_atlasGenerator;
|
SdfFontAtlasGenerator m_atlasGenerator;
|
||||||
MsdfFontAtlasGenerator m_msdfAtlasGenerator;
|
MsdfFontAtlasGenerator m_msdfAtlasGenerator;
|
||||||
#endif
|
#endif
|
||||||
std::vector<SimpleDrawable*> m_drawablesPool;
|
std::vector<std::unique_ptr<Drawable>> m_drawablesPool;
|
||||||
std::vector<Node> m_nodesPool;
|
std::vector<Node> m_nodesPool;
|
||||||
Vector3f_SIMD m_position = { 0, 0, -10 };
|
Vector3f_SIMD m_position = { 0, 0, -10 };
|
||||||
OpenVulkano::Scene::UI::SimpleUi m_ui;
|
UI::SimpleUi m_ui;
|
||||||
std::shared_ptr<OpenVulkano::Scene::UI::PerformanceInfo> m_perfInfo;
|
std::shared_ptr<UI::PerformanceInfo> m_perfInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
IGraphicsApp* TextExampleApp::Create() { return new TextExampleAppImpl(); }
|
IGraphicsApp* TextExampleApp::Create() { return new TextExampleAppImpl(); }
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
#include "Input/InputManager.hpp"
|
#include "Input/InputManager.hpp"
|
||||||
#include "Host/GraphicsAppManager.hpp"
|
#include "Host/GraphicsAppManager.hpp"
|
||||||
#include "Math/Math.hpp"
|
#include "Math/Math.hpp"
|
||||||
#include "Base/EngineConfiguration.hpp"
|
|
||||||
#include "Controller/FreeCamCameraController.hpp"
|
#include "Controller/FreeCamCameraController.hpp"
|
||||||
#include "Base/FrameMetadata.hpp"
|
#include "Base/FrameMetadata.hpp"
|
||||||
|
|
||||||
@@ -30,14 +29,14 @@ namespace OpenVulkano
|
|||||||
{
|
{
|
||||||
OpenVulkano::Scene::Scene scene;
|
OpenVulkano::Scene::Scene scene;
|
||||||
PerspectiveCamera cam;
|
PerspectiveCamera cam;
|
||||||
OpenVulkano::FreeCamCameraController camController;
|
FreeCamCameraController camController;
|
||||||
Material mat;
|
Material mat;
|
||||||
Shader shader;
|
Shader shader;
|
||||||
SimpleDrawable drawable;
|
SimpleDrawable drawable;
|
||||||
Node node;
|
Node node;
|
||||||
|
|
||||||
OpenVulkano::Scene::UI::SimpleUi m_ui;
|
UI::SimpleUi m_ui;
|
||||||
std::shared_ptr<OpenVulkano::Scene::UI::PerformanceInfo> m_perfInfo;
|
std::shared_ptr<UI::PerformanceInfo> m_perfInfo;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Init() override
|
void Init() override
|
||||||
@@ -45,9 +44,9 @@ namespace OpenVulkano
|
|||||||
scene.Init();
|
scene.Init();
|
||||||
cam.Init(70, 16, 9, 0.1f, 100);
|
cam.Init(70, 16, 9, 0.1f, 100);
|
||||||
scene.SetCamera(&cam);
|
scene.SetCamera(&cam);
|
||||||
shader.AddShaderProgram(OpenVulkano::ShaderProgramType::VERTEX, "Shader/basic");
|
shader.AddShaderProgram(ShaderProgramType::VERTEX, "Shader/basic");
|
||||||
shader.AddShaderProgram(OpenVulkano::ShaderProgramType::FRAGMENT, "Shader/basicTexture");
|
shader.AddShaderProgram(ShaderProgramType::FRAGMENT, "Shader/basicTexture");
|
||||||
shader.AddVertexInputDescription(OpenVulkano::Vertex::GetVertexInputDescription());
|
shader.AddVertexInputDescription(Vertex::GetVertexInputDescription());
|
||||||
shader.AddDescriptorSetLayoutBinding(Texture::DESCRIPTOR_SET_LAYOUT_BINDING);
|
shader.AddDescriptorSetLayoutBinding(Texture::DESCRIPTOR_SET_LAYOUT_BINDING);
|
||||||
static Geometry geo = GeometryFactory::MakeCube();
|
static Geometry geo = GeometryFactory::MakeCube();
|
||||||
mat.texture = &Texture::PLACEHOLDER;
|
mat.texture = &Texture::PLACEHOLDER;
|
||||||
@@ -63,7 +62,7 @@ namespace OpenVulkano
|
|||||||
//camController.SetDefaultKeybindings();
|
//camController.SetDefaultKeybindings();
|
||||||
camController.SetPosition({0, 0, 2});
|
camController.SetPosition({0, 0, 2});
|
||||||
|
|
||||||
m_perfInfo = std::make_shared<OpenVulkano::Scene::UI::PerformanceInfo>();
|
m_perfInfo = std::make_shared<UI::PerformanceInfo>();
|
||||||
m_ui.AddElement(m_perfInfo);
|
m_ui.AddElement(m_perfInfo);
|
||||||
GetGraphicsAppManager()->GetRenderer()->SetActiveUi(&m_ui);
|
GetGraphicsAppManager()->GetRenderer()->SetActiveUi(&m_ui);
|
||||||
}
|
}
|
||||||
@@ -73,9 +72,9 @@ namespace OpenVulkano
|
|||||||
{
|
{
|
||||||
t += CURRENT_FRAME.frameTime * 0.25;
|
t += CURRENT_FRAME.frameTime * 0.25;
|
||||||
|
|
||||||
Math::Matrix4f rotation = Math::Utils::rotate(t, Math::Vector3f_SIMD{1.0f, 0.0f, 0.0f});
|
Matrix4f rotation = Math::Utils::rotate(t, 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, Vector3f_SIMD{0.0f, 1.0f, 0.0f});
|
||||||
rotation *= Math::Utils::rotate(t, Math::Vector3f_SIMD{0.0f, 0.0f, 1.0f});
|
rotation *= Math::Utils::rotate(t, Vector3f_SIMD{0.0f, 0.0f, 1.0f});
|
||||||
node.SetMatrix(rotation);
|
node.SetMatrix(rotation);
|
||||||
|
|
||||||
camController.Tick();
|
camController.Tick();
|
||||||
|
|||||||
@@ -20,40 +20,32 @@ using namespace OpenVulkano;
|
|||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
std::vector<std::string> examples;
|
int selectedExample = -1;
|
||||||
for (const auto& e : EXAMPLE_APPS)
|
if (argc == 2)
|
||||||
{
|
{
|
||||||
examples.emplace_back(e.first);
|
selectedExample = strtol(argv[1], nullptr, 10);
|
||||||
}
|
}
|
||||||
|
if (selectedExample < 0)
|
||||||
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 (event == ftxui::Event::CtrlC || event == ftxui::Event::CtrlZ)
|
std::vector<std::string> examples;
|
||||||
|
for (const auto& e : EXAMPLE_APPS)
|
||||||
{
|
{
|
||||||
screen.ExitLoopClosure()();
|
examples.emplace_back(e.first);
|
||||||
shouldExit = true;
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
});
|
|
||||||
screen.Loop(menu);
|
|
||||||
|
|
||||||
if (shouldExit)
|
ftxui::MenuOption option;
|
||||||
{
|
auto screen = ftxui::ScreenInteractive::TerminalOutput();
|
||||||
return 0;
|
bool shouldExit = true;
|
||||||
}
|
option.on_enter = [&]() { shouldExit = false; screen.ExitLoopClosure()(); };
|
||||||
|
auto menu = ftxui::Menu(&examples, &selectedExample, option);
|
||||||
|
screen.Loop(menu);
|
||||||
|
|
||||||
if (selectedExample >= examples.size())
|
if (shouldExit) return 0;
|
||||||
{
|
|
||||||
throw std::runtime_error("Invalid menu selection!");
|
if (selectedExample >= examples.size())
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Invalid menu selection!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<IGraphicsApp> app(EXAMPLE_APPS[selectedExample].second());
|
std::unique_ptr<IGraphicsApp> app(EXAMPLE_APPS[selectedExample].second());
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
namespace OpenVulkano
|
|
||||||
{
|
|
||||||
class ICloseable
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual ~ICloseable() = default;
|
|
||||||
|
|
||||||
virtual void Close() = 0;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -7,7 +7,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ITickable.hpp"
|
#include "ITickable.hpp"
|
||||||
#include "ICloseable.hpp"
|
|
||||||
#include "Version.hpp"
|
#include "Version.hpp"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@@ -15,7 +14,7 @@ namespace OpenVulkano
|
|||||||
{
|
{
|
||||||
class IGraphicsAppManager;
|
class IGraphicsAppManager;
|
||||||
|
|
||||||
class IGraphicsApp : public ITickable, public ICloseable
|
class IGraphicsApp : public ITickable
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
IGraphicsAppManager* m_manager = nullptr;
|
IGraphicsAppManager* m_manager = nullptr;
|
||||||
@@ -25,6 +24,7 @@ namespace OpenVulkano
|
|||||||
|
|
||||||
virtual void Init() = 0;
|
virtual void Init() = 0;
|
||||||
virtual void InitPostGraphics() {}
|
virtual void InitPostGraphics() {}
|
||||||
|
virtual void Close() {}
|
||||||
virtual void CloseFinalize() {}
|
virtual void CloseFinalize() {}
|
||||||
[[nodiscard]] IGraphicsAppManager* GetGraphicsAppManager() const { return m_manager; }
|
[[nodiscard]] IGraphicsAppManager* GetGraphicsAppManager() const { return m_manager; }
|
||||||
void SetGraphicsAppManager(IGraphicsAppManager* manager) { m_manager = manager; }
|
void SetGraphicsAppManager(IGraphicsAppManager* manager) { m_manager = manager; }
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ITickable.hpp"
|
#include "ITickable.hpp"
|
||||||
#include "ICloseable.hpp"
|
|
||||||
#include "UI/IWindow.hpp"
|
#include "UI/IWindow.hpp"
|
||||||
|
|
||||||
namespace OpenVulkano
|
namespace OpenVulkano
|
||||||
@@ -12,11 +11,11 @@ namespace OpenVulkano
|
|||||||
PlatformInitFailedException(char const* const message) : runtime_error(message) {}
|
PlatformInitFailedException(char const* const message) : runtime_error(message) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class IPlatform : public ITickable, public ICloseable
|
class IPlatform : public ITickable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void Init() = 0;
|
virtual void Init() = 0;
|
||||||
|
virtual void Close() = 0;
|
||||||
virtual IWindow* MakeWindow() = 0;
|
virtual IWindow* MakeWindow() = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
|
|
||||||
#include "IResourceManager.hpp"
|
#include "IResourceManager.hpp"
|
||||||
#include "Base/ITickable.hpp"
|
#include "Base/ITickable.hpp"
|
||||||
#include "Base/ICloseable.hpp"
|
|
||||||
#include "Scene/Scene.hpp"
|
#include "Scene/Scene.hpp"
|
||||||
#include "Scene/UI/UI.hpp"
|
#include "Scene/UI/UI.hpp"
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -18,12 +17,13 @@ namespace OpenVulkano
|
|||||||
class IWindow;
|
class IWindow;
|
||||||
class IGraphicsAppManager;
|
class IGraphicsAppManager;
|
||||||
|
|
||||||
class IRenderer : public ITickable, public ICloseable
|
class IRenderer : public ITickable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~IRenderer() = default;
|
virtual ~IRenderer() = default;
|
||||||
|
|
||||||
virtual void Init(IGraphicsAppManager* graphicsAppManager, IWindow* window) = 0;
|
virtual void Init(IGraphicsAppManager* graphicsAppManager, IWindow* window) = 0;
|
||||||
|
virtual void Close() = 0;
|
||||||
|
|
||||||
virtual std::string GetMainRenderDeviceName() = 0;
|
virtual std::string GetMainRenderDeviceName() = 0;
|
||||||
virtual void Resize(uint32_t newWidth, uint32_t newHeight) = 0;
|
virtual void Resize(uint32_t newWidth, uint32_t newHeight) = 0;
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
|
|
||||||
#include "Math/Math.hpp"
|
#include "Math/Math.hpp"
|
||||||
#include "Base/PlatformEnums.hpp"
|
#include "Base/PlatformEnums.hpp"
|
||||||
#include "Base/ICloseable.hpp"
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
@@ -36,12 +35,13 @@ namespace OpenVulkano
|
|||||||
bool resizeable = true;
|
bool resizeable = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
class IWindow : public ICloseable
|
class IWindow
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
~IWindow() override = default;
|
virtual ~IWindow() = default;
|
||||||
|
|
||||||
virtual void Init(RenderAPI::RenderApi renderApi) = 0;
|
virtual void Init(RenderAPI::RenderApi renderApi) = 0;
|
||||||
|
virtual void Close() = 0;
|
||||||
|
|
||||||
virtual bool WindowHasBeenDestroyed() const = 0;
|
virtual bool WindowHasBeenDestroyed() const = 0;
|
||||||
virtual void SetWindowHasBeenDestroyed() = 0;
|
virtual void SetWindowHasBeenDestroyed() = 0;
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Base/ITickable.hpp"
|
#include "Base/ITickable.hpp"
|
||||||
#include "Base/ICloseable.hpp"
|
|
||||||
|
|
||||||
namespace OpenVulkano
|
namespace OpenVulkano
|
||||||
{
|
{
|
||||||
@@ -16,7 +15,7 @@ namespace OpenVulkano
|
|||||||
class Camera;
|
class Camera;
|
||||||
}
|
}
|
||||||
|
|
||||||
class CameraController : public ITickable, ICloseable
|
class CameraController : public ITickable
|
||||||
{
|
{
|
||||||
Scene::Camera* m_camera;
|
Scene::Camera* m_camera;
|
||||||
|
|
||||||
@@ -30,7 +29,7 @@ namespace OpenVulkano
|
|||||||
|
|
||||||
virtual void Init(Scene::Camera* camera) { m_camera = camera; }
|
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; }
|
void SetCamera(Scene::Camera* camera) { m_camera = camera; }
|
||||||
|
|
||||||
|
|||||||
@@ -105,7 +105,14 @@ namespace OpenVulkano
|
|||||||
|
|
||||||
String& Trim() noexcept { return TrimBack().TrimFront(); }
|
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
|
String& TrimFront() noexcept
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Base/ITickable.hpp"
|
#include "Base/ITickable.hpp"
|
||||||
#include "Base/ICloseable.hpp"
|
|
||||||
#include "Base/IPlatform.hpp"
|
#include "Base/IPlatform.hpp"
|
||||||
#include "InputDeviceGLFW.hpp"
|
#include "InputDeviceGLFW.hpp"
|
||||||
#include <array>
|
#include <array>
|
||||||
@@ -18,7 +17,7 @@ namespace OpenVulkano
|
|||||||
{
|
{
|
||||||
class WindowGLFW;
|
class WindowGLFW;
|
||||||
|
|
||||||
class InputProviderGLFW final : public ITickable, public ICloseable
|
class InputProviderGLFW final : public ITickable
|
||||||
{
|
{
|
||||||
friend WindowGLFW;
|
friend WindowGLFW;
|
||||||
static InputProviderGLFW* INSTANCE;
|
static InputProviderGLFW* INSTANCE;
|
||||||
@@ -32,7 +31,7 @@ namespace OpenVulkano
|
|||||||
public:
|
public:
|
||||||
void Init();
|
void Init();
|
||||||
|
|
||||||
void Close() override;
|
virtual void Close();
|
||||||
|
|
||||||
void PreTick();
|
void PreTick();
|
||||||
|
|
||||||
|
|||||||
@@ -6,12 +6,11 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Base/ICloseable.hpp"
|
|
||||||
#include "InputKey.hpp"
|
#include "InputKey.hpp"
|
||||||
|
|
||||||
namespace OpenVulkano::Input
|
namespace OpenVulkano::Input
|
||||||
{
|
{
|
||||||
class InputDevice : public ICloseable
|
class InputDevice
|
||||||
{
|
{
|
||||||
InputDeviceType deviceType = InputDeviceType::UNKNOWN;
|
InputDeviceType deviceType = InputDeviceType::UNKNOWN;
|
||||||
int index = -1;
|
int index = -1;
|
||||||
@@ -38,11 +37,11 @@ namespace OpenVulkano::Input
|
|||||||
[[nodiscard]] virtual bool ReadButtonDown(int16_t key) const = 0;
|
[[nodiscard]] virtual bool ReadButtonDown(int16_t key) const = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
~InputDevice() override = default;
|
virtual ~InputDevice() = default;
|
||||||
|
|
||||||
virtual void Tick() {}
|
virtual void Tick() {}
|
||||||
|
|
||||||
void Close() override
|
virtual void Close()
|
||||||
{
|
{
|
||||||
this->deviceType = InputDeviceType::UNKNOWN;
|
this->deviceType = InputDeviceType::UNKNOWN;
|
||||||
this->index = -1;
|
this->index = -1;
|
||||||
|
|||||||
@@ -14,101 +14,111 @@ namespace OpenVulkano::Math
|
|||||||
/**
|
/**
|
||||||
* \brief A class that represents an axis aligned bounding box
|
* \brief A class that represents an axis aligned bounding box
|
||||||
*/
|
*/
|
||||||
class AABB final : public Range<Math::Vector3f>
|
template<typename T>
|
||||||
|
class AABB_T final : public Range<T>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AABB() : Range(Math::Vector3f(INFINITY), Math::Vector3f(-INFINITY)) {}
|
AABB_T() : Range<T>(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<T>(min, max) {}
|
||||||
|
|
||||||
AABB(const Vector3f& point) : Range(point, point)
|
AABB_T(const T& point) : Range<T>(point, point)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
AABB(const Vector3f& point, float radius) : Range(point - radius, point + radius)
|
AABB_T(const T& point, float radius) : Range<T>(point - radius, point + radius)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Initiates the AABB to a single point (min=max=point)
|
* \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
|
* \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<T>::min = Range<T>::max = point;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Init(const Math::Vector3f& min, const Math::Vector3f& max)
|
void Init(const T& min, const T& max)
|
||||||
{
|
{
|
||||||
this->min = min;
|
this->min = min;
|
||||||
this->max = max;
|
this->max = max;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Init(const Math::Vector3f& point, float radius)
|
void Init(const T& point, float radius)
|
||||||
{
|
{
|
||||||
min = point - radius;
|
Range<T>::min = point - radius;
|
||||||
max = point + radius;
|
Range<T>::max = point + radius;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Initiates the AABB from some other AABB
|
* \brief Initiates the AABB from some other AABB
|
||||||
* \param other The other AABB that should be copied
|
* \param other The other AABB that should be copied
|
||||||
*/
|
*/
|
||||||
void Init(const AABB& other)
|
void Init(const AABB_T& other)
|
||||||
{
|
{
|
||||||
min = other.GetMin();
|
Range<T>::min = other.GetMin();
|
||||||
max = other.GetMax();
|
Range<T>::max = other.GetMax();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Grow(const Math::Vector3f& point)
|
void Grow(const T& point)
|
||||||
{
|
{
|
||||||
min = Math::Utils::min(min, point);
|
Range<T>::min = Math::Utils::min(Range<T>::min, point);
|
||||||
max = Math::Utils::max(max, point);
|
Range<T>::max = Math::Utils::max(Range<T>::max, point);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Grow(const AABB& otherAABB)
|
void Grow(const AABB_T& otherAABB)
|
||||||
{
|
{
|
||||||
min = Math::Utils::min(min, otherAABB.GetMin());
|
Range<T>::min = Math::Utils::min(Range<T>::min, otherAABB.GetMin());
|
||||||
max = Math::Utils::max(max, otherAABB.GetMax());
|
Range<T>::max = Math::Utils::max(Range<T>::max, otherAABB.GetMax());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Grow(const AABB& otherAABB, Math::Matrix4f transformation)
|
void Grow(const AABB_T& otherAABB, Math::Matrix4f transformation)
|
||||||
{
|
{
|
||||||
//TODO
|
//TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] Math::Vector3f GetDiagonal() const
|
[[nodiscard]] T GetDiagonal() const
|
||||||
{
|
{
|
||||||
return GetSize();
|
return Range<T>::GetSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] Math::Vector3f GetCenter() const
|
[[nodiscard]] T GetCenter() const
|
||||||
{
|
{
|
||||||
return min + (GetDiagonal() * 0.5f);
|
return Range<T>::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<T>::max)) && Math::Utils::all(Math::Utils::greaterThanEqual(Range<T>::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
|
* \param other The other AABB that should be checked
|
||||||
* \return true if the AABB overlaps with the other, false if not
|
* \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 ||
|
return Math::Utils::all(Math::Utils::lessThanEqual(Range<T>::min, other.GetMax())) && Math::Utils::all(Math::Utils::greaterThanEqual(Range<T>::max, other.GetMin()));
|
||||||
other.max.y < min.y || other.min.z > max.z || other.max.z < min.z);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[[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<T>::min, position)) && Math::Utils::all(Math::Utils::lessThanEqual(position, Range<T>::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<T>::min, position)) && Math::Utils::all(Math::Utils::lessThan(position, Range<T>::max));
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool IsEmpty() const
|
[[nodiscard]] bool IsEmpty() const
|
||||||
{
|
{
|
||||||
return min == Math::Vector3f(INFINITY) && max == Math::Vector3f(-INFINITY);
|
return Range<T>::min == T(INFINITY) && Range<T>::max == T(-INFINITY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -116,8 +126,13 @@ namespace OpenVulkano::Math
|
|||||||
*/
|
*/
|
||||||
void Reset()
|
void Reset()
|
||||||
{
|
{
|
||||||
min = Math::Vector3f(INFINITY);
|
Range<T>::min = T(INFINITY);
|
||||||
max = Math::Vector3f(-INFINITY);
|
Range<T>::max = T(-INFINITY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AABB_T& operator +=(const AABB_T& other) { Grow(other); return *this; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef AABB_T<Vector3f> AABB;
|
||||||
|
typedef AABB_T<Vector2f> AABB2f;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,6 +52,12 @@ namespace OpenVulkano::Math
|
|||||||
}
|
}
|
||||||
return angle;
|
return angle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr void SortPair(T& e1, T& e2)
|
||||||
|
{
|
||||||
|
if (e1 > e2) std::swap(e1, e2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> using Matrix2_SIMD = glm::tmat2x2<T, glm::aligned>;
|
template<typename T> using Matrix2_SIMD = glm::tmat2x2<T, glm::aligned>;
|
||||||
@@ -177,3 +183,15 @@ glm::vec<L, float, Q> operator / (const float lhs, const glm::vec<L, T, Q>& rhs)
|
|||||||
{
|
{
|
||||||
return lhs / glm::vec<L, float, Q>(rhs);
|
return lhs / glm::vec<L, float, Q>(rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<glm::length_t L, typename T, glm::qualifier Q, typename = std::enable_if_t<std::is_integral_v<T>>>
|
||||||
|
glm::vec<L, float, Q> operator * (const float lhs, const glm::vec<L, T, Q>& rhs)
|
||||||
|
{
|
||||||
|
return lhs * glm::vec<L, float, Q>(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<glm::length_t L, typename T, glm::qualifier Q, typename = std::enable_if_t<std::is_integral_v<T>>>
|
||||||
|
glm::vec<L, float, Q> operator * (const glm::vec<L, float, Q>& lhs, const T rhs)
|
||||||
|
{
|
||||||
|
return lhs * static_cast<float>(rhs);
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include "Scene/Texture.hpp"
|
#include "Scene/Texture.hpp"
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <magic_enum.hpp>
|
||||||
|
|
||||||
namespace OpenVulkano::Scene
|
namespace OpenVulkano::Scene
|
||||||
{
|
{
|
||||||
@@ -34,15 +35,22 @@ namespace OpenVulkano::Scene
|
|||||||
BITMAP,
|
BITMAP,
|
||||||
UNKNOWN
|
UNKNOWN
|
||||||
};
|
};
|
||||||
static constexpr std::string_view DEFAULT_FG_SHADERS[] = { "Shader/text", "Shader/msdfText" };
|
|
||||||
|
|
||||||
public:
|
static constexpr std::string_view DEFAULT_FG_SHADERS[] = { "Shader/sdfText", "Shader/msdfText", "Shader/text" };
|
||||||
FontAtlasType(Type type) : m_type(type) {}
|
|
||||||
Type GetType() const { return m_type; }
|
constexpr FontAtlasType(Type type) : m_type(type) {}
|
||||||
const std::string_view& GetDefaultFragmentShader() const
|
|
||||||
|
[[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<int>(m_type)];
|
return DEFAULT_FG_SHADERS[static_cast<int>(m_type)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr operator Type() const { return m_type; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Type m_type;
|
Type m_type;
|
||||||
};
|
};
|
||||||
@@ -51,7 +59,7 @@ namespace OpenVulkano::Scene
|
|||||||
{
|
{
|
||||||
// vertical difference between baselines
|
// vertical difference between baselines
|
||||||
double lineHeight = 0;
|
double lineHeight = 0;
|
||||||
int16_t atlasType = FontAtlasType::UNKNOWN;
|
FontAtlasType atlasType = FontAtlasType::UNKNOWN;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AtlasData
|
struct AtlasData
|
||||||
@@ -60,6 +68,8 @@ namespace OpenVulkano::Scene
|
|||||||
AtlasMetadata meta;
|
AtlasMetadata meta;
|
||||||
Unique<Image::Image> img;
|
Unique<Image::Image> img;
|
||||||
Texture texture;
|
Texture texture;
|
||||||
|
|
||||||
|
operator bool() const { return !glyphs.empty() && texture.textureBuffer; }
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -6,7 +6,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Base/ICloseable.hpp"
|
|
||||||
#include "Scene/IRayIntersectable.hpp"
|
#include "Scene/IRayIntersectable.hpp"
|
||||||
#include "DrawEncoder.hpp"
|
#include "DrawEncoder.hpp"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@@ -27,7 +26,7 @@ namespace OpenVulkano::Scene
|
|||||||
BACKGROUND = 0, MAIN, TRANSPARENT, POST
|
BACKGROUND = 0, MAIN, TRANSPARENT, POST
|
||||||
};
|
};
|
||||||
|
|
||||||
class Drawable : public ICloseable, public IRayIntersectable
|
class Drawable : public IRayIntersectable
|
||||||
{
|
{
|
||||||
std::vector<Node*> m_nodes;
|
std::vector<Node*> m_nodes;
|
||||||
Scene* m_scene = nullptr;
|
Scene* m_scene = nullptr;
|
||||||
@@ -43,7 +42,7 @@ namespace OpenVulkano::Scene
|
|||||||
|
|
||||||
~Drawable() override {/* if (m_scene) Drawable::Close();*/ }
|
~Drawable() override {/* if (m_scene) Drawable::Close();*/ }
|
||||||
|
|
||||||
void Close() override;
|
virtual void Close();
|
||||||
|
|
||||||
void SetShader(Shader* shader) { m_shader = shader; }
|
void SetShader(Shader* shader) { m_shader = shader; }
|
||||||
|
|
||||||
|
|||||||
@@ -7,30 +7,31 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "IFontAtlasGenerator.hpp"
|
#include "IFontAtlasGenerator.hpp"
|
||||||
|
#include "AtlasData.hpp"
|
||||||
#include "Math/AABB.hpp"
|
#include "Math/AABB.hpp"
|
||||||
#include "FreetypeHelper.hpp"
|
#include "Extensions/FreetypeHelper.hpp"
|
||||||
#include <variant>
|
#include <variant>
|
||||||
#include <set>
|
|
||||||
|
|
||||||
namespace OpenVulkano::Scene
|
namespace OpenVulkano::Scene
|
||||||
{
|
{
|
||||||
class FontAtlasGeneratorBase : public IFontAtlasGenerator
|
class FontAtlasGeneratorBase : public IFontAtlasGenerator
|
||||||
{
|
{
|
||||||
|
protected:
|
||||||
|
int m_channelsCount;
|
||||||
|
std::shared_ptr<AtlasData> m_atlasData;
|
||||||
|
|
||||||
public:
|
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;
|
void SaveAtlasMetadataInfo(const std::string& outputFile, bool packIntoSingleFile = true) const override;
|
||||||
std::shared_ptr<AtlasData> GetAtlasData() const { return m_atlasData; }
|
[[nodiscard]] const std::shared_ptr<AtlasData>& GetAtlasData() const override { return m_atlasData; }
|
||||||
int GetAtlasChannelsCount() const { return m_channelsCount; }
|
[[nodiscard]] int GetAtlasChannelsCount() const { return m_channelsCount; }
|
||||||
static std::set<uint32_t> LoadAllGlyphs(const std::variant<std::string, Array<char>>& data);
|
[[nodiscard]] static std::set<uint32_t> LoadAllGlyphs(const std::variant<std::string, Array<char>>& data);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void SavePng(std::string output) const;
|
void SavePng(std::string output) const;
|
||||||
void SetupAtlasData(Math::Vector2ui textureResolution, double lineHeight, FontAtlasType::Type atlasType);
|
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);
|
void SetGlyphData(GlyphInfo& info, Math::Vector2d bearing, Math::Vector2d size, const Math::AABB& aabb, double advance);
|
||||||
static std::string GetFreetypeErrorDescription(FT_Error error);
|
[[nodiscard]] static std::string GetFreetypeErrorDescription(FT_Error error);
|
||||||
static std::pair<FtLibraryRecPtr, FtFaceRecPtr> InitFreetype(const std::variant<std::string, Array<char>>& source);
|
[[nodiscard]] static std::pair<FtLibraryRecPtr, FtFaceRecPtr> InitFreetype(const std::variant<std::string, Array<char>>& source);
|
||||||
protected:
|
|
||||||
int m_channelsCount;
|
|
||||||
std::shared_ptr<AtlasData> m_atlasData;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -6,7 +6,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Base/ICloseable.hpp"
|
|
||||||
#include "Base/Render/RenderResource.hpp"
|
#include "Base/Render/RenderResource.hpp"
|
||||||
#include "Math/AABB.hpp"
|
#include "Math/AABB.hpp"
|
||||||
#include "Base/Utils.hpp"
|
#include "Base/Utils.hpp"
|
||||||
@@ -22,7 +21,7 @@ namespace OpenVulkano
|
|||||||
UINT16 = sizeof(uint16_t), UINT32 = sizeof(uint32_t)
|
UINT16 = sizeof(uint16_t), UINT32 = sizeof(uint32_t)
|
||||||
};
|
};
|
||||||
|
|
||||||
class Geometry : public RenderResourceHolder<Geometry>, public ICloseable
|
class Geometry : public RenderResourceHolder<Geometry>
|
||||||
{
|
{
|
||||||
friend class MeshLoader;
|
friend class MeshLoader;
|
||||||
public:
|
public:
|
||||||
@@ -51,7 +50,7 @@ namespace OpenVulkano
|
|||||||
|
|
||||||
void SetIndices(const uint32_t* data, uint32_t size, uint32_t dstOffset = 0) const;
|
void SetIndices(const uint32_t* data, uint32_t size, uint32_t dstOffset = 0) const;
|
||||||
|
|
||||||
void Close() override;
|
virtual void Close();
|
||||||
|
|
||||||
void Free();
|
void Free();
|
||||||
|
|
||||||
|
|||||||
@@ -6,24 +6,25 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Scene/AtlasData.hpp"
|
#include <Data/Containers/Array.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <map>
|
|
||||||
#include <variant>
|
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
namespace OpenVulkano::Scene
|
namespace OpenVulkano::Scene
|
||||||
{
|
{
|
||||||
|
struct AtlasData;
|
||||||
|
|
||||||
class IFontAtlasGenerator
|
class IFontAtlasGenerator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
virtual ~IFontAtlasGenerator() = default;
|
||||||
virtual void GenerateAtlas(const std::string& fontFile, const std::set<uint32_t>& charset,
|
virtual void GenerateAtlas(const std::string& fontFile, const std::set<uint32_t>& charset,
|
||||||
const std::optional<std::string>& pngOutput = std::nullopt) = 0;
|
const std::optional<std::string>& pngOutput = std::nullopt) = 0;
|
||||||
virtual void GenerateAtlas(const Array<char>& fontData, const std::set<uint32_t>& charset,
|
virtual void GenerateAtlas(const Array<char>& fontData, const std::set<uint32_t>& charset,
|
||||||
const std::optional<std::string>& pngOutput = std::nullopt) = 0;
|
const std::optional<std::string>& pngOutput = std::nullopt) = 0;
|
||||||
virtual void SaveAtlasMetadataInfo(const std::string& outputFile, bool packIntoSingleFile = true) const = 0;
|
virtual void SaveAtlasMetadataInfo(const std::string& outputFile, bool packIntoSingleFile = true) const = 0;
|
||||||
virtual std::shared_ptr<AtlasData> GetAtlasData() const = 0;
|
virtual const std::shared_ptr<AtlasData>& GetAtlasData() const = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ namespace OpenVulkano::Scene
|
|||||||
class IRayIntersectable
|
class IRayIntersectable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
virtual ~IRayIntersectable() = default;
|
||||||
virtual std::optional<RayHit> Intersect(const Ray& ray) const = 0;
|
virtual std::optional<RayHit> Intersect(const Ray& ray) const = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Base/ICloseable.hpp"
|
|
||||||
#include "Base/Render/RenderResource.hpp"
|
#include "Base/Render/RenderResource.hpp"
|
||||||
#include "Math/Math.hpp"
|
#include "Math/Math.hpp"
|
||||||
#include "Math/Pose.hpp"
|
#include "Math/Pose.hpp"
|
||||||
@@ -20,7 +19,7 @@ namespace OpenVulkano::Scene
|
|||||||
{
|
{
|
||||||
class Scene;
|
class Scene;
|
||||||
|
|
||||||
class Node : public RenderResourceHolder<Node>, public ICloseable
|
class Node : public RenderResourceHolder<Node>
|
||||||
{
|
{
|
||||||
friend Scene;
|
friend Scene;
|
||||||
|
|
||||||
@@ -41,11 +40,11 @@ namespace OpenVulkano::Scene
|
|||||||
|
|
||||||
Node(const Math::Matrix4f& pose);
|
Node(const Math::Matrix4f& pose);
|
||||||
|
|
||||||
~Node() noexcept override;
|
virtual ~Node() noexcept;
|
||||||
|
|
||||||
void Init();
|
void Init();
|
||||||
|
|
||||||
void Close() override;
|
virtual void Close();
|
||||||
|
|
||||||
void AddChild(Node* node);
|
void AddChild(Node* node);
|
||||||
|
|
||||||
|
|||||||
@@ -7,27 +7,77 @@
|
|||||||
#include "LabelDrawable.hpp"
|
#include "LabelDrawable.hpp"
|
||||||
#include "Scene/TextDrawable.hpp"
|
#include "Scene/TextDrawable.hpp"
|
||||||
#include "Scene/DrawEncoder.hpp"
|
#include "Scene/DrawEncoder.hpp"
|
||||||
|
#include "Scene/Vertex.hpp"
|
||||||
|
#include "Scene/Shader/Shader.hpp"
|
||||||
#include "Scene/IFontAtlasGenerator.hpp"
|
#include "Scene/IFontAtlasGenerator.hpp"
|
||||||
#include "Base/Logger.hpp"
|
#include "Base/Logger.hpp"
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
namespace OpenVulkano::Scene
|
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>& atlasData, const LabelDrawableSettings& settings,
|
Shader MakeLabelTextShader(const FontAtlasType type, const bool billboard)
|
||||||
bool isBillboard)
|
{
|
||||||
: Drawable(DrawEncoder::GetDrawEncoder<LabelDrawable>(), DrawPhase::MAIN)
|
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<int>(type) << 1 | billboard];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LabelDrawable::LabelDrawable(const std::shared_ptr<AtlasData>& atlasData, const LabelDrawableSettings& settings)
|
||||||
|
: Drawable(DrawEncoder::GetDrawEncoder<LabelDrawable>(), DrawPhase::MAIN), m_atlasData(atlasData)
|
||||||
|
, m_labelBuffer(sizeof(LabelUniformData), &m_labelData, 4)
|
||||||
{
|
{
|
||||||
if (atlasData->glyphs.empty() || !atlasData->texture.size)
|
if (atlasData->glyphs.empty() || !atlasData->texture.size)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Can't create label drawable. Either glyphs or texture is empty");
|
throw std::runtime_error("Can't create label drawable. Either glyphs or texture is empty");
|
||||||
}
|
}
|
||||||
m_atlasData = atlasData;
|
|
||||||
m_isBillboard = isBillboard;
|
|
||||||
SetLabelSettings(settings);
|
SetLabelSettings(settings);
|
||||||
SetupShaders();
|
SetShader(IsBillboard() ? &BACKGROUND_BILLBOARD_SHADER : &BACKGROUND_SHADER);
|
||||||
SetupBuffers();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LabelDrawable::SetLabelSettings(const LabelDrawableSettings& settings)
|
void LabelDrawable::SetLabelSettings(const LabelDrawableSettings& settings)
|
||||||
@@ -43,124 +93,27 @@ namespace OpenVulkano::Scene
|
|||||||
|
|
||||||
void LabelDrawable::AddText(const std::string& text, const TextConfig& config)
|
void LabelDrawable::AddText(const std::string& text, const TextConfig& config)
|
||||||
{
|
{
|
||||||
if (text.empty())
|
if (text.empty()) return;
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
TextDrawable& textDrawable = m_texts.emplace_back(m_atlasData, config);
|
TextDrawable& textDrawable = m_texts.emplace_back(m_atlasData, config);
|
||||||
// do not render glyph's background
|
textDrawable.GetConfig().backgroundColor.a = 0; // do not render glyph's background
|
||||||
textDrawable.GetConfig().backgroundColor.a = 0;
|
|
||||||
textDrawable.SetShader(&m_textShader);
|
|
||||||
double lineHeight = m_atlasData->meta.lineHeight;
|
double lineHeight = m_atlasData->meta.lineHeight;
|
||||||
|
|
||||||
textDrawable.GenerateText(text, m_position);
|
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
|
// update position for next text entry
|
||||||
m_position.y = m_bbox.GetMin().y - lineHeight;
|
m_position.y = m_bbox.GetMin().y - lineHeight;
|
||||||
|
|
||||||
const auto& min = m_bbox.GetMin();
|
Math::Vector2f padding = m_settings.padding * 2;
|
||||||
const auto& max = m_bbox.GetMax();
|
if (m_settings.hasArrow) padding.y += m_settings.arrowLength;
|
||||||
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);
|
|
||||||
|
|
||||||
m_labelData.textSize.x = v2.position.x - v.position.x;
|
m_labelData.textSize = Math::Vector2f(m_bbox.GetSize()) + padding * 2;
|
||||||
m_labelData.textSize.y = v3.position.y - v.position.y;
|
m_labelData.bboxCenter = { m_bbox.GetCenter() };
|
||||||
m_labelData.bboxCenter.x = (v2.position.x + v.position.x) / 2;
|
if (m_settings.hasArrow) m_labelData.bboxCenter.y -= m_settings.arrowLength;
|
||||||
m_labelData.bboxCenter.y = (v3.position.y + v.position.y) / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LabelDrawable::SetBillboardSettings(const BillboardControlBlock& settings)
|
|
||||||
{
|
|
||||||
m_billboardSettings = settings;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<RayHit> LabelDrawable::Intersect(const Ray& ray) const
|
std::optional<RayHit> LabelDrawable::Intersect(const Ray& ray) const
|
||||||
{
|
{
|
||||||
return ray.IntersectAABB(m_bbox);
|
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<FontAtlasType::Type>(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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,79 +6,66 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Base/Wrapper.hpp"
|
|
||||||
#include "Scene/Drawable.hpp"
|
#include "Scene/Drawable.hpp"
|
||||||
#include "Scene/Shader/Shader.hpp"
|
|
||||||
#include "Scene/Texture.hpp"
|
|
||||||
#include "Scene/UniformBuffer.hpp"
|
#include "Scene/UniformBuffer.hpp"
|
||||||
#include "Scene/Vertex.hpp"
|
|
||||||
#include "Scene/BillboardControlBlock.hpp"
|
|
||||||
#include "Math/AABB.hpp"
|
#include "Math/AABB.hpp"
|
||||||
#include "Scene/TextDrawable.hpp"
|
#include "Scene/TextDrawable.hpp"
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
namespace OpenVulkano::Scene
|
namespace OpenVulkano::Scene
|
||||||
{
|
{
|
||||||
|
class Shader;
|
||||||
|
|
||||||
struct LabelDrawableSettings
|
struct LabelDrawableSettings
|
||||||
{
|
{
|
||||||
Math::Vector4f backgroundColor = { 1, 0, 0, 1 };
|
Math::Vector4f backgroundColor = { 1, 0, 0, 1 };
|
||||||
float horizontalOffset = 0.05f;
|
Math::Vector2f padding = { 0.2f, 0.2f };
|
||||||
float verticalOffset = 0.05f;
|
|
||||||
float cornerRadius = 0.05f;
|
float cornerRadius = 0.05f;
|
||||||
float arrowLength = 0.5f;
|
float arrowLength = 0.5f;
|
||||||
float arrowWidth = 0.2f;
|
float arrowWidth = 0.2f;
|
||||||
int32_t hasRoundedCorners = false;
|
bool hasRoundedCorners = false;
|
||||||
int32_t hasArrow = false;
|
bool hasArrow = false;
|
||||||
|
bool isBillboard = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LabelUniformData
|
struct LabelUniformData
|
||||||
{
|
{
|
||||||
Math::Vector4f textSize = { 0, 0, 0, 0 };
|
|
||||||
Math::Vector4f color = { 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 cornerRadius = 0.f;
|
||||||
float arrowLength = 0.f;
|
float arrowLength = 0.f;
|
||||||
float arrowWidth = 0.f;
|
float arrowWidth = 0.f;
|
||||||
int32_t hasRoundedCorners = false;
|
int32_t hasRoundedCorners = false;
|
||||||
int32_t hasArrow = false;
|
int32_t hasArrow = false;
|
||||||
|
int32_t isBillboardFixedSize = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class LabelDrawable final : public Drawable
|
class LabelDrawable final : public Drawable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LabelDrawable(const std::shared_ptr<AtlasData>& atlasData,
|
LabelDrawable(const std::shared_ptr<AtlasData>& atlasData, const LabelDrawableSettings& settings = LabelDrawableSettings());
|
||||||
const LabelDrawableSettings& settings = LabelDrawableSettings(), bool isBillboard = false);
|
|
||||||
void AddText(const std::string& text, const TextConfig& config = TextConfig());
|
void AddText(const std::string& text, const TextConfig& config = TextConfig());
|
||||||
void SetLabelSettings(const LabelDrawableSettings& settings);
|
void SetLabelSettings(const LabelDrawableSettings& settings);
|
||||||
void SetBillboardSettings(const BillboardControlBlock& settings);
|
void SetPosition(const Math::Vector2f& pos) { m_position = pos; }
|
||||||
void SetPosition(const Math::Vector3f& pos) { m_position = pos; }
|
|
||||||
std::list<TextDrawable>& GetTexts() { return m_texts; }
|
[[nodiscard]] std::list<TextDrawable>& GetTexts() { return m_texts; }
|
||||||
LabelDrawableSettings& GetSettings() { return m_settings; }
|
[[nodiscard]] LabelDrawableSettings& GetSettings() { return m_settings; }
|
||||||
UniformBuffer* GetBillboardBuffer() { return &m_billboardBuffer; }
|
[[nodiscard]] UniformBuffer* GetLabelBuffer() { return &m_labelBuffer; }
|
||||||
UniformBuffer* GetLabelBuffer() { return &m_labelBuffer; }
|
[[nodiscard]] Math::Vector2f& GetPosition() { return m_position; }
|
||||||
BillboardControlBlock& GetBillboardSettings() { return m_billboardSettings; }
|
[[nodiscard]] bool IsBillboard() const { return m_settings.isBillboard; }
|
||||||
Math::Vector3f& GetPosition() { return m_position; }
|
[[nodiscard]] const Math::AABB2f& GetBoundingBox() const { return m_bbox; }
|
||||||
bool IsBillboard() const { return m_isBillboard; }
|
|
||||||
const Math::AABB& GetBoundingBox() const { return m_bbox; }
|
[[nodiscard]] std::optional<RayHit> Intersect(const Ray& ray) const override;
|
||||||
std::optional<RayHit> Intersect(const Ray& ray) const override;
|
|
||||||
private:
|
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<TextDrawable> m_texts;
|
|
||||||
Shader m_textShader;
|
|
||||||
LabelDrawableSettings m_settings;
|
LabelDrawableSettings m_settings;
|
||||||
LabelUniformData m_labelData;
|
|
||||||
std::shared_ptr<AtlasData> m_atlasData;
|
std::shared_ptr<AtlasData> m_atlasData;
|
||||||
BillboardControlBlock m_billboardSettings;
|
UniformBuffer m_labelBuffer;
|
||||||
Math::Vector3f m_position = { 0, 0, 0 };
|
LabelUniformData m_labelData;
|
||||||
Math::AABB m_bbox;
|
std::list<TextDrawable> m_texts; // Using list instead of vector for stable iterators
|
||||||
bool m_isBillboard;
|
Math::Vector2f m_position = { 0, 0 };
|
||||||
|
Math::AABB2f m_bbox;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,12 +10,9 @@
|
|||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
int SolveQuadraticEquation(float a, float b, float c, float& x0, float& x1)
|
int SolveQuadraticEquation(float a, float b, float c, float& x0, float& x1)
|
||||||
{
|
{
|
||||||
float discr = b * b - 4 * a * c;
|
const float discr = b * b - 4 * a * c;
|
||||||
if (discr < 0)
|
if (discr < 0) return 0;
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (discr == 0)
|
if (discr == 0)
|
||||||
{
|
{
|
||||||
x0 = x1 = (-b) / (2 * a);
|
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));
|
float q = (b > 0) ? -0.5 * (b + std::sqrt(discr)) : -0.5 * (b - std::sqrt(discr));
|
||||||
x0 = q / a;
|
x0 = q / a;
|
||||||
x1 = c / q;
|
x1 = c / q;
|
||||||
if (x0 > x1)
|
OpenVulkano::Math::Utils::SortPair(x0, x1);
|
||||||
{
|
|
||||||
std::swap(x0, x1);
|
|
||||||
}
|
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -50,10 +44,10 @@ namespace OpenVulkano::Scene
|
|||||||
std::optional<RayHit> Ray::IntersectTriangle(const Math::Vector3f& v0, const Math::Vector3f& v1,
|
std::optional<RayHit> Ray::IntersectTriangle(const Math::Vector3f& v0, const Math::Vector3f& v1,
|
||||||
const Math::Vector3f& v2) const
|
const Math::Vector3f& v2) const
|
||||||
{
|
{
|
||||||
RayHit hitRes;
|
|
||||||
float d;
|
float d;
|
||||||
if (intersectRayTriangle(m_origin, m_dir, v0, v1, v2, m_baryPos, d) && d >= 0)
|
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;
|
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 e = v1 - v0;
|
||||||
Math::Vector3f e2 = v2 - v0;
|
Math::Vector3f e2 = v2 - v0;
|
||||||
@@ -81,96 +75,73 @@ namespace OpenVulkano::Scene
|
|||||||
std::optional<RayHit> Ray::IntersectQuad(const Math::Vector3f& v0, const Math::Vector3f& v1,
|
std::optional<RayHit> Ray::IntersectQuad(const Math::Vector3f& v0, const Math::Vector3f& v1,
|
||||||
const Math::Vector3f& v2, const Math::Vector3f& v3) const
|
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;
|
return hitRes;
|
||||||
}
|
}
|
||||||
if (auto hitRes = IntersectTriangle(v0, v2, v3))
|
if (const auto hitRes = IntersectTriangle(v0, v2, v3))
|
||||||
{
|
{
|
||||||
return hitRes;
|
return hitRes;
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<RayHit> 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<RayHit> Ray::IntersectAABB(const Math::AABB& bbox) const
|
std::optional<RayHit> Ray::IntersectAABB(const Math::AABB& bbox) const
|
||||||
{
|
{
|
||||||
RayHit h1, h2;
|
RayHit h1, h2;
|
||||||
const int intersections = this->IntersectAABB(bbox, h1, h2);
|
const int intersections = this->IntersectAABB(bbox, h1, h2);
|
||||||
switch (intersections)
|
if (intersections == 1) return h1;
|
||||||
{
|
if (intersections == 2) return (h1.distance2 < h2.distance2) ? h1 : h2;
|
||||||
case 1:
|
|
||||||
return h1;
|
|
||||||
case 2:
|
|
||||||
return (h1.distance2 < h2.distance2) ? h1 : h2;
|
|
||||||
}
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
int Ray::IntersectAABB(const Math::AABB& bbox, RayHit& p1, RayHit& p2) const
|
int Ray::IntersectAABB(const Math::AABB& bbox, RayHit& p1, RayHit& p2) const
|
||||||
{
|
{
|
||||||
const auto tmin = (bbox.min - m_origin) / m_dir;
|
auto tmin = (bbox.min - m_origin) / m_dir;
|
||||||
const auto tmax = (bbox.max - m_origin) / m_dir;
|
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;
|
|
||||||
|
|
||||||
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);
|
tmax.x = tmax.y;
|
||||||
}
|
|
||||||
if ((txmin > tymax) || (tymin > txmax))
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tymin > txmin)
|
if ((tmin.x > tmax.z) || (tmin.z > tmax.x)) return 0;
|
||||||
{
|
|
||||||
txmin = tymin;
|
|
||||||
}
|
|
||||||
if (tymax < txmax)
|
|
||||||
{
|
|
||||||
txmax = tymax;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tzmin > tzmax)
|
|
||||||
{
|
|
||||||
std::swap(tzmin, tzmax);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((txmin > tzmax) || (tzmin > txmax))
|
if (tmin.z > tmin.x)
|
||||||
{
|
{
|
||||||
return 0;
|
tmin.x = tmin.z;
|
||||||
}
|
}
|
||||||
|
if (tmax.z < tmax.x)
|
||||||
if (tzmin > txmin)
|
|
||||||
{
|
{
|
||||||
txmin = tzmin;
|
tmax.x = tmax.z;
|
||||||
}
|
|
||||||
if (tzmax < txmax)
|
|
||||||
{
|
|
||||||
txmax = tzmax;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int intersections = 2;
|
int intersections = 2;
|
||||||
if (txmin < 0)
|
if (tmin.x < 0)
|
||||||
{
|
{
|
||||||
if (txmax < 0)
|
if (tmax.x < 0) return 0;
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
intersections--;
|
intersections--;
|
||||||
txmin = txmax;
|
tmin.x = tmax.x;
|
||||||
}
|
}
|
||||||
|
|
||||||
p1.point = m_origin + txmin * m_dir;
|
p1.point = m_origin + tmin.x * m_dir;
|
||||||
p2.point = m_origin + txmax * m_dir;
|
p2.point = m_origin + tmax.x * m_dir;
|
||||||
p1.distance2 = distance2(m_origin, p1.point);
|
p1.distance2 = distance2(m_origin, p1.point);
|
||||||
p2.distance2 = distance2(m_origin, p2.point);
|
p2.distance2 = distance2(m_origin, p2.point);
|
||||||
p1.normal = p2.normal = Math::Vector3f(0);
|
p1.normal = p2.normal = Math::Vector3f(0);
|
||||||
@@ -179,15 +150,11 @@ namespace OpenVulkano::Scene
|
|||||||
|
|
||||||
std::optional<RayHit> Ray::IntersectPlane(const Math::Vector3f& pOrigin, const Math::Vector3f& pNorm) const
|
std::optional<RayHit> Ray::IntersectPlane(const Math::Vector3f& pOrigin, const Math::Vector3f& pNorm) const
|
||||||
{
|
{
|
||||||
RayHit hit;
|
|
||||||
Math::Vector3f norm = normalize(pNorm);
|
Math::Vector3f norm = normalize(pNorm);
|
||||||
float d;
|
float d;
|
||||||
if (intersectRayPlane(m_origin, m_dir, pOrigin, pNorm, d))
|
if (intersectRayPlane(m_origin, m_dir, pOrigin, pNorm, d))
|
||||||
{
|
{
|
||||||
hit.SetDistance(d);
|
return {{ m_origin + m_dir * d, norm, d, d * d }};
|
||||||
hit.point = m_origin + m_dir * d;
|
|
||||||
hit.normal = norm;
|
|
||||||
return hit;
|
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@@ -201,56 +168,36 @@ namespace OpenVulkano::Scene
|
|||||||
float x1, x2;
|
float x1, x2;
|
||||||
int roots = ::SolveQuadraticEquation(a, b, c, x1, x2);
|
int roots = ::SolveQuadraticEquation(a, b, c, x1, x2);
|
||||||
|
|
||||||
if (roots == 0)
|
if (roots == 0) return 0;
|
||||||
{
|
SortPair(x1, x2);
|
||||||
return 0;
|
bool calcP2 = false;
|
||||||
}
|
|
||||||
if (x1 > x2)
|
|
||||||
{
|
|
||||||
std::swap(x1, x2);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (roots == 1)
|
if (roots == 1)
|
||||||
{
|
{
|
||||||
// ray intersects sphere behind the origin
|
if (x1 < 0) return 0; // 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;
|
|
||||||
}
|
}
|
||||||
else if (roots == 2)
|
else
|
||||||
{
|
{
|
||||||
// ray intersects sphere behind the origin
|
if (x1 < 0 && x2 < 0) return 0; // ray intersects sphere behind the origin
|
||||||
if (x1 < 0 && x2 < 0)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (x1 >= 0 && x2 >= 0)
|
if (x1 >= 0 && x2 >= 0)
|
||||||
{
|
{
|
||||||
p1.point = m_origin + x1 * m_dir;
|
calcP2 = true;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
--roots;
|
--roots;
|
||||||
if (x1 < 0)
|
if (x1 < 0) x1 = x2;
|
||||||
{
|
|
||||||
x1 = x2;
|
|
||||||
}
|
|
||||||
p1.point = m_origin + x1 * m_dir;
|
|
||||||
p1.distance2 = distance2(m_origin, p1.point);
|
|
||||||
p1.normal = normalize(p1.point - center);
|
|
||||||
p2 = p1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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;
|
return roots;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,21 +20,32 @@ namespace OpenVulkano::Scene
|
|||||||
Math::Vector3f point;
|
Math::Vector3f point;
|
||||||
Math::Vector3f normal;
|
Math::Vector3f normal;
|
||||||
float distance2;
|
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
|
[[nodiscard]] float GetDistance() const
|
||||||
{
|
{
|
||||||
if (distance == -1)
|
if (distance == -1) distance = std::sqrt(distance2);
|
||||||
{
|
|
||||||
distance = std::sqrt(distance2);
|
|
||||||
}
|
|
||||||
return distance;
|
return distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetDistance(float d)
|
void SetDistance(float d)
|
||||||
{
|
{
|
||||||
this->distance = d;
|
this->distance = d;
|
||||||
this->distance2 = d * d;
|
this->distance2 = d * d;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const RayHit& other) const;
|
bool operator==(const RayHit& other) const;
|
||||||
bool operator!=(const RayHit& other) const;
|
bool operator!=(const RayHit& other) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mutable float distance = -1;
|
mutable float distance = -1;
|
||||||
};
|
};
|
||||||
@@ -66,6 +77,7 @@ namespace OpenVulkano::Scene
|
|||||||
const Math::Vector3f& n1, const Math::Vector3f& n2) const;
|
const Math::Vector3f& n1, const Math::Vector3f& n2) const;
|
||||||
[[nodiscard]] std::optional<RayHit> IntersectQuad(const Math::Vector3f& v0, const Math::Vector3f& v1,
|
[[nodiscard]] std::optional<RayHit> IntersectQuad(const Math::Vector3f& v0, const Math::Vector3f& v1,
|
||||||
const Math::Vector3f& v2, const Math::Vector3f& v3) const;
|
const Math::Vector3f& v2, const Math::Vector3f& v3) const;
|
||||||
|
[[nodiscard]] std::optional<RayHit> IntersectAABB(const Math::AABB2f& bbox) const;
|
||||||
[[nodiscard]] std::optional<RayHit> IntersectAABB(const Math::AABB& bbox) const;
|
[[nodiscard]] std::optional<RayHit> IntersectAABB(const Math::AABB& bbox) const;
|
||||||
int IntersectAABB(const Math::AABB& bbox, RayHit& p1, RayHit& p2) const;
|
int IntersectAABB(const Math::AABB& bbox, RayHit& p1, RayHit& p2) const;
|
||||||
[[nodiscard]] std::optional<RayHit> IntersectPlane(const Math::Vector3f& pOrigin,
|
[[nodiscard]] std::optional<RayHit> IntersectPlane(const Math::Vector3f& pOrigin,
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ namespace OpenVulkano
|
|||||||
{
|
{
|
||||||
namespace Scene
|
namespace Scene
|
||||||
{
|
{
|
||||||
class Scene : public ICloseable
|
class Scene
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Node* root;
|
Node* root;
|
||||||
@@ -46,7 +46,7 @@ namespace OpenVulkano
|
|||||||
this->root = root;
|
this->root = root;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Close() override
|
virtual void Close()
|
||||||
{
|
{
|
||||||
//TODO
|
//TODO
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Base/ICloseable.hpp"
|
|
||||||
#include "Base/Utils.hpp"
|
#include "Base/Utils.hpp"
|
||||||
#include "Base/Render/RenderResource.hpp"
|
#include "Base/Render/RenderResource.hpp"
|
||||||
#include "VertexInputDescription.hpp"
|
#include "VertexInputDescription.hpp"
|
||||||
@@ -81,8 +80,7 @@ namespace OpenVulkano::Scene
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Shader final : public RenderResourceHolder<Shader>
|
||||||
class Shader final : public RenderResourceHolder<Shader>, public ICloseable
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
std::vector<ShaderProgram> shaderPrograms{};
|
std::vector<ShaderProgram> shaderPrograms{};
|
||||||
@@ -96,9 +94,11 @@ namespace OpenVulkano::Scene
|
|||||||
bool depthTest = true;
|
bool depthTest = true;
|
||||||
bool depthWrite = true;
|
bool depthWrite = true;
|
||||||
bool dynamicViewport = true; // If disabled the swapchains fullscreen viewport will always be used, regardless of framebuffer or viewport
|
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() = default;
|
||||||
~Shader() override { Shader::Close(); }
|
~Shader() { Shader::Close(); }
|
||||||
|
|
||||||
Shader& AddShaderProgram(const ShaderProgram& shaderProgram)
|
Shader& AddShaderProgram(const ShaderProgram& shaderProgram)
|
||||||
{
|
{
|
||||||
@@ -128,6 +128,7 @@ namespace OpenVulkano::Scene
|
|||||||
{
|
{
|
||||||
CheckShaderInitState();
|
CheckShaderInitState();
|
||||||
if (bindingId < 0) bindingId = static_cast<int>(vertexInputDescriptions.size());
|
if (bindingId < 0) bindingId = static_cast<int>(vertexInputDescriptions.size());
|
||||||
|
// ReSharper disable once CppDFALoopConditionNotUpdated
|
||||||
while (bindingId > static_cast<int>(vertexInputDescriptions.size()))
|
while (bindingId > static_cast<int>(vertexInputDescriptions.size()))
|
||||||
{
|
{
|
||||||
vertexInputDescriptions.emplace_back(0, 0);
|
vertexInputDescriptions.emplace_back(0, 0);
|
||||||
@@ -149,6 +150,7 @@ namespace OpenVulkano::Scene
|
|||||||
if (setId < 0) setId = static_cast<int>(descriptorSets.size() + 2);
|
if (setId < 0) setId = static_cast<int>(descriptorSets.size() + 2);
|
||||||
if (setId < 2) throw std::runtime_error("Cant bind set id 0 or 1! They are used for node and camera!");
|
if (setId < 2) throw std::runtime_error("Cant bind set id 0 or 1! They are used for node and camera!");
|
||||||
setId -= 2;
|
setId -= 2;
|
||||||
|
// ReSharper disable once CppDFALoopConditionNotUpdated
|
||||||
while (setId >= static_cast<int>(descriptorSets.size()))
|
while (setId >= static_cast<int>(descriptorSets.size()))
|
||||||
{
|
{
|
||||||
descriptorSets.emplace_back();
|
descriptorSets.emplace_back();
|
||||||
@@ -163,7 +165,14 @@ namespace OpenVulkano::Scene
|
|||||||
pushConstantRanges.push_back(pushConstantRange);
|
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())
|
if (HasRenderResource())
|
||||||
GetRenderResource().Release();
|
GetRenderResource().Release();
|
||||||
|
|||||||
@@ -12,6 +12,8 @@
|
|||||||
|
|
||||||
namespace OpenVulkano
|
namespace OpenVulkano
|
||||||
{
|
{
|
||||||
|
enum class VertexStepMode : uint32_t { VERTEX = 0, INSTANCE };
|
||||||
|
|
||||||
struct VertexInputParameter
|
struct VertexInputParameter
|
||||||
{
|
{
|
||||||
uint32_t location;
|
uint32_t location;
|
||||||
@@ -32,13 +34,16 @@ namespace OpenVulkano
|
|||||||
{
|
{
|
||||||
uint32_t bindingId;
|
uint32_t bindingId;
|
||||||
uint32_t vertexSize;
|
uint32_t vertexSize;
|
||||||
|
VertexStepMode stepMode = VertexStepMode::VERTEX;
|
||||||
std::vector<VertexInputParameter> inputParameters;
|
std::vector<VertexInputParameter> inputParameters;
|
||||||
|
|
||||||
VertexInputDescription(uint32_t bindingId, uint32_t vertexSize) : bindingId(bindingId), vertexSize(vertexSize)
|
VertexInputDescription(uint32_t bindingId, uint32_t vertexSize) : bindingId(bindingId), vertexSize(vertexSize)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
VertexInputDescription(uint32_t bindingId, const VertexInputDescription& vertexDescription)
|
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)
|
for (auto& param : inputParameters)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,9 +6,7 @@
|
|||||||
|
|
||||||
#include "TextDrawable.hpp"
|
#include "TextDrawable.hpp"
|
||||||
#include "Scene/Geometry.hpp"
|
#include "Scene/Geometry.hpp"
|
||||||
#include "Scene/Material.hpp"
|
#include "Shader/Shader.hpp"
|
||||||
#include "Scene/Vertex.hpp"
|
|
||||||
#include "Scene/UniformBuffer.hpp"
|
|
||||||
#include "Scene/IFontAtlasGenerator.hpp"
|
#include "Scene/IFontAtlasGenerator.hpp"
|
||||||
#include "Base/Logger.hpp"
|
#include "Base/Logger.hpp"
|
||||||
#include "Host/ResourceLoader.hpp"
|
#include "Host/ResourceLoader.hpp"
|
||||||
@@ -20,89 +18,58 @@
|
|||||||
|
|
||||||
namespace OpenVulkano::Scene
|
namespace OpenVulkano::Scene
|
||||||
{
|
{
|
||||||
Shader& TextDrawable::GetSdfDefaultShader()
|
namespace
|
||||||
{
|
{
|
||||||
static bool once = true;
|
constexpr uint32_t MISSING_GLYPH_SYMBOL = '?';
|
||||||
static Shader sdfDefaultShader;
|
|
||||||
if (once)
|
Shader DEFAULT_SHADER_BITMAP = TextDrawable::MakeDefaultShader(FontAtlasType::BITMAP);
|
||||||
{
|
Shader DEFAULT_SHADER_SDF = TextDrawable::MakeDefaultShader(FontAtlasType::SDF);
|
||||||
sdfDefaultShader.AddShaderProgram(OpenVulkano::ShaderProgramType::VERTEX, "Shader/sdfText");
|
Shader DEFAULT_SHADER_MSDF = TextDrawable::MakeDefaultShader(FontAtlasType::MSDF);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Shader& TextDrawable::GetMsdfDefaultShader()
|
Shader TextDrawable::MakeDefaultShader(const FontAtlasType type)
|
||||||
{
|
{
|
||||||
static bool once = true;
|
Shader shader;
|
||||||
static Shader msdfDefaultShader;
|
shader.AddShaderProgram(ShaderProgramType::VERTEX, "Shader/text");
|
||||||
if (once)
|
shader.AddShaderProgram(ShaderProgramType::FRAGMENT, std::string(type.GetDefaultFragmentShader()));
|
||||||
{
|
VertexInputDescription inputDesc(0, sizeof(TextGlyphVertex));
|
||||||
msdfDefaultShader.AddShaderProgram(OpenVulkano::ShaderProgramType::VERTEX, "Shader/sdfText");
|
inputDesc.AddInputParameter(DataFormat::R32G32_SFLOAT, offsetof(TextGlyphVertex, position));
|
||||||
msdfDefaultShader.AddShaderProgram(OpenVulkano::ShaderProgramType::FRAGMENT, "Shader/msdfText");
|
inputDesc.AddInputParameter(DataFormat::R32G32_SFLOAT, offsetof(TextGlyphVertex, position)+8);
|
||||||
msdfDefaultShader.AddVertexInputDescription(OpenVulkano::Vertex::GetVertexInputDescription());
|
inputDesc.AddInputParameter(DataFormat::R32G32_SFLOAT, offsetof(TextGlyphVertex, position)+16);
|
||||||
msdfDefaultShader.AddDescriptorSetLayoutBinding(Texture::DESCRIPTOR_SET_LAYOUT_BINDING);
|
inputDesc.AddInputParameter(DataFormat::R32G32_SFLOAT, offsetof(TextGlyphVertex, position)+24);
|
||||||
DescriptorSetLayoutBinding desc = UniformBuffer::DESCRIPTOR_SET_LAYOUT_BINDING;
|
inputDesc.AddInputParameter(DataFormat::R32G32_SFLOAT, offsetof(TextGlyphVertex, uv));
|
||||||
desc.stageFlags = ShaderProgramType::FRAGMENT;
|
inputDesc.AddInputParameter(DataFormat::R32G32_SFLOAT, offsetof(TextGlyphVertex, uv)+8);
|
||||||
msdfDefaultShader.AddDescriptorSetLayoutBinding(desc);
|
inputDesc.AddInputParameter(DataFormat::R32G32_SFLOAT, offsetof(TextGlyphVertex, uv)+16);
|
||||||
msdfDefaultShader.alphaBlend = true;
|
inputDesc.AddInputParameter(DataFormat::R32G32_SFLOAT, offsetof(TextGlyphVertex, uv)+24);
|
||||||
msdfDefaultShader.cullMode = CullMode::NONE;
|
inputDesc.AddInputParameter(DataFormat::R8G8B8A8_UNORM, offsetof(TextGlyphVertex, color));
|
||||||
once = false;
|
inputDesc.AddInputParameter(DataFormat::R8G8B8A8_UNORM, offsetof(TextGlyphVertex, background));
|
||||||
}
|
inputDesc.stepMode = VertexStepMode::INSTANCE;
|
||||||
return msdfDefaultShader;
|
shader.AddVertexInputDescription(inputDesc);
|
||||||
}
|
shader.AddDescriptorSetLayoutBinding(Texture::DESCRIPTOR_SET_LAYOUT_BINDING);
|
||||||
|
shader.alphaBlend = true;
|
||||||
Shader& TextDrawable::GetBitmapDefaultShader()
|
shader.cullMode = CullMode::NONE;
|
||||||
{
|
shader.topology = Topology::TRIANGLE_FAN;
|
||||||
static bool once = true;
|
return shader;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TextDrawable::TextDrawable(const TextConfig& config)
|
TextDrawable::TextDrawable(const TextConfig& config)
|
||||||
{
|
: Drawable(DrawEncoder::GetDrawEncoder<TextDrawable>()), m_cfg(config)
|
||||||
m_cfg = config;
|
{}
|
||||||
m_uniBuffer.Init(sizeof(TextConfig), &m_cfg, 3);
|
|
||||||
m_uniBuffer.binding.stageFlags = ShaderProgramType::FRAGMENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
TextDrawable::TextDrawable(const Array<char>& atlasMetadata, const TextConfig& config)
|
TextDrawable::TextDrawable(const Array<char>& atlasMetadata, const TextConfig& config)
|
||||||
: TextDrawable(atlasMetadata, nullptr, config)
|
: TextDrawable(atlasMetadata, nullptr, config)
|
||||||
{
|
{}
|
||||||
}
|
|
||||||
|
|
||||||
TextDrawable::TextDrawable(const std::string& atlasMetadataFile, const TextConfig& 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::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<char>& atlasMetadata, Texture* atlasTex, const TextConfig& config)
|
TextDrawable::TextDrawable(const Array<char>& atlasMetadata, Texture* atlasTex, const TextConfig& config)
|
||||||
|
: Drawable(DrawEncoder::GetDrawEncoder<TextDrawable>()), m_cfg(config)
|
||||||
{
|
{
|
||||||
uint32_t isPacked;
|
uint32_t isPacked;
|
||||||
std::memcpy(&isPacked, atlasMetadata.Data() + (atlasMetadata.Size() - sizeof(uint32_t)), sizeof(uint32_t));
|
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<AtlasData>();
|
m_atlasData = std::make_shared<AtlasData>();
|
||||||
if (isPacked)
|
if (isPacked)
|
||||||
{
|
{
|
||||||
m_material.texture = &m_atlasData->texture;
|
Texture* texture = &m_atlasData->texture;
|
||||||
m_atlasData->img = Image::IImageLoader::loadData((const uint8_t*) atlasMetadata.Data(),
|
m_atlasData->img = Image::IImageLoader::loadData(reinterpret_cast<const uint8_t*>(atlasMetadata.Data()), offsetToMetadata);
|
||||||
offsetToMetadata);
|
texture->format = m_atlasData->img->dataFormat;
|
||||||
m_material.texture->format = m_atlasData->img->dataFormat;
|
texture->resolution = m_atlasData->img->resolution;
|
||||||
m_material.texture->resolution = m_atlasData->img->resolution;
|
texture->size = m_atlasData->img->data.Size();
|
||||||
m_material.texture->size = m_atlasData->img->data.Size();
|
texture->textureBuffer = m_atlasData->img->data.Data();
|
||||||
m_material.texture->textureBuffer = m_atlasData->img->data.Data();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (atlasTex == nullptr) { throw std::runtime_error("Atlas texture cannot be null with non-packed atlas metadata"); }
|
if (atlasTex == nullptr) { throw std::runtime_error("Atlas texture cannot be null with non-packed atlas metadata"); }
|
||||||
m_atlasData->texture = *atlasTex;
|
m_atlasData->texture = *atlasTex;
|
||||||
m_material.texture = atlasTex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// metadata info
|
// metadata info
|
||||||
@@ -146,67 +111,47 @@ namespace OpenVulkano::Scene
|
|||||||
read_bytes += sizeof(GlyphInfo);
|
read_bytes += sizeof(GlyphInfo);
|
||||||
readMetadataBytes += 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)
|
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>& atlasData, const TextConfig& config)
|
TextDrawable::TextDrawable(const std::shared_ptr<AtlasData>& atlasData, const TextConfig& config)
|
||||||
|
: Drawable(DrawEncoder::GetDrawEncoder<TextDrawable>()), m_atlasData(atlasData), m_cfg(config)
|
||||||
{
|
{
|
||||||
if (!atlasData || atlasData->glyphs.empty() || !atlasData->texture.textureBuffer)
|
if (!atlasData || !*atlasData) throw std::runtime_error("Cannot initialize text drawable with empty atlas data");
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
m_text = text;
|
||||||
auto GetActualLength = [&]()
|
m_symbolCount = 0;
|
||||||
{
|
const size_t len = utf8::distance(text.begin(), text.end());
|
||||||
auto begin = text.begin();
|
m_vertexBuffer.Close();
|
||||||
auto end = text.end();
|
TextGlyphVertex* vertices = m_vertexBuffer.Init<TextGlyphVertex>(len);
|
||||||
size_t len = 0;
|
std::map<uint32_t, GlyphInfo>* symbols = &m_atlasData->glyphs;
|
||||||
while (begin != end)
|
AtlasMetadata* meta = &m_atlasData->meta;
|
||||||
{
|
|
||||||
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<uint32_t, GlyphInfo>* symbols;
|
|
||||||
m_material.texture = &m_atlasData->texture;
|
|
||||||
symbols = &m_atlasData->glyphs;
|
|
||||||
meta = &m_atlasData->meta;
|
|
||||||
|
|
||||||
double cursorX = pos.x;
|
double cursorX = pos.x;
|
||||||
auto begin = text.begin();
|
|
||||||
auto end = text.end();
|
|
||||||
const double lineHeight = meta->lineHeight;
|
const double lineHeight = meta->lineHeight;
|
||||||
double posY = pos.y;
|
double posY = pos.y;
|
||||||
int i = 0;
|
Math::Vector3f bmin(pos, 0), bmax(pos, 0);
|
||||||
Math::Vector3f bmin(pos), bmax(pos);
|
for (auto begin = text.begin(), end = text.end(); begin != end;)
|
||||||
bool firstGlyph = true;
|
|
||||||
while (begin != end)
|
|
||||||
{
|
{
|
||||||
uint32_t c = utf8::next(begin, end);
|
uint32_t c = utf8::next(begin, end);
|
||||||
if (c == '\n')
|
if (c == '\n')
|
||||||
@@ -215,72 +160,56 @@ namespace OpenVulkano::Scene
|
|||||||
cursorX = pos.x;
|
cursorX = pos.x;
|
||||||
continue;
|
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);
|
Logger::RENDER->warn("Could not find glyph for character {}, using fallback", c);
|
||||||
if (symbols->find(static_cast<uint32_t>('?')) != symbols->end())
|
c = fallbackGlyph;
|
||||||
{
|
|
||||||
c = static_cast<uint32_t>('?');
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Logger::RENDER->error("Could not find glyph for character ? to replace glyph {}", c);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
GlyphInfo& info = symbols->at(c);
|
||||||
|
|
||||||
// left bottom
|
for (int i = 0; i < 4; i++)
|
||||||
m_geometry.vertices[vIdx].position.x = info.xyz[0].x + cursorX;
|
{
|
||||||
m_geometry.vertices[vIdx].position.y = posY - info.xyz[0].y;
|
vertices->position[i].x = info.xyz[i].x + cursorX;
|
||||||
m_geometry.vertices[vIdx].position.z = info.xyz[0].z;
|
vertices->uv[i] = info.uv[i];
|
||||||
m_geometry.vertices[vIdx].textureCoordinates = Math::Vector3f(info.uv[0], 0);
|
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
|
// 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( <= )
|
// when setting for depth comparison operator will be available( <= )
|
||||||
cursorX += info.advance + 0.08;
|
cursorX += info.advance + 0.08;
|
||||||
if (firstGlyph)
|
|
||||||
{
|
bmax.x = std::max(bmax.x, vertices->position[1].x);
|
||||||
bmin.x = m_geometry.vertices[vIdx].position.x;
|
bmax.y = std::max(bmax.y, vertices->position[2].y);
|
||||||
firstGlyph = false;
|
bmin.y = std::min(bmin.y, vertices->position[1].y);
|
||||||
}
|
vertices++;
|
||||||
bmax.x = std::max(bmax.x, m_geometry.vertices[vIdx + 1].position.x);
|
m_symbolCount++;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
bmin.x = vertices->position[0].x;
|
||||||
m_bbox.Init(bmin, bmax);
|
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>& atlasData)
|
void TextDrawable::SetAtlasData(const std::shared_ptr<AtlasData>& atlasData)
|
||||||
{
|
{
|
||||||
if (!atlasData || atlasData->glyphs.empty() || !atlasData->texture.textureBuffer)
|
if (!atlasData || !*atlasData) throw std::runtime_error("Cannot initialize text drawable with empty atlas data");
|
||||||
{
|
|
||||||
throw std::runtime_error("Cannot initialize text drawable with empty atlas data");
|
|
||||||
}
|
|
||||||
m_atlasData = atlasData;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -6,62 +6,63 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "SimpleDrawable.hpp"
|
#include "Drawable.hpp"
|
||||||
#include "Texture.hpp"
|
#include "Texture.hpp"
|
||||||
#include "Material.hpp"
|
#include "VertexBuffer.hpp"
|
||||||
#include "Geometry.hpp"
|
|
||||||
#include "UniformBuffer.hpp"
|
|
||||||
#include "AtlasData.hpp"
|
#include "AtlasData.hpp"
|
||||||
#include "Image/Image.hpp"
|
#include "Image/Image.hpp"
|
||||||
#include <map>
|
|
||||||
#include <optional>
|
|
||||||
|
|
||||||
namespace OpenVulkano::Scene
|
namespace OpenVulkano::Scene
|
||||||
{
|
{
|
||||||
|
|
||||||
class IFontAtlasGenerator;
|
class IFontAtlasGenerator;
|
||||||
|
|
||||||
struct TextConfig
|
struct TextConfig
|
||||||
{
|
{
|
||||||
Math::Vector4f textColor = { 1, 1, 1, 1 };
|
Math::Vector4uc textColor = { 255, 255, 255, 255 };
|
||||||
Math::Vector4f borderColor = { 1, 0, 0, 1 };
|
Math::Vector4uc backgroundColor = { 0, 255, 0, 0 };
|
||||||
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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class TextDrawable : public SimpleDrawable
|
struct TextGlyphVertex
|
||||||
{
|
{
|
||||||
|
std::array<Math::Vector2f, 4> position;
|
||||||
|
std::array<Math::Vector2f, 4> uv;
|
||||||
|
Math::Vector4uc color = { 255, 255, 255, 255 };
|
||||||
|
Math::Vector4uc background = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
class TextDrawable : public Drawable
|
||||||
|
{
|
||||||
|
VertexBuffer m_vertexBuffer;
|
||||||
|
std::shared_ptr<AtlasData> m_atlasData;
|
||||||
|
Math::AABB2f m_bbox;
|
||||||
|
std::string m_text;
|
||||||
|
size_t m_symbolCount = 0;
|
||||||
|
TextConfig m_cfg;
|
||||||
|
|
||||||
|
uint32_t GetFallbackGlyph() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static Shader& GetSdfDefaultShader();
|
|
||||||
static Shader& GetMsdfDefaultShader();
|
|
||||||
static Shader& GetBitmapDefaultShader();
|
|
||||||
TextDrawable(const TextConfig& config = TextConfig());
|
TextDrawable(const TextConfig& config = TextConfig());
|
||||||
TextDrawable(const Array<char>& atlasMetadata, const TextConfig& config = TextConfig());
|
TextDrawable(const Array<char>& atlasMetadata, const TextConfig& config = TextConfig());
|
||||||
TextDrawable(const std::string& atlasMetadataFile, 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 std::string& atlasMetadataFile, Texture* atlasTex, const TextConfig& config = TextConfig());
|
||||||
TextDrawable(const Array<char>& atlasMetadata, Texture* atlasTex, const TextConfig& config = TextConfig());
|
TextDrawable(const Array<char>& atlasMetadata, Texture* atlasTex, const TextConfig& config = TextConfig());
|
||||||
TextDrawable(const std::shared_ptr<AtlasData>& atlasData, const TextConfig& config = TextConfig());
|
TextDrawable(const std::shared_ptr<AtlasData>& 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 SetConfig(const TextConfig& cfg) { m_cfg = cfg; }
|
||||||
void SetShader(Shader* shader) { m_shader = shader; }
|
|
||||||
void SetAtlasData(const std::shared_ptr<AtlasData>& atlasData);
|
void SetAtlasData(const std::shared_ptr<AtlasData>& atlasData);
|
||||||
Math::AABB& GetBoundingBox() { return m_bbox; }
|
|
||||||
TextConfig& GetConfig() { return m_cfg; }
|
[[nodiscard]] Math::AABB2f& GetBoundingBox() { return m_bbox; }
|
||||||
Shader* GetShader() { return m_shader; }
|
[[nodiscard]] TextConfig& GetConfig() { return m_cfg; }
|
||||||
[[nodiscard]] const std::string& GetText() const { return m_text; }
|
[[nodiscard]] const std::string& GetText() const { return m_text; }
|
||||||
std::shared_ptr<AtlasData> GetAtlasData() { return m_atlasData; }
|
[[nodiscard]] const std::shared_ptr<AtlasData>& GetAtlasData() { return m_atlasData; }
|
||||||
private:
|
|
||||||
Geometry m_geometry;
|
[[nodiscard]] VertexBuffer* GetVertexBuffer() { return &m_vertexBuffer; }
|
||||||
Material m_material;
|
[[nodiscard]] Texture* GetTexture() { return &m_atlasData->texture; }
|
||||||
UniformBuffer m_uniBuffer;
|
[[nodiscard]] size_t GetSymbolCount() const { return m_symbolCount; }
|
||||||
std::shared_ptr<AtlasData> m_atlasData;
|
|
||||||
Math::AABB m_bbox;
|
[[nodiscard]] static Shader MakeDefaultShader(FontAtlasType type);
|
||||||
Shader* m_shader = nullptr;
|
[[nodiscard]] static Shader* GetDefaultShader(FontAtlasType type);
|
||||||
std::string m_text;
|
|
||||||
TextConfig m_cfg;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,11 +19,15 @@ namespace OpenVulkano::Scene
|
|||||||
|
|
||||||
DescriptorSetLayoutBinding binding;
|
DescriptorSetLayoutBinding binding;
|
||||||
uint32_t setId;
|
uint32_t setId;
|
||||||
size_t size = 0;
|
size_t size;
|
||||||
const void* data = nullptr;
|
const void* data;
|
||||||
UpdateFrequency updateFrequency = UpdateFrequency::Never;
|
UpdateFrequency updateFrequency = UpdateFrequency::Never;
|
||||||
bool updated = true;
|
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)
|
void Init(size_t size, const void* data, uint32_t setId = 2, const DescriptorSetLayoutBinding& binding = DESCRIPTOR_SET_LAYOUT_BINDING)
|
||||||
{
|
{
|
||||||
this->size = size;
|
this->size = size;
|
||||||
|
|||||||
54
openVulkanoCpp/Scene/VertexBuffer.hpp
Normal file
54
openVulkanoCpp/Scene/VertexBuffer.hpp
Normal file
@@ -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<VertexBuffer>
|
||||||
|
{
|
||||||
|
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<typename T>
|
||||||
|
T* Init(size_t count)
|
||||||
|
{
|
||||||
|
Init(count * sizeof(T));
|
||||||
|
return static_cast<T*>(const_cast<void*>(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Close()
|
||||||
|
{
|
||||||
|
if (ownsMemory && data) free(const_cast<void*>(data));
|
||||||
|
data = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateFrequency GetUpdateFrequency() const { return updateFrequency; }
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -3,71 +3,71 @@
|
|||||||
layout(location = 1) in vec2 texCoord;
|
layout(location = 1) in vec2 texCoord;
|
||||||
layout(location = 0) out vec4 outColor;
|
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 color;
|
vec2 textSize;
|
||||||
vec4 bboxCenter;
|
vec2 bboxCenter;
|
||||||
float radius;
|
float radius;
|
||||||
float arrowLength;
|
float arrowLength;
|
||||||
float arrowWidth;
|
float arrowWidth;
|
||||||
bool hasRoundedCorners;
|
bool hasRoundedCorners;
|
||||||
bool hasArrow;
|
bool hasArrow;
|
||||||
} labelInfo;
|
} labelInfo;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
if (labelInfo.hasRoundedCorners || labelInfo.hasArrow)
|
if (labelInfo.hasRoundedCorners || labelInfo.hasArrow)
|
||||||
{
|
{
|
||||||
vec2 bbox = vec2(labelInfo.textSize);
|
vec2 bbox = vec2(labelInfo.textSize);
|
||||||
const float arrowLength = int(labelInfo.hasArrow) * labelInfo.arrowLength;
|
const float arrowLength = int(labelInfo.hasArrow) * labelInfo.arrowLength;
|
||||||
float arrowWidth = labelInfo.arrowWidth;
|
float arrowWidth = labelInfo.arrowWidth;
|
||||||
vec2 uvScaled = texCoord;
|
vec2 uvScaled = texCoord;
|
||||||
|
|
||||||
float distX = min(uvScaled.x, bbox.x - uvScaled.x);
|
float distX = min(uvScaled.x, bbox.x - uvScaled.x);
|
||||||
float distY = min(uvScaled.y - arrowLength, bbox.y - uvScaled.y);
|
float distY = min(uvScaled.y - arrowLength, bbox.y - uvScaled.y);
|
||||||
float distanceFromCorner = distX * distY;
|
float distanceFromCorner = distX * distY;
|
||||||
|
|
||||||
if (distanceFromCorner < labelInfo.radius)
|
if (distanceFromCorner < labelInfo.radius)
|
||||||
{
|
{
|
||||||
// plain arrow
|
// plain arrow
|
||||||
if (labelInfo.hasArrow && !labelInfo.hasRoundedCorners)
|
if (labelInfo.hasArrow && !labelInfo.hasRoundedCorners)
|
||||||
{
|
{
|
||||||
// Some bias to prevent line between arrow and label +
|
// 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,
|
// check that we are dealing with lower parts of the label where arrow should be drawn,
|
||||||
// to prevent discarding fragments from upper corners
|
// to prevent discarding fragments from upper corners
|
||||||
if (distY <= 0.01 && uvScaled.y < (bbox.y - arrowWidth) && arrowLength != 0.0f)
|
if (distY <= 0.01 && uvScaled.y < (bbox.y - arrowWidth) && arrowLength != 0.0f)
|
||||||
{
|
{
|
||||||
arrowWidth = arrowWidth * ((arrowLength + distY) / arrowLength);
|
arrowWidth = arrowWidth * ((arrowLength + distY) / arrowLength);
|
||||||
if (distX < (bbox.x - arrowWidth) * 0.5)
|
if (distX < (bbox.x - arrowWidth) * 0.5)
|
||||||
{
|
{
|
||||||
discard;
|
discard;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO: rounded corners + rounded arrow.
|
// TODO: rounded corners + rounded arrow.
|
||||||
// now renders rounded corners and sharp arrow
|
// now renders rounded corners and sharp arrow
|
||||||
else if (labelInfo.hasArrow && labelInfo.hasRoundedCorners)
|
else if (labelInfo.hasArrow && labelInfo.hasRoundedCorners)
|
||||||
{
|
{
|
||||||
if (distY <= 0.05 && uvScaled.y < (bbox.y - arrowWidth) && arrowLength != 0.0f)
|
if (distY <= 0.05 && uvScaled.y < (bbox.y - arrowWidth) && arrowLength != 0.0f)
|
||||||
{
|
{
|
||||||
arrowWidth = arrowWidth * ((arrowLength + distY) / arrowLength);
|
arrowWidth = arrowWidth * ((arrowLength + distY) / arrowLength);
|
||||||
if (distX < (bbox.x - arrowWidth) * 0.5)
|
if (distX < (bbox.x - arrowWidth) * 0.5)
|
||||||
{
|
{
|
||||||
discard;
|
discard;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
discard;
|
discard;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// no arrow, rounded corners
|
// no arrow, rounded corners
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
discard;
|
discard;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
outColor = labelInfo.color;
|
outColor = labelInfo.color;
|
||||||
}
|
}
|
||||||
@@ -8,18 +8,19 @@ layout(set = 0, binding = 0) uniform NodeData
|
|||||||
|
|
||||||
layout(set = 1, binding = 0) uniform CameraData
|
layout(set = 1, binding = 0) uniform CameraData
|
||||||
{
|
{
|
||||||
mat4 viewProjection;
|
mat4 viewProjection;
|
||||||
} cam;
|
} cam;
|
||||||
|
|
||||||
layout(set = 5, binding = 0) uniform LabelData
|
layout(set = 4, binding = 0) uniform LabelData
|
||||||
{
|
{
|
||||||
vec4 textSize;
|
vec4 color;
|
||||||
vec4 color;
|
vec2 textSize;
|
||||||
vec4 bboxCenter;
|
vec2 bboxCenter;
|
||||||
float radius;
|
float radius;
|
||||||
float arrowLength;
|
float arrowLength;
|
||||||
bool hasRoundedCorners;
|
float arrowWidth;
|
||||||
bool hasArrow;
|
bool hasRoundedCorners;
|
||||||
|
bool hasArrow;
|
||||||
} labelInfo;
|
} labelInfo;
|
||||||
|
|
||||||
layout(location = 0) out vec4 color;
|
layout(location = 0) out vec4 color;
|
||||||
@@ -28,18 +29,18 @@ layout(location = 1) out vec2 textureCoordinates;
|
|||||||
// Background plane positions are in clipped space
|
// Background plane positions are in clipped space
|
||||||
const vec4 PLANE[4] = vec4[](
|
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)
|
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[](
|
const vec2 TEX_COORDS[4] = vec2[](
|
||||||
vec2(0, 0), vec2(1, 0), vec2(0, 1), vec2(1, 1)
|
vec2(0, 0), vec2(1, 0), vec2(0, 1), vec2(1, 1)
|
||||||
);
|
);
|
||||||
|
|
||||||
void main() {
|
void main()
|
||||||
vec4 position = PLANE[gl_VertexIndex];
|
{
|
||||||
vec2 bbox = labelInfo.textSize.xy;
|
vec4 position = PLANE[gl_VertexIndex];
|
||||||
position.xy *= bbox;
|
position.xy *= labelInfo.textSize;
|
||||||
position.xy += vec2(labelInfo.bboxCenter);
|
position.xy += labelInfo.bboxCenter;
|
||||||
position.z = -0.001;
|
//position.z = -0.001;
|
||||||
gl_Position = cam.viewProjection * node.world * position;
|
gl_Position = cam.viewProjection * node.world * position;
|
||||||
textureCoordinates = TEX_COORDS[gl_VertexIndex] * bbox;
|
textureCoordinates = TEX_COORDS[gl_VertexIndex] * labelInfo.textSize;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,35 +8,31 @@ layout(set = 0, binding = 0) uniform NodeData
|
|||||||
|
|
||||||
layout(set = 1, binding = 0) uniform CameraData
|
layout(set = 1, binding = 0) uniform CameraData
|
||||||
{
|
{
|
||||||
mat4 viewProjection;
|
mat4 viewProjection;
|
||||||
mat4 view;
|
mat4 view;
|
||||||
mat4 projection;
|
mat4 projection;
|
||||||
vec4 camPos;
|
vec4 camPos;
|
||||||
float nearPlane;
|
float nearPlane;
|
||||||
float farPlane;
|
float farPlane;
|
||||||
float width;
|
float width;
|
||||||
float height;
|
float height;
|
||||||
float fov;
|
float fov;
|
||||||
float aspect;
|
float aspect;
|
||||||
float scaleFactor;
|
float scaleFactor;
|
||||||
float pixelScaleFactor;
|
float pixelScaleFactor;
|
||||||
} cam;
|
} cam;
|
||||||
|
|
||||||
layout(set = 4, binding = 0) uniform BillboardData
|
layout(set = 4, binding = 0) uniform LabelData
|
||||||
{
|
{
|
||||||
vec2 size;
|
vec4 color;
|
||||||
bool isFixedSize;
|
vec2 textSize;
|
||||||
} billboardInfo;
|
vec2 bboxCenter;
|
||||||
|
float radius;
|
||||||
layout(set = 5, binding = 0) uniform LabelData
|
float arrowLength;
|
||||||
{
|
float arrowWidth;
|
||||||
vec4 textSize;
|
bool hasRoundedCorners;
|
||||||
vec4 color;
|
bool hasArrow;
|
||||||
vec4 bboxCenter;
|
bool isBillboardFixedSize;
|
||||||
float radius;
|
|
||||||
float arrowLength;
|
|
||||||
bool hasRoundedCorners;
|
|
||||||
bool hasArrow;
|
|
||||||
} labelInfo;
|
} labelInfo;
|
||||||
|
|
||||||
layout(location = 0) out vec4 color;
|
layout(location = 0) out vec4 color;
|
||||||
@@ -45,43 +41,41 @@ layout(location = 1) out vec2 textureCoordinates;
|
|||||||
// Background plane positions are in clipped space
|
// Background plane positions are in clipped space
|
||||||
const vec4 PLANE[4] = vec4[](
|
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)
|
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() {
|
const vec2 TEX_COORDS[4] = vec2[](vec2(0, 0), vec2(1, 0), vec2(0, 1), vec2(1, 1));
|
||||||
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;
|
|
||||||
|
|
||||||
if (!billboardInfo.isFixedSize)
|
void main()
|
||||||
{
|
{
|
||||||
mat4 mv = cam.view * node.world;
|
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;
|
if (!labelInfo.isBillboardFixedSize)
|
||||||
mv[0][1] = 0;
|
{
|
||||||
mv[0][2] = 0;
|
mat4 mv = cam.view * node.world;
|
||||||
|
|
||||||
mv[1][0] = 0;
|
mv[0][0] = 1;
|
||||||
mv[1][1] = 1;
|
mv[0][1] = 0;
|
||||||
mv[1][2] = 0;
|
mv[0][2] = 0;
|
||||||
|
|
||||||
mv[2][0] = 0;
|
mv[1][0] = 0;
|
||||||
mv[2][1] = 0;
|
mv[1][1] = 1;
|
||||||
mv[2][2] = 1;
|
mv[1][2] = 0;
|
||||||
|
|
||||||
gl_Position = cam.projection * mv * vec4(position.xyz, 1);
|
mv[2][0] = 0;
|
||||||
}
|
mv[2][1] = 0;
|
||||||
else
|
mv[2][2] = 1;
|
||||||
{
|
|
||||||
vec4 billboardPos = vec4(0.5, 0.5, 0.5, 1);
|
gl_Position = cam.projection * mv * vec4(position.xyz, 1);
|
||||||
vec4 viewPos = cam.view * node.world * billboardPos;
|
}
|
||||||
float dist = -viewPos.z;
|
else
|
||||||
gl_Position = cam.projection * (viewPos + vec4(position.xy*dist*0.2,0,0));
|
{
|
||||||
}
|
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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,47 +1,40 @@
|
|||||||
#version 450
|
#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(location = 0) out vec4 outColor;
|
||||||
|
|
||||||
layout(set = 2, binding = 0) uniform sampler2D texSampler;
|
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));
|
return max(min(r, g), min(max(r, g), b));
|
||||||
}
|
}
|
||||||
|
|
||||||
// this parameter should be same as FontAtlasGeneratorConfig::pixelRange
|
// this parameter should be same as FontAtlasGeneratorConfig::pixelRange
|
||||||
const float pxRange = 3;
|
const float pxRange = 3;
|
||||||
|
|
||||||
float screenPxRange() {
|
float screenPxRange()
|
||||||
vec2 unitRange = vec2(pxRange)/vec2(textureSize(texSampler, 0));
|
{
|
||||||
vec2 screenTexSize = vec2(1.0)/fwidth(texCoord);
|
vec2 unitRange = vec2(pxRange) / vec2(textureSize(texSampler, 0));
|
||||||
return max(0.5*dot(unitRange, screenTexSize), 1.0);
|
vec2 screenTexSize = vec2(1.0) / fwidth(texCoord);
|
||||||
|
return max(0.5 * dot(unitRange, screenTexSize), 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec3 msd = texture(texSampler, texCoord).rgb;
|
vec3 msd = texture(texSampler, texCoord).rgb;
|
||||||
float sd = median(msd.r, msd.g, msd.b);
|
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);
|
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
|
else
|
||||||
{
|
{
|
||||||
outColor = vec4(vec3(textConfig.textColor), opacity);
|
outColor = vec4(vec3(color), opacity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,39 +1,24 @@
|
|||||||
#version 450
|
#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(location = 0) out vec4 outColor;
|
||||||
|
|
||||||
layout(set = 2, binding = 0) uniform sampler2D texSampler;
|
layout(set = 2, binding = 0) uniform sampler2D texSampler;
|
||||||
|
|
||||||
layout(set = 3, binding = 0) uniform TextConfig
|
const float threshold = 0.4f;
|
||||||
{
|
const float smoothing = 1.f/32.f;
|
||||||
vec4 textColor;
|
|
||||||
vec4 borderColor;
|
|
||||||
vec4 backgroundColor;
|
|
||||||
float threshold;
|
|
||||||
float borderSize;
|
|
||||||
float smoothing;
|
|
||||||
bool applyBorder;
|
|
||||||
} textConfig;
|
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
float distance = texture(texSampler, texCoord).r;
|
float distance = texture(texSampler, texCoord).r;
|
||||||
float alpha = smoothstep(textConfig.threshold - textConfig.smoothing, textConfig.threshold + textConfig.smoothing, distance);
|
float alpha = smoothstep(threshold - smoothing, threshold + smoothing, distance);
|
||||||
if (textConfig.applyBorder)
|
outColor = vec4(color) * alpha;
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (textConfig.backgroundColor.a != 0)
|
if (bgColor.a != 0)
|
||||||
{
|
{
|
||||||
outColor = mix(textConfig.backgroundColor, outColor, alpha);
|
outColor = mix(bgColor, outColor, alpha);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
32
openVulkanoCpp/Shader/sdfTextWithBorder.frag
Normal file
32
openVulkanoCpp/Shader/sdfTextWithBorder.frag
Normal file
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,25 +1,15 @@
|
|||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
layout(location = 0) in vec4 color;
|
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(location = 0) out vec4 outColor;
|
||||||
|
|
||||||
layout(set = 2, binding = 0) uniform sampler2D texSampler;
|
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()
|
void main()
|
||||||
{
|
{
|
||||||
vec4 sampled = vec4(1.0, 1.0, 1.0, texture(texSampler, texCoord).r);
|
vec4 sampled = vec4(1.0, 1.0, 1.0, texture(texSampler, texCoord).r);
|
||||||
outColor = vec4(textConfig.textColor) * sampled;
|
outColor = vec4(color) * sampled;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
#version 450
|
#version 450
|
||||||
layout(location = 0) in vec3 position;
|
|
||||||
layout(location = 1) in vec3 normal;
|
layout(location = 0) in vec2 position[4];
|
||||||
layout(location = 2) in vec3 tangent;
|
layout(location = 4) in vec2 textureCoordinates[4];
|
||||||
layout(location = 3) in vec3 biTangent;
|
layout(location = 8) in vec4 color;
|
||||||
layout(location = 4) in vec3 textureCoordinates;
|
layout(location = 9) in vec4 bgColor;
|
||||||
layout(location = 5) in vec4 color;
|
|
||||||
|
|
||||||
layout(location = 0) out vec4 outColor;
|
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
|
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
|
layout(set = 1, binding = 0) uniform CameraData
|
||||||
{
|
{
|
||||||
mat4 viewProjection;
|
mat4 viewProjection;
|
||||||
mat4 view;
|
|
||||||
mat4 projection;
|
|
||||||
vec4 camPos;
|
|
||||||
} cam;
|
} cam;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
gl_Position = cam.viewProjection * node.world * vec4(position, 1.0);
|
gl_Position = cam.viewProjection * node.world * vec4(position[gl_VertexIndex], 0.0, 1.0);
|
||||||
fragTextureCoordinates.xy = textureCoordinates.xy;
|
fragTextureCoordinates = textureCoordinates[gl_VertexIndex];
|
||||||
outColor = color;
|
outColor = color;
|
||||||
|
outBgColor = bgColor;
|
||||||
}
|
}
|
||||||
|
|||||||
71
openVulkanoCpp/Shader/textBillboard.vert
Normal file
71
openVulkanoCpp/Shader/textBillboard.vert
Normal file
@@ -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;
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "Base/ICloseable.hpp"
|
|
||||||
#include "Device.hpp"
|
#include "Device.hpp"
|
||||||
|
|
||||||
namespace OpenVulkano
|
namespace OpenVulkano
|
||||||
@@ -9,7 +9,7 @@ namespace OpenVulkano
|
|||||||
/**
|
/**
|
||||||
* \brief A not managed buffer. This should be used rarely.
|
* \brief A not managed buffer. This should be used rarely.
|
||||||
*/
|
*/
|
||||||
struct Buffer : public ICloseable
|
struct Buffer
|
||||||
{
|
{
|
||||||
vk::Device device;
|
vk::Device device;
|
||||||
vk::DeviceMemory memory;
|
vk::DeviceMemory memory;
|
||||||
@@ -94,7 +94,7 @@ namespace OpenVulkano
|
|||||||
device.invalidateMappedMemoryRanges(vk::MappedMemoryRange(memory, offset, size));
|
device.invalidateMappedMemoryRanges(vk::MappedMemoryRange(memory, offset, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Close() override
|
void Close()
|
||||||
{
|
{
|
||||||
if (mapped) UnMap();
|
if (mapped) UnMap();
|
||||||
if(memory)
|
if(memory)
|
||||||
|
|||||||
@@ -6,14 +6,13 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Base/ICloseable.hpp"
|
|
||||||
#include <vulkan/vulkan.hpp>
|
#include <vulkan/vulkan.hpp>
|
||||||
|
|
||||||
namespace OpenVulkano
|
namespace OpenVulkano
|
||||||
{
|
{
|
||||||
namespace Vulkan
|
namespace Vulkan
|
||||||
{
|
{
|
||||||
struct CommandHelper : virtual ICloseable
|
struct CommandHelper final
|
||||||
{
|
{
|
||||||
vk::Device device;
|
vk::Device device;
|
||||||
vk::CommandPool cmdPool;
|
vk::CommandPool cmdPool;
|
||||||
@@ -42,7 +41,7 @@ namespace OpenVulkano
|
|||||||
return level;
|
return level;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Close() override
|
void Close()
|
||||||
{
|
{
|
||||||
device.freeCommandBuffers(cmdPool, 1, &cmdBuffer);
|
device.freeCommandBuffers(cmdPool, 1, &cmdBuffer);
|
||||||
device.destroyCommandPool(cmdPool);
|
device.destroyCommandPool(cmdPool);
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ namespace OpenVulkano
|
|||||||
{
|
{
|
||||||
class Device;
|
class Device;
|
||||||
|
|
||||||
class Context final : public ICloseable
|
class Context final
|
||||||
{
|
{
|
||||||
bool enableValidationLayer, initialized;
|
bool enableValidationLayer, initialized;
|
||||||
std::set<std::string> requiredExtensions;
|
std::set<std::string> requiredExtensions;
|
||||||
@@ -45,14 +45,14 @@ namespace OpenVulkano
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
~Context() override
|
~Context()
|
||||||
{
|
{
|
||||||
if (initialized) Close();
|
if (initialized) Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Init(IGraphicsAppManager* graphicsAppManager, IVulkanWindow* window);
|
void Init(IGraphicsAppManager* graphicsAppManager, IVulkanWindow* window);
|
||||||
|
|
||||||
void Close() override;
|
void Close();
|
||||||
|
|
||||||
void Resize(uint32_t newWidth, uint32_t newHeight);
|
void Resize(uint32_t newWidth, uint32_t newHeight);
|
||||||
|
|
||||||
|
|||||||
@@ -10,13 +10,12 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include "Base/ICloseable.hpp"
|
|
||||||
|
|
||||||
namespace OpenVulkano
|
namespace OpenVulkano
|
||||||
{
|
{
|
||||||
namespace Vulkan
|
namespace Vulkan
|
||||||
{
|
{
|
||||||
class Device : public ICloseable
|
class Device final
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
vk::PhysicalDevice physicalDevice;
|
vk::PhysicalDevice physicalDevice;
|
||||||
@@ -106,7 +105,7 @@ namespace OpenVulkano
|
|||||||
return memoryProperties.memoryTypes[memoryType].propertyFlags;
|
return memoryProperties.memoryTypes[memoryType].propertyFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Close() override;
|
void Close();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Base/ICloseable.hpp"
|
|
||||||
#include "Image.hpp"
|
#include "Image.hpp"
|
||||||
#include "Device.hpp"
|
#include "Device.hpp"
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
@@ -17,7 +16,7 @@ namespace OpenVulkano::Vulkan
|
|||||||
{
|
{
|
||||||
class RenderPass;
|
class RenderPass;
|
||||||
|
|
||||||
class FrameBuffer : ICloseable
|
class FrameBuffer
|
||||||
{
|
{
|
||||||
Image depthBuffer;
|
Image depthBuffer;
|
||||||
std::vector<vk::Framebuffer> frameBuffers;
|
std::vector<vk::Framebuffer> frameBuffers;
|
||||||
@@ -50,7 +49,7 @@ namespace OpenVulkano::Vulkan
|
|||||||
protected:
|
protected:
|
||||||
void Resize(vk::Extent3D size);
|
void Resize(vk::Extent3D size);
|
||||||
|
|
||||||
void Close() override
|
virtual void Close()
|
||||||
{
|
{
|
||||||
DestroyFrameBuffer();
|
DestroyFrameBuffer();
|
||||||
if(depthBuffer) depthBuffer.Close();
|
if(depthBuffer) depthBuffer.Close();
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ namespace OpenVulkano::Vulkan
|
|||||||
SetLayout(cmdBuffer, vk::ImageSubresourceRange(aspectMask, 0, 1, 0, 1), newLayout, oldLayout);
|
SetLayout(cmdBuffer, vk::ImageSubresourceRange(aspectMask, 0, 1, 0, 1), newLayout, oldLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Close() override;
|
virtual void Close();
|
||||||
|
|
||||||
operator bool() const { return image.operator bool(); }
|
operator bool() const { return image.operator bool(); }
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Base/ICloseable.hpp"
|
|
||||||
#include "MetalBackedTexture.h"
|
#include "MetalBackedTexture.h"
|
||||||
|
|
||||||
#import <CoreVideo/CVPixelBuffer.h>
|
#import <CoreVideo/CVPixelBuffer.h>
|
||||||
@@ -16,19 +15,20 @@ namespace OpenVulkano::Vulkan
|
|||||||
{
|
{
|
||||||
class Renderer;
|
class Renderer;
|
||||||
|
|
||||||
class MetalTextureCache : public ICloseable
|
class MetalTextureCache final
|
||||||
{
|
{
|
||||||
CVMetalTextureCacheRef m_textureCache = nullptr;
|
CVMetalTextureCacheRef m_textureCache = nullptr;
|
||||||
Vulkan::ResourceManager* m_resourceManager = nullptr;
|
Vulkan::ResourceManager* m_resourceManager = nullptr;
|
||||||
std::map<void*, MetalBackedTexture> m_mtlToVkTextureMap;
|
std::map<void*, MetalBackedTexture> m_mtlToVkTextureMap;
|
||||||
Renderer* m_renderer;
|
Renderer* m_renderer;
|
||||||
|
IEventHandler* m_eventHandler = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
~MetalTextureCache() { if (m_resourceManager) Close(); }
|
~MetalTextureCache() { if (m_resourceManager) Close(); }
|
||||||
|
|
||||||
void Init(IRenderer* renderer);
|
void Init(IRenderer* renderer);
|
||||||
|
|
||||||
void Close() override;
|
void Close();
|
||||||
|
|
||||||
Scene::Texture* Get(CVPixelBufferRef pixelBuffer, MTLPixelFormat pixelFormat);
|
Scene::Texture* Get(CVPixelBufferRef pixelBuffer, MTLPixelFormat pixelFormat);
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ namespace OpenVulkano::Vulkan
|
|||||||
Logger::AR->error("Failed to create metal texture cache! Status code: {}", result);
|
Logger::AR->error("Failed to create metal texture cache! Status code: {}", result);
|
||||||
}
|
}
|
||||||
m_resourceManager = &m_renderer->GetResourceManager();
|
m_resourceManager = &m_renderer->GetResourceManager();
|
||||||
m_renderer->RegisterCloseable(this);
|
m_renderer->OnClose += EventHandler(this, &MetalTextureCache::Close);
|
||||||
}
|
}
|
||||||
|
|
||||||
Scene::Texture* MetalTextureCache::Get(CVPixelBufferRef pixelBuffer, MTLPixelFormat pixelFormat)
|
Scene::Texture* MetalTextureCache::Get(CVPixelBufferRef pixelBuffer, MTLPixelFormat pixelFormat)
|
||||||
@@ -57,7 +57,7 @@ namespace OpenVulkano::Vulkan
|
|||||||
void MetalTextureCache::Close()
|
void MetalTextureCache::Close()
|
||||||
{
|
{
|
||||||
m_mtlToVkTextureMap.clear();
|
m_mtlToVkTextureMap.clear();
|
||||||
m_renderer->UnregisterCloseable(this);
|
m_eventHandler->SetInvalid();
|
||||||
m_renderer = nullptr;
|
m_renderer = nullptr;
|
||||||
m_resourceManager = nullptr;
|
m_resourceManager = nullptr;
|
||||||
//TODO delete the texture cache object?
|
//TODO delete the texture cache object?
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ namespace OpenVulkano::Vulkan
|
|||||||
{
|
{
|
||||||
class FrameBuffer;
|
class FrameBuffer;
|
||||||
|
|
||||||
class RenderPass : public ICloseable
|
class RenderPass
|
||||||
{ //TODO allow to control the render rect size
|
{ //TODO allow to control the render rect size
|
||||||
protected:
|
protected:
|
||||||
vk::Device m_device;
|
vk::Device m_device;
|
||||||
@@ -27,14 +27,14 @@ namespace OpenVulkano::Vulkan
|
|||||||
|
|
||||||
RenderPass() = default;
|
RenderPass() = default;
|
||||||
|
|
||||||
~RenderPass() override
|
virtual ~RenderPass()
|
||||||
{
|
{
|
||||||
if (m_frameBuffer) RenderPass::Close();
|
if (m_frameBuffer) RenderPass::Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Init(Device* device, FrameBuffer* frameBuffer, bool clearColor = false, bool clearDepth = false);
|
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<float, 4>{ 0.39f, 0.58f, 0.93f, 1.0f }))
|
void SetClearColor(vk::ClearColorValue clearColor = vk::ClearColorValue(std::array<float, 4>{ 0.39f, 0.58f, 0.93f, 1.0f }))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -89,12 +89,7 @@ namespace OpenVulkano::Vulkan
|
|||||||
{
|
{
|
||||||
context.device->device.destroySemaphore(sema);
|
context.device->device.destroySemaphore(sema);
|
||||||
}
|
}
|
||||||
while (!closeables.empty())
|
OnClose();
|
||||||
{
|
|
||||||
ICloseable* closeable = closeables.back();
|
|
||||||
closeables.pop_back();
|
|
||||||
closeable->Close();
|
|
||||||
}
|
|
||||||
depthBufferQuery.Close();
|
depthBufferQuery.Close();
|
||||||
uiRenderer.Close();
|
uiRenderer.Close();
|
||||||
resourceManager.Close();
|
resourceManager.Close();
|
||||||
|
|||||||
@@ -40,7 +40,6 @@ namespace OpenVulkano::Vulkan
|
|||||||
std::vector<std::vector<CommandHelper>> commands;
|
std::vector<std::vector<CommandHelper>> commands;
|
||||||
std::vector<std::vector<vk::CommandBuffer>> submitBuffers;
|
std::vector<std::vector<vk::CommandBuffer>> submitBuffers;
|
||||||
UiRenderer uiRenderer;
|
UiRenderer uiRenderer;
|
||||||
std::vector<ICloseable*> closeables;
|
|
||||||
DepthBufferQuery depthBufferQuery;
|
DepthBufferQuery depthBufferQuery;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -83,14 +82,12 @@ namespace OpenVulkano::Vulkan
|
|||||||
|
|
||||||
Context& GetContext() { return context; }
|
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; }
|
IResourceManager* GetIResourceManager() override { return &resourceManager; }
|
||||||
|
|
||||||
|
|
||||||
float GetLastQueriedDepthValue() override { return depthBufferQuery.GetQueriedValue(); }
|
float GetLastQueriedDepthValue() override { return depthBufferQuery.GetQueriedValue(); }
|
||||||
void SetQueryDepthValue(const Math::Vector2f& depthCoordinates) override { depthBufferQuery.SetQueryCoordinates(depthCoordinates); }
|
void SetQueryDepthValue(const Math::Vector2f& depthCoordinates) override { depthBufferQuery.SetQueryCoordinates(depthCoordinates); }
|
||||||
|
|
||||||
|
Event<> OnClose;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ResourceManager.hpp"
|
#include "ResourceManager.hpp"
|
||||||
|
|
||||||
|
#include <Scene/VertexBuffer.hpp>
|
||||||
|
|
||||||
#include "ManagedBuffer.hpp"
|
#include "ManagedBuffer.hpp"
|
||||||
#include "MemoryAllocation.hpp"
|
#include "MemoryAllocation.hpp"
|
||||||
#include "Scene/Vertex.hpp"
|
#include "Scene/Vertex.hpp"
|
||||||
@@ -21,6 +24,7 @@
|
|||||||
#include "Vulkan/Scene/VulkanTexture.hpp"
|
#include "Vulkan/Scene/VulkanTexture.hpp"
|
||||||
#include "Vulkan/Scene/VulkanCamera.hpp"
|
#include "Vulkan/Scene/VulkanCamera.hpp"
|
||||||
#include "Vulkan/Scene/VulkanUniformBuffer.hpp"
|
#include "Vulkan/Scene/VulkanUniformBuffer.hpp"
|
||||||
|
#include "Vulkan/Scene/VulkanVertexBuffer.hpp"
|
||||||
|
|
||||||
namespace OpenVulkano::Vulkan
|
namespace OpenVulkano::Vulkan
|
||||||
{
|
{
|
||||||
@@ -173,6 +177,21 @@ namespace OpenVulkano::Vulkan
|
|||||||
return geometry->GetRenderResource();
|
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)
|
void ResourceManager::PrepareMaterial(Scene::Material* material)
|
||||||
{
|
{
|
||||||
if (material->texture && !material->texture->HasRenderResource())
|
if (material->texture && !material->texture->HasRenderResource())
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ namespace OpenVulkano
|
|||||||
class Shader;
|
class Shader;
|
||||||
class Camera;
|
class Camera;
|
||||||
class UniformBuffer;
|
class UniformBuffer;
|
||||||
|
class VertexBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Vulkan
|
namespace Vulkan
|
||||||
@@ -45,11 +46,12 @@ namespace OpenVulkano
|
|||||||
class VulkanNode;
|
class VulkanNode;
|
||||||
class VulkanShader;
|
class VulkanShader;
|
||||||
class VulkanUniformBuffer;
|
class VulkanUniformBuffer;
|
||||||
|
class VulkanVertexBuffer;
|
||||||
class UniformBuffer;
|
class UniformBuffer;
|
||||||
class ManagedBuffer;
|
class ManagedBuffer;
|
||||||
class MemoryAllocation;
|
class MemoryAllocation;
|
||||||
|
|
||||||
class ResourceManager : public IShaderOwner, public IResourceManager
|
class ResourceManager final : public IShaderOwner, public IResourceManager
|
||||||
{
|
{
|
||||||
friend UniformBuffer;
|
friend UniformBuffer;
|
||||||
friend VulkanTexture;
|
friend VulkanTexture;
|
||||||
@@ -63,6 +65,7 @@ namespace OpenVulkano
|
|||||||
MemoryPool memPool;
|
MemoryPool memPool;
|
||||||
std::vector<Unique<VulkanShader>> shaders;
|
std::vector<Unique<VulkanShader>> shaders;
|
||||||
std::vector<Unique<VulkanGeometry>> geometries;
|
std::vector<Unique<VulkanGeometry>> geometries;
|
||||||
|
std::vector<Unique<VulkanVertexBuffer>> vertexBuffers;
|
||||||
std::vector<Unique<VulkanNode>> nodes;
|
std::vector<Unique<VulkanNode>> nodes;
|
||||||
std::vector<Unique<VulkanTexture>> textures;
|
std::vector<Unique<VulkanTexture>> textures;
|
||||||
std::vector<Unique<VulkanCamera>> cameras;
|
std::vector<Unique<VulkanCamera>> cameras;
|
||||||
@@ -100,6 +103,8 @@ namespace OpenVulkano
|
|||||||
|
|
||||||
VulkanUniformBuffer* PrepareUniformBuffer(Scene::UniformBuffer* buffer);
|
VulkanUniformBuffer* PrepareUniformBuffer(Scene::UniformBuffer* buffer);
|
||||||
|
|
||||||
|
VulkanVertexBuffer* PrepareVertexBuffer(Scene::VertexBuffer* vbo);
|
||||||
|
|
||||||
VulkanNode* PrepareNode(Scene::Node* node);
|
VulkanNode* PrepareNode(Scene::Node* node);
|
||||||
|
|
||||||
VulkanTexture* PrepareTexture(Scene::Texture* texture);
|
VulkanTexture* PrepareTexture(Scene::Texture* texture);
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Base/ICloseable.hpp"
|
|
||||||
#include "Vulkan/Resources/ManagedBuffer.hpp"
|
#include "Vulkan/Resources/ManagedBuffer.hpp"
|
||||||
#include "Vulkan/Scene/IRecordable.hpp"
|
#include "Vulkan/Scene/IRecordable.hpp"
|
||||||
|
|
||||||
@@ -14,7 +13,7 @@ namespace OpenVulkano::Vulkan
|
|||||||
{
|
{
|
||||||
class ManagedBuffer;
|
class ManagedBuffer;
|
||||||
|
|
||||||
class UniformBuffer final : public IRecordable, public ICloseable
|
class UniformBuffer final : public IRecordable
|
||||||
{
|
{
|
||||||
ManagedBuffer::Ptr m_buffer = nullptr;
|
ManagedBuffer::Ptr m_buffer = nullptr;
|
||||||
vk::DescriptorSet m_descriptorSet;
|
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 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;
|
void Record(VulkanDrawContext* drawContext) override;
|
||||||
|
|
||||||
|
|||||||
@@ -12,107 +12,61 @@
|
|||||||
#include "Vulkan/VulkanDrawContext.hpp"
|
#include "Vulkan/VulkanDrawContext.hpp"
|
||||||
#include "Vulkan/Scene/VulkanTexture.hpp"
|
#include "Vulkan/Scene/VulkanTexture.hpp"
|
||||||
#include "Vulkan/Scene/VulkanUniformBuffer.hpp"
|
#include "Vulkan/Scene/VulkanUniformBuffer.hpp"
|
||||||
|
#include "Vulkan/Scene/VulkanVertexBuffer.hpp"
|
||||||
|
|
||||||
using namespace OpenVulkano::Scene;
|
using namespace OpenVulkano::Scene;
|
||||||
|
|
||||||
namespace OpenVulkano::Vulkan
|
namespace OpenVulkano::Vulkan
|
||||||
{
|
{
|
||||||
|
|
||||||
void EncodeBackground(LabelDrawable* labelDrawable, Vulkan::VulkanDrawContext* drawContext)
|
void EncodeBackground(LabelDrawable* labelDrawable, VulkanDrawContext* drawContext)
|
||||||
{
|
{
|
||||||
if (labelDrawable->IsBillboard())
|
VulkanUniformBuffer* vkBuffer = labelDrawable->GetLabelBuffer()->GetRenderResource();
|
||||||
{
|
if (!vkBuffer) vkBuffer = drawContext->renderer->GetResourceManager().PrepareUniformBuffer(labelDrawable->GetLabelBuffer());
|
||||||
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);
|
|
||||||
}
|
|
||||||
vkBuffer->Record(drawContext);
|
vkBuffer->Record(drawContext);
|
||||||
|
|
||||||
for (Node* node: labelDrawable->GetNodes())
|
for (Node* node: labelDrawable->GetNodes())
|
||||||
{
|
{
|
||||||
if (!node->IsEnabled()) [[unlikely]]
|
if (!node->IsEnabled()) [[unlikely]] continue;
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
drawContext->EncodeNode(node);
|
drawContext->EncodeNode(node);
|
||||||
}
|
}
|
||||||
drawContext->commandBuffer.draw(4, 1, 0, 0);
|
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())
|
for (TextDrawable& entry : labelDrawable->GetTexts())
|
||||||
{
|
{
|
||||||
OpenVulkano::Scene::Shader* shader = entry.GetShader();
|
drawContext->EncodeShader(entry.GetShader());
|
||||||
drawContext->EncodeShader(shader);
|
VertexBuffer* vbo = entry.GetVertexBuffer();
|
||||||
Geometry* mesh = entry.GetMesh();
|
VulkanVertexBuffer* renderVbo = vbo->GetRenderResource();
|
||||||
VulkanGeometry* renderGeo = mesh->GetRenderResource();
|
if (!renderVbo) renderVbo = drawContext->renderer->GetResourceManager().PrepareVertexBuffer(vbo);
|
||||||
if (!renderGeo)
|
renderVbo->RecordBind(drawContext->commandBuffer);
|
||||||
{
|
|
||||||
renderGeo = drawContext->renderer->GetResourceManager().PrepareGeometry(mesh);
|
|
||||||
}
|
|
||||||
renderGeo->RecordBind(drawContext->commandBuffer);
|
|
||||||
|
|
||||||
std::array<OpenVulkano::Scene::UniformBuffer*, 2> uniforms = { nullptr, nullptr };
|
|
||||||
// fragment shader buffer
|
|
||||||
uniforms[0] = entry.GetBuffer();
|
|
||||||
if (labelDrawable->IsBillboard())
|
if (labelDrawable->IsBillboard())
|
||||||
{
|
{
|
||||||
// vertex shader buffer
|
VulkanUniformBuffer* vkBuffer = labelDrawable->GetLabelBuffer()->GetRenderResource();
|
||||||
uniforms[1] = labelDrawable->GetBillboardBuffer();
|
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)
|
renderTexture = drawContext->renderer->GetResourceManager().PrepareTexture(entry.GetTexture());
|
||||||
{
|
|
||||||
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->Record(drawContext);
|
||||||
|
|
||||||
for (Node* node: labelDrawable->GetNodes())
|
for (Node* node: labelDrawable->GetNodes())
|
||||||
{
|
{
|
||||||
if (!node->IsEnabled()) [[unlikely]]
|
if (!node->IsEnabled()) [[unlikely]] continue;
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
drawContext->EncodeNode(node);
|
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<LabelDrawable*>(instance);
|
LabelDrawable* labelDrawable = static_cast<LabelDrawable*>(instance);
|
||||||
EncodeBackground(labelDrawable, drawContext);
|
EncodeBackground(labelDrawable, drawContext);
|
||||||
@@ -122,5 +76,5 @@ namespace OpenVulkano::Vulkan
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
void* labelDrawableVulkanEncoderReg = DrawEncoder::RegisterVulkanEncodeFunction<LabelDrawable>(&OpenVulkano::Vulkan::EncodeLabelDrawable);
|
[[maybe_unused]] void* labelDrawableVulkanEncoderReg = DrawEncoder::RegisterVulkanEncodeFunction<LabelDrawable>(&OpenVulkano::Vulkan::EncodeLabelDrawable);
|
||||||
}
|
}
|
||||||
45
openVulkanoCpp/Vulkan/Scene/TextDrawableVulkanEncoder.cpp
Normal file
45
openVulkanoCpp/Vulkan/Scene/TextDrawableVulkanEncoder.cpp
Normal file
@@ -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<TextDrawable*>(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<TextDrawable>(&OpenVulkano::Vulkan::EncodeTextDrawable);
|
||||||
|
}
|
||||||
@@ -54,7 +54,7 @@ namespace OpenVulkano::Vulkan
|
|||||||
|
|
||||||
for(const auto& description : shader->vertexInputDescriptions)
|
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<vk::VertexInputRate>(description.stepMode));
|
||||||
if (shader->vertexInputDescriptions.size() > 1)
|
if (shader->vertexInputDescriptions.size() > 1)
|
||||||
{
|
{
|
||||||
for(const auto& param : description.inputParameters)
|
for(const auto& param : description.inputParameters)
|
||||||
@@ -84,6 +84,13 @@ namespace OpenVulkano::Vulkan
|
|||||||
vk::PipelineInputAssemblyStateCreateInfo inputAssembly = { {}, static_cast<vk::PrimitiveTopology>(shader->topology), 0 };
|
vk::PipelineInputAssemblyStateCreateInfo inputAssembly = { {}, static_cast<vk::PrimitiveTopology>(shader->topology), 0 };
|
||||||
vk::PipelineRasterizationStateCreateInfo rasterizer = {};
|
vk::PipelineRasterizationStateCreateInfo rasterizer = {};
|
||||||
rasterizer.cullMode = static_cast<vk::CullModeFlagBits>(shader->cullMode);
|
rasterizer.cullMode = static_cast<vk::CullModeFlagBits>(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::PipelineMultisampleStateCreateInfo msaa = {};
|
||||||
vk::PipelineDepthStencilStateCreateInfo depth = { {}, shader->depthTest, shader->depthWrite, static_cast<vk::CompareOp>(shader->depthCompareOp) };
|
vk::PipelineDepthStencilStateCreateInfo depth = { {}, shader->depthTest, shader->depthWrite, static_cast<vk::CompareOp>(shader->depthCompareOp) };
|
||||||
depth.maxDepthBounds = 1;
|
depth.maxDepthBounds = 1;
|
||||||
|
|||||||
@@ -11,39 +11,36 @@
|
|||||||
#include <vulkan/vulkan.hpp>
|
#include <vulkan/vulkan.hpp>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace OpenVulkano
|
namespace OpenVulkano::Vulkan
|
||||||
{
|
{
|
||||||
namespace Vulkan
|
class Context;
|
||||||
{
|
class IShaderOwner;
|
||||||
class Context;
|
|
||||||
class IShaderOwner;
|
|
||||||
|
|
||||||
class VulkanShader final : public IRenderResource<Scene::Shader>, public IRecordable
|
class VulkanShader final : public IRenderResource<Scene::Shader>, public IRecordable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
vk::Device device;
|
vk::Device device;
|
||||||
std::vector<vk::ShaderModule> shaderModules; // TODO manage live time somewhere else to allow sharing of shader programs
|
std::vector<vk::ShaderModule> shaderModules; // TODO manage live time somewhere else to allow sharing of shader programs
|
||||||
std::vector<vk::PipelineShaderStageCreateInfo> shaderStageCreateInfo;
|
std::vector<vk::PipelineShaderStageCreateInfo> shaderStageCreateInfo;
|
||||||
vk::Pipeline pipeline; // TODO pipeline and shader config should be split
|
vk::Pipeline pipeline; // TODO pipeline and shader config should be split
|
||||||
std::vector<vk::DescriptorSetLayout> descriptorSetLayouts;
|
std::vector<vk::DescriptorSetLayout> descriptorSetLayouts;
|
||||||
vk::PipelineLayout pipelineLayout;
|
vk::PipelineLayout pipelineLayout;
|
||||||
IShaderOwner* owner = nullptr;
|
IShaderOwner* owner = nullptr;
|
||||||
Context* context = 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:
|
private:
|
||||||
void BuildPipeline();
|
void BuildPipeline();
|
||||||
|
|
||||||
void CreatePipelineLayout();
|
void CreatePipelineLayout();
|
||||||
};
|
};
|
||||||
}
|
|
||||||
}
|
}
|
||||||
43
openVulkanoCpp/Vulkan/Scene/VulkanVertexBuffer.hpp
Normal file
43
openVulkanoCpp/Vulkan/Scene/VulkanVertexBuffer.hpp
Normal file
@@ -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<Scene::VertexBuffer>
|
||||||
|
{
|
||||||
|
ManagedBuffer::Ptr m_vertexBuffer;
|
||||||
|
|
||||||
|
public:
|
||||||
|
VulkanVertexBuffer(Scene::VertexBuffer* vbo, ManagedBuffer::Ptr& vertexBuffer)
|
||||||
|
: IRenderResource<Scene::VertexBuffer>(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
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user