commit 0a836ee9e2e9afcd5b5d9896c4f37899a85013c6
parent bc3dcbe74ab4c77aff83896addf26e9e4dff2e25
Author: William Casarin <jb55@jb55.com>
Date: Sun, 10 May 2020 01:29:41 -0700
finally fix shader crashes
Signed-off-by: William Casarin <jb55@jb55.com>
Diffstat:
8 files changed, 167 insertions(+), 186 deletions(-)
diff --git a/src/game.c b/src/game.c
@@ -111,20 +111,16 @@ void init_misc(struct game *game, int width, int height) {
};
create_ui(&game->ui, width, height, &res->programs[UI_PROGRAM]);
-
check_gl();
init_terrain(terrain, size);
- int seed;
/* terrain->samples = load_samples(&seed, &terrain->n_samples); */
terrain->n_samples = 0;
create_terrain(terrain, size, game->seed);
/* update_terrain(terrain, terrain->cell_size); */
-
/* get_entity(&terrain->entity_id)->flags |= ENT_INVISIBLE; */
- create_skybox(&res->skybox, &res->programs[SKYBOX_PROGRAM]);
- /* node_translate(&res->skybox.node, V3(-100.0, -100.0, 0.0)); */
+ create_skybox(&res->skybox, &res->programs[SKYBOX_PROGRAM]); /* node_translate(&res->skybox.node, V3(-100.0, -100.0, 0.0)); */
/* node_scale(&res->skybox.node, size/4.0); */
mat4_id(mvp);
diff --git a/src/game.h b/src/game.h
@@ -27,29 +27,7 @@ struct resources {
struct vbo vertex_buffer, element_buffer, normal_buffer;
struct fbo shadow_buffer;
- struct gpu_program programs[NUM_PROGRAMS];
-
- struct uniforms {
- GLint ambient_str;
- GLint camera_position;
- GLint depth_mvp;
- GLint depth_vp;
- GLint diffuse_on;
- GLint fog_on;
- GLint light_dir;
- GLint light_intensity;
- GLint model;
- GLint model_view;
- GLint mvp;
- GLint normal_matrix;
- GLint sky_intensity;
- GLint piece_color;
- GLint sun_color;
- GLint time;
- GLint view_proj;
- } uniforms;
-
- gpu_addr vertex_attrs[MAX_VERTEX_ATTRS];
+ struct gpu_program programs[MAX_PROGRAMS];
node_id root_id;
entity_id player_id;
diff --git a/src/model.h b/src/model.h
@@ -18,12 +18,12 @@
typedef struct resource_id model_id;
enum program_type {
- DEFAULT_PROGRAM,
- TERRAIN_PROGRAM,
- UI_PROGRAM,
- SKYBOX_PROGRAM,
- CHESS_PIECE_PROGRAM,
- NUM_PROGRAMS,
+ DEFAULT_PROGRAM,
+ TERRAIN_PROGRAM,
+ UI_PROGRAM,
+ SKYBOX_PROGRAM,
+ CHESS_PIECE_PROGRAM,
+ NUM_PROGRAMS,
};
diff --git a/src/render.c b/src/render.c
@@ -62,8 +62,33 @@ static const float bias_matrix[] = {
0.5, 0.5, 0.5, 1.0
};
-void
-init_gl(struct resources *resources, int width, int height) {
+static void add_attribute(struct gpu_program *program,
+ const char *name,
+ enum vertex_attr attr)
+{
+ int id = program->vertex_attrs[attr] =
+ (gpu_addr)glGetAttribLocation(program->handle, name);
+ /* assert(id != -1); */
+ check_gl();
+}
+
+static void add_uniform(struct gpu_program *program,
+ const char *name,
+ enum uniform_id id)
+{
+ struct uniform *var = &program->uniforms[id];
+ var->name = name;
+ var->id = id;
+ var->location = glGetUniformLocation(program->handle, var->name);
+ if (var->location == -1) {
+ debug("warn: could not find uniform location: %s in program %s\n",
+ var->name, program->name);
+ }
+ /* assert(var->location != -1); */
+ check_gl();
+}
+
+void init_gl(struct resources *resources, int width, int height) {
struct shader vertex, terrain_vertex, chess_piece_vertex, terrain_geom, fragment, fragment_smooth;
struct shader terrain_teval, terrain_tc;
float tmp_matrix[16];
@@ -77,7 +102,8 @@ init_gl(struct resources *resources, int width, int height) {
check_gl();
// Shaders
- ok = make_shader(GL_VERTEX_SHADER, SHADER("vertex-color.glsl"), &vertex);
+ ok = make_shader(GL_VERTEX_SHADER, SHADER("vertex-color.glsl"),
+ &vertex);
rtassert(ok, "vertex-color shader");
ok = make_shader(GL_VERTEX_SHADER, SHADER("terrain.v.glsl"), &terrain_vertex);
@@ -102,113 +128,56 @@ init_gl(struct resources *resources, int width, int height) {
struct shader *terrain_shaders[] =
{ &terrain_vertex, &fragment };
- ok = make_program_from_shaders(terrain_shaders, ARRAY_SIZE(terrain_shaders),
- &resources->programs[TERRAIN_PROGRAM]);
+ struct gpu_program *programs = resources->programs;
+ struct gpu_program *program;
+ ok = make_program("terrain", &terrain_vertex, &fragment,
+ &programs[TERRAIN_PROGRAM]);
// TODO: replace rtassert with error reporting/handling
rtassert(ok, "terrain program");
check_gl();
- ok = make_program(&vertex, &fragment, &resources->programs[DEFAULT_PROGRAM]);
+ ok = make_program("vertex-color", &vertex, &fragment, &programs[DEFAULT_PROGRAM]);
rtassert(ok, "vertex-color program");
check_gl();
- ok = make_program(&chess_piece_vertex, &fragment, &resources->programs[CHESS_PIECE_PROGRAM]);
+ program = &programs[CHESS_PIECE_PROGRAM];
+ ok = make_program("chess-piece", &chess_piece_vertex, &fragment, program);
rtassert(ok, "chess-piece program");
- check_gl();
+ add_uniform(program, "piece_color", UNIFORM_PIECE_COLOR);
- // Program variables
- GLuint programs[] =
- { resources->programs[TERRAIN_PROGRAM].handle
- , resources->programs[DEFAULT_PROGRAM].handle
- , resources->programs[CHESS_PIECE_PROGRAM].handle
- };
+ struct uniform *var;
+ for (int i = 0; i < NUM_PROGRAMS; ++i) {
+ struct gpu_program *program = &programs[i];
+ if (program == NULL) {
+ debug("program %d is NULL\n", i);
+ continue;
+ }
- // uniforms shared between all shaders
- for (size_t i = 0; i < ARRAY_SIZE(programs); ++i) {
- GLuint handle = programs[i];
+ if (program->name == NULL) {
+ debug("program %d name is NULL, not initialized?\n", i);
+ continue;
+ }
// Program variables
- resources->uniforms.camera_position =
- glGetUniformLocation(handle, "camera_position");
- check_gl();
-
- // TODO: more flexible uniforms
- resources->uniforms.piece_color = glGetUniformLocation(handle, "piece_color");
- check_gl();
-
- /* resources->uniforms.depth_vp = */
- /* glGetUniformLocation(handle, "depth_vp"); */
- /* check_gl(); */
-
- resources->uniforms.depth_mvp =
- glGetUniformLocation(handle, "depth_mvp");
- check_gl();
- resources->uniforms.camera_position =
- glGetUniformLocation(handle, "camera_position");
- check_gl();
-
-
- resources->uniforms.light_intensity =
- glGetUniformLocation(handle, "light_intensity");
- check_gl();
-
- resources->uniforms.sky_intensity =
- glGetUniformLocation(handle, "sky_intensity");
- check_gl();
-
- resources->uniforms.time =
- glGetUniformLocation(handle, "time");
- check_gl();
-
- resources->uniforms.light_dir =
- glGetUniformLocation(handle, "light_dir");
- check_gl();
-
- resources->uniforms.sun_color =
- glGetUniformLocation(handle, "sun_color");
- check_gl();
-
- resources->uniforms.fog_on =
- glGetUniformLocation(handle, "fog_on");
- check_gl();
-
- /* resources->uniforms.diffuse_on = */
- /* glGetUniformLocation(handle, "diffuse_on"); */
- /* check_gl(); */
-
- resources->uniforms.model =
- glGetUniformLocation(handle, "model");
- check_gl();
-
- resources->uniforms.mvp =
- glGetUniformLocation(handle, "mvp");
- check_gl();
-
- /* resources->uniforms.model_view = */
- /* glGetUniformLocation(handle, "model_view"); */
-
- resources->uniforms.normal_matrix =
- glGetUniformLocation(handle, "normal_matrix");
- check_gl();
-
- resources->vertex_attrs[va_normal] =
- (gpu_addr)glGetAttribLocation(handle, "normal");
- check_gl();
-
- resources->vertex_attrs[va_position] =
- (gpu_addr)glGetAttribLocation(handle, "position");
- check_gl();
-
+ add_uniform(program, "camera_position", UNIFORM_CAMERA_POSITION);
+ add_uniform(program, "depth_mvp", UNIFORM_DEPTH_MVP);
+ add_uniform(program, "light_intensity", UNIFORM_LIGHT_INTENSITY);
+ add_uniform(program, "sky_intensity", UNIFORM_SKY_INTENSITY);
+ add_uniform(program, "time", UNIFORM_TIME);
+ add_uniform(program, "light_dir", UNIFORM_LIGHT_DIR);
+ add_uniform(program, "sun_color", UNIFORM_SUN_COLOR);
+ add_uniform(program, "fog_on", UNIFORM_FOG_ON);
+ add_uniform(program, "model", UNIFORM_MODEL);
+ add_uniform(program, "mvp", UNIFORM_MVP);
+ add_uniform(program, "normal_matrix", UNIFORM_NORMAL_MATRIX);
+
+ // Attributes
+ add_attribute(program, "normal", va_normal);
+ add_attribute(program, "position", va_position);
+ add_attribute(program, "color", va_color);
}
- // TODO: auto-generate these somehow?
- resources->vertex_attrs[va_color] =
- (gpu_addr)glGetAttribLocation(resources->programs[DEFAULT_PROGRAM]
- .handle, "color");
-
- /* assert(resources->attributes.color != 0xFFFFFFFF); */
- check_gl();
}
@@ -227,6 +196,34 @@ static void gamma_correct(float *c, float *d) {
d[2] = powf(c[2], gamma);
}
+static inline void uniform_3f(struct gpu_program *program,
+ enum uniform_id id, const float *v3)
+{
+ glUniform3f(program->uniforms[id].location, v3[0], v3[1], v3[2]);
+ check_gl();
+}
+
+static inline void uniform_1i(struct gpu_program *program,
+ enum uniform_id id, int i)
+{
+ glUniform1i(program->uniforms[id].location, i);
+ check_gl();
+}
+
+static inline void uniform_m4f(struct gpu_program *program,
+ enum uniform_id id, float *m)
+{
+ glUniformMatrix4fv(program->uniforms[id].location, 1, 0, m);
+ check_gl();
+}
+
+static inline void uniform_1f(struct gpu_program *program,
+ enum uniform_id id, float f)
+{
+ glUniform1f(program->uniforms[id].location, f);
+ check_gl();
+}
+
void render (struct game *game, struct render_config *config) {
float gtmp[3];
struct resources *res = &game->test_resources;
@@ -264,7 +261,7 @@ void render (struct game *game, struct render_config *config) {
struct entity *entities =
get_all_entities(&num_entities, NULL);
- struct gpu_program *current_program = NULL;
+ struct gpu_program *program = NULL;
mat4_inverse((float*)camera, view);
mat4_multiply(projection, view, view_proj);
@@ -290,6 +287,8 @@ void render (struct game *game, struct render_config *config) {
struct entity *entity = &entities[i];
struct model *model = get_model(&entity->model_id);
assert(model);
+ struct node *node = get_node(&entity->node_id);
+ assert(node);
if (entity->flags & ENT_INVISIBLE)
continue;
@@ -297,65 +296,41 @@ void render (struct game *game, struct render_config *config) {
if (config->is_depth_pass && !(entity->flags & ENT_CASTS_SHADOWS))
continue;
- current_program = &game->test_resources.programs[model->shader];
+ program = &game->test_resources.programs[model->shader];
- glUseProgram(current_program->handle);
+ glUseProgram(program->handle);
check_gl();
- glUniform3f(res->uniforms.camera_position,
- camera[M_X],
- camera[M_Y],
- camera[M_Z]);
- check_gl();
-
- if (entity->flags & ENT_IS_WHITE)
- glUniform3f(res->uniforms.piece_color, 0.9f, 0.9f, 0.9f);
- else
- glUniform3f(res->uniforms.piece_color, 0.2f, 0.2f, 0.2f);
- check_gl();
-
- glUniform1i(res->uniforms.fog_on, res->fog_on);
- check_gl();
+ uniform_3f(program, UNIFORM_CAMERA_POSITION, &camera[M_X]);
- glUniform3f(res->uniforms.light_dir, light[0], light[1], light[2]);
- check_gl();
+ if (model->shader == CHESS_PIECE_PROGRAM) {
+ if (entity->flags & ENT_IS_WHITE)
+ uniform_3f(program, UNIFORM_PIECE_COLOR, V3(0.9f, 0.9f, 0.9f));
+ else
+ uniform_3f(program, UNIFORM_PIECE_COLOR, V3(0.2f, 0.2f, 0.2f));
+ }
- glUniform1f(res->uniforms.light_intensity, res->light_intensity);
- check_gl();
-
- glUniform1f(res->uniforms.sky_intensity, sky_intensity);
- check_gl();
-
- glUniform3f(res->uniforms.sun_color,
- res->sun_color[0],
- res->sun_color[1],
- res->sun_color[2]);
- check_gl();
-
- struct node *node = get_node(&entity->node_id);
- assert(node);
- if (node == NULL)
- return;
+ uniform_1i(program, UNIFORM_FOG_ON, res->fog_on);
+ uniform_3f(program, UNIFORM_LIGHT_DIR, light);
+ uniform_1f(program, UNIFORM_LIGHT_INTENSITY, res->light_intensity);
+ uniform_1f(program, UNIFORM_SKY_INTENSITY, sky_intensity);
+ uniform_3f(program, UNIFORM_SUN_COLOR, res->sun_color);
mat4_multiply(view_proj, node->mat, mvp);
mat4_copy(node->mat, model_view);
mat4_multiply(config->depth_vp, model_view, depth_mvp);
- glUniformMatrix4fv(res->uniforms.depth_mvp, 1, 0, depth_mvp);
- check_gl();
-
- glUniformMatrix4fv(res->uniforms.mvp, 1, 0, mvp);
- check_gl();
-
- glUniformMatrix4fv(res->uniforms.model, 1, 0, node->mat);
- check_gl();
+ uniform_m4f(program, UNIFORM_DEPTH_MVP, depth_mvp);
+ uniform_m4f(program, UNIFORM_MVP, mvp);
+ uniform_m4f(program, UNIFORM_MODEL, node->mat);
- recalc_normals(res->uniforms.normal_matrix, model_view, normal_matrix);
+ recalc_normals(program->uniforms[UNIFORM_NORMAL_MATRIX].location,
+ model_view, normal_matrix);
check_gl();
struct geometry *geo = get_geometry(&model->geom_id);
/* debug("geo node %s\n", node->label); */
assert(geo);
- render_geometry(geo, res->vertex_attrs, current_program);
+ render_geometry(geo, program->vertex_attrs, program);
check_gl();
}
diff --git a/src/shader.c b/src/shader.c
@@ -199,7 +199,8 @@ int reload_program(struct gpu_program *program) {
return 2;
}
- ok = make_program_from_shaders(new_shaders_p, n_shaders, &new_program);
+ ok = make_program_from_shaders(program->name, new_shaders_p,
+ n_shaders, &new_program);
if (!ok) {
for (int i = 0; i < n_shaders; i++) {
@@ -214,16 +215,17 @@ int reload_program(struct gpu_program *program) {
#endif
int
-make_program(struct shader *vertex,
+make_program(const char *name,
+ struct shader *vertex,
struct shader *fragment,
struct gpu_program *program)
{
struct shader *shaders[] = { vertex, fragment };
- return make_program_from_shaders(shaders, 2, program);
+ return make_program_from_shaders(name, shaders, 2, program);
}
-int
-make_program_from_shaders(struct shader **shaders, int n_shaders, struct gpu_program *program)
+int make_program_from_shaders(const char *name, struct shader **shaders,
+ int n_shaders, struct gpu_program *program)
{
GLint program_ok;
@@ -231,6 +233,7 @@ make_program_from_shaders(struct shader **shaders, int n_shaders, struct gpu_pro
program->handle = glCreateProgram();
check_gl();
program->n_shaders = n_shaders;
+ program->name = name;
assert(n_shaders <= MAX_SHADERS);
for (int i = 0; i < n_shaders; i++) {
diff --git a/src/shader.h b/src/shader.h
@@ -3,13 +3,13 @@
#include <time.h>
#include "gl.h"
+#include "vbo.h"
#define SHADER(f) "etc/shaders/" f
#define MAX_SHADER_INCLUDES 16
#define MAX_INCLUDE_FNAME_LEN 64
#define MAX_SHADERS 5
-#define MAX_UNIFORMS 32
struct shader {
GLenum type;
@@ -21,10 +21,40 @@ struct shader {
time_t load_mtime;
};
+enum uniform_id {
+ UNIFORM_AMBIENT_STR,
+ UNIFORM_CAMERA_POSITION,
+ UNIFORM_DEPTH_MVP,
+ UNIFORM_DEPTH_VP,
+ UNIFORM_DIFFUSE_ON,
+ UNIFORM_FOG_ON,
+ UNIFORM_LIGHT_DIR,
+ UNIFORM_LIGHT_INTENSITY,
+ UNIFORM_MODEL,
+ UNIFORM_MODEL_VIEW,
+ UNIFORM_MVP,
+ UNIFORM_NORMAL_MATRIX,
+ UNIFORM_SKY_INTENSITY,
+ UNIFORM_SUN_COLOR,
+ UNIFORM_TIME,
+ UNIFORM_VIEW_PROJ,
+ UNIFORM_PIECE_COLOR,
+ MAX_UNIFORMS
+};
+
+struct uniform {
+ enum uniform_id id;
+ const char *name;
+ int location;
+};
+
struct gpu_program {
struct shader shaders[MAX_SHADERS];
+ struct uniform uniforms[MAX_UNIFORMS];
+ gpu_addr vertex_attrs[MAX_VERTEX_ATTRS];
int n_shaders;
GLuint handle;
+ const char *name;
};
#define NO_GEOM_SHADER NULL
@@ -33,14 +63,13 @@ int reload_program(struct gpu_program *program);
int make_shader(GLenum type, const char *filename, struct shader *shader);
void init_gpu_program(struct gpu_program *program);
-int make_program_from_shaders(struct shader **shaders,
+int make_program_from_shaders(const char *name,
+ 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);
+int make_program(const char *name, struct shader *vertex, struct shader *fragment, struct gpu_program *program);
#endif /* POLYADVENT_SHADER_H */
diff --git a/src/skybox.c b/src/skybox.c
@@ -86,7 +86,7 @@ void create_skybox(struct skybox *skybox, struct gpu_program *program) {
make_shader(GL_FRAGMENT_SHADER, SHADER("skybox.f.glsl"), &frag);
check_gl();
- ok = make_program_from_shaders(shaders, 2, skybox->program);
+ ok = make_program("skybox", &vertex, &frag, skybox->program);
assert(ok);
check_gl();
diff --git a/src/ui.c b/src/ui.c
@@ -106,7 +106,7 @@ void create_ui(struct ui *ui, int width, int height, struct gpu_program *shader)
ok = make_shader(GL_FRAGMENT_SHADER, SHADER("ui.f.glsl"), &fragment);
assert(ok && "ui fragment shader");
- ok = make_program(&vertex, &fragment, ui->shader);
+ ok = make_program("ui", &vertex, &fragment, ui->shader);
assert(ok && "ui program");
GLuint program = ui->shader->handle;