glc_shader.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 
00003  This file is part of the GLC-lib library.
00004  Copyright (C) 2005-2008 Laurent Ribon (laumaya@users.sourceforge.net)
00005  http://glc-lib.sourceforge.net
00006 
00007  GLC-lib is free software; you can redistribute it and/or modify
00008  it under the terms of the GNU Lesser General Public License as published by
00009  the Free Software Foundation; either version 3 of the License, or
00010  (at your option) any later version.
00011 
00012  GLC-lib is distributed in the hope that it will be useful,
00013  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  GNU Lesser General Public License for more details.
00016 
00017  You should have received a copy of the GNU Lesser General Public License
00018  along with GLC-lib; if not, write to the Free Software
00019  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00020 
00021 *****************************************************************************/
00022 
00024 
00025 #include "glc_shader.h"
00026 #include <QTextStream>
00027 #include <QMutexLocker>
00028 #include "../glc_exception.h"
00029 #include "../glc_state.h"
00030 #include "../glc_context.h"
00031 #include "glc_light.h"
00032 
00033 // Static member initialization
00034 QStack<GLC_uint> GLC_Shader::m_ShadingGroupStack;
00035 GLuint GLC_Shader::m_CurrentShadingGroupId= 0;
00036 QHash<GLC_uint, GLC_Shader*> GLC_Shader::m_ShaderProgramHash;
00037 
00038 GLC_Shader::GLC_Shader()
00039 : m_VertexShader(QGLShader::Vertex)
00040 , m_FragmentShader(QGLShader::Fragment)
00041 , m_ProgramShader()
00042 , m_ProgramShaderId(glc::GLC_GenShaderGroupID())
00043 , m_Name("Empty Shader")
00044 , m_PositionAttributeId(-1)
00045 , m_TextcoordAttributeId(-1)
00046 , m_ColorAttributeId(-1)
00047 , m_NormalAttributeId(-1)
00048 , m_ModelViewLocationId(-1)
00049 , m_MvpLocationId(-1)
00050 , m_InvModelViewLocationId(-1)
00051 , m_EnableLightingId(-1)
00052 , m_LightsEnableStateId(-1)
00053 , m_LightsPositionId()
00054 , m_LightsAmbientColorId()
00055 , m_LightsDiffuseColorId()
00056 , m_LightsSpecularColorId()
00057 , m_LightsSpotDirectionId()
00058 , m_LightsAttenuationFactorsId()
00059 , m_LightsSpotExponentId()
00060 , m_LightsSpotCutoffAngleId()
00061 , m_LightsComputeDistanceAttenuationId()
00062 {
00063         initLightsUniformId();
00064         m_ShaderProgramHash.insert(m_ProgramShaderId, this);
00065 }
00066 
00067 GLC_Shader::GLC_Shader(QFile& vertex, QFile& fragment)
00068 : m_VertexShader(QGLShader::Vertex)
00069 , m_FragmentShader(QGLShader::Fragment)
00070 , m_ProgramShader()
00071 , m_ProgramShaderId(glc::GLC_GenShaderGroupID())
00072 , m_Name("Empty Shader")
00073 , m_PositionAttributeId(-1)
00074 , m_TextcoordAttributeId(-1)
00075 , m_ColorAttributeId(-1)
00076 , m_NormalAttributeId(-1)
00077 , m_ModelViewLocationId(-1)
00078 , m_MvpLocationId(-1)
00079 , m_InvModelViewLocationId(-1)
00080 , m_EnableLightingId(-1)
00081 , m_LightsEnableStateId(-1)
00082 , m_LightsPositionId()
00083 , m_LightsAmbientColorId()
00084 , m_LightsDiffuseColorId()
00085 , m_LightsSpecularColorId()
00086 , m_LightsSpotDirectionId()
00087 , m_LightsAttenuationFactorsId()
00088 , m_LightsSpotExponentId()
00089 , m_LightsSpotCutoffAngleId()
00090 , m_LightsComputeDistanceAttenuationId()
00091 {
00092         initLightsUniformId();
00093         m_ShaderProgramHash.insert(m_ProgramShaderId, this);
00094         setVertexAndFragmentShader(vertex, fragment);
00095 }
00096 
00097 GLC_Shader::GLC_Shader(const GLC_Shader& shader)
00098 : m_VertexShader(QGLShader::Vertex)
00099 , m_FragmentShader(QGLShader::Fragment)
00100 , m_ProgramShader()
00101 , m_ProgramShaderId(glc::GLC_GenShaderGroupID())
00102 , m_Name(shader.m_Name)
00103 , m_PositionAttributeId(-1)
00104 , m_TextcoordAttributeId(-1)
00105 , m_ColorAttributeId(-1)
00106 , m_NormalAttributeId(-1)
00107 , m_ModelViewLocationId(-1)
00108 , m_MvpLocationId(-1)
00109 , m_InvModelViewLocationId(-1)
00110 , m_EnableLightingId(-1)
00111 , m_LightsEnableStateId(-1)
00112 , m_LightsPositionId()
00113 , m_LightsAmbientColorId()
00114 , m_LightsDiffuseColorId()
00115 , m_LightsSpecularColorId()
00116 , m_LightsSpotDirectionId()
00117 , m_LightsAttenuationFactorsId()
00118 , m_LightsSpotExponentId()
00119 , m_LightsSpotCutoffAngleId()
00120 , m_LightsComputeDistanceAttenuationId()
00121 {
00122         initLightsUniformId();
00123         m_ShaderProgramHash.insert(m_ProgramShaderId, this);
00124 
00125         if (shader.m_VertexShader.isCompiled())
00126         {
00127                 m_VertexShader.compileSourceCode(shader.m_VertexShader.sourceCode());
00128         }
00129         if (shader.m_FragmentShader.isCompiled())
00130         {
00131                 m_FragmentShader.compileSourceCode(shader.m_FragmentShader.sourceCode());
00132         }
00133 
00134         createAndCompileProgrammShader();
00135 }
00136 
00137 GLC_Shader::~GLC_Shader()
00138 {
00139         deleteShader();
00140 }
00141 
00143 // Get Functions
00145 
00146 bool GLC_Shader::canBeDeleted() const
00147 {
00148         return m_CurrentShadingGroupId != m_ProgramShaderId;
00149 }
00150 
00151 int GLC_Shader::shaderCount()
00152 {
00153         return m_ShaderProgramHash.size();
00154 }
00155 
00156 bool GLC_Shader::asShader(GLC_uint shadingGroupId)
00157 {
00158         return m_ShaderProgramHash.contains(shadingGroupId);
00159 }
00160 
00161 GLC_Shader* GLC_Shader::shaderHandle(GLC_uint shadingGroupId)
00162 {
00163         return m_ShaderProgramHash.value(shadingGroupId);
00164 }
00165 
00166 bool GLC_Shader::hasActiveShader()
00167 {
00168         return 0 != m_CurrentShadingGroupId;
00169 }
00170 
00171 GLC_Shader* GLC_Shader::currentShaderHandle()
00172 {
00173         return m_ShaderProgramHash.value(m_CurrentShadingGroupId);
00174 }
00175 
00177 // OpenGL Functions
00179 
00180 void GLC_Shader::use()
00181 {
00182         if (GLC_State::isInSelectionMode()) return;
00183         // Program shader must be valid
00184         Q_ASSERT(m_ProgramShader.isLinked());
00185 
00186         m_ShadingGroupStack.push(m_ProgramShaderId);
00187         // Test if the program shader is not already the current one
00188         if (m_CurrentShadingGroupId != m_ProgramShaderId)
00189         {
00190                 m_CurrentShadingGroupId= m_ProgramShaderId;
00191                 m_ShaderProgramHash.value(m_CurrentShadingGroupId)->m_ProgramShader.bind();
00192                 GLC_Context::current()->updateUniformVariables();
00193         }
00194 
00195 }
00196 
00197 bool GLC_Shader::use(GLC_uint shaderId)
00198 {
00199         Q_ASSERT(0 != shaderId);
00200         if (GLC_State::isInSelectionMode()) return false;
00201 
00202         if (m_ShaderProgramHash.contains(shaderId))
00203         {
00204                 m_ShadingGroupStack.push(shaderId);
00205                 // Test if the program shader is not already the current one
00206                 if (m_CurrentShadingGroupId != shaderId)
00207                 {
00208                         m_CurrentShadingGroupId= shaderId;
00209                         m_ShaderProgramHash.value(m_CurrentShadingGroupId)->m_ProgramShader.bind();
00210                         GLC_Context::current()->updateUniformVariables();
00211                 }
00212 
00213                 return true;
00214         }
00215         else
00216         {
00217                 return false;
00218         }
00219 }
00220 
00221 void GLC_Shader::unuse()
00222 {
00223 
00224         if (GLC_State::isInSelectionMode()) return;
00225 
00226         Q_ASSERT(!m_ShadingGroupStack.isEmpty());
00227 
00228         const GLC_uint stackShadingGroupId= m_ShadingGroupStack.pop();
00229         if (m_ShadingGroupStack.isEmpty())
00230         {
00231                 m_CurrentShadingGroupId= 0;
00232                 m_ShaderProgramHash.value(stackShadingGroupId)->m_ProgramShader.release();
00233         }
00234         else
00235         {
00236                 m_CurrentShadingGroupId= m_ShadingGroupStack.top();
00237                 m_ShaderProgramHash.value(m_CurrentShadingGroupId)->m_ProgramShader.bind();
00238         }
00239 }
00240 
00241 void GLC_Shader::createAndCompileProgrammShader()
00242 {
00243         qDebug() << "GLC_Shader::createAndCompileProgrammShader()";
00244         m_ProgramShader.addShader(&m_VertexShader);
00245         m_ProgramShader.addShader(&m_FragmentShader);
00246 
00247         if (!m_ProgramShader.link())
00248         {
00249                 QString message("GLC_Shader::setVertexAndFragmentShader Failed to link program ");
00250                 GLC_Exception exception(message);
00251                 throw(exception);
00252         }
00253         else
00254         {
00255                 m_PositionAttributeId= m_ProgramShader.attributeLocation("a_position");
00256                 //qDebug() << "m_PositionAttributeId " << m_PositionAttributeId;
00257                 m_TextcoordAttributeId= m_ProgramShader.attributeLocation("a_textcoord0");
00258                 //qDebug() << "m_TextcoordAttributeId " << m_TextcoordAttributeId;
00259                 m_ColorAttributeId= m_ProgramShader.attributeLocation("a_color");
00260                 //qDebug() << "m_ColorAttributeId " << m_ColorAttributeId;
00261                 m_NormalAttributeId= m_ProgramShader.attributeLocation("a_normal");
00262                 //qDebug() << "m_NormalAttributeId " << m_NormalAttributeId;
00263 
00264                 m_ModelViewLocationId= m_ProgramShader.uniformLocation("modelview_matrix");
00265                 //qDebug() << "m_ModelViewLocationId " << m_ModelViewLocationId;
00266                 m_MvpLocationId= m_ProgramShader.uniformLocation("mvp_matrix");
00267                 //qDebug() << "m_MvpLocationId " << m_MvpLocationId;
00268                 m_InvModelViewLocationId= m_ProgramShader.uniformLocation("inv_modelview_matrix");
00269                 //qDebug() << "m_InvModelViewLocationId " << m_InvModelViewLocationId;
00270                 m_EnableLightingId= m_ProgramShader.uniformLocation("enable_lighting");
00271                 //qDebug() << "m_EnableLightingId " << m_EnableLightingId;
00272                 m_LightsEnableStateId= m_ProgramShader.uniformLocation("light_enable_state");
00273                 //qDebug() << "m_LightsEnableStateId " << m_LightsEnableStateId;
00274                 const int size= GLC_Light::maxLightCount();
00275                 for (int i= (GL_LIGHT0); i < (size + GL_LIGHT0); ++i)
00276                 {
00277                         m_LightsPositionId[i]= m_ProgramShader.uniformLocation("light_state[" + QString::number(i) + "].position");
00278                         //qDebug() << "Position id " << m_LightsPositionId.value(i);
00279                         m_LightsAmbientColorId[i]= m_ProgramShader.uniformLocation("light_state[" + QString::number(i) + "].ambient_color");
00280                         //qDebug() << "m_LightsAmbientColorId " << m_LightsAmbientColorId.value(i);
00281                         m_LightsDiffuseColorId[i]= m_ProgramShader.uniformLocation("light_state[" + QString::number(i) + "].diffuse_color");
00282                         //qDebug() << "m_LightsDiffuseColorId " << m_LightsDiffuseColorId.value(i);
00283                         m_LightsSpecularColorId[i]= m_ProgramShader.uniformLocation("light_state[" + QString::number(i) + "].specular_color");
00284                         //qDebug() << "m_LightsSpecularColorId " << m_LightsSpecularColorId.value(i);
00285                         m_LightsSpotDirectionId[i]= m_ProgramShader.uniformLocation("light_state[" + QString::number(i) + "].spot_direction");
00286                         //qDebug() << "m_LightsSpotDirectionId " << m_LightsSpotDirectionId.value(i);
00287                         m_LightsAttenuationFactorsId[i]= m_ProgramShader.uniformLocation("light_state[" + QString::number(i) + "].attenuation_factors");
00288                         //qDebug() << "m_LightsAttenuationFactorsId " << m_LightsAttenuationFactorsId.value(i);
00289                         m_LightsSpotExponentId[i]= m_ProgramShader.uniformLocation("light_state[" + QString::number(i) + "].spot_exponent");
00290                         //qDebug() << "m_LightsSpotExponentId " << m_LightsSpotExponentId.value(i);
00291                         m_LightsSpotCutoffAngleId[i]= m_ProgramShader.uniformLocation("light_state[" + QString::number(i) + "].spot_cutoff_angle");
00292                         //qDebug() << "m_LightsSpotCutoffAngleId " << m_LightsSpotCutoffAngleId.value(i);
00293                         m_LightsComputeDistanceAttenuationId[i]= m_ProgramShader.uniformLocation("light_state[" + QString::number(i) + "].compute_distance_attenuation");
00294                         //qDebug() << "m_LightsComputeDistanceAttenuationId " << m_LightsComputeDistanceAttenuationId.value(i);
00295 
00296 
00297                 }
00298         }
00299 }
00300 
00301 void GLC_Shader::deleteShader()
00302 {
00303         if (m_ProgramShaderId != 0)
00304         {
00305                 // Test if the shader is the current one
00306                 if (m_CurrentShadingGroupId == m_ProgramShaderId)
00307                 {
00308                         qDebug() << "Warning deleting current shader";
00309                 }
00310                 //removing shader id from the stack
00311                 if (m_ShadingGroupStack.contains(m_ProgramShaderId))
00312                 {
00313                         int indexToDelete= m_ShadingGroupStack.indexOf(m_ProgramShaderId);
00314                         while (indexToDelete != -1)
00315                         {
00316                                 m_ShadingGroupStack.remove(indexToDelete);
00317                                 indexToDelete= m_ShadingGroupStack.indexOf(m_ProgramShaderId);
00318                         }
00319                 }
00320                 m_ShaderProgramHash.remove(m_ProgramShaderId);
00321         }
00322 
00323 }
00324 
00326 // Set Functions
00328 
00329 
00330 void GLC_Shader::setVertexAndFragmentShader(QFile& vertexFile, QFile& fragmentFile)
00331 {
00332         m_Name= QFileInfo(vertexFile).baseName();
00333         vertexFile.open(QIODevice::ReadOnly);
00334         m_VertexShader.compileSourceCode(vertexFile.readAll());
00335         vertexFile.close();
00336 
00337         fragmentFile.open(QIODevice::ReadOnly);
00338         m_FragmentShader.compileSourceCode(fragmentFile.readAll());
00339         fragmentFile.close();
00340 }
00341 
00342 
00343 void GLC_Shader::replaceShader(const GLC_Shader& sourceShader)
00344 {
00345         Q_ASSERT(isUsable() == sourceShader.isUsable());
00346 
00347         // Test if the source shader is the same than this shader
00348         if (this == &sourceShader)
00349         {
00350                 return;
00351         }
00352         m_ProgramShader.removeAllShaders();
00353 
00354         if (sourceShader.m_VertexShader.isCompiled())
00355         {
00356                 m_VertexShader.compileSourceCode(sourceShader.m_VertexShader.sourceCode());
00357         }
00358         if (sourceShader.m_FragmentShader.isCompiled())
00359         {
00360                 m_FragmentShader.compileSourceCode(sourceShader.m_FragmentShader.sourceCode());
00361         }
00362 
00363         m_ProgramShader.link();
00364 
00365 }
00366 
00367 void GLC_Shader::initLightsUniformId()
00368 {
00369         m_LightsPositionId.clear();
00370         m_LightsAmbientColorId.clear();
00371         m_LightsDiffuseColorId.clear();
00372         m_LightsSpecularColorId.clear();
00373         m_LightsSpotDirectionId.clear();
00374         m_LightsAttenuationFactorsId.clear();
00375         m_LightsSpotExponentId.clear();
00376         m_LightsSpotCutoffAngleId.clear();
00377         m_LightsComputeDistanceAttenuationId.clear();
00378 
00379         for (int i= 0; i < GLC_Light::maxLightCount(); ++i)
00380         {
00381                 m_LightsPositionId.insert(GL_LIGHT0 + i, -1);
00382                 m_LightsAmbientColorId.insert(GL_LIGHT0 + i, -1);
00383                 m_LightsDiffuseColorId.insert(GL_LIGHT0 + i, -1);
00384                 m_LightsSpecularColorId.insert(GL_LIGHT0 + i, -1);
00385                 m_LightsSpotDirectionId.insert(GL_LIGHT0 + i, -1);
00386                 m_LightsAttenuationFactorsId.insert(GL_LIGHT0 + i, -1);
00387                 m_LightsSpotExponentId.insert(GL_LIGHT0 + i, -1);
00388                 m_LightsSpotCutoffAngleId.insert(GL_LIGHT0 + i, -1);
00389                 m_LightsComputeDistanceAttenuationId.insert(GL_LIGHT0 + i, -1);
00390         }
00391 }
00392 

SourceForge.net Logo

©2005-2011 Laurent Ribon