From 85533814e1cd9667611a0f597db95e962e6338a2 Mon Sep 17 00:00:00 2001
From: Jack <jack@jackmchristensen.com>
Date: Wed, 28 Aug 2024 22:24:23 -0400
Subject: [PATCH] Dynamic tessellation based on slope

TODO normals do not reflect slope tessellation
---
 imgui.ini                      | 10 +++++-----
 shaders/tessellation_ctrl.glsl | 36 ++++++++++++++++++++++++++++------
 source/interface.cpp           |  1 -
 source/scene.cpp               |  7 ++++---
 4 files changed, 39 insertions(+), 15 deletions(-)

diff --git a/imgui.ini b/imgui.ini
index b15b204..111b61d 100644
--- a/imgui.ini
+++ b/imgui.ini
@@ -30,20 +30,20 @@ DockId=0x00000003,0
 
 [Window][Viewport]
 Pos=0,34
-Size=2134,1641
+Size=2178,1641
 Collapsed=0
 DockId=0x00000003,0
 
 [Window][Scene Settings]
-Pos=2137,34
-Size=743,1641
+Pos=2181,34
+Size=699,1641
 Collapsed=0
 DockId=0x00000004,0
 
 [Docking][Data]
 DockSpace     ID=0x6F42A598 Window=0xE80F322C Pos=0,34 Size=2880,1641 Split=X Selected=0x9F2D9299
   DockNode    ID=0x00000001 Parent=0x6F42A598 SizeRef=0,0 Split=X Selected=0x13926F0B
-    DockNode  ID=0x00000003 Parent=0x00000001 SizeRef=2134,701 CentralNode=1 Selected=0x13926F0B
-    DockNode  ID=0x00000004 Parent=0x00000001 SizeRef=743,701 Selected=0x413E6147
+    DockNode  ID=0x00000003 Parent=0x00000001 SizeRef=578,701 CentralNode=1 Selected=0x13926F0B
+    DockNode  ID=0x00000004 Parent=0x00000001 SizeRef=699,701 Selected=0x413E6147
   DockNode    ID=0x00000002 Parent=0x6F42A598 SizeRef=419,701 Selected=0xF69494A7
 
diff --git a/shaders/tessellation_ctrl.glsl b/shaders/tessellation_ctrl.glsl
index 94d8dd3..0577fc4 100644
--- a/shaders/tessellation_ctrl.glsl
+++ b/shaders/tessellation_ctrl.glsl
@@ -26,19 +26,43 @@ out TC_OUT {
     vec2 texCoord;
 } tc_out[];
 
+float getHeight(vec2 uv) {
+    return texture(heightTexture, uv).r * displacementScale;
+}
+
+float calculateSlope() {
+    float step = 1.0f / (float(gridDensity) * maxTessellation + 1.0f);
+
+    // Find surrounding heights
+    float hLeft = getHeight(tc_in[gl_InvocationID].texCoord + vec2(-step, 0.0f));
+    float hRight = getHeight(tc_in[gl_InvocationID].texCoord + vec2(step, 0.0f));
+    float hUp = getHeight(tc_in[gl_InvocationID].texCoord + vec2(0.0f, step));
+    float hDown = getHeight(tc_in[gl_InvocationID].texCoord + vec2(0.0f, -step));
+
+    float slopeX = abs(hLeft - hRight);
+    float slopeY = abs(hUp - hDown);
+
+    float maxSlope = max(slopeX, slopeY);
+
+    return maxSlope;
+}
+
 void main() {
     // Pass through position and texture coordinates to the tessellation evaluation shader
     tc_out[gl_InvocationID].position = tc_in[gl_InvocationID].position;
     tc_out[gl_InvocationID].texCoord = tc_in[gl_InvocationID].texCoord;
 
+    float slope = calculateSlope();
+    float tessLevel = tessellationFactor * (1.0f + slope * 10.0f);
+
     // Set tessellation levels
     if (gl_InvocationID == 0) {
-        gl_TessLevelOuter[0] = maxTessellation; 
-        gl_TessLevelOuter[1] = maxTessellation; 
-        gl_TessLevelOuter[2] = maxTessellation; 
-        gl_TessLevelOuter[3] = maxTessellation; 
+        gl_TessLevelOuter[0] = tessLevel; 
+        gl_TessLevelOuter[1] = tessLevel; 
+        gl_TessLevelOuter[2] = tessLevel; 
+        gl_TessLevelOuter[3] = tessLevel; 
 
-        gl_TessLevelInner[0] = maxTessellation; 
-        gl_TessLevelInner[1] = maxTessellation; 
+        gl_TessLevelInner[0] = tessLevel; 
+        gl_TessLevelInner[1] = tessLevel; 
     }
 }
\ No newline at end of file
diff --git a/source/interface.cpp b/source/interface.cpp
index 70735f6..8f2fa00 100644
--- a/source/interface.cpp
+++ b/source/interface.cpp
@@ -20,7 +20,6 @@ void ApplyUIScaling(GLFWwindow* window) {
 
     ImGuiIO& io = ImGui::GetIO();
     io.Fonts->Clear();
-    std::cout << "Current Path: " << std::filesystem::current_path() << std::endl;
 
 #ifdef _WIN32
     io.Fonts->AddFontFromFileTTF("imgui/misc/fonts/JetBrainsMono/JetBrainsMono-Medium.ttf", 8.0f * scale);
diff --git a/source/scene.cpp b/source/scene.cpp
index c1e2e2e..b52658d 100644
--- a/source/scene.cpp
+++ b/source/scene.cpp
@@ -240,8 +240,7 @@ void Scene::Display(GLFWwindow* window) {
 
     glUseProgram(shader_program_);
 
-    //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
-
+    // glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
     
     Window* viewport = Interface::GetWindowByName(windows_, "Viewport");
     if (viewport && viewport->size.x > 0 && viewport->size.y > 0) {
@@ -270,7 +269,9 @@ void Scene::Display(GLFWwindow* window) {
     glPatchParameteri(GL_PATCH_VERTICES, 4);
     glDrawElements(GL_PATCHES, indices.size(), GL_UNSIGNED_INT, 0);
 
-    //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+    FBO::Unbind();
+
+    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
 
     FBO::Bind(lht_fbo_);
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);