Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

OpenGLShader.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr                                                                       
00003  *cr            (C) Copyright 1995-2011 The Board of Trustees of the           
00004  *cr                        University of Illinois                       
00005  *cr                         All Rights Reserved                        
00006  *cr                                                                   
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  * RCS INFORMATION:
00011  *
00012  *      $RCSfile: OpenGLShader.C,v $
00013  *      $Author: johns $        $Locker:  $             $State: Exp $
00014  *      $Revision: 1.24 $       $Date: 2011/11/20 01:35:27 $
00015  *
00016  ***************************************************************************
00017  * DESCRIPTION:
00018  *   Class to store and handle enumeration and initialization of OpenGL 
00019  *   shaders.
00020  ***************************************************************************/
00021 
00022 #include <string.h>
00023 
00024 #include "OpenGLExtensions.h"
00025 
00026 #if defined(VMDUSEOPENGLSHADER)   // only compile this file if oglsl is enabled
00027 #include "OpenGLShader.h"
00028 #include "Inform.h"
00029 #include "utilities.h"
00030 
00031 #include <stdlib.h>
00032 #include <stdio.h>
00033 #include <math.h>
00034 
00036 // constructor ... initialize some variables
00037 OpenGLShader::OpenGLShader(OpenGLExtensions * glextptr) {
00038   ext = glextptr; 
00039   isvalid = 0;
00040   ProgramObject = 0;
00041   VertexShaderObject = 0;
00042   FragmentShaderObject = 0;
00043   lastshader = 0;
00044 }
00045 
00046 // destructor
00047 OpenGLShader::~OpenGLShader(void) {
00048 }
00049 
00050 int OpenGLShader::LoadShader(const char * shaderpath) {
00051   int rc;
00052   GLubyte *vertexShader = NULL;
00053   GLubyte *fragmentShader = NULL;
00054 
00055   reset();
00056   rc = ReadShaderSource(shaderpath, &vertexShader, &fragmentShader);
00057   if (rc) {
00058     rc = CompileShaders(vertexShader, fragmentShader);
00059   }
00060 
00061   return rc;
00062 }
00063 
00064 void OpenGLShader::UseShader(int on) {
00065   if (lastshader != on) {
00066     if (on && isvalid) {
00067       GLUSEPROGRAMOBJECTARB(ProgramObject);
00068     } else if (!on && isvalid) {
00069       GLUSEPROGRAMOBJECTARB(0);
00070     }
00071   }
00072   lastshader = on;
00073 }
00074 
00075 int OpenGLShader::reset(void) {
00076   // delete any previous objects
00077   if (ProgramObject != 0) {
00078     if (VertexShaderObject != 0) {
00079       GLDETACHOBJECTARB(ProgramObject, VertexShaderObject);
00080     }
00081     if (FragmentShaderObject != 0) {
00082       GLDETACHOBJECTARB(ProgramObject, FragmentShaderObject);
00083     }
00084 
00085     ProgramObject = 0;
00086     VertexShaderObject = 0;
00087     FragmentShaderObject = 0;
00088 
00089     isvalid = 0;
00090     lastshader = 0;
00091   }
00092 
00093   // Create shader and program objects.
00094   ProgramObject        = GLCREATEPROGRAMOBJECTARB();
00095   VertexShaderObject   = GLCREATESHADEROBJECTARB(GL_VERTEX_SHADER_ARB);
00096   FragmentShaderObject = GLCREATESHADEROBJECTARB(GL_FRAGMENT_SHADER_ARB);
00097 
00098   return 1; // success
00099 }
00100 
00101 void OpenGLShader::PrintInfoLog(GLhandleARB obj, const char *msg) {
00102   GLint blen = 0;   /* length of buffer to allocate */
00103   GLint slen = 0;   /* strlen actually written to buffer */
00104   GLcharARB *infoLog;
00105 
00106   GLGETOBJECTPARAMETERIVARB(obj, GL_OBJECT_INFO_LOG_LENGTH_ARB , &blen);
00107   if (blen > 1) {
00108     if ((infoLog = (GLcharARB *) calloc(1, blen)) == NULL) {
00109       msgErr << "OpenGLShader could not allocate InfoLog buffer" << sendmsg;
00110       return;
00111     }
00112 
00113     GLGETINFOLOGARB(obj, blen, &slen, infoLog);
00114     msgInfo << "  " << msg << sendmsg;
00115     msgInfo << "    " << ((char *) infoLog) << sendmsg;
00116     free(infoLog);
00117   }
00118 }
00119 
00120 
00121 int OpenGLShader::CompileShaders(GLubyte *vertexShader, GLubyte *fragmentShader) {
00122   GLint vert_compiled = 0;
00123   GLint frag_compiled = 0;
00124   GLint linked = 0;
00125   GLint     length;
00126 
00127   // Bail out if we don't have valid pointers for shader source code
00128   if (vertexShader == NULL || fragmentShader == NULL) {
00129     ProgramObject = 0;
00130     return 0;
00131   }
00132 
00133   // Hand the source code strings to OpenGL.
00134   length = strlen((const char *) vertexShader);
00135   GLSHADERSOURCEARB(VertexShaderObject, 1, (const char **) &vertexShader, &length);
00136   free(vertexShader);   // OpenGL copies the shaders, we can free our copy
00137 
00138   length = strlen((const char *) fragmentShader);
00139   GLSHADERSOURCEARB(FragmentShaderObject, 1, (const char **) &fragmentShader, &length);
00140   free(fragmentShader); // OpenGL copies the shaders, we can free our copy
00141 
00142   // Compile the vertex and fragment shader, and print out
00143   // the compiler log file if one is available.
00144   GLCOMPILESHADERARB(VertexShaderObject);
00145   GLGETOBJECTPARAMETERIVARB(VertexShaderObject,
00146                   GL_OBJECT_COMPILE_STATUS_ARB, &vert_compiled);
00147 
00148   if (getenv("VMDGLSLVERBOSE") != NULL)
00149     PrintInfoLog(VertexShaderObject, "OpenGL vertex shader compilation log: ");
00150 
00151   GLCOMPILESHADERARB(FragmentShaderObject);
00152   GLGETOBJECTPARAMETERIVARB(FragmentShaderObject,
00153                   GL_OBJECT_COMPILE_STATUS_ARB, &frag_compiled);
00154 
00155   if (getenv("VMDGLSLVERBOSE") != NULL)
00156     PrintInfoLog(FragmentShaderObject, "OpenGL fragment shader compilation log: ");
00157 
00158   if (!vert_compiled || !frag_compiled) {
00159     ProgramObject = 0;
00160     return 0;
00161   }
00162 
00163   // Populate the program object with the two compiled shaders
00164   GLATTACHOBJECTARB(ProgramObject, VertexShaderObject);
00165   GLATTACHOBJECTARB(ProgramObject, FragmentShaderObject);
00166 
00167   // We want the shaders to go away as soon as they are detached from
00168   // the program object (or program objects) they are attached to. We
00169   // can simply call delete now to achieve that. Note that calling
00170   // delete on a program object will result in all shaders attached to
00171   // that program object to be detached. If delete has been called for
00172   // these shaders, calling delete on the program object will result in
00173   // the shaders being deleted as well.
00174   GLDELETEOBJECTARB(VertexShaderObject);
00175   GLDELETEOBJECTARB(FragmentShaderObject);
00176 
00177   // Link the whole thing together and print out the linker log file
00178   GLLINKPROGRAMARB(ProgramObject);
00179   GLGETOBJECTPARAMETERIVARB(ProgramObject, GL_OBJECT_LINK_STATUS_ARB, &linked);
00180 
00181   if (getenv("VMDGLSLVERBOSE") != NULL)
00182     PrintInfoLog(ProgramObject, "OpenGL shader linkage log: " );
00183 
00184   if (vert_compiled && frag_compiled && linked) {
00185     isvalid = 1;
00186     return 1;
00187   } else {
00188     ProgramObject = 0;
00189     return 0;
00190   }
00191 }
00192 
00193 int OpenGLShader::ReadShaderSource(const char *filename, GLubyte **vertexShader, GLubyte **fragmentShader) {
00194   char *vsfilename, *fsfilename;
00195   FILE *vsfp, *fsfp;
00196   long vsize, fsize, count;
00197 
00198   vsfilename = (char *) calloc(1, strlen(filename) + strlen(".vert") + 1);
00199   strcpy(vsfilename, filename); 
00200   strcat(vsfilename, ".vert"); 
00201   vsfp = fopen(vsfilename, "r");
00202 
00203   fsfilename = (char *) calloc(1, strlen(filename) + strlen(".frag") + 1);
00204   strcpy(fsfilename, filename); 
00205   strcat(fsfilename, ".frag"); 
00206   fsfp = fopen(fsfilename, "r");
00207 
00208   if ((vsfp == NULL) || (fsfp == NULL)) {
00209     msgErr << "Failed to open OpenGL shader source files: " 
00210            << vsfilename << ", " << fsfilename << sendmsg;
00211     free(vsfilename);
00212     free(fsfilename);
00213     return 0;
00214   }
00215 
00216   // find size and load vertex shader
00217   fseek(vsfp, 0, SEEK_END);
00218   vsize = ftell(vsfp); 
00219   fseek(vsfp, 0, SEEK_SET);
00220   *vertexShader = (GLubyte *) calloc(1, vsize + 1);
00221   memset(*vertexShader, 0, vsize + 1);
00222   count=fread(*vertexShader, 1, vsize, vsfp);
00223 
00224   // find size and load fragment shader
00225   fseek(fsfp, 0, SEEK_END);
00226   fsize = ftell(fsfp); 
00227   fseek(fsfp, 0, SEEK_SET);
00228   *fragmentShader = (GLubyte *) calloc(1, fsize + 1);
00229   memset(*fragmentShader, 0, fsize + 1);
00230   count=fread(*fragmentShader, 1, fsize, fsfp);
00231 
00232   free(vsfilename);
00233   free(fsfilename);
00234 
00235   return 1;
00236 }
00237 
00238 #endif

Generated on Mon May 21 01:51:08 2012 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002