From 495882951400b4ce7741bd311a7d70b0e7afb3be Mon Sep 17 00:00:00 2001
From: Tobias Frisch <tfrisch@uni-koblenz.de>
Date: Sun, 8 May 2022 23:06:53 +0200
Subject: [PATCH] Added red point rendering to clipping in skull demo

Signed-off-by: Tobias Frisch <tfrisch@uni-koblenz.de>
---
 projects/head_demo/assets/shaders/clip.inc    | 19 +++++++
 projects/head_demo/assets/shaders/red.frag    | 10 ++++
 projects/head_demo/assets/shaders/shader.geom | 46 ++++-----------
 projects/head_demo/assets/shaders/wired.geom  | 51 +++++++++++++++++
 projects/head_demo/src/main.cpp               | 57 ++++++++++++++++---
 5 files changed, 142 insertions(+), 41 deletions(-)
 create mode 100644 projects/head_demo/assets/shaders/clip.inc
 create mode 100644 projects/head_demo/assets/shaders/red.frag
 create mode 100644 projects/head_demo/assets/shaders/wired.geom

diff --git a/projects/head_demo/assets/shaders/clip.inc b/projects/head_demo/assets/shaders/clip.inc
new file mode 100644
index 00000000..edb5ac3c
--- /dev/null
+++ b/projects/head_demo/assets/shaders/clip.inc
@@ -0,0 +1,19 @@
+
+#define CLIP_SCALE 10000.0f
+
+vec4 clipPosition(vec4 pos) {
+    return vec4(
+        max(clipX, pos.x),
+        max(clipY, pos.y),
+        max(clipZ, pos.z),
+        1.0f / CLIP_SCALE
+    );
+}
+
+vec4 clipByLimit(vec4 pos) {
+    if (pos.x / pos.w < clipLimit) {
+        return vec4(pos.xyz / pos.w, 1.0f);
+    } else {
+        return vec4(clipLimit, pos.y / pos.w, pos.z / pos.w, 1.0f);
+    }
+}
diff --git a/projects/head_demo/assets/shaders/red.frag b/projects/head_demo/assets/shaders/red.frag
new file mode 100644
index 00000000..3991f939
--- /dev/null
+++ b/projects/head_demo/assets/shaders/red.frag
@@ -0,0 +1,10 @@
+#version 450
+#extension GL_ARB_separate_shader_objects : enable
+
+layout(location = 0) in vec3 passNormal;
+
+layout(location = 0) out vec3 outColor;
+
+void main()	{
+    outColor = (vec3(0.3f, 0, 0) + max(dot(passNormal, vec3(1.0f, -1.0f, 0.5f)), 0.0f) * vec3(0.7f, 0, 0));
+}
\ No newline at end of file
diff --git a/projects/head_demo/assets/shaders/shader.geom b/projects/head_demo/assets/shaders/shader.geom
index 4dc5121b..275b300e 100644
--- a/projects/head_demo/assets/shaders/shader.geom
+++ b/projects/head_demo/assets/shaders/shader.geom
@@ -1,5 +1,6 @@
 #version 450
 #extension GL_ARB_separate_shader_objects : enable
+#extension GL_GOOGLE_include_directive : enable
 
 layout(triangles) in;
 layout(triangle_strip, max_vertices = 3) out;
@@ -19,24 +20,7 @@ layout( push_constant ) uniform constants{
     mat4 mvp;
 };
 
-#define CLIP_SCALE 10000.0f
-
-vec4 clipPosition(vec4 pos) {
-    return vec4(
-        min(clipX, pos.x),
-        min(clipY, pos.y),
-        min(clipZ, pos.z),
-        1.0f / CLIP_SCALE
-    );
-}
-
-vec4 clipByLimit(vec4 pos) {
-    if (pos.x / pos.w < clipLimit) {
-        return vec4(pos.xyz / pos.w, 1.0f);
-    } else {
-        return vec4(clipLimit, pos.y / pos.w, pos.z / pos.w, 1.0f);
-    }
-}
+#include "clip.inc"
 
 void main()	{
     vec4 v0 = gl_in[0].gl_Position;
@@ -52,24 +36,18 @@ void main()	{
     float dz = abs(v0.z - clipZ) + abs(v1.z - clipZ) + abs(v2.z - clipZ);
 
     if (dx * dy * dz > 0.0f) {
-        v0 = clipByLimit(mvp * (v0 * CLIP_SCALE));
-        v1 = clipByLimit(mvp * (v1 * CLIP_SCALE));
-        v2 = clipByLimit(mvp * (v2 * CLIP_SCALE));
-
-        if ((v0.x < clipLimit) || (v1.x < clipLimit) || (v2.x < clipLimit)) {
-            gl_Position = v0;
-            passNormal = geomNormal[0];
-            EmitVertex();
+        gl_Position = mvp * (v0 * CLIP_SCALE);
+        passNormal = geomNormal[0];
+        EmitVertex();
 
-            gl_Position = v1;
-            passNormal = geomNormal[1];
-            EmitVertex();
+        gl_Position = mvp * (v1 * CLIP_SCALE);
+        passNormal = geomNormal[1];
+        EmitVertex();
 
-            gl_Position = v2;
-            passNormal = geomNormal[2];
-            EmitVertex();
+        gl_Position = mvp * (v2 * CLIP_SCALE);
+        passNormal = geomNormal[2];
+        EmitVertex();
 
-            EndPrimitive();
-        }
+        EndPrimitive();
     }
 }
diff --git a/projects/head_demo/assets/shaders/wired.geom b/projects/head_demo/assets/shaders/wired.geom
new file mode 100644
index 00000000..00633605
--- /dev/null
+++ b/projects/head_demo/assets/shaders/wired.geom
@@ -0,0 +1,51 @@
+#version 450
+#extension GL_ARB_separate_shader_objects : enable
+#extension GL_GOOGLE_include_directive : enable
+
+layout(triangles) in;
+layout(points, max_vertices = 1) out;
+
+layout(location = 0) in vec3 geomNormal[];
+
+layout(location = 0) out vec3 passNormal;
+
+layout(set=1, binding=0) uniform clipBuffer {
+    float clipLimit;
+    float clipX;
+    float clipY;
+    float clipZ;
+};
+
+layout( push_constant ) uniform constants{
+    mat4 mvp;
+};
+
+#include "clip.inc"
+
+void main()	{
+    vec4 v0 = gl_in[0].gl_Position;
+    vec4 v1 = gl_in[1].gl_Position;
+    vec4 v2 = gl_in[2].gl_Position;
+
+    v0 = clipPosition(v0 / CLIP_SCALE);
+    v1 = clipPosition(v1 / CLIP_SCALE);
+    v2 = clipPosition(v2 / CLIP_SCALE);
+
+    float dx = abs(v0.x - clipX) + abs(v1.x - clipX) + abs(v2.x - clipX);
+    float dy = abs(v0.y - clipY) + abs(v1.y - clipY) + abs(v2.y - clipY);
+    float dz = abs(v0.z - clipZ) + abs(v1.z - clipZ) + abs(v2.z - clipZ);
+
+    if (dx * dy * dz <= 0.0f) {
+        v0 = clipByLimit(mvp * gl_in[0].gl_Position);
+        v1 = clipByLimit(mvp * gl_in[1].gl_Position);
+        v2 = clipByLimit(mvp * gl_in[2].gl_Position);
+
+        if ((v0.x < clipLimit) || (v1.x < clipLimit) || (v2.x < clipLimit)) {
+            gl_Position = (v0 + v1 + v2) / 3;
+            passNormal = (geomNormal[0] + geomNormal[1] + geomNormal[2]) / 3;
+            EmitVertex();
+
+            EndPrimitive();
+        }
+    }
+}
diff --git a/projects/head_demo/src/main.cpp b/projects/head_demo/src/main.cpp
index 7acad116..c25ed49f 100644
--- a/projects/head_demo/src/main.cpp
+++ b/projects/head_demo/src/main.cpp
@@ -38,27 +38,43 @@ int main(int argc, const char** argv) {
 			argc > 1 ? argv[1] : "assets/skull_scaled/scene.gltf"
 	));
 	
-	const vkcv::AttachmentDescription present_color_attachment(
+	const vkcv::AttachmentDescription present_color_attachment0(
 			vkcv::AttachmentOperation::STORE,
 			vkcv::AttachmentOperation::CLEAR,
 			core.getSwapchain(windowHandle).getFormat()
 	);
 	
-	const vkcv::AttachmentDescription depth_attachment(
+	const vkcv::AttachmentDescription depth_attachment0(
 			vkcv::AttachmentOperation::STORE,
 			vkcv::AttachmentOperation::CLEAR,
 			vk::Format::eD32Sfloat
 	);
 	
-	vkcv::PassConfig scenePassDefinition({ present_color_attachment, depth_attachment });
+	vkcv::PassConfig scenePassDefinition({ present_color_attachment0, depth_attachment0 });
 	vkcv::PassHandle scenePass = core.createPass(scenePassDefinition);
 	
-	if (!scenePass) {
+	const vkcv::AttachmentDescription present_color_attachment1(
+			vkcv::AttachmentOperation::STORE,
+			vkcv::AttachmentOperation::LOAD,
+			core.getSwapchain(windowHandle).getFormat()
+	);
+	
+	const vkcv::AttachmentDescription depth_attachment1(
+			vkcv::AttachmentOperation::STORE,
+			vkcv::AttachmentOperation::LOAD,
+			vk::Format::eD32Sfloat
+	);
+	
+	vkcv::PassConfig linePassDefinition({ present_color_attachment1, depth_attachment1 });
+	vkcv::PassHandle linePass = core.createPass(linePassDefinition);
+	
+	if ((!scenePass) || (!linePass)) {
 		std::cout << "Error. Could not create renderpass. Exiting." << std::endl;
 		return EXIT_FAILURE;
 	}
 	
 	vkcv::ShaderProgram sceneShaderProgram;
+	vkcv::ShaderProgram lineShaderProgram;
 	vkcv::shader::GLSLCompiler compiler;
 	
 	compiler.compileProgram(sceneShaderProgram, {
@@ -67,6 +83,12 @@ int main(int argc, const char** argv) {
 			{ vkcv::ShaderStage::FRAGMENT, "assets/shaders/shader.frag" }
 	}, nullptr);
 	
+	compiler.compileProgram(lineShaderProgram, {
+			{ vkcv::ShaderStage::VERTEX, "assets/shaders/shader.vert" },
+			{ vkcv::ShaderStage::GEOMETRY, "assets/shaders/wired.geom" },
+			{ vkcv::ShaderStage::FRAGMENT, "assets/shaders/red.frag" }
+	}, nullptr);
+	
 	const std::vector<vkcv::VertexAttachment> vertexAttachments = sceneShaderProgram.getVertexAttachments();
 	std::vector<vkcv::VertexBinding> bindings;
 	for (size_t i = 0; i < vertexAttachments.size(); i++) {
@@ -84,7 +106,7 @@ int main(int argc, const char** argv) {
 	float clipZ = 0.0f;
 	
 	auto clipBuffer = core.createBuffer<float>(vkcv::BufferType::UNIFORM, 4);
-	clipBuffer.fill({ clipLimit, clipX, clipY, clipZ });
+	clipBuffer.fill({ clipLimit, -clipX, -clipY, -clipZ });
 	
 	vkcv::DescriptorWrites clipWrites;
 	clipWrites.uniformBufferWrites = {
@@ -128,9 +150,21 @@ int main(int argc, const char** argv) {
 			{ material0.getDescriptorSetLayout(), clipDescriptorSetLayout },
 			true
 	};
+	
+	const vkcv::GraphicsPipelineConfig linePipelineDefinition{
+			lineShaderProgram,
+			UINT32_MAX,
+			UINT32_MAX,
+			linePass,
+			{sceneLayout},
+			{ material0.getDescriptorSetLayout(), clipDescriptorSetLayout },
+			true
+	};
+	
 	vkcv::GraphicsPipelineHandle scenePipeline = core.createGraphicsPipeline(scenePipelineDefinition);
+	vkcv::GraphicsPipelineHandle linePipeline = core.createGraphicsPipeline(linePipelineDefinition);
 	
-	if (!scenePipeline) {
+	if ((!scenePipeline) || (!linePipeline)) {
 		std::cout << "Error. Could not create graphics pipeline. Exiting." << std::endl;
 		return EXIT_FAILURE;
 	}
@@ -170,7 +204,7 @@ int main(int argc, const char** argv) {
 		start = end;
 		cameraManager.update(0.000001 * static_cast<double>(deltatime.count()));
 		
-		clipBuffer.fill({ clipLimit, clipX, clipY, clipZ });
+		clipBuffer.fill({ clipLimit, -clipX, -clipY, -clipZ });
 		
 		const std::vector<vkcv::ImageHandle> renderTargets = { swapchainInput, depthBuffer };
 		auto cmdStream = core.createCommandStream(vkcv::QueueType::Graphics);
@@ -193,6 +227,15 @@ int main(int argc, const char** argv) {
 							  renderTargets,
 							  windowHandle);
 		
+		scene.recordDrawcalls(cmdStream,
+							  cameraManager.getActiveCamera(),
+							  linePass,
+							  linePipeline,
+							  sizeof(glm::mat4),
+							  recordMesh,
+							  renderTargets,
+							  windowHandle);
+		
 		core.prepareSwapchainImageForPresent(cmdStream);
 		core.submitCommandStream(cmdStream);
 		
-- 
GitLab