00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
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
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
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
00094 ProgramObject = GLCREATEPROGRAMOBJECTARB();
00095 VertexShaderObject = GLCREATESHADEROBJECTARB(GL_VERTEX_SHADER_ARB);
00096 FragmentShaderObject = GLCREATESHADEROBJECTARB(GL_FRAGMENT_SHADER_ARB);
00097
00098 return 1;
00099 }
00100
00101 void OpenGLShader::PrintInfoLog(GLhandleARB obj, const char *msg) {
00102 GLint blen = 0;
00103 GLint slen = 0;
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
00128 if (vertexShader == NULL || fragmentShader == NULL) {
00129 ProgramObject = 0;
00130 return 0;
00131 }
00132
00133
00134 length = strlen((const char *) vertexShader);
00135 GLSHADERSOURCEARB(VertexShaderObject, 1, (const char **) &vertexShader, &length);
00136 free(vertexShader);
00137
00138 length = strlen((const char *) fragmentShader);
00139 GLSHADERSOURCEARB(FragmentShaderObject, 1, (const char **) &fragmentShader, &length);
00140 free(fragmentShader);
00141
00142
00143
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
00164 GLATTACHOBJECTARB(ProgramObject, VertexShaderObject);
00165 GLATTACHOBJECTARB(ProgramObject, FragmentShaderObject);
00166
00167
00168
00169
00170
00171
00172
00173
00174 GLDELETEOBJECTARB(VertexShaderObject);
00175 GLDELETEOBJECTARB(FragmentShaderObject);
00176
00177
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
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
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