static void material_generate_programs(material* m) { for(int i = 0; i < m->num_entries; i++) { material_entry* me = m->entries[i]; me->program = shader_program_new(); bool attached = false; for(int j = 0; j < me->num_items; j++) { if (me->types[j] == mat_item_shader) { asset_hndl ah = me->items[j].as_asset; shader_program_attach_shader(me->program, asset_hndl_ptr(&ah)); attached = true; } } if (attached) { shader_program_link(me->program); } } SDL_GL_CheckError(); }
void shader_program_attach_shader(shader_program* program, shader* shader) { if (shader_program_has_shader(program, shader)) { error("Shader already attached!"); } glAttachShader(shader_program_handle(program), shader_handle(shader)); shader_program_print_log(program); SDL_GL_CheckError(); }
void shader_program_link(shader_program* program) { /* GLint count = -1; glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES, &count); glProgramParameteri(shader_program_handle(program), GL_GEOMETRY_VERTICES_OUT, count); */ glLinkProgram(shader_program_handle(program)); shader_program_print_log(program); GLint is_linked = false; glGetProgramiv(shader_program_handle(program), GL_LINK_STATUS, &is_linked); if (!is_linked) { error("Error linking shader program!"); } SDL_GL_CheckError(); }
static shader* load_shader_file(char* filename, GLenum type) { shader* new_shader = malloc(sizeof(shader)); SDL_RWops* file = SDL_RWFromFile(filename, "r"); if(file == NULL) { error("Cannot load file %s", filename); } long size = SDL_RWseek(file,0,SEEK_END); char* contents = malloc(size+1); contents[size] = '\0'; SDL_RWseek(file, 0, SEEK_SET); SDL_RWread(file, contents, size, 1); SDL_RWclose(file); *new_shader = glCreateShader(type); glShaderSource(shader_handle(new_shader), 1, (const char**)&contents, NULL); glCompileShader(shader_handle(new_shader)); free(contents); shader_print_log(new_shader); int compile_error = 0; glGetShaderiv(shader_handle(new_shader), GL_COMPILE_STATUS, &compile_error); if (compile_error == GL_FALSE) { error("Compiler Error on Shader %s.", filename); } SDL_GL_CheckError(); return new_shader; }
material* mat_load_file(char* filename) { SDL_RWops* file = SDL_RWFromFile(filename, "r"); if(file == NULL) { error("Cannot load file %s", filename); } material* m = material_new(); material_entry* me = material_add_entry(m); char line[1024]; while(SDL_RWreadline(file, line, 1024)) { if (line[0] == '#') { continue; } if (line[0] == '\r') { continue; } if (line[0] == '\n') { continue; } if (strstr(line, "submaterial")) { /* Skip Empty Submaterials */ if (me->num_items == 0) { continue; } else { me = material_add_entry(m); continue; } } char type[512]; char name[512]; char value[512]; int matches = sscanf(line, "%511s %511s = %511s", type, name, value); if (matches != 3) continue; material_item mi; int type_id; char* end; float f0, f1, f2, f3; if (strcmp(type, "shader") == 0) { mi.as_asset = asset_hndl_new_load(P(value)); type_id = mat_item_shader; } else if (strcmp(type, "texture") == 0) { mi.as_asset = asset_hndl_new_load(P(value)); type_id = mat_item_texture; } else if (strcmp(type, "int") == 0) { mi.as_int = atoi(value); type_id = mat_item_int; } else if (strcmp(type, "float") == 0) { mi.as_float = atof(value); type_id = mat_item_float; } else if (strcmp(type, "vec2") == 0) { f0 = strtod(value, &end); f1 = strtod(end, NULL); mi.as_vec2 = vec2_new(f0, f1); type_id = mat_item_vec2; } else if (strcmp(type, "vec3") == 0) { f0 = strtod(value, &end); f1 = strtod(end, &end); f2 = strtod(end, NULL); mi.as_vec3 = vec3_new(f0, f1, f2); type_id = mat_item_vec3; } else if (strcmp(type, "vec4") == 0) { f0 = strtod(value, &end); f1 = strtod(end, &end); f2 = strtod(end, &end); f3 = strtod(end, NULL); mi.as_vec4 = vec4_new(f0, f1, f2, f3); type_id = mat_item_vec4; } else { error("Unknown material item type '%s'", type); return NULL; } material_entry_add_item(me, name, type_id, mi); } SDL_RWclose(file); material_generate_programs(m); SDL_GL_CheckError(); return m; }
image* texture_get_image(texture* t) { int width = 0; int height = 0; int format = 0; glBindTexture(GL_TEXTURE_2D, texture_handle(t)); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &format); if ((width == 0) || (height == 0)) { error("Texture has zero size width/height: (%i, %i)", width, height); } unsigned char* data = malloc(width * height * 4); float* data_flt; unsigned int* data_int; switch (format) { case GL_RGBA: case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); break; case GL_ALPHA16: data_flt = malloc(sizeof(float) * width * height); glGetTexImage(GL_TEXTURE_2D, 0, GL_ALPHA, GL_FLOAT, data_flt); for(int x = 0; x < width; x++) for(int y = 0; y < height; y++) { data[(y*4*width) + (x*4) + 0] = pow(data_flt[(y*width) + x], 256.0) * 255; data[(y*4*width) + (x*4) + 1] = pow(data_flt[(y*width) + x], 256.0) * 255; data[(y*4*width) + (x*4) + 2] = pow(data_flt[(y*width) + x], 256.0) * 255; data[(y*4*width) + (x*4) + 3] = pow(data_flt[(y*width) + x], 256.0) * 255; } free(data_flt); break; case GL_RGBA32F: case GL_RGBA16F: data_flt = malloc(4 * sizeof(float) * width * height); glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, data_flt); for(int x = 0; x < width; x++) for(int y = 0; y < height; y++) { data[(y*4*width) + (x*4) + 0] = clamp(data_flt[(y*4*width) + (x*4) + 0] * 127 + 127, 0, 255); data[(y*4*width) + (x*4) + 1] = clamp(data_flt[(y*4*width) + (x*4) + 1] * 127 + 127, 0, 255); data[(y*4*width) + (x*4) + 2] = clamp(data_flt[(y*4*width) + (x*4) + 2] * 127 + 127, 0, 255); data[(y*4*width) + (x*4) + 3] = clamp(data_flt[(y*4*width) + (x*4) + 3] * 127 + 127, 0, 255); } free(data_flt); break; case GL_DEPTH_COMPONENT: case GL_DEPTH_COMPONENT24: data_int = malloc(sizeof(unsigned int) * width * height); glGetTexImage(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, data_int); for(int x = 0; x < width; x++) for(int y = 0; y < height; y++) { data[(y*4*width) + (x*4) + 0] = data_int[(y*width) + x]; data[(y*4*width) + (x*4) + 1] = data_int[(y*width) + x]; data[(y*4*width) + (x*4) + 2] = data_int[(y*width) + x]; data[(y*4*width) + (x*4) + 3] = data_int[(y*width) + x]; } free(data_int); break; default: error("Can't convert that particular texture format %i to an image.", format); } SDL_GL_CheckError(); image* i = image_new(width, height, data); free(data); return i; }