commit aaa37db9d511804e41d0957522557ec227363d0f
parent 981f0f9c0b582d41d40809e00d9a4e22322e4b1f
Author: Christian Ermann <christianermann@gmail.com>
Date:   Sun, 29 May 2022 16:27:50 -0700
Compute normals in vertex shader, added more shading options.
Diffstat:
6 files changed, 227 insertions(+), 35 deletions(-)
diff --git a/include/shader.h b/include/shader.h
@@ -14,6 +14,8 @@ void Shader_use(Shader *shader);
 
 void Shader_reload(Shader *shader);
 
+void Shader_setInt(const Shader *shader, const char *name, int i);
+void Shader_setFloat(const Shader *shader, const char *name, float f);
 void Shader_setVec3(const Shader *shader, const char *name, Vec3 v);
 void Shader_setMat4(const Shader *shader, const char *name, Mat4 m);
 
diff --git a/shaders/basic.fs b/shaders/basic.fs
@@ -7,36 +7,43 @@ out vec4 frag_color;
 
 const vec3 light_color = vec3(1.0, 1.0, 1.0);
 
+uniform int shade_normals;
 uniform vec3 view_pos;
 uniform vec3 pointlight_pos;
 
 void main()
 {
-    vec3 dx = dFdx(frag_pos);
-    vec3 dy = dFdy(frag_pos);
-    vec3 normal = normalize(cross(dy, dx));
-
-    float slope = (normal.y + 1.0) * 0.5;
-
-    normal = mix(normal, -frag_norm, 1 - slope);
-    vec3 object_color = mix(vec3(0.6, 0.7, 0.5), vec3(0.5, 0.6, 0.7), slope);
-
-    float d = length(pointlight_pos - frag_pos);
-    float attenuation = 1.0 / (1.0 + 0.022 * d + 0.0019 * d * d);
-
-    vec3 light_dir = normalize(frag_pos - pointlight_pos);
-    vec3 view_dir = normalize(view_pos - frag_pos);
-    vec3 reflect_dir = reflect(-light_dir, normal);
-
-    float ambient_strength = 0.1;
-    vec3 ambient = ambient_strength * light_color * attenuation;
-
-    float diffuse_strength = max(dot(normal, light_dir), 0.0);
-    vec3 diffuse = diffuse_strength * light_color * attenuation;
-
-    float specular_strength = 0.5;
-    float spec = pow(max(dot(view_dir, reflect_dir), 0.0), 32);
-    vec3 specular = specular_strength * spec * light_color * attenuation;
+    if (shade_normals == 1)
+    {
+        frag_color = vec4(0.5 * (frag_norm + 1.0), 1.0);
+    }
+    else
+    {
+        vec3 dx = dFdx(frag_pos);
+        vec3 dy = dFdy(frag_pos);
+        vec3 normal = normalize(cross(dy, dx));
+
+        float slope = (normal.y + 1.0) * 0.5;
+        normal = mix(normal, -frag_norm, 1 - slope);
+        vec3 object_color = mix(vec3(0.6, 0.7, 0.5), vec3(0.5, 0.6, 0.7), slope);
+
+        float d = length(pointlight_pos - frag_pos);
+        float attenuation = 1.0 / (1.0 + 0.022 * d + 0.0019 * d * d);
+
+        vec3 light_dir = normalize(frag_pos - pointlight_pos);
+        vec3 view_dir = normalize(view_pos - frag_pos);
+        vec3 reflect_dir = reflect(-light_dir, normal);
+
+        float ambient_strength = 0.1;
+        vec3 ambient = ambient_strength * light_color * attenuation;
+
+        float diffuse_strength = max(dot(normal, light_dir), 0.0);
+        vec3 diffuse = diffuse_strength * light_color * attenuation;
+
+        float specular_strength = 0.5;
+        float spec = pow(max(dot(view_dir, reflect_dir), 0.0), 32);
+        vec3 specular = specular_strength * spec * light_color * attenuation;
     
-    frag_color = vec4((ambient + diffuse + specular) * object_color, 1.0);
+        frag_color = vec4((ambient + diffuse + specular) * object_color, 1.0);
+    }
 }
diff --git a/shaders/basic.vs b/shaders/basic.vs
@@ -1,16 +1,165 @@
 #version 330 core
 
 layout(location = 0) in vec3 in_position;
-layout(location = 1) in vec3 in_normal;
 
 out vec3 frag_pos;
 out vec3 frag_norm;
 
 uniform mat4 camera;
+uniform int time;
+
+const int p[512] = int[512](
+    151, 160, 137,  91,  90,  15, 131,  13, 201,  95,  96,  53, 194, 233,   7,
+    225, 140,  36, 103,  30,  69, 142,   8,  99,  37, 240,  21,  10,  23, 190,
+      6, 148, 247, 120, 234,  75,   0,  26, 197,  62,  94, 252, 219, 203, 117,
+     35,  11,  32,  57, 177,  33,  88, 237, 149,  56,  87, 174,  20, 125, 136,
+    171, 168,  68, 175,  74, 165,  71, 134, 139,  48,  27, 166,  77, 146, 158,
+    231,  83, 111, 229, 122,  60, 211, 133, 230, 220, 105,  92,  41,  55,  46,
+    245,  40, 244, 102, 143,  54,  65,  25,  63, 161,   1, 216,  80,  73, 209,
+     76, 132, 187, 208,  89,  18, 169, 200, 196, 135, 130, 116, 188, 159,  86,
+    164, 100, 109, 198, 173, 186,   3,  64,  52, 217, 226, 250, 124, 123,   5,
+    202,  38, 147, 118, 126, 255,  82,  85, 212, 207, 206,  59, 227,  47,  16,
+     58,  17, 182, 189,  28,  42, 223, 183, 170, 213, 119, 248, 152,   2,  44,
+    154, 163,  70, 221, 153, 101, 155, 167,  43, 172,   9, 129,  22,  39, 253,
+     19,  98, 108, 110,  79, 113, 224, 232, 178, 185, 112, 104, 218, 246,  97,
+    228, 251,  34, 242, 193, 238, 210, 144,  12, 191, 179, 162, 241,  81,  51,
+    145, 235, 249,  14, 239, 107,  49, 192, 214,  31, 181, 199, 106, 157, 184,
+     84, 204, 176, 115, 121,  50,  45, 127,   4, 150, 254, 138, 236, 205,  93,
+    222, 114,  67,  29,  24,  72, 243, 141, 128, 195,  78,  66, 215,  61, 156,
+    180,
+    151, 160, 137,  91,  90,  15, 131,  13, 201,  95,  96,  53, 194, 233,   7,
+    225, 140,  36, 103,  30,  69, 142,   8,  99,  37, 240,  21,  10,  23, 190,
+      6, 148, 247, 120, 234,  75,   0,  26, 197,  62,  94, 252, 219, 203, 117,
+     35,  11,  32,  57, 177,  33,  88, 237, 149,  56,  87, 174,  20, 125, 136,
+    171, 168,  68, 175,  74, 165,  71, 134, 139,  48,  27, 166,  77, 146, 158,
+    231,  83, 111, 229, 122,  60, 211, 133, 230, 220, 105,  92,  41,  55,  46,
+    245,  40, 244, 102, 143,  54,  65,  25,  63, 161,   1, 216,  80,  73, 209,
+     76, 132, 187, 208,  89,  18, 169, 200, 196, 135, 130, 116, 188, 159,  86,
+    164, 100, 109, 198, 173, 186,   3,  64,  52, 217, 226, 250, 124, 123,   5,
+    202,  38, 147, 118, 126, 255,  82,  85, 212, 207, 206,  59, 227,  47,  16,
+     58,  17, 182, 189,  28,  42, 223, 183, 170, 213, 119, 248, 152,   2,  44,
+    154, 163,  70, 221, 153, 101, 155, 167,  43, 172,   9, 129,  22,  39, 253,
+     19,  98, 108, 110,  79, 113, 224, 232, 178, 185, 112, 104, 218, 246,  97,
+    228, 251,  34, 242, 193, 238, 210, 144,  12, 191, 179, 162, 241,  81,  51,
+    145, 235, 249,  14, 239, 107,  49, 192, 214,  31, 181, 199, 106, 157, 184,
+     84, 204, 176, 115, 121,  50,  45, 127,   4, 150, 254, 138, 236, 205,  93,
+    222, 114,  67,  29,  24,  72, 243, 141, 128, 195,  78,  66, 215,  61, 156,
+    180
+);
+
+const vec3 g[16] = vec3[16](
+    vec3( 1,  1,  0),
+    vec3(-1,  1,  0),
+    vec3( 1, -1,  0),
+    vec3(-1, -1,  0),
+    vec3( 1,  0,  1),
+    vec3(-1,  0,  1),
+    vec3( 1,  0, -1),
+    vec3(-1,  0, -1),
+    vec3( 0,  1,  1),
+    vec3( 0, -1,  1),
+    vec3( 0,  1, -1),
+    vec3( 0, -1, -1),
+    vec3( 1,  1,  0),
+    vec3( 0, -1,  1),
+    vec3(-1,  1,  0),
+    vec3( 0, -1, -1)
+);
+
+float fade(float t)
+{
+    return t * t * t * (t * (t * 6 - 15) + 10);
+}
+
+float lerp(float t, float a, float b)
+{
+    return a + t * (b - a);
+}
+
+float grad(int hash, float x, float y, float z)
+{
+    int h = hash & 15;
+    return g[h].x * x + g[h].y * y + g[h].z * z;
+}
+
+float perlin(float x, float y, float z)
+{
+    int X = int(floor(x)) & 255;
+    int Y = int(floor(y)) & 255;
+    int Z = int(floor(z)) & 255;
+
+    x -= floor(x);
+    y -= floor(y);
+    z -= floor(z);
+    
+    float u = fade(x);
+    float v = fade(y);
+    float w = fade(z);
+    
+    int a = p[p[p[X    ] + Y    ] + Z];
+    int b = p[p[p[X + 1] + Y    ] + Z];
+    int c = p[p[p[X    ] + Y + 1] + Z];
+    int d = p[p[p[X + 1] + Y + 1] + Z];
+    int e = p[p[p[X    ] + Y    ] + Z + 1];
+    int f = p[p[p[X + 1] + Y    ] + Z + 1];
+    int g = p[p[p[X    ] + Y + 1] + Z + 1];
+    int h = p[p[p[X + 1] + Y + 1] + Z + 1];
+
+    return lerp(w, lerp(v, lerp(u, grad(a, x    , y    , z    ),
+                                   grad(b, x - 1, y    , z    )),
+                           lerp(u, grad(c, x    , y - 1, z    ),
+                                   grad(d, x - 1, y - 1, z    ))),
+                   lerp(v, lerp(u, grad(e, x    , y    , z - 1),
+                                   grad(f, x - 1, y    , z - 1)),
+                           lerp(u, grad(g, x    , y - 1, z - 1),
+                                   grad(h, x - 1, y - 1, z - 1))));
+}
+
+float perlinSDF(vec3 p)
+{
+    float o1 = perlin(p[0] * 0.01, p[1] * 0.01, p[2] * 0.01);
+    float o2 = perlin(p[0] * 0.05, p[1] * 0.05, p[2] * 0.05) * 0.5;
+    float o3 = perlin(p[0] * 0.10, p[1] * 0.10, p[2] * 0.10) * 0.1;
+    return o1 + o2 + o3;
+}
+
+float terrainSDF(const vec3 p)
+{
+    float o1 = perlin(p.x * 0.005, 0.0, p.z * 0.005) * 50.0;
+    float o2 = perlin(p.x * 0.050, 0.0, p.z * 0.050) *  2.0;
+    float o3 = perlin(p.x * 0.005, 0.0, p.z * 0.005) *  1.0;
+
+    float surface = p[1] - o1 - o2 - o3;
+    float cave = perlinSDF(p);
+
+    float k = 32.0;
+    float h = 0.5 - 0.5 * (cave - surface ) / k;
+    h = clamp(h, 0.0, 1.0);
+
+    float a = cave * (1.0 - h) + surface * h;
+    float b = k * h * (1.0 - h);
+
+    return a + b;
+}
+
+vec3 normal(vec3 p)
+{
+    const float h = 0.01;
+    const vec2 k = vec2(1.0, -1.0);
+    return normalize(
+            k.xyy * terrainSDF(p + k.xyy * h) +
+            k.yyx * terrainSDF(p + k.yyx * h) +
+            k.yxy * terrainSDF(p + k.yxy * h) +
+            k.xxx * terrainSDF(p + k.xxx * h)
+    );
+}
 
 void main()
 {
-    frag_pos = in_position;
-    frag_norm = in_normal;
+    float displacement = 0.2 * cos(0.01 * time + in_position.x) + 0.2 * sin(0.01 * time + in_position.z);
+    vec3 norm = normal(in_position);
+    frag_pos = in_position + norm * displacement;
+    frag_norm = norm;
     gl_Position = camera * vec4(frag_pos, 1.0);
 }
+
diff --git a/src/main.c b/src/main.c
@@ -86,6 +86,9 @@ int main(int argc, char** argv)
 
     Shader *shader = Shader_make("shaders/basic.vs", "shaders/basic.fs");
     Shader_use(shader);
+    Shader_setInt(shader, "shade_normals", 0);
+    
+    int loop_count = 0;
 
     while (!glfwWindowShouldClose(app->window))
     {
@@ -101,7 +104,26 @@ int main(int argc, char** argv)
         {
             Shader_reload(shader);
             Shader_use(shader);
-            break;
+        }
+        if (glfwGetKey(app->window, GLFW_KEY_Z) == GLFW_PRESS)
+        {
+            glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+        }
+        if (glfwGetKey(app->window, GLFW_KEY_X) == GLFW_PRESS)
+        {
+            glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+        }
+        if (glfwGetKey(app->window, GLFW_KEY_N) == GLFW_PRESS)
+        {
+            Shader_setInt(shader, "shade_normals", 1);
+        }
+        if (glfwGetKey(app->window, GLFW_KEY_M) == GLFW_PRESS)
+        {
+            Shader_setInt(shader, "shade_normals", 0);
+        }
+        if (glfwGetKey(app->window, GLFW_KEY_Q) == GLFW_PRESS)
+        {
+            glfwSetWindowShouldClose(app->window, GLFW_TRUE);
         }
 
         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
@@ -109,6 +131,7 @@ int main(int argc, char** argv)
         UserInput_update(&input, app->window);
 
         Camera_move(camera, &input);
+        Shader_setInt(shader, "time", loop_count);
         Shader_setMat4(shader, "camera", camera->matrix);
         Shader_setVec3(shader, "view_pos", camera->position);
         Shader_setVec3(shader, "pointlight_pos", camera->position);
diff --git a/src/marching_cubes.c b/src/marching_cubes.c
@@ -371,7 +371,7 @@ int MC_vertices(const Vec3 corners[8], SDF f, float isolevel, int mc_index,
                 isolevel,
                 vertices[0].position
         );
-        MC_normal(vertices[0].position, f, vertices[0].normal);
+        //MC_normal(vertices[0].position, f, vertices[0].normal);
     }
     if (EDGE_TABLE[mc_index] & 8)
     {
@@ -382,7 +382,7 @@ int MC_vertices(const Vec3 corners[8], SDF f, float isolevel, int mc_index,
                 isolevel,
                 vertices[1].position
         );
-        MC_normal(vertices[1].position, f, vertices[1].normal);
+        //MC_normal(vertices[1].position, f, vertices[1].normal);
     }
     if (EDGE_TABLE[mc_index] & 256)
     {
@@ -393,7 +393,7 @@ int MC_vertices(const Vec3 corners[8], SDF f, float isolevel, int mc_index,
                 isolevel,
                 vertices[2].position
         );
-        MC_normal(vertices[2].position, f, vertices[2].normal);
+        //MC_normal(vertices[2].position, f, vertices[2].normal);
     }
     return 3;
 }
diff --git a/src/shader.c b/src/shader.c
@@ -150,6 +150,18 @@ void Shader_reload(Shader* shader)
     }
 }
 
+void Shader_setInt(const Shader *shader, const char *name, int i)
+{
+    GLint uniform_loc = glGetUniformLocation(shader->program, name);
+    glUniform1i(uniform_loc, i);
+}
+
+void Shader_setFloat(const Shader *shader, const char *name, float f)
+{
+    GLint uniform_loc = glGetUniformLocation(shader->program, name);
+    glUniform1f(uniform_loc, f);
+}
+
 void Shader_setVec3(const Shader *shader, const char *name, Vec3 v)
 {
     GLint uniform_loc = glGetUniformLocation(shader->program, name);
@@ -160,4 +172,4 @@ void Shader_setMat4(const Shader *shader, const char *name, Mat4 m)
 {
     GLint uniform_loc = glGetUniformLocation(shader->program, name);
     glUniformMatrix4fv(uniform_loc, 1, GL_FALSE, m[0]);
-}
-\ No newline at end of file
+}