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
+}