/** init will take a vertex shader file and fragment shader file, and then attempt to create a valid shader program from these. It will also check for any shader compilation issues along the way. */ void Shader::init(const char *vsFile, const char *fsFile) { if (inited) // If we have already initialized the shader return; inited = true; // Mark that we have initialized the shader shader_vp = glCreateShader(GL_VERTEX_SHADER); // Create a vertex shader shader_fp = glCreateShader(GL_FRAGMENT_SHADER); // Create a fragment shader std::string vsText = text_file_read(vsFile); // Read in the vertex shader std::string fsText = text_file_read(fsFile); // Read in the fragment shader const char *vertexText = vsText.c_str(); const char *fragmentText = fsText.c_str(); if (vertexText == NULL) { std::cout << "vertex shader shader file not found." << std::endl; // Output the error return; } if (fragmentText == NULL) { std::cout << "fragment shader file not found." << std::endl; // Output the error return; } glShaderSource(shader_vp, 1, &vertexText, 0); // Set the source for the vertex shader to the loaded text glCompileShader(shader_vp); // Compile the vertex shader validate_shader(shader_vp, vsFile); // Validate the vertex shader glShaderSource(shader_fp, 1, &fragmentText, 0); // Set the source for the fragment shader to the loaded text glCompileShader(shader_fp); // Compile the fragment shader validate_shader(shader_fp, fsFile); // Validate the fragment shader shader_id = glCreateProgram(); // Create a GLSL program glAttachShader(shader_id, shader_vp); // Attach a vertex shader to the program glAttachShader(shader_id, shader_fp); // Attach the fragment shader to the program glBindAttribLocation(shader_id, 0, "in_Position"); // Bind a constant attribute location for positions of vertices glBindAttribLocation(shader_id, 1, "in_Color"); // Bind another constant attribute location, this time for color glLinkProgram(shader_id); // Link the vertex and fragment shaders in the program validate_program(shader_id); // Validate the shader program }
void load_config(Config *c, char *filename) { assert(c != NULL); assert(filename != NULL); int ini_size; char *ini_data = text_file_read(filename, &ini_size); // TODO: test data was read in. char buffer[MAX_LINE_LEN]; enum ConfigSections current_section = UNKNOWN_SECTION; char *key; char *value; while (get_next_line(ini_data, ini_size, buffer, MAX_LINE_LEN) == TRUE) { switch(buffer[0]) { case COMMENT_TOKEN: break; // Ignore this. case EMPTY_LINE_TOKEN: break; // Ignore this. case SPACE_TOKEN: break; // Ignore this. case SECTION_START_TOKEN: current_section = UNKNOWN_SECTION; value = strtok(&buffer[1], "]"); assert(value != NULL); if (strncmp(value, "app", sizeof("app")) == 0) { current_section = APP_SECTION; } if (strncmp(value, "object", sizeof("object")) == 0) { current_section = OBJECT_SECTION; } if (strncmp(value, "textures", sizeof("textures")) == 0) { current_section = TEXTURES_SECTION; } if (strncmp(value, "vert_shader", sizeof("vert_shader")) == 0) { current_section = VERT_SECTION; } if (strncmp(value, "frag_shader", sizeof("frag_shader")) == 0) { current_section = FRAG_SECTION; } break; default: if (current_section != APP_SECTION && current_section != OBJECT_SECTION && current_section != TEXTURES_SECTION && current_section != VERT_SECTION && current_section != FRAG_SECTION) { continue; } key = strtok(&buffer[0], "="); assert(key != NULL); value = strtok(NULL, "\0"); assert(value != NULL); if (current_section == APP_SECTION) { if (strncmp(key, "object_file", sizeof("object_file")) == 0) { strncpy(c->app.object_filename, value, MAX_FILENAME_LEN); } } if (current_section == OBJECT_SECTION) { if (strncmp(key, "vert_shader_file", sizeof("vert_shader_file")) == 0) { strncpy(c->object.vert_shader_filename, value, MAX_FILENAME_LEN); } else if (strncmp(key, "frag_shader_file", sizeof("frag_shader_file")) == 0) { strncpy(c->object.frag_shader_filename, value, MAX_FILENAME_LEN); } } if (current_section == TEXTURES_SECTION) { assert(c->texture_count + 1 != MAX_TEXTURE_COUNT); TextureConfig *t; t = &(c->textures[c->texture_count]); strncpy(t->name, key, MAX_LINE_LEN); strncpy(t->filename, value, MAX_LINE_LEN); c->texture_count++; } if (current_section == VERT_SECTION || current_section == FRAG_SECTION) { char *type; enum UniformDataTypes etype; char *name; type = strtok(key, " "); name = strtok(NULL, "="); int i = 0; char *p; float x = 0.0; float y = 0.0; float z = 0.0; float w = 0.0; etype = UNIFORM_UNKNOWN; if (strncmp(type, "int", sizeof("int")) == 0) { etype = UNIFORM_INT; i = atoi(value); } if (strncmp(type, "float", sizeof("float")) == 0) { etype = UNIFORM_FLOAT; x = atof(value); } if (strncmp(type, "vec2", sizeof("vec2")) == 0) { etype = UNIFORM_VEC2; p = strtok(value, ","); x = atof(p); p = strtok(NULL, "\0"); y = atof(p);; } if (strncmp(type, "vec3", sizeof("vec3")) == 0) { etype = UNIFORM_VEC3; p = strtok(value, ","); x = atof(p); p = strtok(NULL, ","); y = atof(p);; p = strtok(NULL, "\0"); z = atof(p);; } if (strncmp(type, "vec4", sizeof("vec4")) == 0) { etype = UNIFORM_VEC4; p = strtok(value, ","); x = atof(p); p = strtok(NULL, ","); y = atof(p);; p = strtok(NULL, ","); z = atof(p);; p = strtok(NULL, "\0"); w = atof(p);; } UniformConfig *uconfig; if (current_section == VERT_SECTION) { assert(c->vert_uniform_count + 1 != MAX_UNIFORM_COUNT); uconfig = &(c->vert_uniforms[c->vert_uniform_count]); c->vert_uniform_count++; } else { assert(c->frag_uniform_count + 1 != MAX_UNIFORM_COUNT); uconfig = &(c->frag_uniforms[c->frag_uniform_count]); c->frag_uniform_count++; } uconfig->type = etype; strncpy(uconfig->name, name, MAX_LINE_LEN); uconfig->i = i; uconfig->x = x; uconfig->y = y; uconfig->z = z; uconfig->w = w; } } } }
void load_shader(Shader *s, char *vert_filename, char *frag_filename) { assert(s != NULL); assert(vert_filename != NULL); assert(frag_filename != NULL); strncpy(s->vert_filename, (vert_filename), MAX_FILENAME_LEN); strncpy(s->frag_filename, (frag_filename), MAX_FILENAME_LEN); s->vert_program_id = glCreateShader(GL_VERTEX_SHADER); if (s->vert_program_id == 0) { set_error_msg(&s->status, "Could not create vert shader."); return; } s->frag_program_id = glCreateShader(GL_FRAGMENT_SHADER); if (s->frag_program_id == 0) { set_error_msg(&s->status, "Could not create frag shader."); return; } char *vs = NULL; int vs_size; vs = text_file_read(s->vert_filename, &vs_size); if (vs == NULL) { set_error_msg(&s->status, "Could not read vert shader '%s'.", s->vert_filename); return; } char *fs = NULL; int fs_size; fs = text_file_read(s->frag_filename, &fs_size); if (fs == NULL) { set_error_msg(&s->status, "Could not read frag shader '%s'.", s->frag_filename); return; } GLenum glerror; GLint result; const char * vv = vs; const char * ff = fs; glShaderSource(s->vert_program_id, 1, &vv, NULL); if ((glerror = glGetError()) != GL_NO_ERROR) { set_error_msg(&s->status, "Could set vert shader source. (%d)", glerror); return; } glShaderSource(s->frag_program_id, 1, &ff, NULL); if ((glerror = glGetError()) != GL_NO_ERROR) { set_error_msg(&s->status, "Could set frag shader source. (%d)", glerror); return; } glCompileShader(s->vert_program_id); glGetShaderiv(s->vert_program_id, GL_COMPILE_STATUS, &result); if (result != GL_TRUE) { set_error_msg(&s->status, "Could not compile vert shader."); return; } glCompileShader(s->frag_program_id); glGetShaderiv(s->frag_program_id, GL_COMPILE_STATUS, &result); if (result != GL_TRUE) { set_error_msg(&s->status, "Could not compile frag shader."); return; } free(vs); free(fs); print_shader_log(s->vert_program_id); print_shader_log(s->frag_program_id); s->program_id = glCreateProgram(); if (s->program_id == 0) { set_error_msg(&s->status, "Could not create program."); return; } glAttachShader(s->program_id, s->vert_program_id); if ((glerror = glGetError()) != GL_NO_ERROR) { set_error_msg(&s->status, "Could not attach vert shader. (%d)", glerror); return; } glAttachShader(s->program_id, s->frag_program_id); if ((glerror = glGetError()) != GL_NO_ERROR) { set_error_msg(&s->status, "Could not attach frag shader. (%d)", glerror); return; } glBindFragDataLocation(s->program_id, 0, "FracColor"); if ((glerror = glGetError()) != GL_NO_ERROR) { set_error_msg(&s->status, "Could not bind frag data location. (%d)", glerror); return; } glLinkProgram(s->program_id); glGetProgramiv(s->program_id, GL_LINK_STATUS, &result); if ((glerror = glGetError()) != GL_NO_ERROR || result == GL_FALSE) { set_error_msg(&s->status, "Could not bind frag data location. (%d,%d)", glerror, result); return; } print_program_log(s->program_id); s->vertex_loc = glGetAttribLocation(s->program_id, "MCvertex"); s->normal_loc = glGetAttribLocation(s->program_id, "MCnormal"); s->tangent_loc = glGetAttribLocation(s->program_id, "MCtangent"); s->tex_coords_loc = glGetAttribLocation(s->program_id, "TexCoord0"); s->proj_matrix_loc = glGetUniformLocation(s->program_id, "MVPMatrix"); s->view_matrix_loc = glGetUniformLocation(s->program_id, "MVMatrix"); s->rot_matrix_loc = glGetUniformLocation(s->program_id, "RotMatrix"); }