diff --git a/editor/shaders/triangle.vert b/editor/shaders/triangle.vert index 26bed64..9f0c10e 100644 --- a/editor/shaders/triangle.vert +++ b/editor/shaders/triangle.vert @@ -5,7 +5,14 @@ layout(location = 1) in vec3 color; layout(location = 0) out vec3 vertColor; +//layout(binding = 0) uniform ModelViewProjection { +// mat4 model; +// mat4 view; +// mat4 projection; +//} mvp; + void main() { - vertColor = color; +// gl_Position = mvp.projection * mvp.view * mvp.model * vec4(position, 1.0); gl_Position = vec4(position, 1.0); + vertColor = color; } diff --git a/engine/Buffer.h b/engine/Buffer.h index 9bce657..3a47fdc 100644 --- a/engine/Buffer.h +++ b/engine/Buffer.h @@ -26,7 +26,7 @@ namespace Vixen::Vk { * @param dataSize The size of the data. * @param offset The offset within this buffer to start writing from. */ - virtual void write(const void *data, size_t dataSize, size_t offset) = 0; + virtual void write(const char *data, size_t dataSize, size_t offset) = 0; [[nodiscard]] size_t getSize() const; @@ -45,7 +45,7 @@ namespace Vixen::Vk { */ Buffer(Usage bufferUsage, const std::size_t &size); - virtual void *map() = 0; + virtual char *map() = 0; virtual void unmap() = 0; }; diff --git a/engine/CMakeLists.txt b/engine/CMakeLists.txt index a244768..784fca1 100644 --- a/engine/CMakeLists.txt +++ b/engine/CMakeLists.txt @@ -10,8 +10,10 @@ find_library(FreeImage_LIBRARY NAMES FreeImage HINTS ${FreeImage_ROOT}) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(FreeImage DEFAULT_MSG FreeImage_INCLUDE_DIR FreeImage_LIBRARY) -set(HEADERS Window.h ShaderModule.h ShaderProgram.h Monitor.h Buffer.h Mesh.h Util.h Renderer.h Vixen.h Framebuffer.h RenderPass.h Material.h Entity.h) -set(SOURCES Window.cpp Buffer.cpp Blending.h) +set(HEADERS Window.h ShaderModule.h ShaderProgram.h Monitor.h Buffer.h Mesh.h Util.h Renderer.h Vixen.h Framebuffer.h RenderPass.h Material.h Entity.h + Camera.h) +set(SOURCES Window.cpp Buffer.cpp Blending.h + Camera.cpp) link_libraries( PkgConfig::GLM diff --git a/engine/Camera.cpp b/engine/Camera.cpp new file mode 100644 index 0000000..c7232bb --- /dev/null +++ b/engine/Camera.cpp @@ -0,0 +1,59 @@ +#include "Camera.h" + +namespace Vixen { + Camera::Camera(float fieldOfView, float nearPlane, float farPlane, glm::vec3 clearColor) + : position(0, 0, 0), +// rotation(glm::quat{}), + rotation({}), + fieldOfView(fieldOfView), + nearPlane(nearPlane), + farPlane(farPlane), + clearColor(clearColor) {} + + glm::mat4 Camera::view() const { +// const auto &reverse = glm::conjugate(rotation); +// glm::mat4 rot = glm::toMat4(reverse); +// glm::mat4 translation = glm::translate({1.0}, -position); +// +// return rot * translation; + return glm::lookAt( + position, + position + rotation, + {0.0f, 1.0f, 0.0f} + ); + } + + glm::mat4 Camera::perspective(float aspectRatio) const { + return glm::perspective( + glm::radians(fieldOfView), + aspectRatio, + nearPlane, + farPlane + ); + } + + const glm::vec3 &Camera::getPosition() const { + return position; + } + +// const glm::quat &Camera::getRotation() const { +// return rotation; +// } + + glm::vec3 Camera::getEulerRotation() const { +// return glm::eulerAngles(rotation); + return rotation; + } + + float Camera::getNearPlane() const { + return nearPlane; + } + + float Camera::getFarPlane() const { + return farPlane; + } + + const glm::vec3 &Camera::getClearColor() const { + return clearColor; + } +} diff --git a/engine/Camera.h b/engine/Camera.h new file mode 100644 index 0000000..8fa03a7 --- /dev/null +++ b/engine/Camera.h @@ -0,0 +1,48 @@ +#pragma once + +#include +#include +#include +#include + +namespace Vixen { + class Camera { + explicit Camera( + float fieldOfView = 114.0f, + float nearPlane = 0.01f, + float farPlane = 1000.0f, + glm::vec3 clearColor = {0.0f, 0.0f, 0.0f} + ); + + [[nodiscard]] glm::mat4 view() const; + + [[nodiscard]] glm::mat4 perspective(float aspectRatio) const; + + public: + [[nodiscard]] const glm::vec3 &getPosition() const; + +// [[nodiscard]] const glm::quat &getRotation() const; + + [[nodiscard]] glm::vec3 getEulerRotation() const; + + [[nodiscard]] float getNearPlane() const; + + [[nodiscard]] float getFarPlane() const; + + [[nodiscard]] const glm::vec3 &getClearColor() const; + + private: + glm::vec3 position; + + //glm::quat rotation; + glm::vec3 rotation; + + float fieldOfView; + + float nearPlane; + + float farPlane; + + glm::vec3 clearColor; + }; +} diff --git a/engine/ShaderModule.h b/engine/ShaderModule.h index cad111a..cbf3215 100644 --- a/engine/ShaderModule.h +++ b/engine/ShaderModule.h @@ -26,18 +26,31 @@ namespace Vixen { struct IO { std::optional binding; std::optional location; + size_t size; size_t offset; }; + private: + Stage stage; + + std::string entrypoint; + + std::vector bindings; + + std::vector inputs; + + std::vector uniformBuffers; + + public: ShaderModule( Stage stage, + std::string entrypoint, const std::vector &bindings, - const std::vector &inputs, - std::string entrypoint + const std::vector &inputs ) : stage(stage), + entrypoint(std::move(entrypoint)), bindings(bindings), - inputs(inputs), - entrypoint(std::move(entrypoint)) {} + inputs(inputs) {} [[nodiscard]] Stage getStage() const { return stage; @@ -54,14 +67,5 @@ namespace Vixen { [[nodiscard]] const std::vector &getInputs() const { return inputs; } - - protected: - Stage stage; - - std::string entrypoint; - - std::vector bindings; - - std::vector inputs; }; } diff --git a/engine/ShaderProgram.h b/engine/ShaderProgram.h index 9c520b1..3c3caf9 100644 --- a/engine/ShaderProgram.h +++ b/engine/ShaderProgram.h @@ -4,9 +4,8 @@ #include "ShaderModule.h" namespace Vixen { - template::value>> + template requires std::is_base_of_v class ShaderProgram { - protected: std::shared_ptr vertex; std::shared_ptr fragment; diff --git a/engine/Window.cpp b/engine/Window.cpp index d908b50..a269366 100644 --- a/engine/Window.cpp +++ b/engine/Window.cpp @@ -74,7 +74,8 @@ namespace Vixen { if (framebufferSizeChanged) { framebufferSizeChanged = false; - int width, height; + int width; + int height; glfwGetFramebufferSize(window, &width, &height); spdlog::trace("Framebuffer resized to {}x{}", width, height); @@ -102,11 +103,14 @@ namespace Vixen { } void Window::center() const { - uint32_t w, h; + uint32_t w; + uint32_t h; glfwGetWindowSize(window, reinterpret_cast(&w), reinterpret_cast(&h)); const auto mode = glfwGetVideoMode(monitor); - uint32_t x, y; + + uint32_t x; + uint32_t y; glfwGetMonitorPos(monitor, reinterpret_cast(&x), reinterpret_cast(&y)); glfwSetWindowPos( window, @@ -139,10 +143,12 @@ namespace Vixen { } void Window::setWindowedMode(Mode mode) const { - int w, h = 0; - int x, y = 0; - int refreshRate = 0; - GLFWmonitor *m = nullptr; + int w; + int h; + int x; + int y; + int refreshRate; + GLFWmonitor *m; if (mode == Mode::FULLSCREEN) { auto videoMode = glfwGetVideoMode(monitor); diff --git a/engine/vk/GraphicsCard.h b/engine/vk/GraphicsCard.h index f72075a..b131263 100644 --- a/engine/vk/GraphicsCard.h +++ b/engine/vk/GraphicsCard.h @@ -112,10 +112,11 @@ namespace Vixen::Vk { } [[nodiscard]] bool isExtensionSupported(const std::string &extension) const { - return std::find_if( - extensions.begin(), - extensions.end(), - [extension](VkExtensionProperties props) { return extension == props.extensionName; } + return std::ranges::find_if( + extensions, + [extension](VkExtensionProperties props) { + return extension == props.extensionName; + } ) != std::end(extensions); } @@ -137,10 +138,11 @@ namespace Vixen::Vk { } [[nodiscard]] bool isLayerSupported(const std::string &layer) const { - return std::find_if( - layers.begin(), - layers.end(), - [layer](VkLayerProperties props) { return layer == props.layerName; } + return std::ranges::find_if( + layers, + [layer](VkLayerProperties props) { + return layer == props.layerName; + } ) != std::end(layers); } diff --git a/engine/vk/Instance.cpp b/engine/vk/Instance.cpp index 03b75a1..5e92c07 100644 --- a/engine/vk/Instance.cpp +++ b/engine/vk/Instance.cpp @@ -155,9 +155,8 @@ namespace Vixen::Vk { bool Instance::isExtensionSupported(const std::string &extension) { const auto extensions = getSupportedExtensions(); - return std::find_if( - extensions.begin(), - extensions.end(), + return std::ranges::find_if( + extensions, [extension](VkExtensionProperties props) { return extension == props.extensionName; } ) != std::end(extensions); } @@ -175,9 +174,8 @@ namespace Vixen::Vk { bool Instance::isLayerSupported(const std::string &layer) { const auto layers = getSupportedLayers(); - return std::find_if( - layers.begin(), - layers.end(), + return std::ranges::find_if( + layers, [layer](VkLayerProperties props) { return layer == props.layerName; } ) != std::end(layers); } diff --git a/engine/vk/Instance.h b/engine/vk/Instance.h index 60c3ebc..75564b2 100644 --- a/engine/vk/Instance.h +++ b/engine/vk/Instance.h @@ -4,7 +4,6 @@ #include "Vulkan.h" #include "GraphicsCard.h" #include "VkWindow.h" -#include "../Util.h" namespace Vixen::Vk { class Instance { diff --git a/engine/vk/Swapchain.h b/engine/vk/Swapchain.h index 6065b67..978d1bc 100644 --- a/engine/vk/Swapchain.h +++ b/engine/vk/Swapchain.h @@ -49,14 +49,17 @@ namespace Vixen::Vk { currentFrame = (currentFrame + 1) % imageCount; switch (result) { + using + enum State; + case VK_SUCCESS: - return State::OK; + return OK; case VK_SUBOPTIMAL_KHR: spdlog::warn("Suboptimal swapchain state"); - return State::SUBOPTIMAL; + return SUBOPTIMAL; default: checkVulkanResult(result, "Failed to acquire swapchain image"); - return State::OUT_OF_DATE; + return OUT_OF_DATE; } } @@ -73,11 +76,13 @@ namespace Vixen::Vk { void invalidate(); private: + std::shared_ptr device; + uint32_t currentFrame; uint32_t imageCount; - std::shared_ptr device; + VkSurfaceFormatKHR format; VkSwapchainKHR swapchain; @@ -85,8 +90,6 @@ namespace Vixen::Vk { std::vector<::VkImageView> imageViews; - VkSurfaceFormatKHR format{}; - VkExtent2D extent{}; std::vector imageAvailableSemaphores; diff --git a/engine/vk/VkBuffer.cpp b/engine/vk/VkBuffer.cpp index d0cd490..0479cfe 100644 --- a/engine/vk/VkBuffer.cpp +++ b/engine/vk/VkBuffer.cpp @@ -52,7 +52,7 @@ namespace Vixen::Vk { vmaDestroyBuffer(device->getAllocator(), buffer, allocation); } - void VkBuffer::write(const void *data, size_t dataSize, size_t offset) { + void VkBuffer::write(const char *data, size_t dataSize, size_t offset) { if (offset + dataSize > size) throw std::runtime_error("Buffer overflow"); @@ -61,14 +61,14 @@ namespace Vixen::Vk { unmap(); } - void *VkBuffer::map() { - void *data = nullptr; + char *VkBuffer::map() { + void *data; checkVulkanResult( vmaMapMemory(device->getAllocator(), allocation, &data), "Failed to map buffer" ); - return data; + return static_cast(data); } void VkBuffer::unmap() { @@ -104,7 +104,7 @@ namespace Vixen::Vk { const std::shared_ptr &device, Usage usage, size_t size, - const void *data + const char *data ) { auto source = VkBuffer(device, usage | Usage::TRANSFER_SRC, size); auto destination = VkBuffer(device, usage | Usage::TRANSFER_DST, size); diff --git a/engine/vk/VkBuffer.h b/engine/vk/VkBuffer.h index 09196f5..17b2491 100644 --- a/engine/vk/VkBuffer.h +++ b/engine/vk/VkBuffer.h @@ -7,7 +7,6 @@ namespace Vixen::Vk { class VkBuffer : public Buffer { - protected: std::shared_ptr device; VmaAllocation allocation; @@ -25,11 +24,11 @@ namespace Vixen::Vk { ~VkBuffer(); - void *map() override; + char *map() override; void unmap() override; - void write(const void *data, size_t dataSize, size_t offset) override; + void write(const char *data, size_t dataSize, size_t offset) override; /** * Copies data from one buffer to another. @@ -48,7 +47,7 @@ namespace Vixen::Vk { * @param data Pointer to the start of the data. * @return Returns the resulting device local buffer. */ - static VkBuffer stage(const std::shared_ptr &device, Usage usage, size_t size, const void *data); + static VkBuffer stage(const std::shared_ptr &device, Usage usage, size_t size, const char *data); template static VkBuffer stage( diff --git a/engine/vk/VkCommandBuffer.cpp b/engine/vk/VkCommandBuffer.cpp index 5b179c5..d9d6cbc 100644 --- a/engine/vk/VkCommandBuffer.cpp +++ b/engine/vk/VkCommandBuffer.cpp @@ -27,7 +27,6 @@ namespace Vixen::Vk { VkCommandBuffer &VkCommandBuffer::reset() { wait(); - fence.reset(); checkVulkanResult( vkResetCommandBuffer(commandBuffer, 0), "Failed to reset command buffer" @@ -42,23 +41,30 @@ namespace Vixen::Vk { const std::vector<::VkPipelineStageFlags> &waitMasks, const std::vector<::VkSemaphore> &signalSemaphores ) { - VkSubmitInfo info{ - .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, + fence.wait( + std::numeric_limits::max(), + [this, queue, waitSemaphores, waitMasks, signalSemaphores](const auto &f) { + fence.reset(); - .waitSemaphoreCount = static_cast(waitSemaphores.size()), - .pWaitSemaphores = waitSemaphores.data(), - .pWaitDstStageMask = waitMasks.data(), + VkSubmitInfo info{ + .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, - .commandBufferCount = 1, - .pCommandBuffers = &commandBuffer, + .waitSemaphoreCount = static_cast(waitSemaphores.size()), + .pWaitSemaphores = waitSemaphores.data(), + .pWaitDstStageMask = waitMasks.data(), - .signalSemaphoreCount = static_cast(signalSemaphores.size()), - .pSignalSemaphores = signalSemaphores.data(), - }; + .commandBufferCount = 1, + .pCommandBuffers = &commandBuffer, - checkVulkanResult( - vkQueueSubmit(queue, 1, &info, fence.getFence()), - "Failed to submit command buffer to queue" + .signalSemaphoreCount = static_cast(signalSemaphores.size()), + .pSignalSemaphores = signalSemaphores.data(), + }; + + checkVulkanResult( + vkQueueSubmit(queue, 1, &info, f), + "Failed to submit command buffer to queue" + ); + } ); return *this; diff --git a/engine/vk/VkFence.cpp b/engine/vk/VkFence.cpp index 99a4f67..37e0752 100644 --- a/engine/vk/VkFence.cpp +++ b/engine/vk/VkFence.cpp @@ -27,8 +27,4 @@ namespace Vixen::Vk { void VkFence::reset() { vkResetFences(device, 1, &fence); } - - const ::VkFence VkFence::getFence() const { - return fence; - } } diff --git a/engine/vk/VkFence.h b/engine/vk/VkFence.h index b043ef0..89b5327 100644 --- a/engine/vk/VkFence.h +++ b/engine/vk/VkFence.h @@ -32,7 +32,5 @@ namespace Vixen::Vk { } void reset(); - - const ::VkFence getFence() const; }; } diff --git a/engine/vk/VkFramebuffer.cpp b/engine/vk/VkFramebuffer.cpp index 75b2481..8fc512a 100644 --- a/engine/vk/VkFramebuffer.cpp +++ b/engine/vk/VkFramebuffer.cpp @@ -34,7 +34,7 @@ namespace Vixen::Vk { } std::vector<::VkImageView> views{imageViews.size()}; - std::transform(imageViews.begin(), imageViews.end(), views.data(), [](const auto &imageView) { + std::ranges::transform(imageViews, views.data(), [](const auto &imageView) { return imageView->getImageView(); }); VkFramebufferCreateInfo info{ diff --git a/engine/vk/VkImage.cpp b/engine/vk/VkImage.cpp index 4d4087e..a9a7d93 100644 --- a/engine/vk/VkImage.cpp +++ b/engine/vk/VkImage.cpp @@ -88,7 +88,7 @@ namespace Vixen::Vk { VkDeviceSize size = width * height * sizeof(uint32_t); auto staging = VkBuffer(device, Buffer::Usage::INDEX, size); - staging.write(pixels, size, 0); + staging.write(reinterpret_cast(pixels), size, 0); FreeImage_Unload(converted); FreeImage_Unload(bitmap); diff --git a/engine/vk/VkRenderer.cpp b/engine/vk/VkRenderer.cpp index d130699..7be24d7 100644 --- a/engine/vk/VkRenderer.cpp +++ b/engine/vk/VkRenderer.cpp @@ -43,7 +43,6 @@ namespace Vixen::Vk { ) { auto &commandBuffer = renderCommandBuffers[currentFrame]; - commandBuffer.wait(); prepare(commandBuffer, framebuffers[imageIndex], buffer, vertexCount, indexCount); std::vector<::VkSemaphore> waitSemaphores = {imageAvailableSemaphore.getSemaphore()}; @@ -120,18 +119,20 @@ namespace Vixen::Vk { pipeline->bindGraphics(commandBuffer); - VkViewport viewport{}; - viewport.x = 0.0f; - viewport.y = 0.0f; - viewport.width = static_cast(swapchain.getExtent().width); - viewport.height = static_cast(swapchain.getExtent().height); - viewport.minDepth = 0.0f; - viewport.maxDepth = 1.0f; + VkViewport viewport{ + .x = 0.0f, + .y = 0.0f, + .width = static_cast(swapchain.getExtent().width), + .height = static_cast(swapchain.getExtent().height), + .minDepth = 0.0f, + .maxDepth = 1.0f, + }; vkCmdSetViewport(commandBuffer, 0, 1, &viewport); - VkRect2D scissor{}; - scissor.offset = {0, 0}; - scissor.extent = swapchain.getExtent(); + VkRect2D scissor{ + .offset = {0, 0}, + .extent = swapchain.getExtent(), + }; vkCmdSetScissor(commandBuffer, 0, 1, &scissor); ::VkBuffer vertexBuffers[1]{buffer.getBuffer()}; diff --git a/engine/vk/VkShaderModule.cpp b/engine/vk/VkShaderModule.cpp index abe5aed..6933f75 100644 --- a/engine/vk/VkShaderModule.cpp +++ b/engine/vk/VkShaderModule.cpp @@ -8,7 +8,7 @@ namespace Vixen::Vk { const std::vector &bindings, const std::vector &inputs, const std::string &entrypoint - ) : ShaderModule(stage, bindings, inputs, entrypoint), + ) : ShaderModule(stage, entrypoint, bindings, inputs), device(device), module(VK_NULL_HANDLE) { VkShaderModuleCreateInfo info{ @@ -32,9 +32,9 @@ namespace Vixen::Vk { .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, .pNext = VK_NULL_HANDLE, .flags = 0, - .stage = getVulkanShaderStage(stage), + .stage = getVulkanShaderStage(getStage()), .module = module, - .pName = entrypoint.c_str(), + .pName = getEntrypoint().c_str(), .pSpecializationInfo = VK_NULL_HANDLE }; } diff --git a/engine/vk/VkShaderModule.h b/engine/vk/VkShaderModule.h index 05037ed..f2b1ff8 100644 --- a/engine/vk/VkShaderModule.h +++ b/engine/vk/VkShaderModule.h @@ -56,6 +56,8 @@ namespace Vixen::Vk { std::vector inputs{}; + std::vector uniformBuffers{}; + static uint32_t getTypeSize(const glslang::TType *type) { uint32_t size; @@ -242,21 +244,17 @@ namespace Vixen::Vk { auto resources = c.get_shader_resources(); for (const auto &uniformBuffer: resources.uniform_buffers) { - /*const auto &binding = c.get_decoration(input.id, spv::DecorationBinding); - const auto &location = c.get_decoration(input.id, spv::DecorationLocation); - - inputs.push_back( - { - .name = input.name, - .size = 3 * sizeof(float), - .binding = binding == 0 ? - std::nullopt : - std::optional{static_cast(binding)}, - .location = location == 0 ? - std::nullopt : - std::optional{static_cast(location)}, - } - );*/ + uint32_t binding = c.get_decoration(uniformBuffer.id, spv::DecorationBinding); + uint32_t location = c.get_decoration(uniformBuffer.id, spv::DecorationLocation); + + + + uniformBuffers.push_back({ + .binding = binding, + .location = location, + .size = 0, + .offset = 0, + }); } if (!logger.getAllMessages().empty()) diff --git a/engine/vk/Vulkan.h b/engine/vk/Vulkan.h index cdb11ab..0715e91 100644 --- a/engine/vk/Vulkan.h +++ b/engine/vk/Vulkan.h @@ -21,7 +21,7 @@ namespace Vixen::Vk { error("{} ({})", message, string_VkResult(result)); } - static inline std::string getVersionString(glm::vec3 version) { + static inline std::string getVersionString(glm::ivec3 version) { return fmt::format("{}.{}.{}", version.x, version.y, version.z); } diff --git a/engine/vk/test/vikingroom.glb b/engine/vk/test/vikingroom.glb new file mode 100644 index 0000000..5536630 Binary files /dev/null and b/engine/vk/test/vikingroom.glb differ