diff --git a/src/client/client_imgui.cpp b/src/client/client_imgui.cpp index 7917956..834dc0c 100644 --- a/src/client/client_imgui.cpp +++ b/src/client/client_imgui.cpp @@ -106,6 +106,8 @@ int main(int argc, char** argv) const char* shader_list = "shaders/list.txt"; static struct ShaderRegistry shader_registry; loadShadersFromFile(shader_list, &shader_registry); + static std::vector shader_program_registry; + loadShaderProgramsFromFile("shaders/shader_programs.txt", &shader_registry, &shader_program_registry); messager.registerCallback(&debug_messagebus_callback); while(!glfwWindowShouldClose(window)) { glfwPollEvents(); diff --git a/src/common/shaderloader.hpp b/src/common/shaderloader.hpp index 470bfcf..9ee2393 100644 --- a/src/common/shaderloader.hpp +++ b/src/common/shaderloader.hpp @@ -7,11 +7,13 @@ #include #include #include +#include #include #include enum ShaderType { + invalid = 0, vertex = GL_VERTEX_SHADER, fragment = GL_FRAGMENT_SHADER, geometry = GL_GEOMETRY_SHADER, @@ -26,10 +28,21 @@ struct RegisteredShader { GLuint shaderID; } RegisteredShader; -struct RegisteredShaderProgram { +class RegisteredShaderProgram { char *programName; GLuint programID; -} RegisteredShaderProgram; +public: + RegisteredShaderProgram(char *name, GLuint programID) { + int name_size = strlen(name); + char *n = (char*) calloc(name_size, sizeof(char)); + strncpy(n, name, name_size); + this->programName = n; + this->programID = programID; + }; + ~RegisteredShaderProgram() { + free(this->programName); + } +}; struct ShaderRegistry { struct RegisteredShader *list = 0; @@ -62,7 +75,7 @@ struct RegisteredShader* find_shader(struct ShaderRegistry *r, char *name) { int i = 0; struct RegisteredShader *s = 0; for(i; i < r->size; i++) { - s = (r->list) + (i * sizeof(struct RegisteredShader)); + s = &r->list[i]; if(strcmp(s->shaderName, name) == 0) { return s; } @@ -96,10 +109,10 @@ void remove_shader_by_name(struct ShaderRegistry *r, char *name) { -struct ShaderProgramRegistry { +class ShaderProgramRegistry { struct RegisteredShareProgram *list = 0; int size = 0; -} ShaderProgramRegistry; +}; GLuint compile_shader(const char* file_path, int t) { @@ -136,10 +149,106 @@ GLuint compile_shader(const char* file_path, int t) { glGetShaderInfoLog(shader_id, InfoLogLength, NULL, &error_message[0]); printf("%s\n", &error_message[0]); } + else { + printf("compiled shader %d from source %s\n", shader_id, file_path); + } return shader_id; } +int loadShaderProgramsFromFile(const char* file_path, struct ShaderRegistry *shader_registry, + std::vector *program_registry) { + FILE *fp; + char *line; + size_t size = 0; + const char *delim = ":"; + const char *delim2 = ","; + fp = fopen(file_path, "r"); + if (fp == NULL) { + return -1; + } + char *name; + char *program_list; + char *file_path_copy = (char*) calloc(strlen(file_path), sizeof(char)); + strncpy(file_path_copy, file_path, strlen(file_path)); + char *base = dirname((char*) file_path_copy); + while((size = getline(&line, &size, fp)) != -1) { + if(size == 0) { + // Skipping, line length 0 + continue; + } + if(line[0] == '#') { + // Skipping, line is a comment + continue; + } + char *line_copy = (char*) calloc(size, sizeof(char*)); + strncpy(line_copy, line, size); + printf("%s\n", line_copy); + + // Format ,, + name = strtok(line_copy, delim); + program_list = strtok(NULL, delim); + printf("%s\n", program_list); + if (name == NULL || program_list == NULL) { + // Invalid line, not enough elements. + // @TODO Inform the user. + free(line_copy); + name = program_list = NULL; + continue; + } + + // Start a new Shader Program + char *program_list_copy = (char*) calloc(strlen(program_list), sizeof(char)); + strncpy(program_list_copy, program_list, strlen(program_list)); + char *new_line_pos = strrchr(program_list_copy, '\n'); + if (new_line_pos) { + new_line_pos[0] = 0; + } + printf("%s\n", program_list_copy); + char *shader_name = strtok(program_list_copy, delim2); + char *last_shader_name = NULL; + GLuint program = glCreateProgram(); + GLint Result = GL_FALSE; + do { + if (last_shader_name != NULL && shader_name == last_shader_name) { + shader_name = NULL; + break; + } + printf("sname %s ; last_shader %s\n", shader_name, last_shader_name); + struct RegisteredShader *rs = find_shader(shader_registry, shader_name); + if (rs == NULL) { + // Should this be an error, or a warning? + // @TODO Inform the user + printf("could not find shader '%s'", shader_name); + continue; + } + printf("linking program %d with shader %d\n", program, rs->shaderID); + glAttachShader(program, rs->shaderID); + last_shader_name = shader_name; + shader_name = strtok(NULL, delim2); + } + while (shader_name != NULL); + glLinkProgram(program); + // Check the program + int InfoLogLength; + glGetProgramiv(program, GL_LINK_STATUS, &Result); + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &InfoLogLength); + if (InfoLogLength > 0){ + std::vector ProgramErrorMessage(InfoLogLength+1); + glGetProgramInfoLog(program, InfoLogLength, NULL, &ProgramErrorMessage[0]); + printf("%s\n", &ProgramErrorMessage[0]); + } + + // Add to program_registry + if (InfoLogLength == 0) { + program_registry->push_back(RegisteredShaderProgram(name, program)); + } + free(program_list_copy); + free(line_copy); + } + return 0; +} + int loadShadersFromFile(const char* file_path, struct ShaderRegistry *registry) { FILE *fp; char *line; @@ -201,10 +310,10 @@ int loadShadersFromFile(const char* file_path, struct ShaderRegistry *registry) shader_type = geometry; } else { - shader_type = 0; + shader_type = invalid; } - if(shader_type == 0) { + if(shader_type == invalid) { // Invalid line, unknown type. // @TODO Inform the user. free(line_copy); diff --git a/src/shaders/fragmentRed.glsl b/src/shaders/fragmentRed.glsl index d010e6b..a2e45f2 100644 --- a/src/shaders/fragmentRed.glsl +++ b/src/shaders/fragmentRed.glsl @@ -1,5 +1,6 @@ #version 300 es -out vec3 color; +// the precision mediump is required in 3.0es +out mediump vec3 color; void main(){ color = vec3(1,0,0); }