#include "program.h" unsigned int program_use (int program) { glUseProgram (program); return program; } void shader_fail (int shader) { int info_len; glGetShaderiv (shader, GL_INFO_LOG_LENGTH, &info_len); int shader_type; glGetShaderiv (shader, GL_SHADER_TYPE, &shader_type); const char *type = shader_type == GL_VERTEX_SHADER ? "vertex" : "fragment"; if (info_len > 1) { char *info = malloc (sizeof (char) * info_len); glGetShaderInfoLog (shader, info_len, NULL, info); WARN ("Compiling %s shader failed:\n%s", type, info); free (info); } else { WARN ("Compiling %s shader failed without information.", type); } } void program_fail (int program) { int info_len; glGetProgramiv (program, GL_INFO_LOG_LENGTH, &info_len); if (info_len > 1) { char *info = malloc (sizeof (char) * info_len); glGetProgramInfoLog (program, info_len, NULL, info); WARN ("Linking program failed:\n%s", info); free (info); } else { WARN ("Linking program failed without information."); } } unsigned int program_create (const char *v_src, const char *f_src) { int success = 0; int vertex = glCreateShader (GL_VERTEX_SHADER); glShaderSource (vertex, 1, &v_src, NULL); glCompileShader (vertex); glGetShaderiv (vertex, GL_COMPILE_STATUS, &success); if (!success) shader_fail (vertex); int fragment = glCreateShader (GL_FRAGMENT_SHADER); glShaderSource (fragment, 1, &f_src, NULL); glCompileShader (fragment); glGetShaderiv (fragment, GL_COMPILE_STATUS, &success); if (!success) shader_fail (fragment); int program = glCreateProgram (); glAttachShader (program, vertex); glAttachShader (program, fragment); glLinkProgram (program); glGetProgramiv (program, GL_LINK_STATUS, &success); if (!success) program_fail (program); else INFO ("Compiled shaders and linked program %d successfuly.", program); glDeleteShader (vertex); glDeleteShader (fragment); return program; } void program_set_vec3 (int program, const char *name, vec3 value) { glUniform3f (glGetUniformLocation (program, name), value[0], value[1], value[2]); } void program_set_vec4 (int program, const char *name, vec4 value) { glUniform4f (glGetUniformLocation (program, name), value[0], value[1], value[2], value[3]); } void program_set_vec3_ind (int program, const char *name, float x, float y, float z) { glUniform3f (glGetUniformLocation (program, name), x, y, z); } void program_set_float (int program, const char *name, float value) { glUniform1f (glGetUniformLocation (program, name), value); } void program_set_int_array (int program, const char *name, size_t count, int *value) { glUniform1iv (glGetUniformLocation (program, name), count, value); } void program_set_mat3 (int program, const char *name, mat3 value) { glUniformMatrix3fv (glGetUniformLocation (program, name), 1, GL_FALSE, (float *) value); } void program_set_mat4 (int program, const char *name, mat4 value) { glUniformMatrix4fv (glGetUniformLocation (program, name), 1, GL_FALSE, (float *) value); } static const char * gl_type_to_string (GLenum type) { switch (type) { case GL_FLOAT: return "float"; case GL_FLOAT_VEC3: return "vec3"; case GL_FLOAT_VEC4: return "vec4"; case GL_INT: return "int"; case GL_INT_VEC3: return "ivec3"; case GL_INT_VEC4: return "ivec4"; case GL_BOOL: return "bool"; case GL_FLOAT_MAT4: return "mat4"; case GL_SAMPLER_2D: return "sampler2D"; default: return "unknown type"; } } void program_print (int program) /* This function assumes that `program' is the active program. */ { INFO ("== Program %d ==", program); int attr_len; glGetProgramiv (program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &attr_len); char attr[attr_len]; int attribute_no; glGetProgramiv (program, GL_ACTIVE_ATTRIBUTES, &attribute_no); GLenum type; for (GLint i = 0; i < attribute_no; i++) { glGetActiveAttrib (program, i, attr_len, NULL, NULL, &type, attr); INFO ("Attribute #%d: %s %s", i, gl_type_to_string (type), attr); } int uniform_len; glGetProgramiv (program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &uniform_len); char uniform[uniform_len]; int uniform_no; glGetProgramiv (program, GL_ACTIVE_UNIFORMS, &uniform_no); float *vec = malloc (sizeof (float) * 4); for (GLint i = 0; i < uniform_no; i++) { glGetActiveUniform (program, i, uniform_len, NULL, NULL, &type, uniform); switch (type) { case GL_FLOAT_VEC3: glGetUniformfv (program, glGetUniformLocation (program, uniform), vec); INFO ("Uniform #%d: %s %s = (%5.1f,%5.1f,%5.1f)", i, gl_type_to_string (type), uniform, vec[0], vec[1], vec[2]); break; case GL_FLOAT_VEC4: glGetUniformfv (program, glGetUniformLocation (program, uniform), vec); INFO ("Uniform #%d: %s %s = (%5.1f,%5.1f,%5.1f,%5.1f)", i, gl_type_to_string (type), uniform, vec[0], vec[1], vec[2], vec[3]); break; default: INFO ("Uniform #%d: %s %s", i, gl_type_to_string (type), uniform); break; } } free (vec); }