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
69 ShaderNode::ShaderNode( BaseNode* _parent,
70 const std::string& _name)
71 : BaseNode(_parent, _name),
72 shaderDir_("")
73 {
74 }
75
76 ShaderNode::~ShaderNode() {
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
94 ShaderNode::
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
220 GLSL::PtrProgram
221 ShaderNode::
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
261 ShaderNode::
262 disableShader (DrawModes::DrawMode _drawmode) {
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
290 ShaderNode::
291 setShader( DrawModes::DrawMode _drawmode ,
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
391 ShaderNode::
392 setShaderDir( std::string _shaderDir) {
393 shaderDir_ = _shaderDir;
394 }
395
396 DrawModes::DrawMode
397 ShaderNode::
398 availableDrawModes() const
399 {
400 DrawModes::DrawMode drawModes(DrawModes::NONE);
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 //=============================================================================
ACG::SceneGraph::ShaderNode::ShaderNode
ShaderNode(BaseNode *_parent=0, const std::string &_name="<ShaderNode>")
Default constructor. Applies all properties.
Definition: ShaderNode.cc:69
ACG::GLState
Definition: GLState.hh:213
ACG::SceneGraph::ShaderNode::enterPick
void enterPick(GLState &, PickTarget _target, const DrawModes::DrawMode &_drawmode) override
set shader
Definition: ShaderNode.cc:133
ACG::SceneGraph::DrawModes::DrawMode::isAtomic
bool isAtomic() const
Check if this is an atomic draw Mode.
Definition: DrawModes.cc:512
ACG
Namespace providing different geometric functions concerning angles.
Definition: BaseObjectData.hh:68
GLSL::loadFragmentShader
GLSL::PtrFragmentShader loadFragmentShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new vertex shader.
Definition: GLSLShader.cc:983
ACG::SceneGraph::DrawModes::DrawMode::containsAtomicDrawMode
bool containsAtomicDrawMode(const DrawMode &_atomicDrawMode) const
Check whether an Atomic DrawMode is active in this draw Mode.
Definition: DrawModes.cc:520
ACG::SceneGraph::ShaderNode::availableDrawModes
DrawModes::DrawMode availableDrawModes() const override
return available draw modes
Definition: ShaderNode.cc:398
ACG::SceneGraph::ShaderNode::disableShader
void disableShader(DrawModes::DrawMode _drawmode)
Definition: ShaderNode.cc:262
ACG::SceneGraph::ShaderNode::leave
void leave(GLState &, const DrawModes::DrawMode &_drawmode) override
disable shader
Definition: ShaderNode.cc:200
ACG::SceneGraph::ShaderNode::leavePick
void leavePick(GLState &, PickTarget _target, const DrawModes::DrawMode &_drawmode) override
disable shader
Definition: ShaderNode.cc:210
ACG::SceneGraph::ShaderNode::setShader
void setShader(DrawModes::DrawMode _drawmode, const std::string &_vertexShader, const std::string &_fragmentShader, std::string _pickVertexShader="", std::string _pickFragmentShader="")
Definition: ShaderNode.cc:291
SceneGraph
Definition: QtPrincipalAxisDialog.hh:67
ACG::SceneGraph::PickTarget
PickTarget
What target to use for picking.
Definition: PickTarget.hh:73
GLSL::Program
GLSL program class.
Definition: GLSLShader.hh:211
ACG::openGLVersion
bool openGLVersion(const int _major, const int _minor, bool _verbose)
Definition: gl.cc:129
ACG::SceneGraph::BaseNode
Definition: BaseNode.hh:104
ACG::SceneGraph::DrawModes::NONE
DrawMode NONE
not a valid draw mode
Definition: DrawModes.cc:71
ACG::SceneGraph::ShaderNode::hasShader
bool hasShader(DrawModes::DrawMode _drawmode, bool _pick=false)
Check if a shader is available for the given drawMode.
Definition: ShaderNode.cc:95
ACG::SceneGraph::DrawModes::DrawMode::getIndex
size_t getIndex() const
get an index of the current drawMode
Definition: DrawModes.cc:434
ACG::SceneGraph::DrawModes::DrawMode
Specifies a DrawMode.
Definition: DrawModes.hh:288
GLSL::loadVertexShader
GLSL::PtrVertexShader loadVertexShader(const char *name, const GLSL::StringList *macros, bool verbose)
Loads, compiles and installs a new vertex shader.
Definition: GLSLShader.cc:969
ACG::SceneGraph::ShaderNode::setShaderDir
void setShaderDir(std::string _shaderDir)
Sets the shader dir.
Definition: ShaderNode.cc:392
ACG::SceneGraph::ShaderNode::getShader
GLSL::PtrProgram getShader(DrawModes::DrawMode _drawmode, bool _pick=false)
Get the shader for the given drawMode.
Definition: ShaderNode.cc:222
ACG::SceneGraph::ShaderNode::enter
void enter(GLState &, const DrawModes::DrawMode &_drawmode) override
set shader
Definition: ShaderNode.cc:121
ACG::SceneGraph::ShaderNode::~ShaderNode
virtual ~ShaderNode()
Destructor.
Definition: ShaderNode.cc:76