00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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
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
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
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
00095 ProgramObject = GLCREATEPROGRAMOBJECTARB();
00096 VertexShaderObject = GLCREATESHADEROBJECTARB(GL_VERTEX_SHADER_ARB);
00097 FragmentShaderObject = GLCREATESHADEROBJECTARB(GL_FRAGMENT_SHADER_ARB);
00098
00099 return 1;
00100 }
00101
00102 void OpenGLShader::PrintInfoLog(GLhandleARB obj, const char *msg) {
00103 GLint blen = 0;
00104 GLint slen = 0;
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
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
00142 length = GLint(strlen((const char *) vertexShader));
00143 GLSHADERSOURCEARB(VertexShaderObject, 1, (const char **) &vertexShader, &length);
00144 free(vertexShader);
00145
00146 length = GLint(strlen((const char *) fragmentShader));
00147 GLSHADERSOURCEARB(FragmentShaderObject, 1, (const char **) &fragmentShader, &length);
00148 free(fragmentShader);
00149
00150
00151
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
00178 GLATTACHOBJECTARB(ProgramObject, VertexShaderObject);
00179 GLATTACHOBJECTARB(ProgramObject, FragmentShaderObject);
00180
00181
00182
00183
00184
00185
00186
00187
00188 GLDELETEOBJECTARB(VertexShaderObject);
00189 GLDELETEOBJECTARB(FragmentShaderObject);
00190
00191
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
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
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