#include "GPU_physics.h" #include "shaderSupport.h" #include "fboSupport.h" static void showGLerror () { GLenum err ; while ( (err = glGetError()) != GL_NO_ERROR ) fprintf ( stderr, "OpenGL Error: %s\n", gluErrorString ( err ) ) ; } #define DEFAULT_VERT_SHADER \ "void main()" \ "{" \ " gl_TexCoord[0] = gl_MultiTexCoord0 ;" \ " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex ;" \ "}" class FrameBufferObject ; class GLSL_Shader { GLenum type ; GLhandleARB handle ; char *name ; char *source ; public: GLSL_Shader () { type = (GLenum) 0 ; handle = 0 ; name = NULL ; source = NULL ; } ~GLSL_Shader () { delete [] name ; delete [] source ; } bool compileFile ( const char *fname , GLenum type ) ; bool compileString ( const char *source, GLenum type, const char *name ) ; GLenum getType () { return type ; } GLhandleARB getHandle () { return handle ; } } ; static char *readShaderText ( const char *fname ) { FILE *fd = fopen ( fname, "r" ) ; int size = 0; /* File operations denied? ok, just close and return failure */ if (fseek(fd, 0, SEEK_END) || (size = ftell(fd)) == EOF || fseek(fd, 0, SEEK_SET)) { printf("Error: cannot get filesize from %s\n", fname); exit (1); } char *shader = new char [ size + 1 ] ; if ( fd == NULL ) { fprintf ( stderr, "Cannot read shader '%s'\n", fname ) ; exit ( 1 ) ; } int count = fread ( shader, 1, size, fd ) ; shader [ count ] = '\0' ; fclose ( fd ) ; return shader ; } /*****************************\ * * * Error handling stuff * * * \*****************************/ static void showShaderInfo ( const char *which, GLhandleARB handle, const char *name ) { int len = 0 ; showGLerror () ; glGetObjectParameterivARB ( handle, GL_OBJECT_INFO_LOG_LENGTH_ARB, (GLint*) &len ) ; showGLerror () ; if ( len > 0 ) { int trueLen ; char *s = new char [ len ] ; glGetInfoLogARB ( handle, len, (GLint*)&trueLen, s ) ; if ( trueLen > 0 && s [ 0 ] != '\0' ) fprintf ( stderr, "%s:%s - \n%s\n", which, name, s ) ; delete [] s ; } } /************************************\ * * * Single Shader Stuff * * * \************************************/ bool GLSL_Shader::compileFile ( const char *fname, GLenum _type ) { return compileString ( readShaderText ( fname ), _type, fname ) ; } bool GLSL_Shader::compileString ( const char *_source, GLenum _type, const char *_name ) { delete [] name ; delete [] source ; type = _type ; name = strdup ( _name ) ; source = strdup ( _source ) ; GLint stat ; handle = glCreateShaderObjectARB ( type ) ; glShaderSourceARB ( handle, 1, (const GLcharARB **) & source, NULL); glCompileShaderARB ( handle ) ; glGetObjectParameterivARB ( handle, GL_OBJECT_COMPILE_STATUS_ARB, & stat ) ; showShaderInfo ( "Compiling", handle, name ) ; if ( ! stat ) { fprintf ( stderr, "Failed to compile shader '%s'.\n", name ) ; return false ; } return true ; } /************************************\ * * * Shader Pair Stuff * * * \************************************/ GLint GLSL_ShaderPair::getUniformLocation ( const char *uni_name ) { assert ( success ) ; GLint loc = glGetUniformLocationARB ( handle, uni_name ) ; if ( loc == -1 ) fprintf ( stderr, "No such uniform as '%s' or" " '%s' is unused in shader pair '%s'.\n", uni_name, uni_name, name ) ; else showGLerror () ; return loc ; } void GLSL_ShaderPair::showActiveUniforms ( FILE *fd ) { GLint maxlen = 0 ; GLint maxattrs = 0 ; if ( fd == NULL ) fd = stderr ; glGetObjectParameterivARB ( handle, GL_OBJECT_ACTIVE_UNIFORMS_ARB, &maxattrs ) ; if ( maxattrs == 0 ) { fprintf ( fd, "No Active Uniforms.\n" ) ; return ; } glGetObjectParameterivARB ( handle, GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB, &maxlen ) ; char *name = new char [ maxlen+1 ] ; fprintf ( fd, "Active Uniforms:\n" ) ; for ( int i = 0 ; i < maxattrs ; i++ ) { GLsizei len ; GLint size ; GLenum vartype ; char *vartypename ; GLint location ; glGetActiveUniformARB ( handle, i, maxlen+1, &len, &size, &vartype, name ) ; location = glGetUniformLocationARB ( handle, name ) ; switch ( vartype ) { case GL_FLOAT : vartypename = "float " ; break ; case GL_FLOAT_VEC2_ARB : vartypename = "vec2 " ; break ; case GL_FLOAT_VEC3_ARB : vartypename = "vec3 " ; break ; case GL_FLOAT_VEC4_ARB : vartypename = "vec4 " ; break ; case GL_INT : vartypename = "int " ; break ; case GL_INT_VEC2_ARB : vartypename = "intvec2 " ; break ; case GL_INT_VEC3_ARB : vartypename = "intvec3 " ; break ; case GL_INT_VEC4_ARB : vartypename = "intvec4 " ; break ; case GL_BOOL : vartypename = "bool " ; break ; case GL_BOOL_VEC2_ARB : vartypename = "boolvec2 " ; break ; case GL_BOOL_VEC3_ARB : vartypename = "boolvec3 " ; break ; case GL_BOOL_VEC4_ARB : vartypename = "boolvec4 " ; break ; case GL_FLOAT_MAT2_ARB : vartypename = "mat2 " ; break ; case GL_FLOAT_MAT3_ARB : vartypename = "mat3 " ; break ; case GL_FLOAT_MAT4_ARB : vartypename = "mat4 " ; break ; case GL_SAMPLER_1D_ARB : vartypename = "sampler1D" ; break ; case GL_SAMPLER_2D_ARB : vartypename = "sampler2D" ; break ; case GL_SAMPLER_3D_ARB : vartypename = "sampler3D" ; break ; default : vartypename = "?????????" ; break ; } if ( size == 1 ) fprintf ( fd, "%2d) %s %s ; // @%d\n", i, vartypename, name, location ) ; else fprintf ( fd, "%2d) %s %s [ %d ] ; // @%d\n", i, vartypename, name, size, location ) ; } fprintf ( fd, "\n" ) ; delete name ; } void GLSL_ShaderPair::showActiveAttribs ( FILE *fd ) { if ( fd == NULL ) fd = stderr ; GLint maxlen = 0 ; GLint maxattrs = 0 ; glGetObjectParameterivARB ( handle, GL_OBJECT_ACTIVE_ATTRIBUTES_ARB, &maxattrs ) ; if ( maxattrs == 0 ) { fprintf ( fd, "No Active Attributes.\n" ) ; return ; } glGetObjectParameterivARB ( handle, GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB, &maxlen ) ; char *name = new char [ maxlen+1 ] ; fprintf ( fd, "Active Attributes:\n" ) ; for ( int i = 0 ; i < maxattrs ; i++ ) { GLsizei len ; GLint size ; GLenum vartype ; char *vartypename ; GLint location ; glGetActiveAttribARB ( handle, i, maxlen+1, &len, &size, &vartype, name ) ; location = glGetAttribLocationARB ( handle, name ) ; switch ( vartype ) { case GL_FLOAT : vartypename = "float" ; break ; case GL_FLOAT_VEC2_ARB : vartypename = "vec2 " ; break ; case GL_FLOAT_VEC3_ARB : vartypename = "vec3 " ; break ; case GL_FLOAT_VEC4_ARB : vartypename = "vec4 " ; break ; case GL_FLOAT_MAT2_ARB : vartypename = "mat2 " ; break ; case GL_FLOAT_MAT3_ARB : vartypename = "mat3 " ; break ; case GL_FLOAT_MAT4_ARB : vartypename = "mat4 " ; break ; default : vartypename = "???? " ; break ; } if ( size == 1 ) fprintf ( fd, "%2d) %s %s ; // @%d\n", i, vartypename, name, location ) ; else fprintf ( fd, "%2d) %s %s [ %d ] ; // @%d\n", i, vartypename, name, size, location ) ; } fprintf ( fd, "\n" ) ; delete name ; } bool GLSL_ShaderPair::link () { GLint stat ; handle = glCreateProgramObjectARB () ; glAttachObjectARB ( handle, vertShader -> getHandle () ) ; glAttachObjectARB ( handle, fragShader -> getHandle () ) ; glLinkProgramARB ( handle ) ; glGetObjectParameterivARB ( handle, GL_OBJECT_LINK_STATUS_ARB, &stat ) ; showShaderInfo ( "Linking", handle, name ) ; glValidateProgramARB ( handle ) ; showShaderInfo ( "Validate", handle, name ) ; if ( ! stat ) { fprintf ( stderr, "Failed to link shader.\n" ) ; return false ; } return true ; } GLSL_ShaderPair::GLSL_ShaderPair ( const char *_name, const char *vertFname, const char *fragFname ) { name = strdup ( _name ) ; handle = 0 ; vertShader = new GLSL_Shader () ; fragShader = new GLSL_Shader () ; bool res1 = ( vertFname == NULL ) ? vertShader -> compileString ( DEFAULT_VERT_SHADER, GL_VERTEX_SHADER_ARB, "Default Vertex Shader" ) : vertShader -> compileFile ( vertFname, GL_VERTEX_SHADER_ARB ) ; bool res2 = fragShader -> compileFile ( fragFname, GL_FRAGMENT_SHADER_ARB ) ; success = ( res1 && res2 && link () ) ; } GLSL_ShaderPair::GLSL_ShaderPair ( const char *_name, const char *vertSource, const char *vertName, const char *fragSource, const char *fragName ) { name = strdup ( _name ) ; handle = 0 ; vertShader = new GLSL_Shader () ; fragShader = new GLSL_Shader () ; bool res1 = ( vertSource == NULL ) ? vertShader -> compileString ( DEFAULT_VERT_SHADER, GL_VERTEX_SHADER_ARB, "Default Vertex Shader" ) : vertShader -> compileString ( vertSource, GL_VERTEX_SHADER_ARB, vertName ); bool res2 = fragShader -> compileString ( fragSource, GL_FRAGMENT_SHADER_ARB, fragName ); success = ( res1 && res2 && link () ) ; } GLSL_ShaderPair::~GLSL_ShaderPair () { delete [] name ; delete vertShader ; delete fragShader ; } void GLSL_ShaderPair::applyTexture ( const char *uniformName, FrameBufferObject *fbo, int slot ) { fbo -> use ( slot ) ; glUniform1iARB ( getUniformLocation ( uniformName ), slot ) ; }