#include <iostream> #include <vkcv/Core.hpp> #include <GLFW/glfw3.h> #include <vkcv/camera/CameraManager.hpp> #include <chrono> #include <vkcv/asset/asset_loader.hpp> #include <vkcv/Logger.hpp> glm::mat4 arrayTo4x4Matrix(std::array<float,16> array){ glm::mat4 matrix; for (int i = 0; i < 4; i++){ for (int j = 0; j < 4; j++){ matrix[i][j] = array[j * 4 + i]; } } return matrix; } int main(int argc, const char** argv) { const char* applicationName = "First Scene"; uint32_t windowWidth = 800; uint32_t windowHeight = 600; vkcv::Window window = vkcv::Window::create( applicationName, windowWidth, windowHeight, true ); vkcv::camera::CameraManager cameraManager(window); uint32_t camIndex0 = cameraManager.addCamera(vkcv::camera::ControllerType::PILOT); uint32_t camIndex1 = cameraManager.addCamera(vkcv::camera::ControllerType::TRACKBALL); cameraManager.getCamera(camIndex0).setPosition(glm::vec3(0, 0, -3)); window.initEvents(); vkcv::Core core = vkcv::Core::create( window, applicationName, VK_MAKE_VERSION(0, 0, 1), { vk::QueueFlagBits::eGraphics ,vk::QueueFlagBits::eCompute , vk::QueueFlagBits::eTransfer }, {}, { "VK_KHR_swapchain" } ); vkcv::asset::Scene scene; const char* path = argc > 1 ? argv[1] : "resources/Sponza/Sponza.gltf"; int result = vkcv::asset::loadScene(path, scene); if (result == 1) { std::cout << "Mesh loading successful!" << std::endl; } else { std::cout << "Mesh loading failed: " << result << std::endl; return 1; } assert(!scene.vertexGroups.empty()); std::vector<std::vector<uint8_t>> vBuffers; std::vector<std::vector<uint8_t>> iBuffers; std::vector<vkcv::VertexBufferBinding> vBufferBindings; std::vector<std::vector<vkcv::VertexBufferBinding>> vertexBufferBindings; std::vector<vkcv::asset::VertexAttribute> vAttributes; for (int i = 0; i < scene.vertexGroups.size(); i++) { vBuffers.push_back(scene.vertexGroups[i].vertexBuffer.data); iBuffers.push_back(scene.vertexGroups[i].indexBuffer.data); auto& attributes = scene.vertexGroups[i].vertexBuffer.attributes; std::sort(attributes.begin(), attributes.end(), [](const vkcv::asset::VertexAttribute& x, const vkcv::asset::VertexAttribute& y) { return static_cast<uint32_t>(x.type) < static_cast<uint32_t>(y.type); }); } std::vector<vkcv::Buffer<uint8_t>> vertexBuffers; for (const vkcv::asset::VertexGroup& group : scene.vertexGroups) { vertexBuffers.push_back(core.createBuffer<uint8_t>( vkcv::BufferType::VERTEX, group.vertexBuffer.data.size())); vertexBuffers.back().fill(group.vertexBuffer.data); } std::vector<vkcv::Buffer<uint8_t>> indexBuffers; for (const auto& dataBuffer : iBuffers) { indexBuffers.push_back(core.createBuffer<uint8_t>( vkcv::BufferType::INDEX, dataBuffer.size())); indexBuffers.back().fill(dataBuffer); } int vertexBufferIndex = 0; for (const auto& vertexGroup : scene.vertexGroups) { for (const auto& attribute : vertexGroup.vertexBuffer.attributes) { vAttributes.push_back(attribute); vBufferBindings.push_back(vkcv::VertexBufferBinding(attribute.offset, vertexBuffers[vertexBufferIndex].getVulkanHandle())); } vertexBufferBindings.push_back(vBufferBindings); vBufferBindings.clear(); vertexBufferIndex++; } const vkcv::AttachmentDescription present_color_attachment( vkcv::AttachmentOperation::STORE, vkcv::AttachmentOperation::CLEAR, core.getSwapchainImageFormat() ); const vkcv::AttachmentDescription depth_attachment( vkcv::AttachmentOperation::STORE, vkcv::AttachmentOperation::CLEAR, vk::Format::eD32Sfloat ); vkcv::PassConfig scenePassDefinition({ present_color_attachment, depth_attachment }); vkcv::PassHandle scenePass = core.createPass(scenePassDefinition); if (!scenePass) { std::cout << "Error. Could not create renderpass. Exiting." << std::endl; return EXIT_FAILURE; } vkcv::ShaderProgram sceneShaderProgram{}; sceneShaderProgram.addShader(vkcv::ShaderStage::VERTEX, std::filesystem::path("resources/shaders/vert.spv")); sceneShaderProgram.addShader(vkcv::ShaderStage::FRAGMENT, std::filesystem::path("resources/shaders/frag.spv")); const std::vector<vkcv::VertexAttachment> vertexAttachments = sceneShaderProgram.getVertexAttachments(); std::vector<vkcv::VertexBinding> bindings; for (size_t i = 0; i < vertexAttachments.size(); i++) { bindings.push_back(vkcv::VertexBinding(i, { vertexAttachments[i] })); } const vkcv::VertexLayout sceneLayout(bindings); uint32_t setID = 0; std::vector<vkcv::DescriptorBinding> descriptorBindings = { sceneShaderProgram.getReflectedDescriptors()[setID] }; vkcv::SamplerHandle sampler = core.createSampler( vkcv::SamplerFilterType::LINEAR, vkcv::SamplerFilterType::LINEAR, vkcv::SamplerMipmapMode::LINEAR, vkcv::SamplerAddressMode::REPEAT ); std::vector<vkcv::Image> sceneImages; std::vector<vkcv::DescriptorSetHandle> descriptorSets; for (const auto& vertexGroup : scene.vertexGroups) { descriptorSets.push_back(core.createDescriptorSet(descriptorBindings)); const auto& material = scene.materials[vertexGroup.materialIndex]; int baseColorIndex = material.baseColor; if (baseColorIndex < 0) { vkcv_log(vkcv::LogLevel::WARNING, "Material lacks base color"); baseColorIndex = 0; } vkcv::asset::Texture& sceneTexture = scene.textures[baseColorIndex]; sceneImages.push_back(core.createImage(vk::Format::eR8G8B8A8Srgb, sceneTexture.w, sceneTexture.h)); sceneImages.back().fill(sceneTexture.data.data()); vkcv::DescriptorWrites setWrites; setWrites.sampledImageWrites = { vkcv::SampledImageDescriptorWrite(0, sceneImages.back().getHandle()) }; setWrites.samplerWrites = { vkcv::SamplerDescriptorWrite(1, sampler) }; core.writeDescriptorSet(descriptorSets.back(), setWrites); } const vkcv::PipelineConfig scenePipelineDefsinition{ sceneShaderProgram, UINT32_MAX, UINT32_MAX, scenePass, {sceneLayout}, { core.getDescriptorSet(descriptorSets[0]).layout }, true }; vkcv::PipelineHandle scenePipeline = core.createGraphicsPipeline(scenePipelineDefsinition); if (!scenePipeline) { std::cout << "Error. Could not create graphics pipeline. Exiting." << std::endl; return EXIT_FAILURE; } vkcv::ImageHandle depthBuffer = core.createImage(vk::Format::eD32Sfloat, windowWidth, windowHeight).getHandle(); const vkcv::ImageHandle swapchainInput = vkcv::ImageHandle::createSwapchainImageHandle(); std::vector<vkcv::DrawcallInfo> drawcalls; for(int i = 0; i < scene.vertexGroups.size(); i++){ vkcv::Mesh renderMesh(vertexBufferBindings[i], indexBuffers[i].getVulkanHandle(), scene.vertexGroups[i].numIndices); vkcv::DescriptorSetUsage descriptorUsage(0, core.getDescriptorSet(descriptorSets[i]).vulkanHandle); drawcalls.push_back(vkcv::DrawcallInfo(renderMesh, {descriptorUsage})); } std::vector<glm::mat4> modelMatrices; modelMatrices.resize(scene.vertexGroups.size(), glm::mat4(1.f)); for (const auto &mesh : scene.meshes) { const glm::mat4 m = arrayTo4x4Matrix(mesh.modelMatrix); for (const auto &vertexGroupIndex : mesh.vertexGroups) { modelMatrices[vertexGroupIndex] = m; } } std::vector<glm::mat4> mvp; auto start = std::chrono::system_clock::now(); while (window.isWindowOpen()) { vkcv::Window::pollEvents(); if(window.getHeight() == 0 || window.getWidth() == 0) continue; uint32_t swapchainWidth, swapchainHeight; if (!core.beginFrame(swapchainWidth, swapchainHeight)) { continue; } if ((swapchainWidth != windowWidth) || ((swapchainHeight != windowHeight))) { depthBuffer = core.createImage(vk::Format::eD32Sfloat, swapchainWidth, swapchainHeight).getHandle(); windowWidth = swapchainWidth; windowHeight = swapchainHeight; } auto end = std::chrono::system_clock::now(); auto deltatime = std::chrono::duration_cast<std::chrono::microseconds>(end - start); start = end; cameraManager.update(0.000001 * static_cast<double>(deltatime.count())); glm::mat4 vp = cameraManager.getActiveCamera().getMVP(); mvp.clear(); for (const auto& m : modelMatrices) { mvp.push_back(vp * m); } vkcv::PushConstantData pushConstantData((void*)mvp.data(), sizeof(glm::mat4)); const std::vector<vkcv::ImageHandle> renderTargets = { swapchainInput, depthBuffer }; auto cmdStream = core.createCommandStream(vkcv::QueueType::Graphics); core.recordDrawcallsToCmdStream( cmdStream, scenePass, scenePipeline, pushConstantData, drawcalls, renderTargets); core.prepareSwapchainImageForPresent(cmdStream); core.submitCommandStream(cmdStream); core.endFrame(); } return 0; }