#include #include #include #include #include #include "glslUtil.h" /************************************************************************** * Helper Functions * *************************************************************************/ static char *loadFile(const char *fname) { struct stat st; if (stat(fname, &st) != 0) return NULL; if (st.st_size <= 0) return NULL; char * buff = malloc(st.st_size + 1); FILE *fil = fopen(fname, "r"); fread(buff, st.st_size, 1, fil); fclose(fil); buff[st.st_size] = '\0'; return buff; } void guMatrixLoadIdentity(guMatrix4x4 *m) { int i, j; for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { (*m)[i][j] = (i == j) ? 1.0 : 0.0; } } } void guMatrixMult(guMatrix4x4 *m, guMatrix4x4 *a, guMatrix4x4 *b) { guMatrix4x4 tmp; int i, j, p; if (m == a) { memcpy(&tmp, a, sizeof(tmp)); a = &tmp; } for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { GLfloat v = 0.0; for (p = 0; p < 4; p++) { v += (*a)[p][i] * (*b)[j][p]; } (*m)[j][i] = v; } } } void guMatrixTranslate(guMatrix4x4 *m, GLfloat x, GLfloat y, GLfloat z) { int i; for (i = 0; i < 4; i++) { (*m)[3][i] += (*m)[0][i] * x + (*m)[1][i] * y + (*m)[2][i] * z; } } void guMatrixScale(guMatrix4x4 *m, GLfloat x, GLfloat y, GLfloat z) { int i; for (i = 0; i < 4; i++) { (*m)[0][i] *= x; (*m)[1][i] *= y; (*m)[2][i] *= z; } } void guMatrixRotate(guMatrix4x4 *m, GLfloat angle, GLfloat x, GLfloat y, GLfloat z) { GLfloat lx = x, ly = y, lz = z, p; p = lx*lx + ly*ly + lz*lz; if (p != 1.0) { GLfloat scale = sqrt(p); lx /= scale; ly /= scale; lz /= scale; } GLfloat c = cos(M_PI * angle / 180.0); GLfloat s = sin(M_PI * angle / 180.0); guMatrix4x4 mult; GLfloat oc = 1 - c; mult[0][0] = lx * lx * oc + c; mult[1][0] = lx * ly * oc - lz * s; mult[2][0] = lx * lz * oc + ly * s; mult[3][0] = 0.0; mult[0][1] = ly * lx * oc + lz * s; mult[1][1] = ly * ly * oc + c; mult[2][1] = ly * lz * oc - lx * s; mult[3][1] = 0.0; mult[0][2] = lx * lz * oc - ly * s; mult[1][2] = ly * lz * oc + lx * s; mult[2][2] = lz * lz * oc + c; mult[3][2] = 0.0; mult[0][3] = 0.0; mult[1][3] = 0.0; mult[2][3] = 0.0; mult[3][3] = 1.0; guMatrixMult(m, m, &mult); } void guMatrixFrustum(guMatrix4x4 *m, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat near, GLfloat far) { int i, j; guMatrix4x4 mult; for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { mult[i][j] = 0.0; } } GLfloat rl = right - left; GLfloat tb = top - bottom; GLfloat fn = far - near; mult[0][0] = 2 * near / rl; mult[2][0] = (right + left) / rl; mult[1][1] = 2 * near / tb; mult[2][1] = (top + bottom) / tb; mult[2][2] = - (far + near) / fn; mult[3][2] = - 2 * far * near / fn; mult[2][3] = -1.0; guMatrixMult(m, m, &mult); } void guMatrixPerspective(guMatrix4x4 *m, GLfloat fovy, GLfloat aspect, GLfloat near, GLfloat far) { int i, j; guMatrix4x4 mult; for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { mult[i][j] = 0.0; } } GLfloat f = 1.0 / tan(M_PI * fovy / 360.0); GLfloat nf = near - far; mult[0][0] = f / aspect; mult[1][1] = f; mult[2][2] = (far + near) / nf; mult[3][2] = (2 * far * near) / nf; mult[2][3] = -1.0; guMatrixMult(m, m, &mult); } void guMatrixOrtho(guMatrix4x4 *m, GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat near, GLfloat far) { int i, j; guMatrix4x4 mult; for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { mult[i][j] = 0.0; } } GLfloat rl = right - left; GLfloat tb = top - bottom; GLfloat fn = far - near; mult[0][0] = 2 / rl; mult[3][0] = - (right + left) / rl; mult[1][1] = 2 / tb; mult[3][1] = - (top + bottom) / tb; mult[2][2] = -2 / fn; mult[3][2] = - (far + near) / fn; mult[3][3] = 1.0; guMatrixMult(m, m, &mult); } void guMatrix4x4To3x3(guMatrix3x3 *out, const guMatrix4x4 *in) { int i; for (i = 0; i < 3; i++) { memcpy(&(*out)[i], &(*in)[i], sizeof((*out)[0][0] * 3)); } } char *guGetShaderLog(GLuint id) { GLint log_length; glGetShaderiv(id, GL_INFO_LOG_LENGTH, &log_length); if (log_length > 0) { char *log = malloc(sizeof(char) * log_length); glGetShaderInfoLog(id, log_length, &log_length, log); return log; } return NULL; } char *guGetProgramLog(GLuint id) { GLint log_length; glGetProgramiv(id, GL_INFO_LOG_LENGTH, &log_length); if (log_length > 0) { char *log = malloc(sizeof(char) * log_length); glGetProgramInfoLog(id, log_length, &log_length, log); return log; } return NULL; } GLuint guMakeShaderFromFile(GLenum shaderType, const char *fname) { char *source; source = loadFile(fname); if (source == NULL) { fprintf(stderr, "Error reading file '%s'\n", fname); return 0; } GLuint id = guMakeShader(shaderType, source); free(source); return id; } GLuint guMakeShader(GLenum shaderType, const char *source) { GLuint id; GLint status; id = glCreateShader(shaderType); if (id <= 0) { fprintf(stderr, "Error creating shader object\n"); goto out; } glShaderSource(id, 1, &source, NULL); glCompileShader(id); glGetShaderiv(id, GL_COMPILE_STATUS, &status); if (status != GL_TRUE) { fprintf(stderr, "Error compiling shader\n"); char *log = guGetShaderLog(id); fprintf(stderr, "Shader Log:\n%s\n", log); free(log); goto cleanup_shader; } return id; cleanup_shader: glDeleteShader(id); out: return 0; } GLuint guMakeBuffer(GLenum target, GLenum usage, const void *ptr, size_t sz) { GLuint id; glGenBuffers(1, &id); glBindBuffer(target, id); glBufferData(target, sz, ptr, usage); return id; } GLuint guMakeProgramFromSource(const char *v_shader, const char *f_shader, const guAttribBinding *bindings) { GLuint v_shader_id = guMakeShader(GL_VERTEX_SHADER, v_shader); GLuint f_shader_id = guMakeShader(GL_FRAGMENT_SHADER, f_shader); if (v_shader_id <= 0 || f_shader_id <= 0) return 0; GLuint id = guMakeProgram(v_shader_id, f_shader_id, bindings); glDeleteShader(v_shader_id); glDeleteShader(f_shader_id); return id; } GLuint guMakeProgramFromFiles(const char *v_shader, const char *f_shader, const guAttribBinding *bindings) { GLuint v_shader_id = guMakeShaderFromFile(GL_VERTEX_SHADER, v_shader); GLuint f_shader_id = guMakeShaderFromFile(GL_FRAGMENT_SHADER, f_shader); if (v_shader_id <= 0 || f_shader_id <= 0) return 0; GLuint id = guMakeProgram(v_shader_id, f_shader_id, bindings); glDeleteShader(v_shader_id); glDeleteShader(f_shader_id); return id; } GLuint guMakeProgram(GLuint v_shader_id, GLuint f_shader_id, const guAttribBinding *bindings) { GLuint program = glCreateProgram(); glAttachShader(program, v_shader_id); glAttachShader(program, f_shader_id); if (bindings != NULL) { int i; for (i = 0; bindings[i].name != NULL; i++) { glBindAttribLocation(program, bindings[i].index, bindings[i].name); } } glLinkProgram(program); GLint link_status; glGetProgramiv(program, GL_LINK_STATUS, &link_status); if (link_status != GL_TRUE) { char *log = guGetProgramLog(program); fprintf(stderr, "Program log:\n%s\n", log); free(log); return 0; } return program; } void guGetUniformLocations(GLuint program, guUniformLocation *locs) { int i; for (i = 0; locs[i].name != NULL; i++) { *locs[i].loc = glGetUniformLocation(program, locs[i].name); } } void guGetUniformLocationsArray(GLuint program, const char **names, GLint *locations) { int i; for (i = 0; names[i] != NULL; i++) { locations[i] = glGetUniformLocation(program, names[i]); } }