commit 060f3115bf0f1f659dd44ef3738c12327ec2ef43 Author: Josh Holtrop Date: Mon May 16 15:46:46 2011 -0400 add initial glslUtil library diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..c5213ff --- /dev/null +++ b/Makefile @@ -0,0 +1,10 @@ +export SCONSFLAGS := -Q + +all: + @scons + +install: + @scons $@ + +clean: + @scons -c diff --git a/SConstruct b/SConstruct new file mode 100644 index 0000000..7be3e6c --- /dev/null +++ b/SConstruct @@ -0,0 +1,4 @@ +# vim:filetype=python + +env = Environment(CFLAGS = ['-Wall'], CPPFLAGS = ['-DGL_GLEXT_PROTOTYPES']) +env.Object('glslUtil.o', 'glslUtil.c') diff --git a/glslUtil.c b/glslUtil.c new file mode 100644 index 0000000..15885b8 --- /dev/null +++ b/glslUtil.c @@ -0,0 +1,349 @@ + +#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); + } +} diff --git a/glslUtil.h b/glslUtil.h new file mode 100644 index 0000000..ff652aa --- /dev/null +++ b/glslUtil.h @@ -0,0 +1,65 @@ + +#ifndef GLSLUTIL_H +#define GLSLUTIL_H + +#ifdef GL_INCLUDE_FILE +#include GL_INCLUDE_FILE +#else +#include +#endif + +typedef GLfloat guMatrix3x3[3][3]; +typedef GLfloat guMatrix4x4[4][4]; +typedef struct { + GLuint index; + const char *name; +} guAttribBinding; +typedef struct { + GLint *loc; + const char *name; +} guUniformLocation; + +#ifdef __cplusplus +extern "C" { +#endif + +void guMatrixLoadIdentity(guMatrix4x4 *m); +void guMatrixMult(guMatrix4x4 *m, guMatrix4x4 *a, guMatrix4x4 *b); +void guMatrixTranslate(guMatrix4x4 *m, GLfloat x, GLfloat y, GLfloat z); +void guMatrixScale(guMatrix4x4 *m, GLfloat x, GLfloat y, GLfloat z); +void guMatrixRotate(guMatrix4x4 *m, GLfloat angle, + GLfloat x, GLfloat y, GLfloat z); +void guMatrixFrustum(guMatrix4x4 *m, + GLfloat left, GLfloat right, + GLfloat bottom, GLfloat top, + GLfloat near, GLfloat far); +void guMatrixPerspective(guMatrix4x4 *m, GLfloat fovy, GLfloat aspect, + GLfloat near, GLfloat far); +void guMatrixOrtho(guMatrix4x4 *m, + GLfloat left, GLfloat right, + GLfloat bottom, GLfloat top, + GLfloat near, GLfloat far); + +void guMatrix4x4To3x3(guMatrix3x3 *out, const guMatrix4x4 *in); + +char *guGetShaderLog(GLuint id); +char *guGetProgramLog(GLuint id); +GLuint guMakeShaderFromFile(GLenum shaderType, const char *fname); +GLuint guMakeShader(GLenum shaderType, const char *source); +GLuint guMakeProgramFromSource(const char *v_shader, const char *f_shader, + const guAttribBinding *bindings); +GLuint guMakeProgramFromFiles(const char *v_shader, const char *f_shader, + const guAttribBinding *bindings); +GLuint guMakeProgram(GLuint v_shader_id, GLuint f_shader_id, + const guAttribBinding *bindings); + +void guGetUniformLocations(GLuint program, guUniformLocation *locs); + +GLuint guMakeBuffer(GLenum target, GLenum usage, const void *ptr, size_t sz); + +#ifdef __cplusplus +} +#endif + +#endif +