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

OpenGLShader.C

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

Generated on Thu Apr 25 02:43:02 2024 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002