From 3b37257a9e783a90da98a000ca43b64521ec2f85 Mon Sep 17 00:00:00 2001
From: Alexander Gauggel <agauggel@uni-koblenz.de>
Date: Sat, 3 Jul 2021 10:57:27 +0200
Subject: [PATCH] [#87] Setup mesh shader project

---
 projects/CMakeLists.txt                       |   3 +-
 projects/mesh_shader/.gitignore               |   1 +
 projects/mesh_shader/CMakeLists.txt           |  28 ++++
 .../mesh_shader/resources/shaders/shader.frag |   9 ++
 .../mesh_shader/resources/shaders/shader.vert |  25 ++++
 projects/mesh_shader/src/main.cpp             | 137 ++++++++++++++++++
 6 files changed, 202 insertions(+), 1 deletion(-)
 create mode 100644 projects/mesh_shader/.gitignore
 create mode 100644 projects/mesh_shader/CMakeLists.txt
 create mode 100644 projects/mesh_shader/resources/shaders/shader.frag
 create mode 100644 projects/mesh_shader/resources/shaders/shader.vert
 create mode 100644 projects/mesh_shader/src/main.cpp

diff --git a/projects/CMakeLists.txt b/projects/CMakeLists.txt
index 34fbcb0c..8f9dbbec 100644
--- a/projects/CMakeLists.txt
+++ b/projects/CMakeLists.txt
@@ -4,4 +4,5 @@ add_subdirectory(bloom)
 add_subdirectory(first_triangle)
 add_subdirectory(first_mesh)
 add_subdirectory(first_scene)
-add_subdirectory(voxelization)
\ No newline at end of file
+add_subdirectory(voxelization)
+add_subdirectory(mesh_shader)
\ No newline at end of file
diff --git a/projects/mesh_shader/.gitignore b/projects/mesh_shader/.gitignore
new file mode 100644
index 00000000..7e24fd7b
--- /dev/null
+++ b/projects/mesh_shader/.gitignore
@@ -0,0 +1 @@
+first_triangle
\ No newline at end of file
diff --git a/projects/mesh_shader/CMakeLists.txt b/projects/mesh_shader/CMakeLists.txt
new file mode 100644
index 00000000..0b2847cd
--- /dev/null
+++ b/projects/mesh_shader/CMakeLists.txt
@@ -0,0 +1,28 @@
+cmake_minimum_required(VERSION 3.16)
+project(mesh_shader)
+
+# setting c++ standard for the project
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+# this should fix the execution path to load local files from the project
+set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
+
+# adding source files to the project
+add_executable(mesh_shader src/main.cpp)
+
+# this should fix the execution path to load local files from the project (for MSVC)
+if(MSVC)
+	set_target_properties(mesh_shader PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
+	set_target_properties(mesh_shader PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
+
+	# in addition to setting the output directory, the working directory has to be set
+	# by default visual studio sets the working directory to the build directory, when using the debugger
+	set_target_properties(mesh_shader PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
+endif()
+
+# including headers of dependencies and the VkCV framework
+target_include_directories(mesh_shader SYSTEM BEFORE PRIVATE ${vkcv_include} ${vkcv_includes} ${vkcv_testing_include} ${vkcv_camera_include} ${vkcv_shader_compiler_include} ${vkcv_gui_include})
+
+# linking with libraries from all dependencies and the VkCV framework
+target_link_libraries(mesh_shader vkcv vkcv_testing vkcv_camera vkcv_shader_compiler vkcv_gui)
diff --git a/projects/mesh_shader/resources/shaders/shader.frag b/projects/mesh_shader/resources/shaders/shader.frag
new file mode 100644
index 00000000..080678be
--- /dev/null
+++ b/projects/mesh_shader/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/mesh_shader/resources/shaders/shader.vert b/projects/mesh_shader/resources/shaders/shader.vert
new file mode 100644
index 00000000..e129186a
--- /dev/null
+++ b/projects/mesh_shader/resources/shaders/shader.vert
@@ -0,0 +1,25 @@
+#version 450
+#extension GL_ARB_separate_shader_objects : enable
+
+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(positions[gl_VertexIndex], 1.0);
+	fragColor = colors[gl_VertexIndex];
+}
\ No newline at end of file
diff --git a/projects/mesh_shader/src/main.cpp b/projects/mesh_shader/src/main.cpp
new file mode 100644
index 00000000..925a6308
--- /dev/null
+++ b/projects/mesh_shader/src/main.cpp
@@ -0,0 +1,137 @@
+#include <iostream>
+#include <vkcv/Core.hpp>
+#include <GLFW/glfw3.h>
+#include <vkcv/camera/CameraManager.hpp>
+#include <chrono>
+
+#include <vkcv/shader/GLSLCompiler.hpp>
+#include <vkcv/gui/GUI.hpp>
+
+int main(int argc, const char** argv) {
+	const char* applicationName = "Mesh shader";
+
+	const int windowWidth = 1280;
+	const int windowHeight = 720;
+	vkcv::Window window = vkcv::Window::create(
+		applicationName,
+		windowWidth,
+		windowHeight,
+		false
+	);
+
+	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::gui::GUI gui (core, window);
+
+	const auto& context = core.getContext();
+	const vk::Instance& instance = context.getInstance();
+	const vk::PhysicalDevice& physicalDevice = context.getPhysicalDevice();
+	const vk::Device& device = context.getDevice();
+
+	const vkcv::AttachmentDescription present_color_attachment(
+		vkcv::AttachmentOperation::STORE,
+		vkcv::AttachmentOperation::CLEAR,
+		core.getSwapchain().getFormat());
+
+	vkcv::PassConfig trianglePassDefinition({ present_color_attachment });
+	vkcv::PassHandle trianglePass = core.createPass(trianglePassDefinition);
+
+	if (!trianglePass)
+	{
+		std::cout << "Error. Could not create renderpass. Exiting." << std::endl;
+		return EXIT_FAILURE;
+	}
+
+	vkcv::ShaderProgram triangleShaderProgram{};
+	vkcv::shader::GLSLCompiler compiler;
+	
+	compiler.compile(vkcv::ShaderStage::VERTEX, std::filesystem::path("resources/shaders/shader.vert"),
+					 [&triangleShaderProgram](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
+		 triangleShaderProgram.addShader(shaderStage, path);
+	});
+	
+	compiler.compile(vkcv::ShaderStage::FRAGMENT, std::filesystem::path("resources/shaders/shader.frag"),
+					 [&triangleShaderProgram](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
+		triangleShaderProgram.addShader(shaderStage, path);
+	});
+
+	const vkcv::PipelineConfig trianglePipelineDefinition {
+		triangleShaderProgram,
+		(uint32_t)windowWidth,
+		(uint32_t)windowHeight,
+		trianglePass,
+		{},
+		{},
+		false
+	};
+
+	vkcv::PipelineHandle trianglePipeline = core.createGraphicsPipeline(trianglePipelineDefinition);
+
+	if (!trianglePipeline)
+	{
+		std::cout << "Error. Could not create graphics pipeline. Exiting." << std::endl;
+		return EXIT_FAILURE;
+	}
+
+	auto start = std::chrono::system_clock::now();
+
+	vkcv::ImageHandle swapchainImageHandle = vkcv::ImageHandle::createSwapchainImageHandle();
+
+	const vkcv::Mesh renderMesh({}, nullptr, 3);
+	vkcv::DrawcallInfo drawcall(renderMesh, {});
+
+	const vkcv::ImageHandle swapchainInput = vkcv::ImageHandle::createSwapchainImageHandle();
+
+    vkcv::camera::CameraManager cameraManager(window);
+    uint32_t camIndex0 = cameraManager.addCamera(vkcv::camera::ControllerType::PILOT);
+	
+	cameraManager.getCamera(camIndex0).setPosition(glm::vec3(0, 0, -2));
+
+	while (window.isWindowOpen())
+	{
+        window.pollEvents();
+
+		uint32_t swapchainWidth, swapchainHeight; // No resizing = No problem
+		if (!core.beginFrame(swapchainWidth, swapchainHeight)) {
+			continue;
+		}
+		
+        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 mvp = cameraManager.getActiveCamera().getMVP();
+
+		vkcv::PushConstantData pushConstantData((void*)&mvp, sizeof(glm::mat4));
+		auto cmdStream = core.createCommandStream(vkcv::QueueType::Graphics);
+
+		core.recordDrawcallsToCmdStream(
+			cmdStream,
+			trianglePass,
+			trianglePipeline,
+			pushConstantData,
+			{ drawcall },
+			{ swapchainInput });
+
+		core.prepareSwapchainImageForPresent(cmdStream);
+		core.submitCommandStream(cmdStream);
+		
+		// gui.beginGUI();
+		// 
+		// ImGui::Begin("Settings");
+		// ImGui::End();
+		// 
+		// gui.endGUI();
+	    
+	    core.endFrame();
+	}
+	return 0;
+}
-- 
GitLab