Developer Documentation
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 
45 
46 
47 //=============================================================================
48 //
49 // CLASS ShaderNode - IMPLEMENTATION
50 //
51 //=============================================================================
52 
53 
54 //== INCLUDES =================================================================
55 
56 
57 #include "ShaderNode.hh"
58 
59 
60 //== NAMESPACES ===============================================================
61 
62 namespace ACG {
63 namespace SceneGraph {
64 
65 
66 //== IMPLEMENTATION ==========================================================
67 
68 
70  const std::string& _name)
71  : BaseNode(_parent, _name),
72  shaderDir_("")
73 {
74 }
75 
77  for ( std::map<size_t,ShaderInfo>::iterator it = shaders.begin(); it != shaders.end(); ++it) {
78  if ( it->second.initialized ) {
79 
80  if ( it->second.program != 0 )
81  delete it->second.program;
82 
83  if ( it->second.vertexShader != 0 )
84  delete it->second.vertexShader;
85 
86  if ( it->second.fragmentShader != 0 )
87  delete it->second.fragmentShader;
88  }
89  }
90 }
91 
92 //----------------------------------------------------------------------------
93 bool
95 hasShader( DrawModes::DrawMode _drawmode, bool _pick ) {
96 
97  if ( !_drawmode.isAtomic() ) {
98  std::cerr << "hasShader: Error, draw mode not atomic!" << std::endl;
99  return false;
100  }
101 
102  std::map<size_t,ShaderInfo>::iterator it;
103 
104  if ( _pick ) {
105  it = pickShaders.find(_drawmode.getIndex());
106  if ( it == pickShaders.end() )
107  return false;
108  } else {
109  it = shaders.find(_drawmode.getIndex());
110  if ( it == shaders.end() )
111  return false;
112  }
113 
114  return it->second.initialized;
115 }
116 
117 //----------------------------------------------------------------------------
118 
119 
120 void
121 ShaderNode::enter(GLState& /*_state*/, const DrawModes::DrawMode& _drawmode )
122 {
123  for ( std::map<size_t,ShaderInfo>::iterator it = shaders.begin(); it != shaders.end(); ++it) {
124  if ( _drawmode.containsAtomicDrawMode(DrawModes::DrawMode(it->first)) && it->second.initialized ) {
125  it->second.program->use();
126  }
127  }
128 }
129 
130 //----------------------------------------------------------------------------
131 
132 void
133 ShaderNode::enterPick(GLState& /*_state*/, PickTarget /*_target*/, const DrawModes::DrawMode& _drawmode )
134 {
135  for ( std::map<size_t,ShaderInfo>::iterator it = pickShaders.begin(); it != pickShaders.end(); ++it) {
136  if ( _drawmode.containsAtomicDrawMode(DrawModes::DrawMode(it->first)) && it->second.initialized ) {
137  it->second.program->use();
138  }
139  }
140 }
141 
142 //----------------------------------------------------------------------------
143 std::string
144 ShaderNode::vertexShaderName(DrawModes::DrawMode _drawmode, bool _pick) {
145 
146  if ( !_drawmode.isAtomic() ) {
147  std::cerr << "vertexShaderName: Error, draw mode not atomic!" << std::endl;
148  return std::string("");
149  }
150 
151  std::map<size_t,ShaderInfo>::iterator it;
152 
153  if ( _pick ) {
154  it = pickShaders.find(_drawmode.getIndex());
155  if ( it == pickShaders.end() )
156  return std::string("");
157  } else {
158  it = shaders.find(_drawmode.getIndex());
159  if ( it == shaders.end() )
160  return std::string("");
161  }
162 
163  if ( it->second.initialized )
164  return it->second.vertexShaderFile;
165 
166  return std::string("");
167 }
168 
169 //----------------------------------------------------------------------------
170 std::string
171 ShaderNode::fragmentShaderName(DrawModes::DrawMode _drawmode, bool _pick) {
172 
173  if ( !_drawmode.isAtomic() ) {
174  std::cerr << "fragmentShaderName: Error, draw mode not atomic!" << std::endl;
175  return std::string("");
176  }
177 
178  std::map<size_t,ShaderInfo>::iterator it;
179 
180  if ( _pick ) {
181  it = pickShaders.find(_drawmode.getIndex());
182  if ( it == pickShaders.end() )
183  return std::string("");
184  } else {
185  it = shaders.find(_drawmode.getIndex());
186  if ( it == shaders.end() )
187  return std::string("");
188  }
189 
190  if ( it->second.initialized )
191  return it->second.fragmentShaderFile;
192 
193  return std::string("");
194 }
195 
196 
197 //----------------------------------------------------------------------------
198 
199 
200 void ShaderNode::leave(GLState& /*_state*/, const DrawModes::DrawMode& _drawmode )
201 {
202  for ( std::map<size_t,ShaderInfo>::iterator it = shaders.begin(); it != shaders.end(); ++it)
203  if ( _drawmode.containsAtomicDrawMode(DrawModes::DrawMode(it->first)) && it->second.initialized )
204  it->second.program->disable();
205 }
206 
207 //----------------------------------------------------------------------------
208 
209 
210 void ShaderNode::leavePick(GLState& /*_state*/, PickTarget /*_target*/, const DrawModes::DrawMode& _drawmode )
211 {
212  for ( std::map<size_t,ShaderInfo>::iterator it = pickShaders.begin(); it != pickShaders.end(); ++it)
213  if ( _drawmode.containsAtomicDrawMode(DrawModes::DrawMode(it->first)) && it->second.initialized )
214  it->second.program->disable();
215 }
216 
217 //----------------------------------------------------------------------------
218 
222 getShader( DrawModes::DrawMode _drawmode, bool _pick ) {
223 
224  if ( !_drawmode.isAtomic() ) {
225  std::cerr << "getShader: Error, draw mode not atomic!" << std::endl;
226  return 0;
227  }
228 
229  std::map<size_t,ShaderInfo>::iterator it;
230 
231  if ( _pick ) {
232  it = pickShaders.find(_drawmode.getIndex());
233 
234  if ( it == pickShaders.end() )
235  return 0;
236 
237  if ( it->second.initialized )
238  return it->second.program;
239  else
240  return 0;
241 
242  } else {
243  it = shaders.find(_drawmode.getIndex());
244 
245  if ( it == shaders.end() )
246  return 0;
247 
248  if ( it->second.initialized )
249  return it->second.program;
250  else
251  return 0;
252  }
253 
254  // No shader found for this mode
255  return 0;
256 }
257 
258 //----------------------------------------------------------------------------
259 
260 void
263 
264 
265  if ( !_drawmode.isAtomic() ) {
266  std::cerr << "disableShader: Error, draw mode not atomic!" << std::endl;
267  return;
268  }
269 
270  size_t index = _drawmode.getIndex();
271 
272  // Cleanup old shaders for this mode, if they exist
273  if ( shaders[index].initialized ) {
274  if ( shaders[index].program != 0 )
275  delete shaders[index].program;
276 
277  if ( shaders[index].vertexShader != 0 )
278  delete shaders[index].vertexShader;
279 
280  if ( shaders[index].fragmentShader != 0 )
281  delete shaders[index].fragmentShader;
282 
283  shaders[index].initialized = false;
284  }
285 }
286 
287 //----------------------------------------------------------------------------
288 
289 void
292  const std::string& _vertexShader,
293  const std::string& _fragmentShader,
294  std::string _pickVertexShader,
295  std::string _pickFragmentShader) {
296 
297  if ( !ACG::openGLVersion(2,0) ) {
298  std::cerr << "Shaders not supported with OpenGL Version less than 2.0" << std::endl;
299  return;
300  }
301 
302  if ( shaderDir_ == "" ) {
303  std::cerr << "No shader dir set for shadernode. Unable to load shaders!" << std::endl;
304  return;
305  }
306 
307  if ( !_drawmode.isAtomic() ) {
308  std::cerr << "setShader: Error, draw mode not atomic!" << std::endl;
309  return;
310  }
311 
312  disableShader (_drawmode);
313  size_t index = _drawmode.getIndex();
314 
315  shaders[index].vertexShaderFile = shaderDir_ + _vertexShader;
316  shaders[index].fragmentShaderFile = shaderDir_ + _fragmentShader;
317 
318  const char* vertexShaderFilePath = shaders[index].vertexShaderFile.c_str();
319  const char* fragmentShaderFilePath = shaders[index].fragmentShaderFile.c_str();
320  shaders[index].vertexShader = GLSL::loadVertexShader(vertexShaderFilePath);
321  shaders[index].fragmentShader = GLSL::loadFragmentShader(fragmentShaderFilePath);
322  shaders[index].program = GLSL::PtrProgram(new GLSL::Program());
323 
324  if ( (shaders[index].vertexShader == 0) ||
325  (shaders[index].fragmentShader == 0) ||
326  (shaders[index].program == 0) ) {
327  std::cerr << "Unable to load shaders" << shaders[index].vertexShaderFile <<
328  " or " << shaders[index].fragmentShaderFile << std::endl;
329  shaders[index].vertexShader = 0;
330  shaders[index].fragmentShader = 0;
331  shaders[index].program = 0;
332  shaders[index].initialized = false;
333  return;
334  }
335 
336  shaders[index].program->attach(shaders[index].vertexShader);
337  shaders[index].program->attach(shaders[index].fragmentShader);
338  shaders[index].program->link();
339 
340  shaders[index].initialized = true;
341 
342 
343  // Cleanup old shaders for this mode, if they exist
344  if ( pickShaders[index].initialized ) {
345  if ( pickShaders[index].program != 0 )
346  delete pickShaders[index].program;
347 
348  if ( pickShaders[index].vertexShader != 0 )
349  delete pickShaders[index].vertexShader;
350 
351  if ( pickShaders[index].fragmentShader != 0 )
352  delete pickShaders[index].fragmentShader;
353 
354  pickShaders[index].initialized = false;
355  }
356 
357  if (_pickVertexShader.length () > 0 && _pickFragmentShader.length () > 0)
358  {
359  pickShaders[index].vertexShaderFile = shaderDir_ + _pickVertexShader;
360  pickShaders[index].fragmentShaderFile = shaderDir_ + _pickFragmentShader;
361 
362  const char* vertexShaderFilePath = pickShaders[index].vertexShaderFile.c_str();
363  const char* fragmentShaderFilePath = pickShaders[index].fragmentShaderFile.c_str();
364  pickShaders[index].vertexShader = GLSL::loadVertexShader(vertexShaderFilePath);
365  pickShaders[index].fragmentShader = GLSL::loadFragmentShader(fragmentShaderFilePath);
366  pickShaders[index].program = GLSL::PtrProgram(new GLSL::Program());
367 
368  if ( (pickShaders[index].vertexShader == 0) ||
369  (pickShaders[index].fragmentShader == 0) ||
370  (pickShaders[index].program == 0) ) {
371  std::cerr << "Unable to load pick shaders" << pickShaders[index].vertexShaderFile <<
372  " or " << pickShaders[index].fragmentShaderFile << std::endl;
373  pickShaders[index].vertexShader = 0;
374  pickShaders[index].fragmentShader = 0;
375  pickShaders[index].program = 0;
376  pickShaders[index].initialized = false;
377  return;
378  }
379 
380  pickShaders[index].program->attach(pickShaders[index].vertexShader);
381  pickShaders[index].program->attach(pickShaders[index].fragmentShader);
382  pickShaders[index].program->link();
383 
384  pickShaders[index].initialized = true;
385  }
386 }
387 
388 //----------------------------------------------------------------------------
389 
390 void
392 setShaderDir( std::string _shaderDir) {
393  shaderDir_ = _shaderDir;
394 }
395 
399 {
401 
402  for ( std::map<size_t,ShaderInfo>::const_iterator it = shaders.begin(); it != shaders.end(); ++it) {
403  // If the shader for this drawmode is initialized, this node supports the given draw mode.
404  // Then we add it to the list of supported draw modes
405  if ( it->second.initialized) {
406  drawModes |= DrawModes::DrawMode(it->first);
407  }
408  }
409 
410  return drawModes;
411 
412 }
413 
414 //=============================================================================
415 } // namespace SceneGraph
416 } // namespace ACG
417 //=============================================================================
ShaderNode(BaseNode *_parent=0, const std::string &_name="<ShaderNode>")
Default constructor. Applies all properties.
Definition: ShaderNode.cc:69
void enterPick(GLState &, PickTarget _target, const DrawModes::DrawMode &_drawmode) override
set shader
Definition: ShaderNode.cc:133
bool isAtomic() const
Check if this is an atomic draw Mode.
Definition: DrawModes.cc:512
Namespace providing different geometric functions concerning angles.
GLSL::PtrFragmentShader loadFragmentShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new vertex shader.
Definition: GLSLShader.cc:983
bool containsAtomicDrawMode(const DrawMode &_atomicDrawMode) const
Check whether an Atomic DrawMode is active in this draw Mode.
Definition: DrawModes.cc:520
DrawModes::DrawMode availableDrawModes() const override
return available draw modes
Definition: ShaderNode.cc:398
void disableShader(DrawModes::DrawMode _drawmode)
Definition: ShaderNode.cc:262
void leave(GLState &, const DrawModes::DrawMode &_drawmode) override
disable shader
Definition: ShaderNode.cc:200
void leavePick(GLState &, PickTarget _target, const DrawModes::DrawMode &_drawmode) override
disable shader
Definition: ShaderNode.cc:210
void setShader(DrawModes::DrawMode _drawmode, const std::string &_vertexShader, const std::string &_fragmentShader, std::string _pickVertexShader="", std::string _pickFragmentShader="")
Definition: ShaderNode.cc:291
PickTarget
What target to use for picking.
Definition: PickTarget.hh:73
GLSL program class.
Definition: GLSLShader.hh:211
bool openGLVersion(const int _major, const int _minor, bool _verbose)
Definition: gl.cc:129
DrawMode NONE
not a valid draw mode
Definition: DrawModes.cc:71
bool hasShader(DrawModes::DrawMode _drawmode, bool _pick=false)
Check if a shader is available for the given drawMode.
Definition: ShaderNode.cc:95
size_t getIndex() const
get an index of the current drawMode
Definition: DrawModes.cc:434
GLSL::PtrVertexShader loadVertexShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new vertex shader.
Definition: GLSLShader.cc:969
void setShaderDir(std::string _shaderDir)
Sets the shader dir.
Definition: ShaderNode.cc:392
GLSL::PtrProgram getShader(DrawModes::DrawMode _drawmode, bool _pick=false)
Get the shader for the given drawMode.
Definition: ShaderNode.cc:222
void enter(GLState &, const DrawModes::DrawMode &_drawmode) override
set shader
Definition: ShaderNode.cc:121
virtual ~ShaderNode()
Destructor.
Definition: ShaderNode.cc:76