GLC_lib  2.5.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
glc_shader.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 
3  This file is part of the GLC-lib library.
4  Copyright (C) 2005-2008 Laurent Ribon (laumaya@users.sourceforge.net)
5  http://glc-lib.sourceforge.net
6 
7  GLC-lib is free software; you can redistribute it and/or modify
8  it under the terms of the GNU Lesser General Public License as published by
9  the Free Software Foundation; either version 3 of the License, or
10  (at your option) any later version.
11 
12  GLC-lib is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU Lesser General Public License for more details.
16 
17  You should have received a copy of the GNU Lesser General Public License
18  along with GLC-lib; if not, write to the Free Software
19  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 
21 *****************************************************************************/
22 
24 
25 #include "glc_shader.h"
26 #include <QTextStream>
27 #include <QMutexLocker>
28 #include "../glc_exception.h"
29 #include "../glc_state.h"
30 #include "../glc_context.h"
31 #include "glc_light.h"
32 
33 // Static member initialization
34 QStack<GLC_uint> GLC_Shader::m_ShadingGroupStack;
36 QHash<GLC_uint, GLC_Shader*> GLC_Shader::m_ShaderProgramHash;
37 
39 : m_VertexShader(QGLShader::Vertex)
40 , m_FragmentShader(QGLShader::Fragment)
41 , m_ProgramShader()
42 , m_ProgramShaderId(glc::GLC_GenShaderGroupID())
43 , m_Name("Empty Shader")
44 , m_PositionAttributeId(-1)
45 , m_TextcoordAttributeId(-1)
46 , m_ColorAttributeId(-1)
47 , m_NormalAttributeId(-1)
48 , m_ModelViewLocationId(-1)
49 , m_MvpLocationId(-1)
50 , m_InvModelViewLocationId(-1)
51 , m_EnableLightingId(-1)
52 , m_LightsEnableStateId(-1)
53 , m_LightsPositionId()
54 , m_LightsAmbientColorId()
55 , m_LightsDiffuseColorId()
56 , m_LightsSpecularColorId()
57 , m_LightsSpotDirectionId()
58 , m_LightsAttenuationFactorsId()
59 , m_LightsSpotExponentId()
60 , m_LightsSpotCutoffAngleId()
61 , m_LightsComputeDistanceAttenuationId()
62 {
65 }
66 
67 GLC_Shader::GLC_Shader(QFile& vertex, QFile& fragment)
68 : m_VertexShader(QGLShader::Vertex)
69 , m_FragmentShader(QGLShader::Fragment)
70 , m_ProgramShader()
71 , m_ProgramShaderId(glc::GLC_GenShaderGroupID())
72 , m_Name("Empty Shader")
73 , m_PositionAttributeId(-1)
74 , m_TextcoordAttributeId(-1)
75 , m_ColorAttributeId(-1)
76 , m_NormalAttributeId(-1)
77 , m_ModelViewLocationId(-1)
78 , m_MvpLocationId(-1)
79 , m_InvModelViewLocationId(-1)
80 , m_EnableLightingId(-1)
81 , m_LightsEnableStateId(-1)
82 , m_LightsPositionId()
83 , m_LightsAmbientColorId()
84 , m_LightsDiffuseColorId()
85 , m_LightsSpecularColorId()
86 , m_LightsSpotDirectionId()
87 , m_LightsAttenuationFactorsId()
88 , m_LightsSpotExponentId()
89 , m_LightsSpotCutoffAngleId()
90 , m_LightsComputeDistanceAttenuationId()
91 {
94  setVertexAndFragmentShader(vertex, fragment);
95 }
96 
98 : m_VertexShader(QGLShader::Vertex)
99 , m_FragmentShader(QGLShader::Fragment)
100 , m_ProgramShader()
101 , m_ProgramShaderId(glc::GLC_GenShaderGroupID())
102 , m_Name(shader.m_Name)
103 , m_PositionAttributeId(-1)
104 , m_TextcoordAttributeId(-1)
105 , m_ColorAttributeId(-1)
106 , m_NormalAttributeId(-1)
107 , m_ModelViewLocationId(-1)
108 , m_MvpLocationId(-1)
109 , m_InvModelViewLocationId(-1)
110 , m_EnableLightingId(-1)
111 , m_LightsEnableStateId(-1)
112 , m_LightsPositionId()
113 , m_LightsAmbientColorId()
114 , m_LightsDiffuseColorId()
115 , m_LightsSpecularColorId()
116 , m_LightsSpotDirectionId()
117 , m_LightsAttenuationFactorsId()
118 , m_LightsSpotExponentId()
119 , m_LightsSpotCutoffAngleId()
120 , m_LightsComputeDistanceAttenuationId()
121 {
124 
125  if (shader.m_VertexShader.isCompiled())
126  {
127  m_VertexShader.compileSourceCode(shader.m_VertexShader.sourceCode());
128  }
129  if (shader.m_FragmentShader.isCompiled())
130  {
131  m_FragmentShader.compileSourceCode(shader.m_FragmentShader.sourceCode());
132  }
133 
135 }
136 
138 {
139  deleteShader();
140 }
141 
143 // Get Functions
145 
147 {
149 }
150 
152 {
153  return m_ShaderProgramHash.size();
154 }
155 
156 bool GLC_Shader::asShader(GLC_uint shadingGroupId)
157 {
158  return m_ShaderProgramHash.contains(shadingGroupId);
159 }
160 
162 {
163  return m_ShaderProgramHash.value(shadingGroupId);
164 }
165 
167 {
168  return 0 != m_CurrentShadingGroupId;
169 }
170 
172 {
174 }
175 
177 // OpenGL Functions
179 
181 {
182  if (GLC_State::isInSelectionMode()) return;
183  // Program shader must be valid
184  Q_ASSERT(m_ProgramShader.isLinked());
185 
187  // Test if the program shader is not already the current one
189  {
191  m_ShaderProgramHash.value(m_CurrentShadingGroupId)->m_ProgramShader.bind();
193  }
194 
195 }
196 
197 bool GLC_Shader::use(GLC_uint shaderId)
198 {
199  Q_ASSERT(0 != shaderId);
200  if (GLC_State::isInSelectionMode()) return false;
201 
202  if (m_ShaderProgramHash.contains(shaderId))
203  {
204  m_ShadingGroupStack.push(shaderId);
205  // Test if the program shader is not already the current one
206  if (m_CurrentShadingGroupId != shaderId)
207  {
208  m_CurrentShadingGroupId= shaderId;
209  m_ShaderProgramHash.value(m_CurrentShadingGroupId)->m_ProgramShader.bind();
211  }
212 
213  return true;
214  }
215  else
216  {
217  return false;
218  }
219 }
220 
222 {
223 
224  if (GLC_State::isInSelectionMode()) return;
225 
226  Q_ASSERT(!m_ShadingGroupStack.isEmpty());
227 
228  const GLC_uint stackShadingGroupId= m_ShadingGroupStack.pop();
229  if (m_ShadingGroupStack.isEmpty())
230  {
232  m_ShaderProgramHash.value(stackShadingGroupId)->m_ProgramShader.release();
233  }
234  else
235  {
237  m_ShaderProgramHash.value(m_CurrentShadingGroupId)->m_ProgramShader.bind();
238  }
239 }
240 
242 {
243  qDebug() << "GLC_Shader::createAndCompileProgrammShader()";
244  m_ProgramShader.addShader(&m_VertexShader);
245  m_ProgramShader.addShader(&m_FragmentShader);
246 
247  if (!m_ProgramShader.link())
248  {
249  QString message("GLC_Shader::setVertexAndFragmentShader Failed to link program ");
250  GLC_Exception exception(message);
251  throw(exception);
252  }
253  else
254  {
255  m_PositionAttributeId= m_ProgramShader.attributeLocation("a_position");
256  //qDebug() << "m_PositionAttributeId " << m_PositionAttributeId;
257  m_TextcoordAttributeId= m_ProgramShader.attributeLocation("a_textcoord0");
258  //qDebug() << "m_TextcoordAttributeId " << m_TextcoordAttributeId;
259  m_ColorAttributeId= m_ProgramShader.attributeLocation("a_color");
260  //qDebug() << "m_ColorAttributeId " << m_ColorAttributeId;
261  m_NormalAttributeId= m_ProgramShader.attributeLocation("a_normal");
262  //qDebug() << "m_NormalAttributeId " << m_NormalAttributeId;
263 
264  m_ModelViewLocationId= m_ProgramShader.uniformLocation("modelview_matrix");
265  //qDebug() << "m_ModelViewLocationId " << m_ModelViewLocationId;
266  m_MvpLocationId= m_ProgramShader.uniformLocation("mvp_matrix");
267  //qDebug() << "m_MvpLocationId " << m_MvpLocationId;
268  m_InvModelViewLocationId= m_ProgramShader.uniformLocation("inv_modelview_matrix");
269  //qDebug() << "m_InvModelViewLocationId " << m_InvModelViewLocationId;
270  m_EnableLightingId= m_ProgramShader.uniformLocation("enable_lighting");
271  //qDebug() << "m_EnableLightingId " << m_EnableLightingId;
272  m_LightsEnableStateId= m_ProgramShader.uniformLocation("light_enable_state");
273  //qDebug() << "m_LightsEnableStateId " << m_LightsEnableStateId;
274  const int size= GLC_Light::maxLightCount();
275  for (int i= (GL_LIGHT0); i < (size + GL_LIGHT0); ++i)
276  {
277  m_LightsPositionId[i]= m_ProgramShader.uniformLocation("light_state[" + QString::number(i) + "].position");
278  //qDebug() << "Position id " << m_LightsPositionId.value(i);
279  m_LightsAmbientColorId[i]= m_ProgramShader.uniformLocation("light_state[" + QString::number(i) + "].ambient_color");
280  //qDebug() << "m_LightsAmbientColorId " << m_LightsAmbientColorId.value(i);
281  m_LightsDiffuseColorId[i]= m_ProgramShader.uniformLocation("light_state[" + QString::number(i) + "].diffuse_color");
282  //qDebug() << "m_LightsDiffuseColorId " << m_LightsDiffuseColorId.value(i);
283  m_LightsSpecularColorId[i]= m_ProgramShader.uniformLocation("light_state[" + QString::number(i) + "].specular_color");
284  //qDebug() << "m_LightsSpecularColorId " << m_LightsSpecularColorId.value(i);
285  m_LightsSpotDirectionId[i]= m_ProgramShader.uniformLocation("light_state[" + QString::number(i) + "].spot_direction");
286  //qDebug() << "m_LightsSpotDirectionId " << m_LightsSpotDirectionId.value(i);
287  m_LightsAttenuationFactorsId[i]= m_ProgramShader.uniformLocation("light_state[" + QString::number(i) + "].attenuation_factors");
288  //qDebug() << "m_LightsAttenuationFactorsId " << m_LightsAttenuationFactorsId.value(i);
289  m_LightsSpotExponentId[i]= m_ProgramShader.uniformLocation("light_state[" + QString::number(i) + "].spot_exponent");
290  //qDebug() << "m_LightsSpotExponentId " << m_LightsSpotExponentId.value(i);
291  m_LightsSpotCutoffAngleId[i]= m_ProgramShader.uniformLocation("light_state[" + QString::number(i) + "].spot_cutoff_angle");
292  //qDebug() << "m_LightsSpotCutoffAngleId " << m_LightsSpotCutoffAngleId.value(i);
293  m_LightsComputeDistanceAttenuationId[i]= m_ProgramShader.uniformLocation("light_state[" + QString::number(i) + "].compute_distance_attenuation");
294  //qDebug() << "m_LightsComputeDistanceAttenuationId " << m_LightsComputeDistanceAttenuationId.value(i);
295 
296 
297  }
298  }
299 }
300 
302 {
303  if (m_ProgramShaderId != 0)
304  {
305  // Test if the shader is the current one
307  {
308  qDebug() << "Warning deleting current shader";
309  }
310  //removing shader id from the stack
312  {
313  int indexToDelete= m_ShadingGroupStack.indexOf(m_ProgramShaderId);
314  while (indexToDelete != -1)
315  {
316  m_ShadingGroupStack.remove(indexToDelete);
317  indexToDelete= m_ShadingGroupStack.indexOf(m_ProgramShaderId);
318  }
319  }
321  }
322 
323 }
324 
326 // Set Functions
328 
329 
330 void GLC_Shader::setVertexAndFragmentShader(QFile& vertexFile, QFile& fragmentFile)
331 {
332  m_Name= QFileInfo(vertexFile).baseName();
333  vertexFile.open(QIODevice::ReadOnly);
334  m_VertexShader.compileSourceCode(vertexFile.readAll());
335  vertexFile.close();
336 
337  fragmentFile.open(QIODevice::ReadOnly);
338  m_FragmentShader.compileSourceCode(fragmentFile.readAll());
339  fragmentFile.close();
340 }
341 
342 
343 void GLC_Shader::replaceShader(const GLC_Shader& sourceShader)
344 {
345  Q_ASSERT(isUsable() == sourceShader.isUsable());
346 
347  // Test if the source shader is the same than this shader
348  if (this == &sourceShader)
349  {
350  return;
351  }
352  m_ProgramShader.removeAllShaders();
353 
354  if (sourceShader.m_VertexShader.isCompiled())
355  {
356  m_VertexShader.compileSourceCode(sourceShader.m_VertexShader.sourceCode());
357  }
358  if (sourceShader.m_FragmentShader.isCompiled())
359  {
360  m_FragmentShader.compileSourceCode(sourceShader.m_FragmentShader.sourceCode());
361  }
362 
363  m_ProgramShader.link();
364 
365 }
366 
368 {
369  m_LightsPositionId.clear();
370  m_LightsAmbientColorId.clear();
371  m_LightsDiffuseColorId.clear();
372  m_LightsSpecularColorId.clear();
373  m_LightsSpotDirectionId.clear();
375  m_LightsSpotExponentId.clear();
378 
379  for (int i= 0; i < GLC_Light::maxLightCount(); ++i)
380  {
381  m_LightsPositionId.insert(GL_LIGHT0 + i, -1);
382  m_LightsAmbientColorId.insert(GL_LIGHT0 + i, -1);
383  m_LightsDiffuseColorId.insert(GL_LIGHT0 + i, -1);
384  m_LightsSpecularColorId.insert(GL_LIGHT0 + i, -1);
385  m_LightsSpotDirectionId.insert(GL_LIGHT0 + i, -1);
386  m_LightsAttenuationFactorsId.insert(GL_LIGHT0 + i, -1);
387  m_LightsSpotExponentId.insert(GL_LIGHT0 + i, -1);
388  m_LightsSpotCutoffAngleId.insert(GL_LIGHT0 + i, -1);
389  m_LightsComputeDistanceAttenuationId.insert(GL_LIGHT0 + i, -1);
390  }
391 }
392 

©2005-2013 Laurent Ribon