commit b8699114390f7d006277084c73f04e9a39d3d87e
parent 86dcd139cfc222aafa710dab3d941df5fa481301
Author: William Casarin <jb55@jb55.com>
Date: Thu, 1 Nov 2018 21:40:00 -0700
geometry shader done
but probably won't go with it.
going to try a tessellation shader
Diffstat:
13 files changed, 126 insertions(+), 180 deletions(-)
diff --git a/etc/shaders/lighting.glsl b/etc/shaders/lighting.glsl
@@ -1,6 +1,6 @@
-#include noise.glsl
+//#include noise.glsl
// float clouds(vec3 position) {
@@ -19,16 +19,16 @@ vec3 gamma_correct(vec3 color) {
return pow(color, vec3(1.0/2.2));
}
-vec3 standard_light(vec3 color, vec3 position) {
- vec4 v4_normal = vec4(v_normal , 1);
+vec3 standard_light(vec3 color, vec3 position, vec3 normal) {
+ vec4 v4_normal = vec4(normal, 1);
vec4 trans_normal = normal_matrix * v4_normal;
- vec3 light_dir = vec3()
+ // vec3 light_dir = vec3()
const float pi = 3.14159265;
const float shiny = 12.0;
const float exposure = 0.2;
const float ambient_str = 0.2;
- float spec_str = 0.4 * light_intensity;
+ float spec_str = 0.8 * light_intensity;
// float light_intensity = light_intensity * 0.01;
@@ -56,12 +56,12 @@ vec3 standard_light(vec3 color, vec3 position) {
if (blinn) {
const float energy_conservation = ( 8.0 + shiny ) / ( 8.0 * pi );
vec3 halfway_dir = normalize(light_dir + view_dir); // blinn-phong
- spec = energy_conservation * pow(max(dot(v_normal, halfway_dir), 0.0), shiny);
+ spec = energy_conservation * pow(max(dot(normal, halfway_dir), 0.0), shiny);
}
else {
const float energy_conservation = ( 2.0 + shiny ) / ( 2.0 * pi );
- vec3 reflect_dir = reflect(-light_dir, v_normal); // phong
+ vec3 reflect_dir = reflect(-light_dir, normal); // phong
spec = energy_conservation * pow(max(dot(view_dir, reflect_dir), 0.0), shiny);
}
// spec += pow(max(dot(view_dir, reflect_dir), 0.0), 16.0) * 0.5;
diff --git a/etc/shaders/standard_vtxos.glsl b/etc/shaders/standard_vtxos.glsl
@@ -1,7 +1,7 @@
vec4 v4_pos = vec4(position, 1.0);
gl_Position = mvp * v4_pos;
-v_normal = normal;
-v_color_smooth = v_color = color;
-shadow_coord = depth_mvp * v4_pos;
-v_position = position;
-v_frag_pos = (world * v4_pos).xyz;
+vertex.normal = normal;
+vertex.color = vertex.color_smooth = color;
+vertex.shadow_coord = depth_mvp * v4_pos;
+vertex.position = position;
+vertex.frag_pos = (world * v4_pos).xyz;
diff --git a/etc/shaders/terrain.glsl b/etc/shaders/terrain.glsl
@@ -1,51 +0,0 @@
-#version 300 es
-
-precision mediump float;
-
-in vec3 position;
-in vec3 normal;
-
-#include uniforms.glsl
-
-flat out float v_light;
-flat out vec3 v_color;
-out vec3 v_color_smooth;
-
-out vec3 v_normal;
-out vec3 v_ray;
-out vec3 v_position;
-out vec3 v_frag_pos;
-out vec4 shadow_coord;
-
-const int nlands = 6;
-
-#include lighting.glsl
-
-
-const vec4 land[nlands] = vec4[](
- vec4(0.0, 0.5, 0.79, 0.0), // 0 - water
- vec4(0.9176, 0.8156, 0.6588, 1.0), // 1 - sand
- vec4(0.7, 0.7, 0.156, 2.0), // 2 - grass
- vec4(0.4627, 0.3333, 0.1686, 20.0), // 3 - dirt
- vec4(0.5, 0.5, 0.5, 80.0), // 4 - stone
- vec4(1.0, 1.0, 1.0, 380.0) // 5 - snow
-);
-
-
-void main()
-{
- vec3 color = land[0].xyz;
- for (int i = 0; i < nlands-1; i++) {
- color =
- mix(color,
- land[i+1].xyz,
- smoothstep(land[i].w, land[i+1].w, position.z));
- }
-
- // vec3 color = vec3(position.z*0.05, position.z*0.0095, position.z*0.0001) * 0.5;
-
-
- // v_color = vec3(position.z, position.z, position.z) * 0.005;
-
-#include standard_vtxos.glsl
-}
diff --git a/etc/shaders/test.f.glsl b/etc/shaders/test.f.glsl
@@ -1,33 +1,37 @@
-#version 300 es
+#include profile
precision mediump float;
-flat in vec3 v_color;
-in vec3 v_color_smooth;
-in vec3 v_ray;
-in vec3 v_normal;
-in vec3 v_position;
-in vec4 shadow_coord;
-in vec3 v_frag_pos;
out vec4 frag_color;
#include uniforms.glsl
+in f_data {
+#include shadervars.glsl
+} vertex;
+
+// in flat vec3 v_color;
+// in vec3 v_color_smooth;
+// in vec3 v_ray;
+// in vec3 v_normal;
+// in vec3 v_position;
+// in vec4 v_shadow_coord;
+// in vec3 v_frag_pos;
+
uniform sampler2D shadow_map;
#include lighting.glsl
#include fog.glsl
void main() {
-
const float smoothness = 0.0;
float visibility = 1.0;
- vec4 shadow_sample = texture(shadow_map, shadow_coord.xy);
- vec3 v_ray = camera_position - v_frag_pos;
+ vec4 shadow_sample = texture(shadow_map, vertex.shadow_coord.xy);
+ vec3 v_ray = camera_position - vertex.frag_pos;
- // vec3 color = v_color * (1.0-smoothness)
- // + v_color_smooth * smoothness;
- vec3 color = standard_light(v_color, v_position);
+ // vec3 color = vertex.color * (1.0-smoothness)
+ // + color_smooth * smoothness;
+ vec3 color = standard_light(vertex.color, vertex.position, vertex.normal);
if (fog_on) {
vec3 fog = apply_fog(color, length(v_ray), camera_position, v_ray);
@@ -35,15 +39,13 @@ void main() {
color = fog;
}
- if (light_dir.z > 0.0 && shadow_sample.z < shadow_coord.z ) {
+ if (light_dir.z > 0.0 && shadow_sample.z < vertex.shadow_coord.z ) {
float factor = 1.0/dot(light_dir, vec3(0.0, 0.0, 1.0));
visibility = clamp(0.2 * factor, 0.5, 1.0);
}
color = color * visibility;
- // float dist = length(camera_position - v_position);
+ // float dist = length(camera_position - vertex.position);
- // fragmentColor = vec4(color + diffuse, 1.0);
frag_color = vec4(color, 1.0);
- // fragmentColor = vec4(color * 0.0001 + length(v_ray) * 0.0001, 1.0);
}
diff --git a/etc/shaders/ui.f.glsl b/etc/shaders/ui.f.glsl
@@ -1,4 +1,4 @@
-#version 300 es
+#include profile
precision mediump float;
diff --git a/etc/shaders/ui.v.glsl b/etc/shaders/ui.v.glsl
@@ -1,4 +1,4 @@
-#version 300 es
+#include profile
in vec3 position;
in vec3 color;
diff --git a/etc/shaders/vertex-color.glsl b/etc/shaders/vertex-color.glsl
@@ -1,22 +1,16 @@
-
-#version 300 es
-
+#include profile
precision mediump float;
-
in vec3 position;
in vec3 normal;
in vec3 color;
#include uniforms.glsl
-flat out float v_light;
+out f_data {
+#include shadervars.glsl
+} vertex;
+
flat out vec3 v_color;
-out vec3 v_color_smooth;
-out vec3 v_normal;
-out vec3 v_position;
-out vec3 v_ray;
-out vec3 v_frag_pos;
-out vec4 shadow_coord;
void main()
{
diff --git a/src/game.c b/src/game.c
@@ -54,7 +54,7 @@ void game_init(struct game *game, int width, int height) {
.scale = 1.0
};
- static const int shadowmap_scale = 100.0;
+ static const int shadowmap_scale = 10.0;
// default ortho screenspace projection
mat4_ortho(-shadowmap_scale, // left
diff --git a/src/render.c b/src/render.c
@@ -62,7 +62,7 @@ static const float bias_matrix[] = {
void
init_gl(struct resources *resources, int width, int height) {
- struct shader vertex, terrain_vertex, fragment, fragment_smooth;
+ struct shader vertex, terrain_vertex, terrain_geom, fragment, fragment_smooth;
float tmp_matrix[16];
int ok = 0;
@@ -74,9 +74,14 @@ init_gl(struct resources *resources, int width, int height) {
ok = make_shader(GL_VERTEX_SHADER, SHADER("vertex-color.glsl"), &vertex);
assert(ok && "vertex-color shader");
- ok = make_shader(GL_VERTEX_SHADER, SHADER("terrain.glsl"), &terrain_vertex);
+ ok = make_shader(GL_VERTEX_SHADER, SHADER("terrain.v.glsl"),
+ &terrain_vertex);
assert(ok && "terrain vertex shader");
+ ok = make_shader(GL_GEOMETRY_SHADER, SHADER("terrain.g.glsl"),
+ &terrain_geom);
+ assert(ok && "terrain geometry shader");
+
ok = make_shader(GL_FRAGMENT_SHADER, SHADER("test.f.glsl"), &fragment);
assert(ok && "default fragment shader");
@@ -88,8 +93,8 @@ init_gl(struct resources *resources, int width, int height) {
resources->proj_persp);
// Shader program
- ok = make_program(&terrain_vertex, &fragment,
- &resources->programs[TERRAIN_PROGRAM]);
+ struct shader *shaders[] = { &terrain_vertex, &fragment, &terrain_geom };
+ ok = make_program_from_shaders(shaders, 3, &resources->programs[TERRAIN_PROGRAM]);
assert(ok && "terrain program");
check_gl();
@@ -195,7 +200,7 @@ void render (struct game *game, struct render_config *config) {
glClearColor( gtmp[0], gtmp[1], gtmp[2], 1.0 ); //clear background screen to black
/* glClearColor( 0.5294f * adjust, 0.8078f * adjust, 0.9216f * adjust, 1.0f ); //clear background screen to black */
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
- glEnable(GL_CULL_FACE);
+ /* glEnable(GL_CULL_FACE); */
check_gl();
@@ -239,11 +244,11 @@ void render (struct game *game, struct render_config *config) {
if (config->is_depth_pass) {
mat4_multiply(bias_matrix, view_proj, config->depth_mvp);
- glCullFace(GL_FRONT);
+ glCullFace(GL_FRONT);
}
else {
glUniformMatrix4fv(res->uniforms.depth_mvp, 1, 0, config->depth_mvp);
- glCullFace(GL_BACK);
+ glCullFace(GL_BACK);
}
glUniform3f(res->uniforms.camera_position,
@@ -261,7 +266,7 @@ void render (struct game *game, struct render_config *config) {
res->sun_color[0],
res->sun_color[1],
res->sun_color[2]);
-
+
mat4_multiply(view_proj, entity->node.mat, mvp);
mat4_copy(entity->node.mat, model_view);
diff --git a/src/shader.c b/src/shader.c
@@ -112,6 +112,7 @@ int make_shader(GLenum type, const char *filename, struct shader *shader) {
return 1;
}
+#define N_SHADERS 3
#ifdef DEBUG
int reload_program(struct gpu_program *program) {
@@ -120,96 +121,87 @@ int reload_program(struct gpu_program *program) {
time_t frag_mtime, vert_mtime;
int ok;
- vert_mtime = file_mtime(program->vertex.filename);
- frag_mtime = file_mtime(program->fragment.filename);
+ int n_shaders = program->n_shaders;
+ struct shader new_shaders[n_shaders];
+ struct shader *new_shaders_p[n_shaders];
- int vert_changed =
- vert_mtime != program->vertex.load_mtime;
+ int changes[n_shaders];
- int frag_changed =
- frag_mtime != program->fragment.load_mtime;
+ for (int i = 0; i < n_shaders; i++) {
+ new_shaders_p[i] = &new_shaders[i];
+ changes[i] = 0;
+ struct shader *shader = &program->shaders[i];
- for (int i = 0; i < program->vertex.n_includes; ++i) {
- time_t include_mtime = program->vertex.include_mtimes[i];
- time_t new_mtime = file_mtime(program->vertex.includes[i]);
- vert_changed |= include_mtime != new_mtime;
- }
-
- for (int i = 0; i < program->fragment.n_includes; ++i) {
- time_t include_mtime = program->fragment.include_mtimes[i];
- frag_changed |= include_mtime != file_mtime(program->fragment.includes[i]);
- }
-
- if (!vert_changed && !frag_changed)
- return 2;
-
- // recompile vertex shader
- if (vert_changed) {
- glDeleteShader(program->vertex.handle);
-
- ok =
- make_shader(GL_VERTEX_SHADER,
- program->vertex.filename,
- &vert);
+ if (!shader)
+ continue;
- if (!ok)
- return 0;
- }
-
- // recompile fragment shader
- if (frag_changed) {
- glDeleteShader(program->fragment.handle);
+ time_t mtime = file_mtime(shader->filename);
+ int changed = mtime != shader->load_mtime;
- ok =
- make_shader(GL_FRAGMENT_SHADER,
- program->fragment.filename,
- &frag);
+ for (int j = 0; i < shader->n_includes; ++j) {
+ time_t include_mtime = shader->include_mtimes[j];
+ time_t new_mtime = file_mtime(shader->includes[j]);
+ changed |= mtime != new_mtime;
+ }
+
+ changes[i] = changed;
+
+ if (changed) {
+ GLuint old_handle = shader->handle;
+
+ ok = make_shader(shader->type, shader->filename, &new_shaders[i]);
+ if (!ok) {
+ // clean up all the new shaders we've created so far
+ for (int k = 0; k < i; k++)
+ glDeleteShader(new_shaders[k].handle);
+ return 0;
+ }
+ }
+ }
- if (!ok)
- return 0;
- }
+ int any_changes = 0;
+ for (int i = 0; i < n_shaders; i++)
+ any_changes |= changes[i];
- if (vert_changed) {
- glDeleteShader(program->vertex.handle);
- pvert = |
- vert.load_mtime = vert_mtime;
- }
- else
- pvert = &program->vertex;
+ if (!any_changes)
+ return 2;
- if (frag_changed) {
- glDeleteShader(program->fragment.handle);
- pfrag = &frag;
- frag.load_mtime = frag_mtime;
- }
- else
- pfrag = &program->fragment;
+ // delete old shaders
+ for (int i = 0; i < n_shaders; i++) {
+ glDeleteShader(program->shaders[i].handle);
+ }
glDeleteProgram(program->handle);
- make_program(pvert, pfrag, program);
-
- return 1;
+ // TODO: cleanup failed make_program?
+ return make_program_from_shaders(new_shaders_p, n_shaders, program);
}
#endif
int
-make_program(struct shader *vertex, struct shader *fragment,
- struct gpu_program *program)
+make_program(struct shader *vertex,
+ struct shader *fragment,
+ struct gpu_program *program)
+{
+ struct shader *shaders[] = { vertex, fragment };
+ return make_program_from_shaders(shaders, 2, program);
+}
+
+int
+make_program_from_shaders(struct shader **shaders, int n_shaders, struct gpu_program *program)
{
GLint program_ok;
// TODO: relax these constraints
- assert(vertex);
- assert(fragment);
-
program->handle = glCreateProgram();
- program->fragment = *fragment;
- program->vertex = *vertex;
+ assert(n_shaders <= MAX_SHADERS);
+ for (int i = 0; i < n_shaders; i++) {
+ program->shaders[i] = *shaders[i];
+ struct shader *shader = &program->shaders[i];
- glAttachShader(program->handle, vertex->handle);
- glAttachShader(program->handle, fragment->handle);
+ glAttachShader(program->handle, shader->handle);
+ }
glLinkProgram(program->handle);
diff --git a/src/shader.h b/src/shader.h
@@ -7,7 +7,8 @@
#define SHADER(f) "etc/shaders/" f
#define MAX_SHADER_INCLUDES 8
-#define MAX_INCLUDE_FNAME_LEN 32
+#define MAX_INCLUDE_FNAME_LEN 48
+#define MAX_SHADERS 5
struct shader {
GLenum type;
@@ -20,16 +21,21 @@ struct shader {
};
struct gpu_program {
- struct shader vertex;
- struct shader fragment;
+ struct shader shaders[MAX_SHADERS];
+ int n_shaders;
GLuint handle;
};
+#define NO_GEOM_SHADER NULL
int reload_program(struct gpu_program *program);
int make_shader(GLenum type, const char *filename, struct shader *shader);
+int make_program_from_shaders(struct shader **shaders,
+ int n_shaders,
+ struct gpu_program *program);
+
int make_program(struct shader *vertex,
struct shader *fragment,
struct gpu_program *program);
diff --git a/src/terrain.c b/src/terrain.c
@@ -143,8 +143,10 @@ terrain_create(struct terrain *terrain) {
/* vec3_subtract(v[1], c, tmp1); */
/* vec3_subtract(v[2], c, tmp2); */
+ // standard normals
vec3_subtract(v[1], v[0], tmp1);
vec3_subtract(v[2], v[0], tmp2);
+
vec3_cross(tmp1, tmp2, tmp2);
vec3_normalize(tmp2, tmp2);
diff --git a/src/update.c b/src/update.c
@@ -194,13 +194,9 @@ static int try_reload_shaders(struct resources *res) {
if (ret == 2) {}
else if (ret == 1)
- printf("reload %s + %s success.\n",
- program->vertex.filename,
- program->fragment.filename);
+ printf("reload %s success.\n", program->shaders[0].filename);
else
- printf("reload %s + %s failed.\n",
- program->vertex.filename,
- program->fragment.filename);
+ printf("reload %s failed.\n", program->shaders[0].filename);
// failure ok, clear any errors
glGetError();