00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <iostream>
00011 #include "glshader.h"
00012 #include "gl.h"
00013 #include "glext.h"
00014
00015 using namespace std;
00016
00017
00018 static const string GetInfoLog(int obj);
00019
00020
00021 ostream* g_shaderLogFile = NULL;
00022
00023
00024 GLShader::GLShader(int _id) :
00025 id(_id)
00026 {
00027 }
00028
00029
00030 int
00031 GLShader::getID() const
00032 {
00033 return id;
00034 }
00035
00036
00037 GLShaderStatus
00038 GLShader::compile(const vector<string>& source)
00039 {
00040 if (source.empty())
00041 return ShaderStatus_EmptyProgram;
00042
00043
00044 const char** sourceStrings = new const char*[source.size()];
00045 for (unsigned int i = 0; i < source.size(); i++)
00046 sourceStrings[i] = source[i].c_str();
00047
00048
00049 glx::glShaderSourceARB(id, source.size(), sourceStrings, NULL);
00050 delete[] sourceStrings;
00051
00052
00053 glx::glCompileShaderARB(id);
00054
00055 GLint compileSuccess;
00056 glx::glGetObjectParameterivARB(id, GL_OBJECT_COMPILE_STATUS_ARB,
00057 &compileSuccess);
00058 if (compileSuccess == GL_FALSE)
00059 return ShaderStatus_CompileError;
00060
00061 return ShaderStatus_OK;
00062 }
00063
00064
00065 GLShader::~GLShader()
00066 {
00067 glx::glDeleteObjectARB(id);
00068 }
00069
00070
00071
00072
00073
00074 FloatShaderParameter::FloatShaderParameter() :
00075 slot(-1)
00076 {
00077 }
00078
00079 FloatShaderParameter::FloatShaderParameter(int obj, const char* name)
00080 {
00081 slot = glx::glGetUniformLocationARB(obj, name);
00082 }
00083
00084 FloatShaderParameter&
00085 FloatShaderParameter::operator=(float f)
00086 {
00087 if (slot != -1)
00088 glx::glUniform1fARB(slot, f);
00089 return *this;
00090 }
00091
00092
00093 Vec3ShaderParameter::Vec3ShaderParameter() :
00094 slot(-1)
00095 {
00096 }
00097
00098 Vec3ShaderParameter::Vec3ShaderParameter(int obj, const char* name)
00099 {
00100 slot = glx::glGetUniformLocationARB(obj, name);
00101 }
00102
00103 Vec3ShaderParameter&
00104 Vec3ShaderParameter::operator=(const Vec3f& v)
00105 {
00106 if (slot != -1)
00107 glx::glUniform3fARB(slot, v.x, v.y, v.z);
00108 return *this;
00109 }
00110
00111 Vec3ShaderParameter&
00112 Vec3ShaderParameter::operator=(const Point3f& p)
00113 {
00114 if (slot != -1)
00115 glx::glUniform3fARB(slot, p.x, p.y, p.z);
00116 return *this;
00117 }
00118
00119
00120 Vec4ShaderParameter::Vec4ShaderParameter() :
00121 slot(-1)
00122 {
00123 }
00124
00125 Vec4ShaderParameter::Vec4ShaderParameter(int obj, const char* name)
00126 {
00127 slot = glx::glGetUniformLocationARB(obj, name);
00128 }
00129
00130 Vec4ShaderParameter&
00131 Vec4ShaderParameter::operator=(const Vec4f& v)
00132 {
00133 if (slot != -1)
00134 glx::glUniform4fARB(slot, v.x, v.y, v.z, v.w);
00135 return *this;
00136 }
00137
00138
00139
00140
00141 GLProgram::GLProgram(int _id) :
00142 id(_id)
00143 {
00144 }
00145
00146
00147 GLProgram::~GLProgram()
00148 {
00149 glx::glDeleteObjectARB(id);
00150 }
00151
00152
00153 void
00154 GLProgram::use() const
00155 {
00156 glx::glUseProgramObjectARB(id);
00157 }
00158
00159
00160 void
00161 GLProgram::attach(const GLShader& shader)
00162 {
00163 glx::glAttachObjectARB(id, shader.getID());
00164 }
00165
00166
00167 GLShaderStatus
00168 GLProgram::link()
00169 {
00170 glx::glLinkProgramARB(id);
00171
00172 GLint linkSuccess;
00173 glx::glGetObjectParameterivARB(id, GL_OBJECT_LINK_STATUS_ARB,
00174 &linkSuccess);
00175 if (linkSuccess == GL_FALSE)
00176 {
00177 if (g_shaderLogFile != NULL)
00178 {
00179 *g_shaderLogFile << "Error linking shader program:\n";
00180 *g_shaderLogFile << GetInfoLog(getID());
00181 }
00182 return ShaderStatus_LinkError;
00183 }
00184
00185 return ShaderStatus_OK;
00186 }
00187
00188
00189
00190
00191 GLShaderStatus
00192 GLShaderLoader::CreateVertexShader(const vector<string>& source,
00193 GLVertexShader** vs)
00194 {
00195 GLint vsid = glx::glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
00196
00197 GLVertexShader* shader = new GLVertexShader(vsid);
00198 if (!shader)
00199 return ShaderStatus_OutOfMemory;
00200
00201 GLShaderStatus status = shader->compile(source);
00202 if (status != ShaderStatus_OK)
00203 {
00204 if (g_shaderLogFile != NULL)
00205 {
00206 *g_shaderLogFile << "Error compiling vertex shader:\n";
00207 *g_shaderLogFile << GetInfoLog(shader->getID());
00208 }
00209 return status;
00210 }
00211
00212 *vs = shader;
00213
00214 return ShaderStatus_OK;
00215 }
00216
00217
00218 GLShaderStatus
00219 GLShaderLoader::CreateFragmentShader(const vector<string>& source,
00220 GLFragmentShader** fs)
00221 {
00222 GLint fsid = glx::glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
00223
00224 GLFragmentShader* shader = new GLFragmentShader(fsid);
00225 if (!shader)
00226 return ShaderStatus_OutOfMemory;
00227
00228 GLShaderStatus status = shader->compile(source);
00229 if (status != ShaderStatus_OK)
00230 {
00231 if (g_shaderLogFile != NULL)
00232 {
00233 *g_shaderLogFile << "Error compiling fragment shader:\n";
00234 *g_shaderLogFile << GetInfoLog(shader->getID());
00235 }
00236 return status;
00237 }
00238
00239 *fs = shader;
00240
00241 return ShaderStatus_OK;
00242 }
00243
00244
00245 GLShaderStatus
00246 GLShaderLoader::CreateVertexShader(const string& source,
00247 GLVertexShader** vs)
00248
00249 {
00250 vector<string> v;
00251 v.push_back(source);
00252 return CreateVertexShader(v, vs);
00253 }
00254
00255
00256 GLShaderStatus
00257 GLShaderLoader::CreateFragmentShader(const string& source,
00258 GLFragmentShader** fs)
00259 {
00260 vector<string> v;
00261 v.push_back(source);
00262 return CreateFragmentShader(v, fs);
00263 }
00264
00265
00266 GLShaderStatus
00267 GLShaderLoader::CreateProgram(const GLVertexShader& vs,
00268 const GLFragmentShader& fs,
00269 GLProgram** progOut)
00270 {
00271 GLint progid = glx::glCreateProgramObjectARB();
00272
00273 GLProgram* prog = new GLProgram(progid);
00274 if (!prog)
00275 return ShaderStatus_OutOfMemory;
00276
00277 prog->attach(vs);
00278 prog->attach(fs);
00279
00280 *progOut = prog;
00281
00282 return ShaderStatus_OK;
00283 }
00284
00285
00286 GLShaderStatus
00287 GLShaderLoader::CreateProgram(const vector<string>& vsSource,
00288 const vector<string>& fsSource,
00289 GLProgram** progOut)
00290 {
00291 GLVertexShader* vs = NULL;
00292 GLShaderStatus status = CreateVertexShader(vsSource, &vs);
00293 if (status != ShaderStatus_OK)
00294 return status;
00295
00296 GLFragmentShader* fs = NULL;
00297 status = CreateFragmentShader(fsSource, &fs);
00298 if (status != ShaderStatus_OK)
00299 {
00300 delete vs;
00301 return status;
00302 }
00303
00304 GLProgram* prog = NULL;
00305 status = CreateProgram(*vs, *fs, &prog);
00306 if (status != ShaderStatus_OK)
00307 {
00308 delete vs;
00309 delete fs;
00310 return status;
00311 }
00312
00313 *progOut = prog;
00314
00315
00316 delete vs;
00317 delete fs;
00318
00319 return ShaderStatus_OK;
00320 }
00321
00322
00323 GLShaderStatus
00324 GLShaderLoader::CreateProgram(const string& vsSource,
00325 const string& fsSource,
00326 GLProgram** progOut)
00327 {
00328 vector<string> vsSourceVec;
00329 vsSourceVec.push_back(vsSource);
00330 vector<string> fsSourceVec;
00331 fsSourceVec.push_back(fsSource);
00332
00333 return CreateProgram(vsSourceVec, fsSourceVec, progOut);
00334 }
00335
00336
00337 const string
00338 GetInfoLog(int obj)
00339 {
00340 int logLength = 0;
00341 int charsWritten = 0;
00342
00343 glx::glGetObjectParameterivARB(obj, GL_OBJECT_INFO_LOG_LENGTH_ARB,
00344 &logLength);
00345 if (logLength <= 0)
00346 return string();
00347
00348 char* log = new char[logLength];
00349 if (log == NULL)
00350 return string();
00351
00352 glx::glGetInfoLogARB(obj, logLength, &charsWritten, log);
00353
00354 return string(log, charsWritten);
00355 }