commit 48c9d306969745e809ede5865a1bdd88d2f02f85
parent 2848cdbace72999a9e453f9f487ffdc8bb3d402e
Author: William Casarin <jb55@jb55.com>
Date: Fri, 2 Nov 2018 17:35:39 -0700
bunch of stuff, fixed shader reloading
Diffstat:
18 files changed, 157 insertions(+), 125 deletions(-)
diff --git a/Makefile b/Makefile
@@ -2,7 +2,7 @@ NAME ?= polyadvent
BIN ?= $(NAME)
PREFIX ?= /usr/local
DEFS= -DGLFW_INCLUDE_NONE -DDEBUG
-CFLAGS = $(DEFS) -ggdb -Ofast -I src -Wall -Werror -Wextra -std=c99 \
+CFLAGS = $(DEFS) -ggdb -O -I src -Wall -Werror -Wextra -std=c99 \
-Wno-unused-function \
-Wno-unused-parameter \
-Wno-unused-variable \
diff --git a/etc/shaders/profile b/etc/shaders/profile
@@ -1 +1,2 @@
+
#version 440 core
diff --git a/etc/shaders/shadervars.glsl b/etc/shaders/shadervars.glsl
@@ -4,11 +4,3 @@ vec3 normal;
vec3 position;
vec4 shadow_coord;
vec3 frag_pos;
-
-// out flat vec3 v_color;
-// out vec3 v_color_smooth;
-// out vec3 v_ray;
-// out vec3 v_normal;
-// out vec3 v_position;
-// out vec4 v_shadow_coord;
-// out vec3 v_frag_pos;
diff --git a/etc/shaders/standard_vtxos.glsl b/etc/shaders/standard_vtxos.glsl
@@ -1,6 +1,5 @@
vec4 v4_pos = vec4(position, 1.0);
-vertex.normal = normal;
-vertex.color_smooth = vertex.color = color;
-vertex.shadow_coord = depth_mvp * v4_pos;
-vertex.position = v4_pos.xyz;
-vertex.frag_pos = (world * v4_pos).xyz;
+data_out.normal = normal;
+data_out.color_smooth = data_out.color = color;
+data_out.shadow_coord = depth_mvp * v4_pos;
+data_out.frag_pos = (world * v4_pos).xyz;
diff --git a/etc/shaders/terrain.g.glsl b/etc/shaders/terrain.g.glsl
@@ -28,9 +28,8 @@ void main() {
// vertex.shadow_coord = vertices[i].shadow_coord;
// vertex.frag_pos = vertices[i].frag_pos;
- gl_Position = mvp * gl_in[i].gl_Position;
- vertex.position = gl_Position.xyz;
- // gl_Position = vec4(vertices[i].position, 1.0);
+ // gl_Position = mvp * vec4(400.0 + i * 50.0, 300.0 + i * 50.0, 200.0 + i * 50.0, 1.0);
+ gl_Position = mvp * vec4(vertices[i].position, 1.0);
EmitVertex();
}
diff --git a/etc/shaders/terrain.tc.glsl b/etc/shaders/terrain.tc.glsl
@@ -2,15 +2,15 @@
layout(vertices = 3) out;
-in shader_datab {
+in shader_data {
#include shadervars.glsl
-} vertex[];
+} data_in[];
-out shader_dataz {
+out shader_data {
#include shadervars.glsl
-} tc_vertices[];
+} data_out[];
-#include uniforms.glsl
+// #include uniforms.glsl
// uniform float TessLevelInner;
// uniform float TessLevelOuter;
@@ -18,18 +18,21 @@ out shader_dataz {
void main()
{
- tc_vertices[gl_InvocationID].position = vertex[gl_InvocationID].position;
- tc_vertices[gl_InvocationID].color = vertex[gl_InvocationID].color;
- tc_vertices[gl_InvocationID].color_smooth = vertex[gl_InvocationID].color_smooth;
- tc_vertices[gl_InvocationID].normal = vertex[gl_InvocationID].normal;
-
- gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
- const float inner = 5.0;
- const float outer = 8.0;
+
+ // gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
+ const float inner = 1.0;
+ const float outer = 2.0;
+
if (gl_InvocationID == 0) {
gl_TessLevelInner[0] = inner;
gl_TessLevelOuter[0] = outer;
gl_TessLevelOuter[1] = outer;
gl_TessLevelOuter[2] = outer;
}
+
+ // data_out[gl_InvocationID] = data_in[gl_InvocationID];
+ data_out[gl_InvocationID].position = data_in[gl_InvocationID].position;
+ data_out[gl_InvocationID].color = data_in[gl_InvocationID].color;
+ data_out[gl_InvocationID].color_smooth = data_in[gl_InvocationID].color_smooth;
+ data_out[gl_InvocationID].normal = data_in[gl_InvocationID].normal;
}
diff --git a/etc/shaders/terrain.te.glsl b/etc/shaders/terrain.te.glsl
@@ -2,13 +2,13 @@
layout(triangles, equal_spacing, cw) in;
-in shader_dataz {
+in shader_data {
#include shadervars.glsl
-} tc_vertices[];
+} data_in[];
out shader_data {
#include shadervars.glsl
-} vertex;
+} data_out;
#include uniforms.glsl
@@ -18,16 +18,17 @@ out shader_data {
void main()
{
- vertex.color = tc_vertices[0].color;
- vertex.color_smooth = tc_vertices[0].color_smooth;
- vertex.normal = tc_vertices[0].normal;
- vertex.shadow_coord = depth_mvp * tc_vertices[0].shadow_coord;
-
- vec4 v = gl_TessCoord.x * gl_in[0].gl_Position;
- + gl_TessCoord.y * gl_in[1].gl_Position;
- + gl_TessCoord.z * gl_in[2].gl_Position;
+ vec4 v = gl_TessCoord.x * vec4(data_in[0].position, 1.0);
+ + gl_TessCoord.y * vec4(data_in[1].position, 1.0);
+ + gl_TessCoord.z * vec4(data_in[2].position, 1.0);
// tePatchDistance = gl_TessCoord;
- vertex.frag_pos = (world * v).xyz;
gl_Position = mvp * v;
- vertex.position = gl_Position.xyz;
+
+ data_out.position = gl_Position.xyz;
+ data_out.color = data_in[0].color;
+ data_out.color_smooth = data_in[0].color_smooth;
+ data_out.normal = data_in[0].normal;
+ data_out.shadow_coord = depth_mvp * data_in[0].shadow_coord;
+ data_out.frag_pos = (world * v).xyz;
+
}
diff --git a/etc/shaders/terrain.v.glsl b/etc/shaders/terrain.v.glsl
@@ -7,9 +7,11 @@ in vec3 normal;
#include uniforms.glsl
-out shader_datab {
+out shader_data {
+
#include shadervars.glsl
-} vertex;
+
+} data_out;
void main()
{
@@ -41,5 +43,5 @@ void main()
#include standard_vtxos.glsl
gl_Position = v4_pos;
- vertex.position = gl_Position.xyz;
+ data_out.position = gl_Position.xyz;
}
diff --git a/etc/shaders/test.f.glsl b/etc/shaders/test.f.glsl
@@ -1,3 +1,4 @@
+
#include profile
out vec4 frag_color;
@@ -23,11 +24,11 @@ void main() {
// + 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);
- // vec3 fog = depth_fog(color, shadow_sample);
- color = fog;
- }
+ // if (fog_on) {
+ // vec3 fog = apply_fog(color, length(v_ray), camera_position, v_ray);
+ // // vec3 fog = depth_fog(color, shadow_sample);
+ // color = fog;
+ // }
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));
diff --git a/etc/shaders/vertex-color.glsl b/etc/shaders/vertex-color.glsl
@@ -6,7 +6,7 @@ in vec3 color;
out shader_data {
#include shadervars.glsl
-} vertex;
+} data_out;
#include uniforms.glsl
@@ -14,6 +14,5 @@ out shader_data {
void main()
{
#include standard_vtxos.glsl
-
gl_Position = mvp * v4_pos;
}
diff --git a/src/game.c b/src/game.c
@@ -40,7 +40,7 @@ void game_init(struct game *game, int width, int height) {
mat4 *light_dir = res->light_dir;
int ok = 0;
- const double size = 10000;
+ const double size = 1000;
terrain->settings = (struct perlin_settings){
.depth = 1,
diff --git a/src/geometry.c b/src/geometry.c
@@ -43,10 +43,19 @@ void bind_geometry(struct geometry *geom, struct attributes *attrs) {
check_gl();
}
-void render_geometry(struct geometry *geom, struct attributes *attrs)
+void render_geometry(struct geometry *geom, struct attributes *attrs,
+ struct gpu_program *program)
{
+ int has_tess_shader =
+ get_program_shader(program, GL_TESS_EVALUATION_SHADER) != NULL;
+
+ int type = GL_TRIANGLES;
+ if (has_tess_shader) {
+ glPatchParameteri(GL_PATCH_VERTICES, 3);
+ type = GL_PATCHES;
+ }
bind_geometry(geom, attrs);
- glDrawElements(GL_TRIANGLES,
+ glDrawElements(type,
geom->num_indices, /* count */
GL_UNSIGNED_INT, /* type */
(void*)0 /* element array buffer offset */
diff --git a/src/geometry.h b/src/geometry.h
@@ -4,6 +4,7 @@
#include "common.h"
#include "buffer.h"
+#include "shader.h"
struct buffer_geometry {
struct vbo vertex;
@@ -24,7 +25,8 @@ struct geometry {
float *tex_coords;
};
-void render_geometry(struct geometry *geom, struct attributes *);
+void render_geometry(struct geometry *geom, struct attributes *,
+ struct gpu_program *current_program);
void bind_geometry(struct geometry *geom, struct attributes *);
void init_geometry(struct geometry *geom);
void make_buffer_geometry(struct geometry *geom);
diff --git a/src/render.c b/src/render.c
@@ -106,11 +106,11 @@ init_gl(struct resources *resources, int width, int height) {
/* { &terrain_vertex, &fragment, &terrain_tc, &terrain_teval, */
/* &terrain_geom }; */
- struct shader *terrain_shaders[] =
- { &terrain_vertex, &fragment, &terrain_tc, &terrain_teval };
-
/* struct shader *terrain_shaders[] = */
- /* { &terrain_vertex, &fragment, &terrain_geom }; */
+ /* { &terrain_vertex, &fragment, &terrain_tc, &terrain_teval }; */
+
+ struct shader *terrain_shaders[] =
+ { &terrain_vertex, &fragment, &terrain_geom };
/* struct shader *terrain_shaders[] = */
/* { &terrain_vertex, &fragment }; */
@@ -256,8 +256,13 @@ void render (struct game *game, struct render_config *config) {
, &game->test_resources.player
};
- int terrain_program = game->test_resources.programs[TERRAIN_PROGRAM].handle;
- int default_program = game->test_resources.programs[DEFAULT_PROGRAM].handle;
+ struct gpu_program *current_program = NULL;
+
+ struct gpu_program *terrain_program =
+ &game->test_resources.programs[TERRAIN_PROGRAM];
+
+ struct gpu_program *default_program =
+ &game->test_resources.programs[DEFAULT_PROGRAM];
for (size_t i = 0; i < ARRAY_SIZE(entities); ++i) {
struct entity *entity = entities[i];
@@ -265,10 +270,8 @@ void render (struct game *game, struct render_config *config) {
continue;
// TODO this is a bit wonky, refactor this
- if (i == 0)
- glUseProgram(terrain_program);
- else if (i == 1)
- glUseProgram(default_program);
+ current_program = i == 0 ? terrain_program : default_program;
+ glUseProgram(current_program->handle);
check_gl();
mat4_inverse(camera, view);
@@ -288,17 +291,14 @@ void render (struct game *game, struct render_config *config) {
camera[M_X],
camera[M_Y],
camera[M_Z]);
- printf("%d depth ? %d\n", (int)i, config->is_depth_pass);
glUniform1i(res->uniforms.fog_on, res->fog_on);
glUniform1i(res->uniforms.diffuse_on, res->diffuse_on);
glUniform3f(res->uniforms.light_dir, light[0], light[1], light[2]);
glUniform1f(res->uniforms.light_intensity, res->light_intensity);
check_gl();
- printf("light_intensity uniform %d\n", res->uniforms.light_intensity);
/* glUniform1f(res->uniforms.time, res->time); */
check_gl();
- printf("sky_intensity uniform %d\n", res->uniforms.sky_intensity);
glUniform1f(res->uniforms.sky_intensity, sky_intensity);
check_gl();
glUniform3f(res->uniforms.sun_color,
@@ -322,21 +322,8 @@ void render (struct game *game, struct render_config *config) {
recalc_normals(res->uniforms.normal_matrix, model_view, normal_matrix);
check_gl();
- if (i != 0) {
- render_geometry(&entity->model.geom, &res->attributes);
- check_gl();
- }
- else {
- glPatchParameteri(GL_PATCH_VERTICES, 3);
- check_gl();
- bind_geometry(&entity->model.geom, &res->attributes);
- check_gl();
- glDrawElements(GL_PATCHES,
- entity->model.geom.num_indices,
- GL_UNSIGNED_INT, 0);
- check_gl();
- }
-
+ render_geometry(&entity->model.geom, &res->attributes, current_program);
+ check_gl();
}
if (config->draw_ui)
diff --git a/src/shader.c b/src/shader.c
@@ -18,6 +18,17 @@ static int file_name_lens[MAX_SHADER_INCLUDES];
static char *line_buff[MAX_LINES];
static u32 line_lens[MAX_LINES];
+static char *cached_file_contents(const char *filename) {
+ size_t len;
+ for (int i = 0; i < file_buf_count; i++) {
+ if (memcmp(file_names[i], filename, file_name_lens[i]) == 0) {
+ return file_buffers[i];
+ }
+ }
+
+ return file_contents(filename, &len);
+}
+
static char *strsep(char **stringp, const char *delim) {
if (*stringp == NULL) { return NULL; }
char *token_start = *stringp;
@@ -27,13 +38,14 @@ static char *strsep(char **stringp, const char *delim) {
return token_start;
}
-static char **resolve_imports(char *contents, int *nlines) {
+static char **resolve_imports(char *contents, int *nlines, int level) {
char *line;
- size_t file_len;
+ int nline = 0;
char *resolved_contents;
- static char fname_buf[32];
+ char fname_buf[32] = {0};
while ((line = strsep(&contents, "\n"))) {
+ nline++;
int line_len = contents - line;
int size = sizeof("#include");
if (memcmp(line, "#include ", size) == 0) {
@@ -42,11 +54,15 @@ static char **resolve_imports(char *contents, int *nlines) {
snprintf(fname_buf, 32, SHADER("%.*s"), file_name_len, filename);
file_name_lens[file_buf_count] = file_name_len;
file_names[file_buf_count] = filename;
- /* printf("got include %s\n", fname_buf); */
+
+ /* printf("got include %.*s at line %d level %d ind %d\n", */
+ /* file_name_len, filename, nline, level, file_buf_count); */
+
// TODO (perf): cache file contents based on filename
- resolved_contents = file_contents(fname_buf, &file_len);
- file_buffers[file_buf_count++] = resolved_contents;
- resolve_imports(resolved_contents, nlines);
+ resolved_contents = cached_file_contents(fname_buf);
+ file_buffers[file_buf_count] = resolved_contents;
+ file_buf_count++;
+ resolve_imports(resolved_contents, nlines, level + 1);
}
else {
line_buff[*nlines] = line;
@@ -59,15 +75,28 @@ static char **resolve_imports(char *contents, int *nlines) {
return line_buff;
}
+
+struct shader *get_program_shader(struct gpu_program *program, GLenum type) {
+ struct shader *shader;
+ for (int i = 0; i < program->n_shaders; i++) {
+ shader = &program->shaders[i];
+ if (shader->type == type)
+ return shader;
+ }
+
+ return NULL;
+}
+
+
int make_shader(GLenum type, const char *filename, struct shader *shader) {
size_t length;
int nlines = 0;
- static char fname_buf[32];
GLchar *source = (GLchar *)file_contents(filename, &length);
if (!source)
return 0;
- char **lines = resolve_imports(source, &nlines);
+ assert(file_buf_count == 0);
+ char **lines = resolve_imports(source, &nlines, 0);
GLint shader_ok;
@@ -79,20 +108,21 @@ int make_shader(GLenum type, const char *filename, struct shader *shader) {
glShaderSource(shader->handle, nlines, (const char**)lines,
(const int*)line_lens);
- free(source);
-
// shader dependency stuff
for (int i = 0; i < file_buf_count; ++i) {
assert(i < MAX_SHADER_INCLUDES);
char *p = shader->includes[shader->n_includes];
int name_len = file_name_lens[i];
- assert(name_len < MAX_INCLUDE_FNAME_LEN);
+ /* printf("%.*s name len %d\n", name_len, file_names[i], name_len); */
snprintf(p, MAX_INCLUDE_FNAME_LEN, SHADER("%.*s"), name_len, file_names[i]);
+ assert(name_len < MAX_INCLUDE_FNAME_LEN);
shader->include_mtimes[shader->n_includes] = file_mtime(p);
- /* printf("including %s as dep of %s\n", p, name_len, shader->filename); */
+ /* printf("'%s' included in '%s'\n", p, shader->filename); */
shader->n_includes++;
free(file_buffers[i]);
}
+ free(source);
+
file_buf_count = 0;
glCompileShader(shader->handle);
@@ -116,39 +146,33 @@ int make_shader(GLenum type, const char *filename, struct shader *shader) {
#ifdef DEBUG
int reload_program(struct gpu_program *program) {
- struct shader vert, frag;
- struct shader *pvert, *pfrag;
- time_t frag_mtime, vert_mtime;
int ok;
int n_shaders = program->n_shaders;
+ struct gpu_program new_program;
struct shader new_shaders[n_shaders];
struct shader *new_shaders_p[n_shaders];
int changes[n_shaders];
for (int i = 0; i < n_shaders; i++) {
- new_shaders_p[i] = &new_shaders[i];
changes[i] = 0;
struct shader *shader = &program->shaders[i];
-
- if (!shader)
- continue;
+ new_shaders_p[i] = shader;
time_t mtime = file_mtime(shader->filename);
int changed = mtime != shader->load_mtime;
- for (int j = 0; i < shader->n_includes; ++j) {
+ for (int j = 0; j < 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;
+ changed |= include_mtime != new_mtime;
}
changes[i] = changed;
if (changed) {
- GLuint old_handle = shader->handle;
-
+ /* printf("making shader %s\n", shader->filename); */
ok = make_shader(shader->type, shader->filename, &new_shaders[i]);
if (!ok) {
// clean up all the new shaders we've created so far
@@ -156,6 +180,7 @@ int reload_program(struct gpu_program *program) {
glDeleteShader(new_shaders[k].handle);
return 0;
}
+ new_shaders_p[i] = &new_shaders[i];
}
}
@@ -163,18 +188,21 @@ int reload_program(struct gpu_program *program) {
for (int i = 0; i < n_shaders; i++)
any_changes |= changes[i];
- if (!any_changes)
+ if (!any_changes) {
return 2;
-
- // delete old shaders
- for (int i = 0; i < n_shaders; i++) {
- glDeleteShader(program->shaders[i].handle);
}
- glDeleteProgram(program->handle);
+ ok = make_program_from_shaders(new_shaders_p, n_shaders, &new_program);
+
+ if (!ok) {
+ for (int i = 0; i < n_shaders; i++) {
+ glDeleteShader(program->shaders[i].handle);
+ }
+ return 0;
+ }
- // TODO: cleanup failed make_program?
- return make_program_from_shaders(new_shaders_p, n_shaders, program);
+ *program = new_program;
+ return 1;
}
#endif
@@ -194,12 +222,18 @@ make_program_from_shaders(struct shader **shaders, int n_shaders, struct gpu_pro
// TODO: relax these constraints
program->handle = glCreateProgram();
+ program->n_shaders = n_shaders;
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, shaders[i]->handle);
+ struct shader *shader = shaders[i];
+ program->shaders[i] = *shader;
+ /* printf("attaching shader %s\n", shader->filename); */
+ /* for (int j = 0; j < shader->n_includes; ++j) { */
+ /* printf("attaching shader %s dep %s \n", shader->filename, */
+ /* shader->includes[j]); */
+ /* } */
+ glAttachShader(program->handle, shader->handle);
}
glLinkProgram(program->handle);
diff --git a/src/shader.h b/src/shader.h
@@ -6,8 +6,8 @@
#define SHADER(f) "etc/shaders/" f
-#define MAX_SHADER_INCLUDES 8
-#define MAX_INCLUDE_FNAME_LEN 48
+#define MAX_SHADER_INCLUDES 16
+#define MAX_INCLUDE_FNAME_LEN 64
#define MAX_SHADERS 5
struct shader {
@@ -36,6 +36,8 @@ int make_program_from_shaders(struct shader **shaders,
int n_shaders,
struct gpu_program *program);
+struct shader *get_program_shader(struct gpu_program *program, GLenum type);
+
int make_program(struct shader *vertex,
struct shader *fragment,
struct gpu_program *program);
diff --git a/src/ui.c b/src/ui.c
@@ -68,7 +68,7 @@ void render_ui(struct ui *ui, float *view) {
check_gl();
// render quad
- render_geometry(&ui->quad, &ui->attrs);
+ render_geometry(&ui->quad, &ui->attrs, ui->shader);
check_gl();
}
diff --git a/src/update.c b/src/update.c
@@ -39,10 +39,10 @@ static void movement(struct game *game, struct node *node, float speed_mult) {
if (game->input.keystates[SDL_SCANCODE_S])
node_forward(node, V3(0,-amt,0));
- if (game->input.keystates[SDL_SCANCODE_R])
+ if (game->input.keystates[SDL_SCANCODE_K])
node_translate(node, V3(0, 0,amt));
- if (game->input.keystates[SDL_SCANCODE_F])
+ if (game->input.keystates[SDL_SCANCODE_J])
node_translate(node, V3(0, 0,-amt));
if (game->input.keystates[SDL_SCANCODE_E])
@@ -188,6 +188,7 @@ static void player_movement(struct game *game) {
#ifdef DEBUG
static int try_reload_shaders(struct resources *res) {
int ret;
+ static int wut = 0;
for (int i = 0; i < NUM_PROGRAMS; ++i) {
struct gpu_program *program = &res->programs[i];
ret = reload_program(program);