diff --git a/CMakeLists.txt b/CMakeLists.txt index 5039b4b..9cf720b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,8 +48,15 @@ if(IOS) add_executable(openVulkanoCpp examples/main.m ${resources}) else() file(GLOB_RECURSE sources CONFIGURE_DEPENDS "openVulkanoCpp/*.h" "openVulkanoCpp/*.c" "openVulkanoCpp/*.hpp" "openVulkanoCpp/*.cpp" "examples/*.hpp" "examples/*.cpp") - add_executable(openVulkanoCpp examples/main.cpp) + file(GLOB SHADER_SRC_FILES ${ROOT_FOLDER}/openVulkanoCpp/Shader/*) + list(FILTER SHADER_SRC_FILES EXCLUDE REGEX ".*\\.(hpp|cpp)$") + add_executable(openVulkanoCpp examples/main.cpp ${SHADER_SRC_FILES}) + if (MSVC) + set_property(GLOBAL PROPERTY USE_FOLDERS ON) + source_group("Shaders" FILES ${SHADER_SRC_FILES}) + endif() endif() + FilterPlatformPaths(sources) SetWarningSettings(openVulkanoCpp) set_property(TARGET openVulkanoCpp PROPERTY CXX_STANDARD 20) diff --git a/examples/ExampleApps/BillboardExampleApp.cpp b/examples/ExampleApps/BillboardExampleApp.cpp new file mode 100644 index 0000000..b579a17 --- /dev/null +++ b/examples/ExampleApps/BillboardExampleApp.cpp @@ -0,0 +1,160 @@ +/* + * 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 "BillboardExampleApp.hpp" +#include "Scene/Scene.hpp" +#include "Scene/Shader/Shader.hpp" +#include "Scene/Geometry.hpp" +#include "Scene/GeometryFactory.hpp" +#include "Scene/Material.hpp" +#include "Scene/Vertex.hpp" +#include "Scene/SimpleDrawable.hpp" +#include "Scene/UI/PerformanceInfo.hpp" +#include "Scene/UniformBuffer.hpp" +#include "Input/InputManager.hpp" +#include "Host/GraphicsAppManager.hpp" +#include "Host/GLFW/WindowGLFW.hpp" +#include "Math/Math.hpp" +#include "Base/EngineConfiguration.hpp" +#include "Controller/FreeCamCameraController.hpp" + +namespace OpenVulkano +{ + using namespace Scene; + using namespace Input; + using namespace Math; + + class BillboardExampleAppImpl final : public BillboardExampleApp + { + public: + + struct BillboardControlBlock + { + Math::Vector2f quadSize; + bool isFixedSize; + }; + + void Init() override + { + auto engineConfig = OpenVulkano::EngineConfiguration::GetEngineConfiguration(); + engineConfig->SetNumThreads(4); + engineConfig->SetPreferFramebufferFormatSRGB(false); + + std::srand(1); // Fix seed for random numbers + m_scene.Init(); + m_cam.Init(70, 16, 9, 0.1f, 100); + m_scene.SetCamera(&m_cam); + + m_quadBillboardShader.AddShaderProgram(OpenVulkano::ShaderProgramType::VERTEX, "Shader/billboardFromSinglePoint"); + m_quadBillboardShader.AddShaderProgram(OpenVulkano::ShaderProgramType::GEOMETRY, "Shader/billboardFromSinglePoint"); + m_quadBillboardShader.AddShaderProgram(OpenVulkano::ShaderProgramType::FRAGMENT, "Shader/basicTexture"); + m_quadBillboardShader.AddVertexInputDescription(OpenVulkano::Vertex::GetVertexInputDescription()); + m_quadBillboardShader.AddDescriptorSetLayoutBinding(Texture::DESCRIPTOR_SET_LAYOUT_BINDING); + m_quadBillboardShader.AddDescriptorSetLayoutBinding(UniformBuffer::DESCRIPTOR_SET_LAYOUT_BINDING); + m_quadBillboardShader.topology = Topology::POINT_LIST; + + m_shader.AddShaderProgram(OpenVulkano::ShaderProgramType::VERTEX, "Shader/billboard"); + m_shader.AddShaderProgram(OpenVulkano::ShaderProgramType::FRAGMENT, "Shader/basic"); + m_shader.AddVertexInputDescription(OpenVulkano::Vertex::GetVertexInputDescription()); + m_shader.AddDescriptorSetLayoutBinding(Texture::DESCRIPTOR_SET_LAYOUT_BINDING); + m_shader.AddDescriptorSetLayoutBinding(UniformBuffer::DESCRIPTOR_SET_LAYOUT_BINDING); + m_shader.cullMode = CullMode::NONE; + + constexpr int quadsCnt = 7; + constexpr int otherCnt = 2; + constexpr int cntDrawables = quadsCnt + otherCnt; + + m_bbContolBlock.quadSize = { 100.f, 100.f }; + m_bbContolBlock.isFixedSize = false; + m_uniBuffer.Init(sizeof(BillboardControlBlock), &m_bbContolBlock); + m_uniBuffer.setId = 3; + m_drawablesPool.resize(cntDrawables); + m_nodesPool.resize(cntDrawables); + m_geo.reserve(cntDrawables); + m_texturedMat.texture = &Texture::PLACEHOLDER; + + for (uint32_t i = 0; i < cntDrawables; i++) + { + Geometry* geo = nullptr; + m_nodesPool[i].Init(); + if (i < quadsCnt) + { + geo = new Geometry(); + geo->Init(1, 0); + geo->vertices[0].position = glm::vec3(1 + i, i, 0); + if (i >= 1 && i <= 3) + geo->vertices[0].color = glm::vec4(1, 1, 1, 1); + else + geo->vertices[0].color = glm::vec4(1, 0, 0, 1); + m_nodesPool[i].SetMatrix(Math::Utils::translate(glm::mat4x4(1.f), Vector3f(-5 + std::rand() % 5, -5 + std::rand() % 5, std::rand() % 5))); + m_drawablesPool[i].Init(&m_quadBillboardShader, geo, &m_texturedMat, &m_uniBuffer); + } + else + { + geo = GeometryFactory::MakePyramid(1, 1, glm::vec4(0, 1, 0, 1)); + m_nodesPool[i].SetMatrix(Math::Utils::translate(glm::mat4x4(1.f), Vector3f(-5 + std::rand() % 5, -5 + std::rand() % 5, -std::rand() % 10))); + m_drawablesPool[i].Init(&m_shader, geo, &m_mat, &m_uniBuffer); + } + m_geo.push_back(geo); + m_scene.GetRoot()->AddChild(&m_nodesPool[i]); + m_nodesPool[i].AddDrawable(&m_drawablesPool[i]); + } + + GetGraphicsAppManager()->GetRenderer()->SetScene(&m_scene); + + m_camController.Init(&m_cam); + m_camController.SetDefaultKeybindings(); + m_camController.SetPosition({ 0, 0, 5 }); + m_camController.SetBoostFactor(5); + + std::shared_ptr m_perfInfo = + std::make_shared(); + m_ui.AddElement(m_perfInfo); + GetGraphicsAppManager()->GetRenderer()->SetActiveUi(&m_ui); + } + + void Tick() override + { + m_camController.Tick(); + } + + void Close() override + { + for (Geometry* g: m_geo) + { + delete g; + } + } + + private: + OpenVulkano::Scene::Scene m_scene; + BillboardControlBlock m_bbContolBlock; + PerspectiveCamera m_cam; + UniformBuffer m_uniBuffer; + OpenVulkano::FreeCamCameraController m_camController; + Material m_mat; + Material m_texturedMat; + Shader m_shader; + Shader m_quadBillboardShader; + std::vector m_drawablesPool; + std::vector m_nodesPool; + Vector3f_SIMD m_position = { 0, 0, -10 }; + OpenVulkano::Scene::UI::SimpleUi m_ui; + std::vector m_geo; + std::shared_ptr m_perfInfo; + }; + + IGraphicsApp* BillboardExampleApp::Create() { return new BillboardExampleAppImpl(); } + + std::unique_ptr BillboardExampleApp::CreateUnique() + { + return std::make_unique(); + } + +} + +#pragma clang diagnostic pop +#pragma clang diagnostic pop \ No newline at end of file diff --git a/examples/ExampleApps/BillboardExampleApp.hpp b/examples/ExampleApps/BillboardExampleApp.hpp new file mode 100644 index 0000000..fa1c215 --- /dev/null +++ b/examples/ExampleApps/BillboardExampleApp.hpp @@ -0,0 +1,27 @@ +/* + * 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/IGraphicsApp.hpp" +#include + +namespace OpenVulkano +{ + class BillboardExampleApp : public IGraphicsApp + { + public: + static IGraphicsApp* Create(); + + static std::unique_ptr CreateUnique(); + + [[nodiscard]] std::string GetAppName() const final + { return "Billboard ExampleApp"; } + + [[nodiscard]] OpenVulkano::Version GetAppVersion() const final + { return {"v1.0"}; } + }; +} \ No newline at end of file diff --git a/examples/main.cpp b/examples/main.cpp index 18a8431..388087e 100644 --- a/examples/main.cpp +++ b/examples/main.cpp @@ -8,6 +8,7 @@ #include "ExampleApps/CubesExampleApp.hpp" #include "ExampleApps/MovingCubeApp.hpp" #include "ExampleApps/TexturedCubeExampleApp.hpp" +#include "ExampleApps/BillboardExampleApp.hpp" #include #include @@ -25,6 +26,7 @@ int main(int argc, char** argv) "Cubes Example App", "Moving Cube Example App", "Textured Cube Example App", + "Billboard Example App" }; int selectedExample = 0; @@ -41,6 +43,7 @@ int main(int argc, char** argv) case 0: app = CubesExampleApp::CreateUnique(); break; case 1: app = MovingCubeApp::CreateUnique(); break; case 2: app = TexturedCubeExampleApp::CreateUnique(); break; + case 3: app = BillboardExampleApp::CreateUnique(); break; default: throw std::runtime_error("Invalid menu selection!"); break; } diff --git a/openVulkanoCpp/Base/IGraphicsAppManager.hpp b/openVulkanoCpp/Base/IGraphicsAppManager.hpp index 536c6b5..14cf156 100644 --- a/openVulkanoCpp/Base/IGraphicsAppManager.hpp +++ b/openVulkanoCpp/Base/IGraphicsAppManager.hpp @@ -16,6 +16,7 @@ namespace OpenVulkano virtual RenderAPI::RenderApi GetRenderApi() const = 0; virtual IGraphicsApp* GetGraphicsApp() const = 0; virtual IRenderer* GetRenderer() const = 0; + virtual IWindow* GetWindow() const = 0; virtual bool IsRunning() const = 0; virtual bool IsPaused() const = 0; virtual void Stop() = 0; diff --git a/openVulkanoCpp/Controller/FreeCamCameraController.cpp b/openVulkanoCpp/Controller/FreeCamCameraController.cpp index 89342a1..393514f 100644 --- a/openVulkanoCpp/Controller/FreeCamCameraController.cpp +++ b/openVulkanoCpp/Controller/FreeCamCameraController.cpp @@ -32,8 +32,7 @@ namespace OpenVulkano vec = Math::Utils::normalize(vec); } - float timeScale = CURRENT_FRAME.frameTime; //TODO - + float timeScale = 5 * CURRENT_FRAME.frameTime; //TODO vec = vec * timeScale * 3.0f; // scale vector if (input->GetButton(m_actionBoost)) { diff --git a/openVulkanoCpp/Controller/FreeCamCameraController.hpp b/openVulkanoCpp/Controller/FreeCamCameraController.hpp index ef163c1..2fc33ba 100644 --- a/openVulkanoCpp/Controller/FreeCamCameraController.hpp +++ b/openVulkanoCpp/Controller/FreeCamCameraController.hpp @@ -18,7 +18,7 @@ namespace OpenVulkano class FreeCamCameraController final : public CameraController { - float m_yaw = 0, m_pitch = 0, m_boostFactor = 2; + float m_yaw = 0, m_pitch = 0, m_boostFactor = 1.5; Math::Vector3f_SIMD m_position = { 0, 0, 0 }; Input::InputAction* m_actionForward; diff --git a/openVulkanoCpp/Host/GLFW/InputMappingGLFW.hpp b/openVulkanoCpp/Host/GLFW/InputMappingGLFW.hpp index eadc109..320fdfb 100644 --- a/openVulkanoCpp/Host/GLFW/InputMappingGLFW.hpp +++ b/openVulkanoCpp/Host/GLFW/InputMappingGLFW.hpp @@ -48,7 +48,7 @@ namespace OpenVulkano::GLFW { remappedKey = i - 320; } - else if (i >= GLFW_KEY_NUM_LOCK) + else if (i == GLFW_KEY_NUM_LOCK) { remappedKey = 17; } diff --git a/openVulkanoCpp/Host/GraphicsAppManager.hpp b/openVulkanoCpp/Host/GraphicsAppManager.hpp index 9e53818..5d4b627 100644 --- a/openVulkanoCpp/Host/GraphicsAppManager.hpp +++ b/openVulkanoCpp/Host/GraphicsAppManager.hpp @@ -50,6 +50,8 @@ namespace OpenVulkano [[nodiscard]] IRenderer* GetRenderer() const override { return renderer.get(); } + [[nodiscard]] IWindow* GetWindow() const override { return window; } + [[nodiscard]] bool IsRunning() const override { return running; } [[nodiscard]] bool IsPaused() const override { return paused; } diff --git a/openVulkanoCpp/Input/InputManager.cpp b/openVulkanoCpp/Input/InputManager.cpp index b17ca6a..5e36010 100644 --- a/openVulkanoCpp/Input/InputManager.cpp +++ b/openVulkanoCpp/Input/InputManager.cpp @@ -69,7 +69,7 @@ namespace OpenVulkano::Input for (const KeyBinding binding : action->GetKeys()) { if (binding.key.GetInputDeviceType() != device->GetType()) continue; - if (device->GetButton(binding.key)) return true; + return device->GetButton(binding.key); } } return false; @@ -80,7 +80,7 @@ namespace OpenVulkano::Input for(const InputDevice* device : devices) { if (key.GetInputDeviceType() != device->GetType()) continue; - if (device->GetButton(key)) return true; + return device->GetButton(key); } return false; } diff --git a/openVulkanoCpp/Scene/Camera.hpp b/openVulkanoCpp/Scene/Camera.hpp index 478176b..af6696c 100644 --- a/openVulkanoCpp/Scene/Camera.hpp +++ b/openVulkanoCpp/Scene/Camera.hpp @@ -99,7 +99,7 @@ namespace OpenVulkano::Scene { //TODO this should be done based on the clipspace used by the rendering api // In vulkan the screen space is defined as y=0=top and y=1=bottom and thus the coordinate have to be flipped - m_viewProjection = m_projection * Math::Matrix4f(1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1) * m_view; + m_viewProjection = m_projection * m_view; } void UpdateWorldMatrix(const Math::Matrix4f& parentWorldMat) override @@ -252,6 +252,7 @@ namespace OpenVulkano::Scene void UpdateProjectionMatrix() override { m_projection = Math::Utils::perspectiveRH_ZO(m_fov, m_aspect, m_nearPlane, m_farPlane); + m_projection *= Math::Matrix4f(1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1); UpdateViewProjectionMatrix(); } diff --git a/openVulkanoCpp/Scene/SimpleDrawable.cpp b/openVulkanoCpp/Scene/SimpleDrawable.cpp index 7bc3fac..0920971 100644 --- a/openVulkanoCpp/Scene/SimpleDrawable.cpp +++ b/openVulkanoCpp/Scene/SimpleDrawable.cpp @@ -9,19 +9,21 @@ namespace OpenVulkano::Scene { - void SimpleDrawable::Init(Shader* shader, Geometry* mesh, Material* material) + void SimpleDrawable::Init(Shader* shader, Geometry* mesh, Material* material, UniformBuffer* uniBuffer) { - if (m_mesh || m_material) throw std::runtime_error("Drawable is already initialized."); + if (m_mesh || m_material || m_uniBuffer) throw std::runtime_error("Drawable is already initialized."); m_mesh = mesh; m_material = material; + m_uniBuffer = uniBuffer; SetShader(shader); } void SimpleDrawable::Init(SimpleDrawable* drawable) { - if (m_mesh || m_material) throw std::runtime_error("Drawable is already initialized."); + if (m_mesh || m_material || m_uniBuffer) throw std::runtime_error("Drawable is already initialized."); m_mesh = drawable->m_mesh; m_material = drawable->m_material; + m_uniBuffer = drawable->m_uniBuffer; SetShader(drawable->GetShader()); } } \ No newline at end of file diff --git a/openVulkanoCpp/Scene/SimpleDrawable.hpp b/openVulkanoCpp/Scene/SimpleDrawable.hpp index 49908d2..0f5aa13 100644 --- a/openVulkanoCpp/Scene/SimpleDrawable.hpp +++ b/openVulkanoCpp/Scene/SimpleDrawable.hpp @@ -12,20 +12,22 @@ namespace OpenVulkano::Scene { class Geometry; class Material; + class UniformBuffer; class SimpleDrawable final : public Drawable { Geometry* m_mesh = nullptr; Material* m_material = nullptr; + UniformBuffer* m_uniBuffer = nullptr; public: - SimpleDrawable() : Drawable(DrawEncoder::GetDrawEncoder()) - {} + SimpleDrawable() : Drawable(DrawEncoder::GetDrawEncoder()) {} explicit SimpleDrawable(const SimpleDrawable* toCopy) - : Drawable(DrawEncoder::GetDrawEncoder()) - , m_mesh(toCopy->m_mesh) - , m_material(toCopy->m_material) + : Drawable(DrawEncoder::GetDrawEncoder()) + , m_mesh(toCopy->m_mesh) + , m_material(toCopy->m_material) + , m_uniBuffer(toCopy->m_uniBuffer) { SetShader(toCopy->GetShader()); } @@ -35,12 +37,14 @@ namespace OpenVulkano::Scene //if (m_mesh) SimpleDrawable::Close(); } - void Init(Shader* shader, Geometry* mesh, Material* material); + void Init(Shader* shader, Geometry* mesh, Material* material, UniformBuffer* uniBuffer = nullptr); void Init(SimpleDrawable* drawable); [[nodiscard]] Geometry* GetMesh() const { return m_mesh; } [[nodiscard]] Material* GetMaterial() const { return m_material; } + + [[nodiscard]] UniformBuffer* GetBuffer() const { return m_uniBuffer; } }; } diff --git a/openVulkanoCpp/Scene/UniformBuffer.hpp b/openVulkanoCpp/Scene/UniformBuffer.hpp index 06cf9ef..1551d3f 100644 --- a/openVulkanoCpp/Scene/UniformBuffer.hpp +++ b/openVulkanoCpp/Scene/UniformBuffer.hpp @@ -16,18 +16,19 @@ namespace OpenVulkano::Scene static constexpr inline DescriptorSetLayoutBinding DESCRIPTOR_SET_LAYOUT_BINDING = { 0, DescriptorSetLayoutBinding::Type::TYPE_UNIFORM_BUFFER, 1, ShaderProgramType::ALL_GRAPHICS }; DescriptorSetLayoutBinding binding; - uint32_t setId = 2; + uint32_t setId; ICloseable* renderBuffer = nullptr; size_t size = 0; const void* data = nullptr; UpdateFrequency updateFrequency = UpdateFrequency::Never; bool updated = true; - void Init(size_t size, const void* data, 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->data = data; this->binding = binding; + this->setId = setId; } UpdateFrequency GetUpdateFrequency() const { return updateFrequency; } diff --git a/openVulkanoCpp/Shader/basicTexture.frag b/openVulkanoCpp/Shader/basicTexture.frag index acf99a1..d0095cc 100644 --- a/openVulkanoCpp/Shader/basicTexture.frag +++ b/openVulkanoCpp/Shader/basicTexture.frag @@ -3,6 +3,7 @@ layout(location = 0) in vec4 color; layout(location = 1) in vec2 texCoord; layout(location = 0) out vec4 outColor; + layout(set = 2, binding = 0) uniform sampler2D texSampler; void main() diff --git a/openVulkanoCpp/Shader/billboard.vert b/openVulkanoCpp/Shader/billboard.vert new file mode 100644 index 0000000..261d543 --- /dev/null +++ b/openVulkanoCpp/Shader/billboard.vert @@ -0,0 +1,58 @@ +#version 450 + +#extension GL_ARB_separate_shader_objects : enable + +layout(location = 0) in vec3 pos; +layout(location = 4) in vec3 textureCoordinates; +layout(location = 5) in vec4 color; +layout(location = 0) out vec4 outColor; +layout(location = 1) 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 = 3, binding = 0) uniform BillboardData +{ + vec2 size; + bool isFixedSize; +} billboardInfo; + +void main() { + if (!billboardInfo.isFixedSize) + { + mat4 mv = cam.view * node.world; + + mv[0][0] = 1; + mv[0][1] = 0; + mv[0][2] = 0; + + mv[1][0] = 0; + mv[1][1] = 1; + mv[1][2] = 0; + + mv[2][0] = 0; + mv[2][1] = 0; + mv[2][2] = 1; + + gl_Position = cam.projection * mv * vec4(pos, 1); + } + else + { + vec4 billboardPos = vec4(0.5, 0.5, 0.5, 1); + vec4 viewPos = cam.view * node.world * billboardPos; + float dist = -viewPos.z; + gl_Position = cam.projection * (viewPos + vec4(pos.xy*dist*0.2,0,0)); + } + outColor = color; + outTexture = textureCoordinates.xy; +} diff --git a/openVulkanoCpp/Shader/billboardFromSinglePoint.geom b/openVulkanoCpp/Shader/billboardFromSinglePoint.geom new file mode 100644 index 0000000..13e60f0 --- /dev/null +++ b/openVulkanoCpp/Shader/billboardFromSinglePoint.geom @@ -0,0 +1,96 @@ +#version 450 + +layout(points) in; +layout(triangle_strip, max_vertices = 4) out; + +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; + float nearPlane; + float farPlane; + float width; + float height; + float fov; + float aspect; + float scaleFactor; + float pixelScaleFactor; +} cam; + +layout(set = 3, binding = 0) uniform BillboardData +{ + vec2 size; + bool isFixedSize; +} billboardInfo; + +layout(location = 0) out vec4 color; +layout(location = 1) out vec2 tex; + +layout(location = 0) in VS_OUT { + vec4 color; +} gs_in[]; + +void main() { + // The desired point for the billboard + vec3 pos = gl_in[0].gl_Position.xyz; + if(!billboardInfo.isFixedSize) + { + vec3 cameraRight = normalize(vec3(cam.view[0][0], cam.view[1][0], cam.view[2][0])); + vec3 cameraUp = normalize(vec3(cam.view[0][1], cam.view[1][1], cam.view[2][1])); + const vec2 offsets[4] = { + vec2(0.5, -0.5), + vec2(0.5, 0.5), + vec2(-0.5, -0.5), + vec2(-0.5, 0.5) + }; + const vec2 texCoords[4] = { + vec2(1, 0), + vec2(1, 1), + vec2(0, 0), + vec2(0, 1) + }; + + for (int i = 0; i < 4; i++) + { + vec2 scaledSize = billboardInfo.size / length(billboardInfo.size); + gl_Position = cam.viewProjection * vec4(pos + cameraRight * offsets[i].x * scaledSize.x + cameraUp * offsets[i].y * scaledSize.y, 1.0); + color = gs_in[0].color; + tex = texCoords[i].xy; + EmitVertex(); + } + EndPrimitive(); + } + else + { + const vec2 offsets[4] = { + vec2(-0.5, -0.5), + vec2(-0.5, 0.5), + vec2(0.5, -0.5), + vec2(0.5, 0.5) + }; + const vec2 texCoords[4] = { + vec2(0, 0), + vec2(0, 1), + vec2(1, 0), + vec2(1, 1) + }; + + for (int i = 0; i < 4; i++) + { + gl_Position = cam.viewProjection * vec4(pos, 1); + gl_Position /= gl_Position.w; + gl_Position.xy += offsets[i] * vec2(billboardInfo.size.x/cam.width, billboardInfo.size.x/cam.height); + color = gs_in[0].color; + tex = texCoords[i].xy; + EmitVertex(); + } + EndPrimitive(); + } +} diff --git a/openVulkanoCpp/Shader/billboardFromSinglePoint.vert b/openVulkanoCpp/Shader/billboardFromSinglePoint.vert new file mode 100644 index 0000000..ee8e711 --- /dev/null +++ b/openVulkanoCpp/Shader/billboardFromSinglePoint.vert @@ -0,0 +1,21 @@ +#version 450 + +#extension GL_ARB_separate_shader_objects : enable + +layout(location = 0) in vec3 pos; +layout(location = 5) in vec4 color; + +layout(location = 0) out VS_OUT { + vec4 color; +} vs_out; + +layout(set = 0, binding = 0) uniform NodeData +{ + mat4 world; +} node; + +void main() { + // single point + gl_Position = node.world * vec4(pos, 1); + vs_out.color = color; +} diff --git a/openVulkanoCpp/Vulkan/Scene/SimpleDrawableVulkanEncoder.cpp b/openVulkanoCpp/Vulkan/Scene/SimpleDrawableVulkanEncoder.cpp index b38ea11..54ba990 100644 --- a/openVulkanoCpp/Vulkan/Scene/SimpleDrawableVulkanEncoder.cpp +++ b/openVulkanoCpp/Vulkan/Scene/SimpleDrawableVulkanEncoder.cpp @@ -6,9 +6,11 @@ #include "Scene/SimpleDrawable.hpp" #include "Scene/Material.hpp" +#include "Scene/UniformBuffer.hpp" #include "VulkanGeometry.hpp" #include "VulkanNode.hpp" #include "Vulkan/VulkanDrawContext.hpp" +#include "Vulkan/Scene/VulkanUniformBuffer.hpp" #include "VulkanTexture.hpp" using namespace OpenVulkano::Scene; @@ -22,6 +24,18 @@ namespace OpenVulkano::Vulkan VulkanGeometry* renderGeo = static_cast(mesh->renderGeo); if (!renderGeo) renderGeo = drawContext->renderer->GetResourceManager().PrepareGeometry(mesh); renderGeo->RecordBind(drawContext->commandBuffer); + + if (drawable->GetBuffer()) + { + + VulkanUniformBuffer* vkBuffer = static_cast(drawable->GetBuffer()->renderBuffer); + if (!vkBuffer) + { + vkBuffer = drawContext->renderer->GetResourceManager().PrepareUniformBuffer(drawable->GetBuffer()); + } + vkBuffer->Record(drawContext); + } + if (Material* material = drawable->GetMaterial()) { if (Texture* texture = material->texture) diff --git a/openVulkanoCpp/Vulkan/Scene/VulkanGeometry.hpp b/openVulkanoCpp/Vulkan/Scene/VulkanGeometry.hpp index c96932b..1392fea 100644 --- a/openVulkanoCpp/Vulkan/Scene/VulkanGeometry.hpp +++ b/openVulkanoCpp/Vulkan/Scene/VulkanGeometry.hpp @@ -52,7 +52,8 @@ namespace OpenVulkano::Vulkan void RecordDraw(vk::CommandBuffer& cmdBuffer) { - cmdBuffer.drawIndexed(m_geometry->GetIndexCount(), 1, 0, 0, 0); + if (m_geometry->GetIndexCount()) { cmdBuffer.drawIndexed(m_geometry->GetIndexCount(), 1, 0, 0, 0); } + else { cmdBuffer.draw(m_geometry->GetVertexCount(), 1, 0, 0); } } void Close() override