00001
00002
00003 #include "GPUProgram.h"
00004
00005 #include <stdio.h>
00006 #include <stdlib.h>
00007 #include <iostream>
00008 #include <fstream>
00009
00010
00011 namespace pge {
00012
00013
00014
00015
00016
00017
00018
00019 GPUProgram::GPUProgram(const std::string &vertexSourceFile, const std::string &fragmentSourceFile) {
00020 m_vertexSource = loadProgram(vertexSourceFile);
00021 m_fragmentSource = loadProgram(fragmentSourceFile);
00022
00023 if(!createPrograms()) {
00024 printf("Error: [%s] Could not create shader objects (%s).\n", __FILE__, vertexSourceFile.c_str());
00025 }
00026 }
00027
00028
00029
00030
00031
00032
00033
00034 GPUProgram::~GPUProgram(void) {
00035 glDeleteObjectARB(m_vertexShader);
00036 glDeleteObjectARB(m_fragmentShader);
00037 glDeleteObjectARB(m_programObject);
00038 }
00039
00040
00041
00042
00043
00044
00045
00046 void GPUProgram::bind(void) {
00047 glUseProgramObjectARB(m_programObject);
00048 }
00049
00050
00051
00052
00053
00054
00055
00056 void GPUProgram::release(void) {
00057 glUseProgramObjectARB(0);
00058 }
00059
00060
00061
00062
00063
00064
00065
00066 void GPUProgram::passUniform1i(char *name, int value) {
00067
00068
00069
00070 int location;
00071
00072
00073 location = glGetUniformLocation(m_programObject, (const GLcharARB*)name);
00074 if(location == -1) {
00075
00076 return;
00077 }
00078 glUniform1i(location, value);
00079 }
00080
00081
00082
00083
00084
00085
00086
00087 void GPUProgram::passUniform1f(char *name, float value) {
00088
00089
00090
00091 int location;
00092
00093
00094 location = glGetUniformLocation(m_programObject, (const GLcharARB*)name);
00095 glUniform1f(location, value);
00096 }
00097
00098
00099
00100
00101
00102
00103
00104 void GPUProgram::passUniform3f(char *name, float v1, float v2, float v3) {
00105
00106
00107
00108 int location;
00109
00110
00111 location = glGetUniformLocation(m_programObject, (const GLcharARB*)name);
00112 glUniform3f(location, v1, v2, v3);
00113 }
00114
00115
00116
00117
00118
00119
00120
00121 void GPUProgram::passUniform3f(char *name, Vector3f value) {
00122
00123
00124
00125 int location;
00126
00127
00128 location = glGetUniformLocation(m_programObject, (const GLcharARB*)name);
00129 glUniform3f(location, value.m_v[0], value.m_v[1], value.m_v[2]);
00130 }
00131
00132
00133
00134
00135
00136
00137
00138 void GPUProgram::passUniform4f(char *name, float v1, float v2, float v3, float v4) {
00139
00140
00141
00142 int location;
00143
00144
00145 location = glGetUniformLocation(m_programObject, (const GLcharARB*)name);
00146 glUniform4f(location, v1, v2, v3, v4);
00147 }
00148
00149
00150
00151
00152
00153
00154
00155 void GPUProgram::passUniform4f(char *name, Vector4f value) {
00156
00157
00158
00159 int location;
00160
00161
00162 location = glGetUniformLocation(m_programObject, (const GLcharARB*)name);
00163 glUniform4f(location, value.m_v[0], value.m_v[1], value.m_v[2], value.m_v[3]);
00164 }
00165
00166
00167
00168
00169
00170
00171
00172 void GPUProgram::passUniformMatrix4f(char *name, float *value) {
00173
00174
00175
00176 int location;
00177
00178
00179 location = glGetUniformLocation(m_programObject, (const GLcharARB*)name);
00180 glUniformMatrix4fv(location, 16, false, value);
00181 }
00182
00183
00184
00185
00186
00187
00188
00189 bool GPUProgram::createPrograms(void) {
00190
00191
00192
00193 GLint compileStatus;
00194 GLint linkStatus;
00195 GLint vertexLength;
00196 GLint fragmentLength;
00197 const char *vSource;
00198 const char *fSource;
00199
00200
00201
00202 m_programObject = glCreateProgramObjectARB();
00203 m_vertexShader = glCreateShaderObjectARB(GL_VERTEX_SHADER);
00204 m_fragmentShader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER);
00205
00206 vertexLength = (GLint)m_vertexSource.size();
00207 fragmentLength = (GLint)m_fragmentSource.size();
00208
00209 vSource = m_vertexSource.c_str();
00210 fSource = m_fragmentSource.c_str();
00211
00212
00213 glShaderSourceARB(m_vertexShader, 1, (const GLcharARB **)&vSource, &vertexLength);
00214 glShaderSourceARB(m_fragmentShader, 1, (const GLcharARB **)&fSource, &fragmentLength);
00215
00216
00217 glCompileShader(m_vertexShader);
00218 printLog(m_vertexShader);
00219 glGetObjectParameterivARB(m_vertexShader, GL_OBJECT_COMPILE_STATUS_ARB, &compileStatus);
00220 if(compileStatus == 0) {
00221 printf("ERROR: [%s] Could not compile vertex shader.\n", __FILE__);
00222 return false;
00223 }
00224
00225 glCompileShader(m_fragmentShader);
00226 printLog(m_fragmentShader);
00227 glGetObjectParameterivARB(m_fragmentShader, GL_OBJECT_COMPILE_STATUS_ARB, &compileStatus);
00228 if(compileStatus == 0) {
00229 printf("ERROR: [%s] Could not compile fragment shader.\n", __FILE__);
00230 return false;
00231 }
00232
00233
00234 glAttachObjectARB(m_programObject, m_vertexShader);
00235 glAttachObjectARB(m_programObject, m_fragmentShader);
00236
00237
00238 glLinkProgram(m_programObject);
00239 printLog(m_programObject);
00240 glGetObjectParameterivARB(m_programObject, GL_OBJECT_LINK_STATUS_ARB, &linkStatus);
00241 if(linkStatus == 0) {
00242 return false;
00243 }
00244
00245 return true;
00246 }
00247
00248
00249
00250
00251
00252
00253
00254 std::string GPUProgram::loadProgram(const std::string &filename) {
00255 std::string source = "";
00256 char temp[MAX_LINE];
00257
00258
00259 std::fstream in(filename.c_str(), std::ios::in);
00260
00261 if(!in) {
00262 return "";
00263 }
00264
00265 while(!in.eof()) {
00266 in.getline(temp, MAX_LINE);
00267 source.append(temp);
00268 }
00269
00270 in.close();
00271
00272 return source;
00273 }
00274
00275
00276
00277
00278
00279
00280
00281 void GPUProgram::printLog(GLhandleARB handle) {
00282
00283
00284
00285 int infoLength;
00286 int len;
00287 char *log;
00288
00289
00290 infoLength = 0;
00291 len = 0;
00292 glGetObjectParameterivARB(handle, GL_OBJECT_INFO_LOG_LENGTH_ARB , &infoLength);
00293 if(infoLength > 1) {
00294 log = new char[infoLength];
00295 glGetInfoLogARB(handle, infoLength, &len, log);
00296 printf("INFO: [%s] Compile-log: %s\n", __FILE__, log);
00297 }
00298 }
00299 };