Developer Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
ShaderNode.cc
1 /*===========================================================================*\
2  * *
3  * OpenFlipper *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39  * *
40 \*===========================================================================*/
41 
42 /*===========================================================================*\
43  * *
44  * $Revision$ *
45  * $Author$ *
46  * $Date$ *
47  * *
48 \*===========================================================================*/
49 
50 
51 
52 
53 //=============================================================================
54 //
55 // CLASS ShaderNode - IMPLEMENTATION
56 //
57 //=============================================================================
58 
59 
60 //== INCLUDES =================================================================
61 
62 
63 #include "ShaderNode.hh"
64 
65 
66 //== NAMESPACES ===============================================================
67 
68 namespace ACG {
69 namespace SceneGraph {
70 
71 
72 //== IMPLEMENTATION ==========================================================
73 
74 
76  const std::string& _name)
77  : BaseNode(_parent, _name),
78  shaderDir_("")
79 {
80 }
81 
83  for ( std::map<size_t,ShaderInfo>::iterator it = shaders.begin(); it != shaders.end(); ++it) {
84  if ( it->second.initialized ) {
85 
86  if ( it->second.program != 0 )
87  delete it->second.program;
88 
89  if ( it->second.vertexShader != 0 )
90  delete it->second.vertexShader;
91 
92  if ( it->second.fragmentShader != 0 )
93  delete it->second.fragmentShader;
94  }
95  }
96 }
97 
98 //----------------------------------------------------------------------------
99 bool
101 hasShader( DrawModes::DrawMode _drawmode, bool _pick ) {
102 
103  if ( !_drawmode.isAtomic() ) {
104  std::cerr << "hasShader: Error, draw mode not atomic!" << std::endl;
105  return false;
106  }
107 
108  std::map<size_t,ShaderInfo>::iterator it;
109 
110  if ( _pick ) {
111  it = pickShaders.find(_drawmode.getIndex());
112  if ( it == pickShaders.end() )
113  return false;
114  } else {
115  it = shaders.find(_drawmode.getIndex());
116  if ( it == shaders.end() )
117  return false;
118  }
119 
120  return it->second.initialized;
121 }
122 
123 //----------------------------------------------------------------------------
124 
125 
126 void
127 ShaderNode::enter(GLState& /*_state*/, const DrawModes::DrawMode& _drawmode )
128 {
129  for ( std::map<size_t,ShaderInfo>::iterator it = shaders.begin(); it != shaders.end(); ++it) {
130  if ( _drawmode.containsAtomicDrawMode(it->first) && it->second.initialized ) {
131  it->second.program->use();
132  }
133  }
134 }
135 
136 //----------------------------------------------------------------------------
137 
138 void
139 ShaderNode::enterPick(GLState& /*_state*/, PickTarget /*_target*/, const DrawModes::DrawMode& _drawmode )
140 {
141  for ( std::map<size_t,ShaderInfo>::iterator it = pickShaders.begin(); it != pickShaders.end(); ++it) {
142  if ( _drawmode.containsAtomicDrawMode(it->first) && it->second.initialized ) {
143  it->second.program->use();
144  }
145  }
146 }
147 
148 //----------------------------------------------------------------------------
149 std::string
150 ShaderNode::vertexShaderName(DrawModes::DrawMode _drawmode, bool _pick) {
151 
152  if ( !_drawmode.isAtomic() ) {
153  std::cerr << "vertexShaderName: Error, draw mode not atomic!" << std::endl;
154  return std::string("");
155  }
156 
157  std::map<size_t,ShaderInfo>::iterator it;
158 
159  if ( _pick ) {
160  it = pickShaders.find(_drawmode.getIndex());
161  if ( it == pickShaders.end() )
162  return std::string("");
163  } else {
164  it = shaders.find(_drawmode.getIndex());
165  if ( it == shaders.end() )
166  return std::string("");
167  }
168 
169  if ( it->second.initialized )
170  return it->second.vertexShaderFile;
171 
172  return std::string("");
173 }
174 
175 //----------------------------------------------------------------------------
176 std::string
177 ShaderNode::fragmentShaderName(DrawModes::DrawMode _drawmode, bool _pick) {
178 
179  if ( !_drawmode.isAtomic() ) {
180  std::cerr << "fragmentShaderName: Error, draw mode not atomic!" << std::endl;
181  return std::string("");
182  }
183 
184  std::map<size_t,ShaderInfo>::iterator it;
185 
186  if ( _pick ) {
187  it = pickShaders.find(_drawmode.getIndex());
188  if ( it == pickShaders.end() )
189  return std::string("");
190  } else {
191  it = shaders.find(_drawmode.getIndex());
192  if ( it == shaders.end() )
193  return std::string("");
194  }
195 
196  if ( it->second.initialized )
197  return it->second.fragmentShaderFile;
198 
199  return std::string("");
200 }
201 
202 
203 //----------------------------------------------------------------------------
204 
205 
206 void ShaderNode::leave(GLState& /*_state*/, const DrawModes::DrawMode& _drawmode )
207 {
208  for ( std::map<size_t,ShaderInfo>::iterator it = shaders.begin(); it != shaders.end(); ++it)
209  if ( _drawmode.containsAtomicDrawMode(it->first) && it->second.initialized )
210  it->second.program->disable();
211 }
212 
213 //----------------------------------------------------------------------------
214 
215 
216 void ShaderNode::leavePick(GLState& /*_state*/, PickTarget /*_target*/, const DrawModes::DrawMode& _drawmode )
217 {
218  for ( std::map<size_t,ShaderInfo>::iterator it = pickShaders.begin(); it != pickShaders.end(); ++it)
219  if ( _drawmode.containsAtomicDrawMode(it->first) && it->second.initialized )
220  it->second.program->disable();
221 }
222 
223 //----------------------------------------------------------------------------
224 
228 getShader( DrawModes::DrawMode _drawmode, bool _pick ) {
229 
230  if ( !_drawmode.isAtomic() ) {
231  std::cerr << "getShader: Error, draw mode not atomic!" << std::endl;
232  return 0;
233  }
234 
235  std::map<size_t,ShaderInfo>::iterator it;
236 
237  if ( _pick ) {
238  it = pickShaders.find(_drawmode.getIndex());
239 
240  if ( it == pickShaders.end() )
241  return 0;
242 
243  if ( it->second.initialized )
244  return it->second.program;
245  else
246  return 0;
247 
248  } else {
249  it = shaders.find(_drawmode.getIndex());
250 
251  if ( it == shaders.end() )
252  return 0;
253 
254  if ( it->second.initialized )
255  return it->second.program;
256  else
257  return 0;
258  }
259 
260  // No shader found for this mode
261  return 0;
262 }
263 
264 //----------------------------------------------------------------------------
265 
266 void
269 
270 
271  if ( !_drawmode.isAtomic() ) {
272  std::cerr << "disableShader: Error, draw mode not atomic!" << std::endl;
273  return;
274  }
275 
276  size_t index = _drawmode.getIndex();
277 
278  // Cleanup old shaders for this mode, if they exist
279  if ( shaders[index].initialized ) {
280  if ( shaders[index].program != 0 )
281  delete shaders[index].program;
282 
283  if ( shaders[index].vertexShader != 0 )
284  delete shaders[index].vertexShader;
285 
286  if ( shaders[index].fragmentShader != 0 )
287  delete shaders[index].fragmentShader;
288 
289  shaders[index].initialized = false;
290  }
291 }
292 
293 //----------------------------------------------------------------------------
294 
295 void
298  std::string _vertexShader,
299  std::string _fragmentShader,
300  std::string _pickVertexShader,
301  std::string _pickFragmentShader) {
302 
303  if ( !ACG::openGLVersion(2,0) ) {
304  std::cerr << "Shaders not supported with OpenGL Version less than 2.0" << std::endl;
305  return;
306  }
307 
308  if ( shaderDir_ == "" ) {
309  std::cerr << "No shader dir set for shadernode. Unable to load shaders!" << std::endl;
310  return;
311  }
312 
313  if ( !_drawmode.isAtomic() ) {
314  std::cerr << "setShader: Error, draw mode not atomic!" << std::endl;
315  return;
316  }
317 
318  disableShader (_drawmode);
319  size_t index = _drawmode.getIndex();
320 
321  shaders[index].vertexShaderFile = shaderDir_ + _vertexShader;
322  shaders[index].fragmentShaderFile = shaderDir_ + _fragmentShader;
323 
324  const char* vertexShaderFilePath = shaders[index].vertexShaderFile.c_str();
325  const char* fragmentShaderFilePath = shaders[index].fragmentShaderFile.c_str();
326  shaders[index].vertexShader = GLSL::loadVertexShader(vertexShaderFilePath);
327  shaders[index].fragmentShader = GLSL::loadFragmentShader(fragmentShaderFilePath);
328  shaders[index].program = GLSL::PtrProgram(new GLSL::Program());
329 
330  if ( (shaders[index].vertexShader == 0) ||
331  (shaders[index].fragmentShader == 0) ||
332  (shaders[index].program == 0) ) {
333  std::cerr << "Unable to load shaders" << shaders[index].vertexShaderFile <<
334  " or " << shaders[index].fragmentShaderFile << std::endl;
335  shaders[index].vertexShader = 0;
336  shaders[index].fragmentShader = 0;
337  shaders[index].program = 0;
338  shaders[index].initialized = false;
339  return;
340  }
341 
342  shaders[index].program->attach(shaders[index].vertexShader);
343  shaders[index].program->attach(shaders[index].fragmentShader);
344  shaders[index].program->link();
345 
346  shaders[index].initialized = true;
347 
348 
349  // Cleanup old shaders for this mode, if they exist
350  if ( pickShaders[index].initialized ) {
351  if ( pickShaders[index].program != 0 )
352  delete pickShaders[index].program;
353 
354  if ( pickShaders[index].vertexShader != 0 )
355  delete pickShaders[index].vertexShader;
356 
357  if ( pickShaders[index].fragmentShader != 0 )
358  delete pickShaders[index].fragmentShader;
359 
360  pickShaders[index].initialized = false;
361  }
362 
363  if (_pickVertexShader.length () > 0 && _pickFragmentShader.length () > 0)
364  {
365  pickShaders[index].vertexShaderFile = shaderDir_ + _pickVertexShader;
366  pickShaders[index].fragmentShaderFile = shaderDir_ + _pickFragmentShader;
367 
368  const char* vertexShaderFilePath = pickShaders[index].vertexShaderFile.c_str();
369  const char* fragmentShaderFilePath = pickShaders[index].fragmentShaderFile.c_str();
370  pickShaders[index].vertexShader = GLSL::loadVertexShader(vertexShaderFilePath);
371  pickShaders[index].fragmentShader = GLSL::loadFragmentShader(fragmentShaderFilePath);
372  pickShaders[index].program = GLSL::PtrProgram(new GLSL::Program());
373 
374  if ( (pickShaders[index].vertexShader == 0) ||
375  (pickShaders[index].fragmentShader == 0) ||
376  (pickShaders[index].program == 0) ) {
377  std::cerr << "Unable to load pick shaders" << pickShaders[index].vertexShaderFile <<
378  " or " << pickShaders[index].fragmentShaderFile << std::endl;
379  pickShaders[index].vertexShader = 0;
380  pickShaders[index].fragmentShader = 0;
381  pickShaders[index].program = 0;
382  pickShaders[index].initialized = false;
383  return;
384  }
385 
386  pickShaders[index].program->attach(pickShaders[index].vertexShader);
387  pickShaders[index].program->attach(pickShaders[index].fragmentShader);
388  pickShaders[index].program->link();
389 
390  pickShaders[index].initialized = true;
391  }
392 }
393 
394 //----------------------------------------------------------------------------
395 
396 void
398 setShaderDir( std::string _shaderDir) {
399  shaderDir_ = _shaderDir;
400 }
401 
405 {
407 
408  for ( std::map<size_t,ShaderInfo>::const_iterator it = shaders.begin(); it != shaders.end(); ++it) {
409  // If the shader for this drawmode is initialized, this node supports the given draw mode.
410  // Then we add it to the list of supported draw modes
411  if ( it->second.initialized) {
412  drawModes |= DrawModes::DrawMode(it->first);
413  }
414  }
415 
416  return drawModes;
417 
418 }
419 
420 //=============================================================================
421 } // namespace SceneGraph
422 } // namespace ACG
423 //=============================================================================
void enter(GLState &, const DrawModes::DrawMode &_drawmode)
set shader
Definition: ShaderNode.cc:127
bool hasShader(DrawModes::DrawMode _drawmode, bool _pick=false)
Check if a shader is available for the given drawMode.
Definition: ShaderNode.cc:101
Namespace providing different geometric functions concerning angles.
Definition: DBSCANT.cc:51
size_t getIndex() const
get an index of the current drawMode
GLSL program class.
Definition: MeshNode2T.cc:217
PickTarget
What target to use for picking.
Definition: BaseNode.hh:99
bool containsAtomicDrawMode(DrawMode _atomicDrawMode) const
Check whether an Atomic DrawMode is active in this draw Mode.
void disableShader(DrawModes::DrawMode _drawmode)
Definition: ShaderNode.cc:268
virtual ~ShaderNode()
Destructor.
Definition: ShaderNode.cc:82
GLSL::PtrVertexShader ACGDLLEXPORT loadVertexShader(const char *name, const GLSL::StringList *macros=0, bool verbose=true)
Loads, compiles and installs a new vertex shader.
Definition: GLSLShader.cc:975
bool openGLVersion(const int _major, const int _minor)
Definition: gl.cc:95
void setShader(DrawModes::DrawMode _drawmode, std::string _vertexShader, std::string _fragmentShader, std::string _pickVertexShader="", std::string _pickFragmentShader="")
Definition: ShaderNode.cc:297
void leavePick(GLState &, PickTarget _target, const DrawModes::DrawMode &_drawmode)
disable shader
Definition: ShaderNode.cc:216
void enterPick(GLState &, PickTarget _target, const DrawModes::DrawMode &_drawmode)
set shader
Definition: ShaderNode.cc:139
GLSL::PtrProgram getShader(DrawModes::DrawMode _drawmode, bool _pick=false)
Get the shader for the given drawMode.
Definition: ShaderNode.cc:228
void setShaderDir(std::string _shaderDir)
Sets the shader dir.
Definition: ShaderNode.cc:398
bool isAtomic() const
Check if this is an atomic draw Mode.
ShaderNode(BaseNode *_parent=0, const std::string &_name="<ShaderNode>")
Default constructor. Applies all properties.
Definition: ShaderNode.cc:75
GLSL::PtrFragmentShader ACGDLLEXPORT loadFragmentShader(const char *name, const GLSL::StringList *macros=0, bool verbose=true)
Loads, compiles and installs a new vertex shader.
Definition: GLSLShader.cc:989
void leave(GLState &, const DrawModes::DrawMode &_drawmode)
disable shader
Definition: ShaderNode.cc:206
DrawMode NONE
not a valid draw mode
Definition: DrawModes.cc:77
DrawModes::DrawMode availableDrawModes() const
return available draw modes
Definition: ShaderNode.cc:404