Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members

glshader.cpp

Go to the documentation of this file.
00001 // glshader.cpp
00002 //
00003 // Copyright (C) 2001-2004, Chris Laurel <claurel@shatters.net>
00004 //
00005 // This program is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU General Public License
00007 // as published by the Free Software Foundation; either version 2
00008 // of the License, or (at your option) any later version.
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     // Convert vector of shader source strings to an array for OpenGL
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     // Copy shader source to OpenGL
00049     glx::glShaderSourceARB(id, source.size(), sourceStrings, NULL);
00050     delete[] sourceStrings;
00051 
00052     // Actually compile the shader
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 //************* GLxxxProperty **********
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 //************* GLProgram **************
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 //************* GLShaderLoader ************
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     // No need to keep these around--the program doesn't reference them
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 }

Generated on Sat Jan 14 22:30:27 2006 for Celestia by  doxygen 1.4.1