From 4898a6ff505f734f98ba277d1951a26fb783cb7b Mon Sep 17 00:00:00 2001 From: Alexander Gauggel <agauggel@uni-koblenz.de> Date: Fri, 28 May 2021 20:40:43 +0200 Subject: [PATCH] Add rendering of box into first mesh project --- include/vkcv/Core.hpp | 4 +- projects/first_mesh/CMakeLists.txt | 4 +- .../first_mesh/resources/shaders/compile.bat | 3 + .../first_mesh/resources/shaders/frag.spv | Bin 0 -> 608 bytes .../first_mesh/resources/shaders/shader.frag | 9 ++ .../first_mesh/resources/shaders/shader.vert | 27 ++++ .../first_mesh/resources/shaders/vert.spv | Bin 0 -> 1844 bytes projects/first_mesh/src/main.cpp | 147 +++++++++++------- projects/first_triangle/src/main.cpp | 11 +- src/vkcv/BufferManager.cpp | 3 + src/vkcv/Core.cpp | 12 +- 11 files changed, 147 insertions(+), 73 deletions(-) create mode 100644 projects/first_mesh/resources/shaders/compile.bat create mode 100644 projects/first_mesh/resources/shaders/frag.spv create mode 100644 projects/first_mesh/resources/shaders/shader.frag create mode 100644 projects/first_mesh/resources/shaders/shader.vert create mode 100644 projects/first_mesh/resources/shaders/vert.spv diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp index 3ff2d925..ab0d2aca 100644 --- a/include/vkcv/Core.hpp +++ b/include/vkcv/Core.hpp @@ -186,9 +186,9 @@ namespace vkcv /** * @brief render a beautiful triangle */ - void renderTriangle(const PassHandle renderpassHandle, const PipelineHandle pipelineHandle, + void renderMesh(const PassHandle renderpassHandle, const PipelineHandle pipelineHandle, const int width, const int height, const size_t pushConstantSize, const void* pushConstantData, - const BufferHandle vertexBuffer); + const BufferHandle vertexBuffer, const BufferHandle indexBuffer, const size_t indexCount); /** * @brief end recording and present image diff --git a/projects/first_mesh/CMakeLists.txt b/projects/first_mesh/CMakeLists.txt index ae9c5604..eb0f028d 100644 --- a/projects/first_mesh/CMakeLists.txt +++ b/projects/first_mesh/CMakeLists.txt @@ -22,7 +22,7 @@ if(MSVC) endif() # including headers of dependencies and the VkCV framework -target_include_directories(first_mesh SYSTEM BEFORE PRIVATE ${vkcv_include} ${vkcv_includes} ${vkcv_asset_loader_include}) +target_include_directories(first_mesh SYSTEM BEFORE PRIVATE ${vkcv_include} ${vkcv_includes} ${vkcv_asset_loader_include} ${vkcv_camera_include}) # linking with libraries from all dependencies and the VkCV framework -target_link_libraries(first_mesh vkcv ${vkcv_libraries} vkcv_asset_loader ${vkcv_asset_loader_libraries}) +target_link_libraries(first_mesh vkcv ${vkcv_libraries} vkcv_asset_loader ${vkcv_asset_loader_libraries} vkcv_camera) diff --git a/projects/first_mesh/resources/shaders/compile.bat b/projects/first_mesh/resources/shaders/compile.bat new file mode 100644 index 00000000..b4521235 --- /dev/null +++ b/projects/first_mesh/resources/shaders/compile.bat @@ -0,0 +1,3 @@ +%VULKAN_SDK%\Bin32\glslc.exe shader.vert -o vert.spv +%VULKAN_SDK%\Bin32\glslc.exe shader.frag -o frag.spv +pause \ No newline at end of file diff --git a/projects/first_mesh/resources/shaders/frag.spv b/projects/first_mesh/resources/shaders/frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..cb13e606fc0041e24ff6a63c0ec7dcca466732aa GIT binary patch literal 608 zcmZQ(Qf6mhU}WH8;AIeIfB-=TCI&_Z1_o{hHZbk(6YQf`T#}+^Vrl?V!N<T1qQG+e z4D1Xn3=CkLo0ypglHg=uVBle3U=Uzn28**ZFfcGPFf%YQFfbfq1gYg@aQBIK404Ju zPAy0*N-Rl@FV09zNiB-cPs&P7E-417;R2~~_xE@Aag9$dD2OjEsmw`@&&kY7jZeue zN=+`wEK3Ec<3LiEnU|bXnu4r=m4OB92AJDe8CV%W?#nMNan8@lF9Nw2BnEPCT2W#; zOwgTy1*}dEq=12e0mKKXf$@bIn85x~1pABu%obx{W?*ArU{GLSU=U|uVF39X#0Q0s z0s{*J2RIxUz~a_WKFBSg&;+UHVqgI42k}Abxfwt)!@vL%2dM|~L2dxWjWz=dSS=se zeGT?z46I-`fb0SZfz0^9z{J4Hz`$V3zydad7aA{t46I<i{0s~XATf}7n3w=m3}gpP rOb{vtioXB`cCh<}7#J8p`a$YJ@*sEEF))L}3?%oLfsw(2fsp|KBDy=E literal 0 HcmV?d00001 diff --git a/projects/first_mesh/resources/shaders/shader.frag b/projects/first_mesh/resources/shaders/shader.frag new file mode 100644 index 00000000..d26446a7 --- /dev/null +++ b/projects/first_mesh/resources/shaders/shader.frag @@ -0,0 +1,9 @@ +#version 450 +#extension GL_ARB_separate_shader_objects : enable + +layout(location = 0) in vec3 fragColor; +layout(location = 0) out vec4 outColor; + +void main() { + outColor = vec4(fragColor, 1.0); +} \ No newline at end of file diff --git a/projects/first_mesh/resources/shaders/shader.vert b/projects/first_mesh/resources/shaders/shader.vert new file mode 100644 index 00000000..e6c0e3d6 --- /dev/null +++ b/projects/first_mesh/resources/shaders/shader.vert @@ -0,0 +1,27 @@ +#version 450 +#extension GL_ARB_separate_shader_objects : enable + +layout(location = 0) in vec3 position; + +layout(location = 0) out vec3 fragColor; + +layout( push_constant ) uniform constants{ + mat4 mvp; +}; + +void main() { + vec3 positions[3] = { + vec3(-0.5, 0.5, -1), + vec3( 0.5, 0.5, -1), + vec3(0, -0.5, -1) + }; + + vec3 colors[3] = { + vec3(1, 0, 0), + vec3(0, 1, 0), + vec3(0, 0, 1) + }; + + gl_Position = mvp * vec4(position, 1.0); + fragColor = colors[gl_VertexIndex % 3]; +} \ No newline at end of file diff --git a/projects/first_mesh/resources/shaders/vert.spv b/projects/first_mesh/resources/shaders/vert.spv new file mode 100644 index 0000000000000000000000000000000000000000..74722f38ff0584d51d4a966c748b69a4d3f1d3cb GIT binary patch literal 1844 zcmZQ(Qf6mhU}WH8;AOC5fB-=TCI&_Z1_o{hHZbk(6YQf`T#}+^Vrl?V!N<T1qQG+e z44hy#3j+f~ZenI0h@-&3z@W{*z+lS2z+le6z`)GF%)rFJz;K9>fq{jAlfm65-Z982 zzBsiYu_&=5HNH3_F(tJqK0hfdHMyi1q=pNm#@*lF-N!XPxu77vxTG>CH9jXZFEu_T zvnVyWB(p3Pq>ckgU1nZ#PH76V0#*hV24r`!GO#l6FfcF_<QHd_Waj4;GcYiK)QB=L zFeK;a<QEl#_-qVv3=9nEIq?ChMPaE$C8-r4Kd~`D#6fJ39MlK~HU@UEdQf<Q#WV9t zf-|d9LF!;~Ait;Q#5?C?7Pw><mn7yTr^5AtLJ}lbnv(;UV`X4w0EHpQ43L{u!0yWf z=>!E20~-Si14s-cpIcVI08+08;(-0b3J!aiA3?$(GeB{XR+O0T4Du&f9UC}q(sSY= zp7hL10r}K}ffei@kUnk@!N9-(69f4XBnF~kVj#bP#6bRliGkQ4F;LjMGcbeA1F7>s zayKi~T$n$Uk?ewru`@6*2rw`(fXo1ify{7cU;+CN6h|N}AU?=%$b3+m1KF>|z`!8P zzywZvir`ep0A`CZFf*_*Fo45YoPmV_WDkfBa<?c03j+sK4rIPIln+YfAbA-E76vW` z2CyEGm;wU}1IR9r86a_xdXQPXAk7R6`(b=O2;UyY=Lho}_UnLC0>qynJs@=;IheR0 z0|Ns{41_`AF#SSc{R|8+b;1k`3?MO(86b5aagcjNpkW9y2c!n3Ukt3j!5*Xz<aTie z1_qEA$P5sMiAzAug~`FhC86RVwIDf=ILJOJ1_lO@Ss;BNHK6d7W?%q^Hz+-T><5Lf z3<IdtVPF7-rz}(+Bqj&VXD~e=IS>Ygvpl#gVF0HmYX%ku5FeCJK=A^KH$`Z?fzl_) z9uQv%>`w*;2?iDhP#Oc73v!1X12Z@efy6*&t1>WvOEOS81DOrtgYpzCj@6;^F!i9c z1+oVeb|Cd2KB&wCiGj>Bg1QxCABb-P<-^p2_@HzPayv-g3>qFFH-pRr@j>YrWFE{f zmQXW5>aC$^5M-Vi11mUPgZu^ZF38Lu3``85JO(lgls-Y_9!M>W4=VFOd^-kaaG3~7 zCm=RR92AF+46F<wKWi{BFo41V6ppsgFw|sVU;v4O_#iWMpyhoa11mV5bs0eE666vF z2AG&0R1D-Fn3z6P43w_}7}yy=VFjvSK>9)ILGqxqHIac8EN95TzyPuvqz2?ZP#7CS z;~eBZko!S=kUEgtKw)VCt%JH5SQ$WkD+UGzkQgW|L1uu$(T0J60pxFx97rF?PqqvU W3?OlknV@(A@&7U~GFUJ$G5`QTCya9d literal 0 HcmV?d00001 diff --git a/projects/first_mesh/src/main.cpp b/projects/first_mesh/src/main.cpp index b37429e1..2b5c783b 100644 --- a/projects/first_mesh/src/main.cpp +++ b/projects/first_mesh/src/main.cpp @@ -1,76 +1,103 @@ #include <iostream> -#include <stdio.h> +#include <vkcv/Core.hpp> +#include <GLFW/glfw3.h> +#include <vkcv/camera/CameraManager.hpp> +#include <chrono> #include <vkcv/asset/asset_loader.hpp> int main(int argc, const char** argv) { + const char* applicationName = "First Mesh"; + + const int windowWidth = 800; + const int windowHeight = 600; + vkcv::Window window = vkcv::Window::create( + applicationName, + windowWidth, + windowHeight, + false + ); + + vkcv::CameraManager cameraManager(window, windowWidth, windowHeight); + + window.initEvents(); + + vkcv::Core core = vkcv::Core::create( + window, + applicationName, + VK_MAKE_VERSION(0, 0, 1), + { vk::QueueFlagBits::eTransfer,vk::QueueFlagBits::eGraphics, vk::QueueFlagBits::eCompute }, + {}, + { "VK_KHR_swapchain" } + ); + vkcv::asset::Mesh mesh; - - const char *path = argc > 1 ? argv[1] : "resources/cube/cube.gltf"; + + const char* path = argc > 1 ? argv[1] : "resources/cube/cube.gltf"; int result = vkcv::asset::loadMesh(path, mesh); - + if (result == 1) { std::cout << "Mesh loading successful!" << std::endl; - } else { + } + else { std::cout << "Mesh loading failed: " << result << std::endl; return 1; } - /* Demonstration of how to use the vkcv::asset::Mesh struct. */ - const char *primitive_modes[] = { - "points", "lines", "line loop", "line strip", "triangles", - "triangle strip", "triangle fan" - }; - const char *primitive_types[] = { - "unknown", "position", "normal", "texcoord0" - }; - printf("Mesh %s (%s) has %lu vertex group(s) and %lu material(s):\n", - mesh.name.c_str(), path, mesh.vertexGroups.size(), - mesh.materials.size()); - for (size_t i = 0; i < mesh.vertexGroups.size(); i++) { - printf("--- vertex group %lu ---\n", i); - const auto &vg = mesh.vertexGroups[i]; - printf("primitive mode: %d (%s)\n", vg.mode, - primitive_modes[vg.mode]); - printf("index buffer: %lu bytes for %lu indices ", - vg.indexBuffer.data.size(), vg.numIndices); - const auto itype = vg.indexBuffer.type; - printf("(%s @ %p)\n", - itype == vkcv::asset::UINT32 ? "UINT32" : - itype == vkcv::asset::UINT16 ? "UINT16" : - "UINT8", vg.indexBuffer.data.data()); - printf("\tindices: "); - const size_t n = vg.numIndices; - if (vg.indexBuffer.type == vkcv::asset::UINT32) { - uint32_t *idx = (uint32_t*)vg.indexBuffer.data.data(); - for (size_t j = 0; j < n; j++) printf("%u ", idx[j]); - } else - if (vg.indexBuffer.type == vkcv::asset::UINT16) { - uint16_t *idx = (uint16_t*)vg.indexBuffer.data.data(); - for (size_t j = 0; j < n; j++) printf("%u ", idx[j]); - } else - if (vg.indexBuffer.type == vkcv::asset::UINT8) { - uint8_t *idx = (uint8_t*)vg.indexBuffer.data.data(); - for (size_t j = 0; j < n; j++) printf("%u ", idx[j]); - } else { - fprintf(stderr, "ERROR Invalid IndexType: %d\n", - vg.indexBuffer.type); - return 0; - } - printf("\n"); - printf("vertex buffer: %lu bytes for %lu vertices with %lu " - "attributes (starting at %p)\n", - vg.vertexBuffer.data.size(), vg.numVertices, - vg.vertexBuffer.attributes.size(), - vg.vertexBuffer.data.data()); - printf("attributes:\toffset\tlength\tstride\tcomponents\n"); - for (const auto att : vg.vertexBuffer.attributes) { - printf("%11s\t%u\t%u\t%u\t%hhux%hu\n", - primitive_types[att.type], - att.offset, att.length, att.stride, - att.componentCount, att.componentType); - } + assert(mesh.vertexGroups.size() > 0); + const size_t vertexBufferSize = mesh.vertexGroups[0].vertexBuffer.data.size(); + auto vertexBuffer = core.createBuffer<uint8_t>(vkcv::BufferType::VERTEX, vertexBufferSize, vkcv::BufferMemoryType::DEVICE_LOCAL); + vertexBuffer.fill(mesh.vertexGroups[0].vertexBuffer.data.data(), vertexBufferSize); + + const size_t indexBufferSize = mesh.vertexGroups[0].indexBuffer.data.size(); + auto indexBuffer = core.createBuffer<uint8_t>(vkcv::BufferType::INDEX, indexBufferSize, vkcv::BufferMemoryType::DEVICE_LOCAL); + indexBuffer.fill(mesh.vertexGroups[0].indexBuffer.data.data(), indexBufferSize); + + // an example attachment for passes that output to the window + const vkcv::AttachmentDescription present_color_attachment( + vkcv::AttachmentLayout::UNDEFINED, + vkcv::AttachmentLayout::COLOR_ATTACHMENT, + vkcv::AttachmentLayout::PRESENTATION, + vkcv::AttachmentOperation::STORE, + vkcv::AttachmentOperation::CLEAR, + core.getSwapchainImageFormat()); + + vkcv::PassConfig trianglePassDefinition({ present_color_attachment }); + vkcv::PassHandle trianglePass = core.createPass(trianglePassDefinition); + + if (trianglePass.id == 0) + { + std::cout << "Error. Could not create renderpass. Exiting." << std::endl; + return EXIT_FAILURE; + } + + vkcv::ShaderProgram triangleShaderProgram{}; + triangleShaderProgram.addShader(vkcv::ShaderStage::VERTEX, std::filesystem::path("resources/shaders/vert.spv")); + triangleShaderProgram.addShader(vkcv::ShaderStage::FRAGMENT, std::filesystem::path("resources/shaders/frag.spv")); + triangleShaderProgram.reflectShader(vkcv::ShaderStage::VERTEX); + triangleShaderProgram.reflectShader(vkcv::ShaderStage::FRAGMENT); + + const vkcv::PipelineConfig trianglePipelineDefinition(triangleShaderProgram, windowWidth, windowHeight, trianglePass); + vkcv::PipelineHandle trianglePipeline = core.createGraphicsPipeline(trianglePipelineDefinition); + if (trianglePipeline.id == 0) + { + std::cout << "Error. Could not create graphics pipeline. Exiting." << std::endl; + return EXIT_FAILURE; + } + + auto start = std::chrono::system_clock::now(); + while (window.isWindowOpen()) + { + core.beginFrame(); + window.pollEvents(); + auto end = std::chrono::system_clock::now(); + auto deltatime = end - start; + start = end; + cameraManager.getCamera().updateView(std::chrono::duration<double>(deltatime).count()); + const glm::mat4 mvp = cameraManager.getCamera().getProjection() * cameraManager.getCamera().getView(); + + core.renderMesh(trianglePass, trianglePipeline, windowWidth, windowHeight, sizeof(mvp), &mvp, vertexBuffer.getHandle(), indexBuffer.getHandle(), mesh.vertexGroups[0].numIndices); + core.endFrame(); } - return 0; } diff --git a/projects/first_triangle/src/main.cpp b/projects/first_triangle/src/main.cpp index 6261b4d8..0e21f472 100644 --- a/projects/first_triangle/src/main.cpp +++ b/projects/first_triangle/src/main.cpp @@ -40,16 +40,19 @@ int main(int argc, const char** argv) { const size_t n = 5027; - auto vertexBuffer = core.createBuffer<vec3>(vkcv::BufferType::VERTEX, n, vkcv::BufferMemoryType::DEVICE_LOCAL); + auto testBuffer = core.createBuffer<vec3>(vkcv::BufferType::VERTEX, n, vkcv::BufferMemoryType::DEVICE_LOCAL); vec3 vec_data[n]; for (size_t i = 0; i < n; i++) { vec_data[i] = { 42, static_cast<float>(i), 7 }; } - vertexBuffer.fill(vec_data); + testBuffer.fill(vec_data); + + auto triangleIndexBuffer = core.createBuffer<uint16_t>(vkcv::BufferType::INDEX, n, vkcv::BufferMemoryType::DEVICE_LOCAL); + uint16_t indices[3] = { 0, 1, 2 }; + triangleIndexBuffer.fill(&indices[0], sizeof(indices)); - /*vec3* m = buffer.map(); m[0] = { 0, 0, 0 }; m[1] = { 0, 0, 0 }; @@ -143,7 +146,7 @@ int main(int argc, const char** argv) { cameraManager.getCamera().updateView(std::chrono::duration<double>(deltatime).count()); const glm::mat4 mvp = cameraManager.getCamera().getProjection() * cameraManager.getCamera().getView(); - core.renderTriangle(trianglePass, trianglePipeline, windowWidth, windowHeight, sizeof(mvp), &mvp, vertexBuffer.getHandle()); + core.renderMesh(trianglePass, trianglePipeline, windowWidth, windowHeight, sizeof(mvp), &mvp, testBuffer.getHandle(), triangleIndexBuffer.getHandle(), 3); core.endFrame(); } return 0; diff --git a/src/vkcv/BufferManager.cpp b/src/vkcv/BufferManager.cpp index e9b51128..bb3cf069 100644 --- a/src/vkcv/BufferManager.cpp +++ b/src/vkcv/BufferManager.cpp @@ -69,6 +69,9 @@ namespace vkcv { case BufferType::STAGING: usageFlags = vk::BufferUsageFlagBits::eTransferSrc; break; + case BufferType::INDEX: + usageFlags = vk::BufferUsageFlagBits::eIndexBuffer; + break; default: // TODO: maybe an issue break; diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp index bac12602..13800254 100644 --- a/src/vkcv/Core.cpp +++ b/src/vkcv/Core.cpp @@ -162,9 +162,9 @@ namespace vkcv destroyTemporaryFramebuffers(); } - void Core::renderTriangle(const PassHandle renderpassHandle, const PipelineHandle pipelineHandle, + void Core::renderMesh(const PassHandle renderpassHandle, const PipelineHandle pipelineHandle, const int width, const int height, const size_t pushConstantSize, const void *pushConstantData, - const BufferHandle vertexBuffer) { + const BufferHandle vertexBuffer, const BufferHandle indexBuffer, const size_t indexCount) { if (m_currentSwapchainImageIndex == std::numeric_limits<uint32_t>::max()) { return; @@ -175,7 +175,8 @@ namespace vkcv const vk::Pipeline pipeline = m_PipelineManager->getVkPipeline(pipelineHandle); const vk::PipelineLayout pipelineLayout = m_PipelineManager->getVkPipelineLayout(pipelineHandle); const vk::Rect2D renderArea(vk::Offset2D(0, 0), vk::Extent2D(width, height)); - const vk::Buffer vulkanVertexBuffer = m_BufferManager->getBuffer(vertexBuffer); + const vk::Buffer vulkanVertexBuffer = m_BufferManager->getBuffer(vertexBuffer); + const vk::Buffer vulkanIndexBuffer = m_BufferManager->getBuffer(indexBuffer); const vk::Framebuffer framebuffer = createFramebuffer(m_Context.getDevice(), renderpass, width, height, imageView); m_TemporaryFramebuffers.push_back(framebuffer); @@ -184,7 +185,7 @@ namespace vkcv submitInfo.queueType = QueueType::Graphics; submitInfo.signalSemaphores = { m_SyncResources.renderFinished }; submitCommands(submitInfo, [renderpass, renderArea, imageView, framebuffer, pipeline, pipelineLayout, - pushConstantSize, pushConstantData, vulkanVertexBuffer](const vk::CommandBuffer& cmdBuffer) { + pushConstantSize, pushConstantData, vulkanVertexBuffer, indexCount, vulkanIndexBuffer](const vk::CommandBuffer& cmdBuffer) { const std::array<float, 4> clearColor = { 0.f, 0.f, 0.f, 1.f }; const vk::ClearValue clearValues(clearColor); @@ -196,8 +197,9 @@ namespace vkcv cmdBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline, {}); cmdBuffer.bindVertexBuffers(0, (vulkanVertexBuffer), { 0 }); + cmdBuffer.bindIndexBuffer(vulkanIndexBuffer, 0, vk::IndexType::eUint16); //FIXME: choose proper size cmdBuffer.pushConstants(pipelineLayout, vk::ShaderStageFlagBits::eAll, 0, pushConstantSize, pushConstantData); - cmdBuffer.draw(3, 1, 0, 0, {}); + cmdBuffer.drawIndexed(indexCount, 1, 0, 0, {}); cmdBuffer.endRenderPass(); }, nullptr); } -- GitLab