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
00024
00025 #include "glc_shader.h"
00026 #include <QTextStream>
00027 #include <QMutexLocker>
00028 #include "../glc_exception.h"
00029 #include "../glc_state.h"
00030
00031
00032 QStack<GLC_uint> GLC_Shader::m_ShadingGroupStack;
00033 GLuint GLC_Shader::m_CurrentShadingGroupId= 0;
00034 QHash<GLC_uint, GLC_Shader*> GLC_Shader::m_ShaderProgramHash;
00035
00036 GLC_Shader::GLC_Shader()
00037 : m_VertexShader(QGLShader::Vertex)
00038 , m_FragmentShader(QGLShader::Fragment)
00039 , m_ProgramShader()
00040 , m_ProgramShaderId(glc::GLC_GenShaderGroupID())
00041 , m_Name("Empty Shader")
00042 {
00043 m_ShaderProgramHash.insert(m_ProgramShaderId, this);
00044 }
00045
00046 GLC_Shader::GLC_Shader(QFile& vertex, QFile& fragment)
00047 : m_VertexShader(QGLShader::Vertex)
00048 , m_FragmentShader(QGLShader::Fragment)
00049 , m_ProgramShader()
00050 , m_ProgramShaderId(glc::GLC_GenShaderGroupID())
00051 , m_Name("Empty Shader")
00052 {
00053 m_ShaderProgramHash.insert(m_ProgramShaderId, this);
00054 setVertexAndFragmentShader(vertex, fragment);
00055 }
00056
00057 GLC_Shader::GLC_Shader(const GLC_Shader& shader)
00058 : m_VertexShader(QGLShader::Vertex)
00059 , m_FragmentShader(QGLShader::Fragment)
00060 , m_ProgramShader()
00061 , m_ProgramShaderId(glc::GLC_GenShaderGroupID())
00062 , m_Name(shader.m_Name)
00063 {
00064 m_ShaderProgramHash.insert(m_ProgramShaderId, this);
00065
00066 if (shader.m_VertexShader.isCompiled())
00067 {
00068 m_VertexShader.compileSourceCode(shader.m_VertexShader.sourceCode());
00069 }
00070 if (shader.m_FragmentShader.isCompiled())
00071 {
00072 m_FragmentShader.compileSourceCode(shader.m_FragmentShader.sourceCode());
00073 }
00074
00075 createAndCompileProgrammShader();
00076 }
00077
00078 GLC_Shader::~GLC_Shader()
00079 {
00080 deleteShader();
00081 }
00082
00084
00086
00087 bool GLC_Shader::canBeDeleted() const
00088 {
00089 return m_CurrentShadingGroupId != m_ProgramShaderId;
00090 }
00091
00092 int GLC_Shader::shaderCount()
00093 {
00094 return m_ShaderProgramHash.size();
00095 }
00096
00097 bool GLC_Shader::asShader(GLC_uint shadingGroupId)
00098 {
00099 return m_ShaderProgramHash.contains(shadingGroupId);
00100 }
00101
00102 GLC_Shader* GLC_Shader::shaderHandle(GLC_uint shadingGroupId)
00103 {
00104 return m_ShaderProgramHash.value(shadingGroupId);
00105 }
00106
00107 bool GLC_Shader::hasActiveShader()
00108 {
00109 return 0 != m_CurrentShadingGroupId;
00110 }
00111
00112 GLC_Shader* GLC_Shader::currentShaderHandle()
00113 {
00114 return m_ShaderProgramHash.value(m_CurrentShadingGroupId);
00115 }
00116
00118
00120
00121 void GLC_Shader::use()
00122 {
00123 if (GLC_State::isInSelectionMode()) return;
00124
00125 Q_ASSERT(m_ProgramShader.isLinked());
00126
00127 m_ShadingGroupStack.push(m_ProgramShaderId);
00128
00129 if (m_CurrentShadingGroupId != m_ProgramShaderId)
00130 {
00131 m_CurrentShadingGroupId= m_ProgramShaderId;
00132 m_ShaderProgramHash.value(m_CurrentShadingGroupId)->m_ProgramShader.bind();
00133 }
00134
00135 }
00136
00137 bool GLC_Shader::use(GLuint shaderId)
00138 {
00139 Q_ASSERT(0 != shaderId);
00140 if (GLC_State::isInSelectionMode()) return false;
00141
00142 if (m_ShaderProgramHash.contains(shaderId))
00143 {
00144 m_ShadingGroupStack.push(shaderId);
00145
00146 if (m_CurrentShadingGroupId != shaderId)
00147 {
00148 m_CurrentShadingGroupId= shaderId;
00149 m_ShaderProgramHash.value(m_CurrentShadingGroupId)->m_ProgramShader.bind();
00150 }
00151 return true;
00152 }
00153 else
00154 {
00155 return false;
00156 }
00157 }
00158
00159 void GLC_Shader::unuse()
00160 {
00161
00162 if (GLC_State::isInSelectionMode()) return;
00163
00164 Q_ASSERT(!m_ShadingGroupStack.isEmpty());
00165
00166 const GLC_uint stackShadingGroupId= m_ShadingGroupStack.pop();
00167 if (m_ShadingGroupStack.isEmpty())
00168 {
00169 m_CurrentShadingGroupId= 0;
00170 m_ShaderProgramHash.value(stackShadingGroupId)->m_ProgramShader.release();
00171 }
00172 else
00173 {
00174 m_CurrentShadingGroupId= m_ShadingGroupStack.top();
00175 m_ShaderProgramHash.value(m_CurrentShadingGroupId)->m_ProgramShader.bind();
00176 }
00177 }
00178
00179 void GLC_Shader::createAndCompileProgrammShader()
00180 {
00181 m_ProgramShader.addShader(&m_VertexShader);
00182 m_ProgramShader.addShader(&m_FragmentShader);
00183
00184 if (!m_ProgramShader.link())
00185 {
00186 QString message("GLC_Shader::setVertexAndFragmentShader Failed to link program ");
00187 GLC_Exception exception(message);
00188 throw(exception);
00189 }
00190 }
00191
00192 void GLC_Shader::deleteShader()
00193 {
00194 if (m_ProgramShaderId != 0)
00195 {
00196
00197 if (m_CurrentShadingGroupId == m_ProgramShaderId)
00198 {
00199 qDebug() << "Warning deleting current shader";
00200 }
00201
00202 if (m_ShadingGroupStack.contains(m_ProgramShaderId))
00203 {
00204 int indexToDelete= m_ShadingGroupStack.indexOf(m_ProgramShaderId);
00205 while (indexToDelete != -1)
00206 {
00207 m_ShadingGroupStack.remove(indexToDelete);
00208 indexToDelete= m_ShadingGroupStack.indexOf(m_ProgramShaderId);
00209 }
00210 }
00211 m_ShaderProgramHash.remove(m_ProgramShaderId);
00212 }
00213
00214 }
00215
00217
00219
00220
00221 void GLC_Shader::setVertexAndFragmentShader(QFile& vertexFile, QFile& fragmentFile)
00222 {
00223 m_Name= QFileInfo(vertexFile).baseName();
00224 vertexFile.open(QIODevice::ReadOnly);
00225 m_VertexShader.compileSourceCode(vertexFile.readAll());
00226 vertexFile.close();
00227
00228 fragmentFile.open(QIODevice::ReadOnly);
00229 m_FragmentShader.compileSourceCode(fragmentFile.readAll());
00230 fragmentFile.close();
00231 }
00232
00233
00234 void GLC_Shader::replaceShader(const GLC_Shader& sourceShader)
00235 {
00236 Q_ASSERT(isUsable() == sourceShader.isUsable());
00237
00238
00239 if (this == &sourceShader)
00240 {
00241 return;
00242 }
00243 m_ProgramShader.removeAllShaders();
00244
00245 if (sourceShader.m_VertexShader.isCompiled())
00246 {
00247 m_VertexShader.compileSourceCode(sourceShader.m_VertexShader.sourceCode());
00248 }
00249 if (sourceShader.m_FragmentShader.isCompiled())
00250 {
00251 m_FragmentShader.compileSourceCode(sourceShader.m_FragmentShader.sourceCode());
00252 }
00253
00254 m_ProgramShader.link();
00255
00256 }
00257