glc_shader.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00026
00027 #include "glc_shader.h"
00028 #include <QTextStream>
00029 #include <QMutexLocker>
00030 #include "../glc_exception.h"
00031 #include "../glc_state.h"
00032
00033
00034 QStack<GLuint> GLC_Shader::m_ProgrammStack;
00035
00036 GLuint GLC_Shader::m_CurrentProgramm= 0;
00037
00038 QMutex GLC_Shader::m_Mutex;
00039
00040
00041 GLC_Shader::GLC_Shader()
00042 : m_VertexByteArray()
00043 , m_VertexShader(0)
00044 , m_FragmentByteArray()
00045 , m_FragmentShader(0)
00046 , m_ProgramShader(0)
00047 , m_Name("Empty Shader")
00048 {
00049 qDebug() << "Create Shader";
00050 }
00051
00052
00053 GLC_Shader::GLC_Shader(QFile& vertex, QFile& fragment)
00054 : m_VertexByteArray()
00055 , m_VertexShader(0)
00056 , m_FragmentByteArray()
00057 , m_FragmentShader(0)
00058 , m_ProgramShader(0)
00059 , m_Name()
00060 {
00061 qDebug() << "Create Shader";
00062 setVertexAndFragmentShader(vertex, fragment);
00063 }
00064
00065
00066 GLC_Shader::GLC_Shader(const GLC_Shader& shader)
00067 : m_VertexByteArray(shader.m_VertexByteArray)
00068 , m_VertexShader(0)
00069 , m_FragmentByteArray(shader.m_FragmentByteArray)
00070 , m_FragmentShader(0)
00071 , m_ProgramShader(0)
00072 , m_Name(shader.m_Name)
00073 {
00074 qDebug() << "Create Shader";
00075 if (0 != shader.m_ProgramShader)
00076 {
00077 createAndCompileProgrammShader();
00078 }
00079 }
00080
00081 GLC_Shader::~GLC_Shader()
00082 {
00083 qDebug() << "GLC_Shader::~GLC_Shader";
00084 deleteShader();
00085 }
00086
00088
00090
00091
00092 bool GLC_Shader::canBeDeleted() const
00093 {
00094 return m_CurrentProgramm != m_ProgramShader;
00095 }
00096
00098
00100
00101
00102 void GLC_Shader::use()
00103 {
00104 if (GLC_State::isInSelectionMode()) return;
00105
00106 Q_ASSERT(0 != m_ProgramShader);
00107
00108 if (glIsProgram(m_ProgramShader) != GL_TRUE)
00109 {
00110 QString message("GLC_Shader::use() m_ProgramShader is not a valid program shader ");
00111 GLC_Exception exception(message);
00112 throw(exception);
00113 }
00114
00115 QMutexLocker locker(&m_Mutex);
00116
00117 if (m_CurrentProgramm != m_ProgramShader)
00118 {
00119 if (m_CurrentProgramm != 0)
00120 {
00121 m_ProgrammStack.push(m_CurrentProgramm);
00122 }
00123 m_CurrentProgramm= m_ProgramShader;
00124 glUseProgram(m_CurrentProgramm);
00125 }
00126
00127 }
00128
00129
00130 void GLC_Shader::use(GLuint shaderId)
00131 {
00132 if (GLC_State::isInSelectionMode()) return;
00133
00134
00135 if (m_CurrentProgramm != shaderId)
00136 {
00137 if (m_CurrentProgramm != 0)
00138 {
00139 m_ProgrammStack.push(shaderId);
00140 }
00141 m_CurrentProgramm= shaderId;
00142 glUseProgram(m_CurrentProgramm);
00143 }
00144 else if (glIsProgram(shaderId) != GL_TRUE)
00145 {
00146 QString message("GLC_Shader::use(GLuint id) id is not a valid program shader ");
00147 GLC_Exception exception(message);
00148 throw(exception);
00149 }
00150
00151 }
00152
00153
00154
00155 void GLC_Shader::unuse()
00156 {
00157 if (GLC_State::isInSelectionMode()) return;
00158
00159 QMutexLocker locker(&m_Mutex);
00160 if (m_ProgrammStack.isEmpty())
00161 {
00162 m_CurrentProgramm= 0;
00163 }
00164 else
00165 {
00166 m_CurrentProgramm= m_ProgrammStack.pop();
00167 }
00168 glUseProgram(m_CurrentProgramm);
00169 }
00170
00171 void GLC_Shader::createAndCompileProgrammShader()
00172 {
00173 Q_ASSERT(0 == m_ProgramShader);
00174
00175 createAndLinkVertexShader();
00176 createAndLinkFragmentShader();
00177
00178 m_ProgramShader = glCreateProgram();
00179 glAttachShader(m_ProgramShader, m_VertexShader);
00180 glAttachShader(m_ProgramShader, m_FragmentShader);
00181
00182 glLinkProgram(m_ProgramShader);
00183
00184
00185 GLint params;
00186 glGetProgramiv(m_ProgramShader, GL_LINK_STATUS, ¶ms);
00187 if (params != GL_TRUE)
00188 {
00189 QString message("GLC_Shader::setVertexAndFragmentShader Failed to link program ");
00190 GLC_Exception exception(message);
00191 throw(exception);
00192 }
00193 }
00194
00195
00196 void GLC_Shader::createAndLinkVertexShader()
00197 {
00198 const char* pVertexShaderData= m_VertexByteArray.data();
00199
00200 m_VertexShader = glCreateShader(GL_VERTEX_SHADER);
00201 glShaderSource(m_VertexShader, 1, &pVertexShaderData, NULL);
00202 glCompileShader(m_VertexShader);
00203
00204
00205 GLint params;
00206 glGetShaderiv(m_VertexShader, GL_COMPILE_STATUS, ¶ms);
00207 if (params != GL_TRUE)
00208 {
00209 QString message("GLC_Shader::createAndLinkVertexShader Failed to compile Vertex shader");
00210 GLC_Exception exception(message);
00211 throw(exception);
00212 }
00213 }
00214
00215 void GLC_Shader::deleteShader()
00216 {
00217 qDebug() << "delete Shader";
00218 if (m_ProgramShader != 0)
00219 {
00220
00221 if (m_CurrentProgramm == m_ProgramShader)
00222 {
00223 qDebug() << "Warning deleting current shader";
00224 }
00225
00226 if (m_ProgrammStack.contains(m_ProgramShader))
00227 {
00228 int indexToDelete= m_ProgrammStack.indexOf(m_ProgramShader);
00229 while (indexToDelete != -1)
00230 {
00231 m_ProgrammStack.remove(indexToDelete);
00232 indexToDelete= m_ProgrammStack.indexOf(m_ProgramShader);
00233 }
00234 }
00235
00236 glDetachShader(m_ProgramShader, m_VertexShader);
00237 glDetachShader(m_ProgramShader, m_FragmentShader);
00238
00239 glDeleteShader(m_VertexShader);
00240 m_VertexShader= 0;
00241 glDeleteShader(m_FragmentShader);
00242 m_FragmentShader= 0;
00243
00244 glDeleteProgram(m_ProgramShader);
00245 m_ProgramShader= 0;
00246 }
00247
00248 }
00249
00250
00251 void GLC_Shader::createAndLinkFragmentShader()
00252 {
00253 const char* pFragmentShaderData= m_FragmentByteArray.data();
00254
00255 m_FragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
00256 glShaderSource(m_FragmentShader, 1, &pFragmentShaderData, NULL);
00257 glCompileShader(m_FragmentShader);
00258
00259
00260 GLint params;
00261 glGetShaderiv(m_FragmentShader, GL_COMPILE_STATUS, ¶ms);
00262 if (params != GL_TRUE)
00263 {
00264 QString message("GLC_Shader::createAndLinkFragmentShader Failed to compile fragment shader");
00265 GLC_Exception exception(message);
00266 throw(exception);
00267 }
00268 }
00269
00271
00273
00274
00275 void GLC_Shader::setVertexAndFragmentShader(QFile& vertexFile, QFile& fragmentFile)
00276 {
00277 m_Name= QFileInfo(vertexFile).baseName();
00278 setVertexShader(vertexFile);
00279 setFragmentShader(fragmentFile);
00280 }
00281
00282
00283 void GLC_Shader::replaceShader(const GLC_Shader& sourceShader)
00284 {
00285 Q_ASSERT(isUsable() == sourceShader.isUsable());
00286
00287
00288 if (this == &sourceShader)
00289 {
00290 return;
00291 }
00292 m_VertexByteArray= sourceShader.m_VertexByteArray;
00293 m_FragmentByteArray= sourceShader.m_FragmentByteArray;
00294
00295 if (isUsable())
00296 {
00297 const GLuint oldShaderId= m_ProgramShader;
00298
00299
00300 glDetachShader(m_ProgramShader, m_VertexShader);
00301 glDetachShader(m_ProgramShader, m_FragmentShader);
00302
00303 glDeleteShader(m_VertexShader);
00304 glDeleteShader(m_FragmentShader);
00305
00306 glDeleteProgram(m_ProgramShader);
00307
00308
00309 m_ProgramShader= 0;
00310 m_VertexShader= 0;
00311 m_FragmentShader= 0;
00312
00313
00314 createAndCompileProgrammShader();
00315
00316
00317 if (m_ProgrammStack.contains(oldShaderId))
00318 {
00319 int indexToReplace= m_ProgrammStack.indexOf(oldShaderId);
00320 while (indexToReplace != -1)
00321 {
00322 m_ProgrammStack.replace(indexToReplace, m_ProgramShader);
00323 indexToReplace= m_ProgrammStack.indexOf(oldShaderId);
00324 }
00325 }
00326
00327 if (oldShaderId == m_CurrentProgramm)
00328 {
00329 m_CurrentProgramm= m_ProgramShader;
00330
00331 glUseProgram(m_CurrentProgramm);
00332 }
00333 }
00334 }
00335
00337
00339
00340 void GLC_Shader::setVertexShader(QFile& vertexFile)
00341 {
00342 Q_ASSERT(0 == m_ProgramShader);
00343 m_VertexByteArray= readShaderFile(vertexFile);
00344 }
00345
00346
00347 void GLC_Shader::setFragmentShader(QFile& fragmentFile)
00348 {
00349 Q_ASSERT(0 == m_ProgramShader);
00350 m_FragmentByteArray= readShaderFile(fragmentFile);
00351 }
00352
00353
00354 QByteArray GLC_Shader::readShaderFile(QFile& shaderFile)
00355 {
00356 if (!shaderFile.open(QIODevice::ReadOnly))
00357 {
00358 QString message(QString("GLC_Shader::readShaderFile Failed to open file : ") + shaderFile.fileName());
00359 GLC_Exception exception(message);
00360 throw(exception);
00361 }
00362 QByteArray result(shaderFile.readAll());
00363 result.append('\0');
00364 return result;
00365 }
00366