Developer Documentation
ClassicDepthPeeling.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 * $LastChangedBy$ *
46 * $Date$ *
47 * *
48 \*===========================================================================*/
49 
50 #include "ClassicDepthPeeling.hh"
52 #include <ObjectTypes/Light/LightNode.hh>
53 
54 #include <ACG/GL/GLError.hh>
55 
56 
57 // this define enables a shader export of the generated peel shader for debugging purpose
58 //#define DEPTHPEELING_SHADER_EXPORT
59 
60 
61 DepthPeelingPlugin::DepthPeelingPlugin() :
62  blendQueryID_(0),
63  glStateTmp_(0),
64  numLights_(0)
65 {
66 
67  for (unsigned int i = 0; i < 16; ++i)
68  lightTypes_[i] = LIGHTTYPE_POINT;
69 
70  for (unsigned int i = 0; i < PEEL_NUM_COMBINATIONS; ++i)
71  peelProgs_[i] = 0;
72 
73  for (unsigned int i = 0; i < PEEL_NUM_COMBINATIONS*3; ++i)
74  peelShaders_[i] = 0;
75 
76  for (unsigned int i = 0; i < 8; ++i)
77  blendShaders_[i] = 0;
78 
79  for (unsigned int i = 0; i < 4; ++i)
80  blendDualPeelProg_[i] = 0;
81 
82  for (unsigned int i = 0; i < 16; ++i)
83  glLightIDs_[i] = 0;
84 
85 
86 }
87 
88 DepthPeelingPlugin::~DepthPeelingPlugin() {
89 
90 }
91 
92 
93 DepthPeelingPlugin::ViewerResources::ViewerResources()
94 {
95  rtWidth_ = rtHeight_ = 0;
96 
97  glWidth_ = glHeight_ = 0;
98 
99  memset(blendDualPeelTexID_, 0, 7*4);
100 
101  blendDualPeelFbo_ = 0;
102 }
103 
104 void DepthPeelingPlugin::initializePlugin()
105 {
106  memset(blendShaders_, 0, sizeof(blendShaders_));
107  memset(peelShaders_, 0, sizeof(peelShaders_));
108 
109  memset(blendDualPeelProg_, 0, sizeof(blendDualPeelProg_));
110  memset(peelProgs_, 0, sizeof(peelProgs_));
111 
112  blendQueryID_ = 0;
113  numLights_ = 0;
114 
116 }
117 
119 
120 void DepthPeelingPlugin::exit()
121 {
122  destroyResources();
123 }
124 
126 
127 QString DepthPeelingPlugin::rendererName() {
128  return QString("Classical Depth Peeling Renderer");
129 }
130 
132 
133 void DepthPeelingPlugin::supportedDrawModes(ACG::SceneGraph::DrawModes::DrawMode& _mode) {
135 }
136 
138 
139 
140 void DepthPeelingPlugin::drawQuadProj(float x0, float y0, float w, float h)
141 {
142  // quad in projection space
143  // here only position are passed to GL
144  // tex-coords can be generated in a vertex-shader as follows
145  // uv = pos * (.5, -.5) + (.5, .5)
146 
147  glBegin(GL_QUADS);
148  {
149  glVertex2f(x0, y0);
150  glVertex2f(x0, y0-h);
151  glVertex2f(x0+w, y0-h);
152  glVertex2f(x0+w, y0);
153  }
154  glEnd();
155 }
156 
158 
160 {
161 
162  if (_node)
163  {
164  BaseNode::StatusMode status(_node->status());
165 
166  // If the subtree is hidden, ignore this node and its children while rendering
167  if (status != BaseNode::HideSubtree)
168  {
169 
170  if (_node->status() != BaseNode::HideNode)
171  {
172  ACG::SceneGraph::LightNode* lnode = dynamic_cast<ACG::SceneGraph::LightNode*>(_node);
173  if (lnode)
174  {
176  lnode->getLightSource(&light);
177 
178 // GLenum lightID = lnode->getGLLightID();
179  GLenum lightID = numLights_ + GL_LIGHT0;
180 
181  if (lightID != GL_INVALID_ENUM)
182  {
183  int id = lightID - GL_LIGHT0;
184 
185  if (numLights_ < 8)
186  {
187  if (light.directional())
188  lightTypes_[numLights_] = LIGHTTYPE_DIRECTIONAL;
189  else if (light.spotCutoff() > 179.5f)
190  lightTypes_[numLights_] = LIGHTTYPE_POINT;
191  else
192  lightTypes_[numLights_] = LIGHTTYPE_SPOT;
193 
194  glLightIDs_[numLights_] = id;
195 
196  ++numLights_;
197  }
198 
199  }
200 
201  }
202  }
203 
204  // Process children?
205  if (status != BaseNode::HideChildren)
206  {
207 
208  BaseNode::ChildIter cIt, cEnd(_node->childrenEnd());
209 
210  // Process all children which are not second pass
211  for (cIt = _node->childrenBegin(); cIt != cEnd; ++cIt)
212  if (~(*cIt)->traverseMode() & BaseNode::SecondPass)
213  traverseLightNodes(*cIt);
214 
215  // Process all children which are second pass
216  for (cIt = _node->childrenBegin(); cIt != cEnd; ++cIt)
217  if ((*cIt)->traverseMode() & BaseNode::SecondPass)
218  traverseLightNodes(*cIt);
219 
220  }
221 
222  }
223  }
224 }
225 
226 // depth peeling shader generation
227 
228 void DepthPeelingPlugin::generatePeelingShaders(GLSL::StringList* _strVertexShaderOut,
229  GLSL::StringList* _strFragmentShaderOut,
230  GLSL::StringList* _strGeometryShaderOut,
231  bool _textured,
232  bool _flatShaded,
233  bool _phong,
234  bool _vertexColor,
235  bool _wireFrame)
236 {
237  if (_flatShaded) _phong = false;
238  if (_vertexColor) _phong = false;
239 
240  std::string strColor = "color";
241  std::string strNormal = "normal";
242  std::string strFragPos = "vPosVS";
243 
244  if (_flatShaded)
245  strFragPos = "VPosVS";
246 
247  if (_wireFrame)
248  _flatShaded = _vertexColor = _textured = _phong = false;
249 
250  std::string strCode = "";
251 
252  for (unsigned int i = 0; i < numLights_ && (!_wireFrame); ++i)
253  {
254  // new code block for this light
255  strCode += "{\n";
256 
257  std::string strLight = "gl_LightSource[";
258  std::string strMaterial = "gl_FrontLightProduct[";
259  {
260  char szTmp[8];
261  sprintf(szTmp, "%u]", glLightIDs_[i]);
262 
263  strLight += szTmp;
264  strMaterial += szTmp;
265  }
266 
267  // light vector
268  if (lightTypes_[i] == LIGHTTYPE_DIRECTIONAL)
269  strCode += "vec3 vLightVS = " + strLight + ".position.xyz;\n";
270  else
271  strCode += "vec3 vLightVS = " + strLight + ".position.xyz - " + strFragPos + ".xyz;\n";
272 
273  strCode += "vec3 vLightDir = normalize(vLightVS);\n";
274 
275  // ambient
276  strCode += "vec4 colLight = " + strMaterial + ".ambient;\n";
277 
278  // diffuse
279  strCode += "float ldotn = dot(vLightDir, " + strNormal + ");\n";
280  strCode += "ldotn = clamp(ldotn, 0.0, 1.0);\n";
281  strCode += "colLight += ldotn * ";
282  if (_textured && _phong)
283  strCode += "diffColor * ";
284 
285  if (_vertexColor)
286  {
287  if (_flatShaded)
288  strCode += "vColor[2];\n";
289  else
290  strCode += "gl_Color;\n";
291  }
292  else
293  strCode += strMaterial + ".diffuse;\n";
294 
295  //specular
296  strCode += "colLight += floor(ldotn + 0.9) * pow(ldotn, gl_FrontMaterial.shininess) * " + strMaterial + ".specular;\n";
297 
298 
299  if (lightTypes_[i] == LIGHTTYPE_DIRECTIONAL)
300  strCode += strColor + ".rgb += colLight.rgb;\n";
301  else
302  {
303  // attenuation
304  strCode += "float fLenSq = dot(vLightVS, vLightVS);\n";
305  strCode += "float atten = " + strLight + ".constantAttenuation + " +
306  strLight + ".linearAttenuation * sqrt(fLenSq) + " +
307  strLight + ".quadraticAttenuation * fLenSq;\n";
308 
309  if (lightTypes_[i] == LIGHTTYPE_POINT)
310  strCode += strColor + ".rgb += colLight.rgb / atten;\n";
311  else
312  {
313  // spotlight
314  strCode += "float spot = -dot(vLightDir, " + strLight + ".spotDirection);\n";
315  strCode += "spot *= step(" + strLight + ".spotCosCutoff, spot);\n";
316  strCode += "spot *= pow(spot, " + strLight + ".spotExponent);\n";
317 
318  strCode += strColor + ".rgb += " + "(spot / atten) * colLight.rgb;\n";
319  }
320  }
321 
322  strCode += "}\n";
323  }
324 
325  const char* szVertexShader[] = {"varying vec2 vTexCoord;",
326  "varying vec3 vNormal; // normal: view space",
327  "varying vec4 vPosVS; // position in view space",
328  "varying vec4 vColor; // used in gouraud / flat shading only",
329  "",
330  "void main(void)",
331  "{",
332  " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;",
333  " ",
334  " vNormal = gl_NormalMatrix * gl_Normal; // gl_NormalMatrix : upper left 3x3 of WorldViewIT",
335  " vPosVS = (gl_ModelViewMatrix * gl_Vertex);",
336  " vTexCoord = gl_MultiTexCoord0.xy;",
337  ""};
338  // NOTE: this vertex shader code misses the ending '}' to append the lighting code later
339 
340  // geometry shader for flat shading only
341  const char* szGeometryShaderStart[] = {
342  "#version 120",
343  "#extension GL_ARB_geometry_shader4 : enable",
344  "",
345  "varying vec2 vTexCoord[3];",
346  "varying vec4 vPosVS[3];",
347  "varying vec3 vNormal[3];",
348  "varying vec4 vColor[3];",
349  "",
350  "varying vec2 VTexCoord;",
351  "varying vec3 VNormal;",
352  "varying vec4 VPosVS;",
353  "varying vec4 VColor;",
354  "",
355  "",
356  "void main()",
357  "{",
358  " // recompute triangle normal",
359 // " vec3 normal = cross(vNormal[2].xyz - vNormal[0].xyz, vNormal[1].xyz - vNormal[0].xyz);",
360  " vec3 normal = cross(gl_PositionIn[1].xyz - gl_PositionIn[0].xyz, gl_PositionIn[2].xyz - gl_PositionIn[0].xyz);",
361  " normal = normalize(normal);",
362  " normal = gl_NormalMatrix * normal;",
363 // " normal = vNormal[2].xyz;",
364  " ",
365  " VPosVS = (gl_PositionIn[0] + gl_PositionIn[1] + gl_PositionIn[2]) / 3.0;",
366  " VPosVS = gl_ModelViewMatrix * VPosVS; // triangle center in view space needed for point and spot lights",
367  " vec4 color = vec4(gl_FrontMaterial.emission.rgb, gl_FrontMaterial.diffuse.a);",
368  ""};
369 
370  const char* szGeometryShaderEnd[] = {
371  "",
372  " for(int i = 0; i < 3; i++)",
373  " {",
374  " gl_Position = gl_ModelViewProjectionMatrix * gl_PositionIn[i];",
375  " VTexCoord = vTexCoord[i];",
376  " VNormal = normal;",
377  " VPosVS = vPosVS[i];",
378 // " VColor = (normal+vec3(0.5,0.5,0.5)).xyzz*0.5;",
379  " VColor = color;",
380  " EmitVertex();",
381  " }",
382  " EndPrimitive();",
383  " ",
384  "}"};
385 
386  const char* szFragmentShaderStart[] = {"varying vec2 vTexCoord;",
387  "varying vec3 vNormal; ",
388  "varying vec4 vPosVS;",
389  "varying vec4 vColor;",
390  "",
391  "uniform sampler2D DiffuseTex;",
392  "uniform sampler2DRect DepthBlenderTex;",
393  "uniform sampler2DRect FrontBlenderTex;",
394  "",
395  "#define MAX_DEPTH 1.0",
396  "",
397  "",
398  "void main(void)",
399  "{",
400  " // window-space depth interpolated linearly in screen space",
401  " float fragDepth = gl_FragCoord.z;",
402  "",
403  " vec2 depthBlender = texture2DRect(DepthBlenderTex, gl_FragCoord.xy).xy;",
404  " vec4 forwardTemp = texture2DRect(FrontBlenderTex, gl_FragCoord.xy);",
405  " ",
406  " // Depths and 1.0-alphaMult always increase",
407  " // so we can use pass-through by default with MAX blending",
408  " gl_FragData[0].xy = depthBlender;",
409  " ",
410  " // Front colors always increase (DST += SRC*ALPHA_MULT)",
411  " // so we can use pass-through by default with MAX blending",
412  " gl_FragData[1] = forwardTemp;",
413  " ",
414  " // Because over blending makes color increase or decrease,",
415  " // we cannot pass-through by default.",
416  " // Each pass, only one fragment writes a color greater than 0",
417  " gl_FragData[2] = vec4(0.0);",
418  "",
419  " float nearestDepth = -depthBlender.x;",
420  " float farthestDepth = depthBlender.y;",
421  " float alphaMultiplier = 1.0 - forwardTemp.w;",
422  "",
423  " if (fragDepth < nearestDepth || fragDepth > farthestDepth) {",
424  " // Skip this depth in the peeling algorithm",
425  " gl_FragData[0].xy = vec2(-MAX_DEPTH);",
426  " return;",
427  " }",
428  " ",
429  " if (fragDepth > nearestDepth && fragDepth < farthestDepth) {",
430  " // This fragment needs to be peeled again",
431  " gl_FragData[0].xy = vec2(-fragDepth, fragDepth);",
432  " return;",
433  " }",
434  " ",
435  " // If we made it here, this fragment is on the peeled layer from last pass",
436  " // therefore, we need to shade it, and make sure it is not peeled any farther",
437  "",};
438 
439  const char* szFragmentShaderEnd[] = {"",
440  " gl_FragData[0].xy = vec2(-MAX_DEPTH);",
441  " ",
442  " if (fragDepth == nearestDepth) {",
443  " gl_FragData[1].xyz += color.rgb * color.a * alphaMultiplier;",
444  " gl_FragData[1].w = 1.0 - alphaMultiplier * (1.0 - color.a);",
445  " } else {",
446  " gl_FragData[2] += color;",
447  " }",
448  "}"};
449 
450  // assemble final shaders:
451 
452  // vertex shader
453  for (unsigned int i = 0; i < sizeof(szVertexShader) / sizeof(char*); ++i)
454  {
455  std::string str = szVertexShader[i];
456  if (_phong)
457  {
458  if (!strncmp("varying vec4 vColor", str.c_str(), strlen("varying vec4 vColor")))
459  {
460 // str.replace(str.begin(), str.begin() + 7, "flat out");
461  str += "\n";
462  continue;
463  }
464  }
465  str += "\n";
466  _strVertexShaderOut->push_back(str);
467  }
468 
469  // finalize vertex shader
470  if (!_phong && !_flatShaded && !_wireFrame)
471  {
472  // lighting code:
473  _strVertexShaderOut->push_back("\nvec4 color = vec4(gl_FrontMaterial.emission.rgb, gl_FrontMaterial.diffuse.a);");
474  _strVertexShaderOut->push_back("\nvec3 normal = vNormal;\n");
475 
476  std::string::size_type curPos = 0;
477  std::string::size_type newLinePos = strCode.find_first_of('\n');
478  while (newLinePos != std::string::npos)
479  {
480  _strVertexShaderOut->push_back(strCode.substr(curPos, newLinePos - curPos + 1));
481  curPos = newLinePos + 1;
482  newLinePos = strCode.find_first_of('\n', curPos);
483  }
484  _strVertexShaderOut->push_back("\nvColor = color;\n");
485  }
486  if (_flatShaded)
487  {
488  if (_vertexColor)
489  _strVertexShaderOut->push_back("vColor = gl_Color;\n");
490  _strVertexShaderOut->push_back("gl_Position = gl_Vertex;\n");
491  }
492 
493  _strVertexShaderOut->push_back("\n}");
494 
495  // fragment shader:
496  for (unsigned int i = 0; i < sizeof(szFragmentShaderStart) / sizeof(char*); ++i)
497  {
498  std::string str = szFragmentShaderStart[i];
499  if (_phong)
500  {
501  if (!strncmp("varying vec4 vColor", str.c_str(), strlen("varying vec4 vColor")))
502  {
503 // str.replace(str.begin(), str.begin() + 7, "flat in");
504  str += "\n";
505  continue;
506  }
507  }
508  if (_flatShaded)
509  {
510  if (!strncmp("varying vec2 vTexCoord", str.c_str(), strlen("varying vec2 vTexCoord")))
511  str = "varying vec2 VTexCoord;";
512  if (!strncmp("varying vec3 vNormal", str.c_str(), strlen("varying vec3 vNormal")))
513  str = "varying vec3 VNormal;";
514  if (!strncmp("varying vec4 vPosVS", str.c_str(), strlen("varying vec4 vPosVS")))
515  str = "varying vec4 VPosVS;";
516  if (!strncmp("varying vec4 vColor", str.c_str(), strlen("varying vec4 vColor")))
517  str = "varying vec4 VColor;";
518  }
519  str += "\n";
520  _strFragmentShaderOut->push_back(str);
521  }
522 
523  if (!_wireFrame)
524  {
525  if (!_flatShaded)
526  {
527  _strFragmentShaderOut->push_back(" vec3 normal = normalize(vNormal);\n");
528 // _strFragmentShaderOut->push_back(" vec3 normal = normalize(cross(dFdx(vPosVS.xyz), dFdy(vPosVS.xyz)));\n");
529  _strFragmentShaderOut->push_back(" vec4 color = vec4(gl_FrontMaterial.emission.rgb, gl_FrontMaterial.diffuse.a);\n");
530  if (_textured)
531  _strFragmentShaderOut->push_back(" vec4 diffColor = texture2D(DiffuseTex, vTexCoord); color.a *= diffColor.a;\n");
532  }
533  else
534  {
535  _strFragmentShaderOut->push_back(" vec4 color = vec4(gl_FrontMaterial.emission.rgb, gl_FrontMaterial.diffuse.a);\n");
536  _strFragmentShaderOut->push_back(" vec4 vColor = VColor;\n");
537  if (_textured)
538  _strFragmentShaderOut->push_back(" vec4 diffColor = texture2D(DiffuseTex, VTexCoord); color.a *= diffColor.a;\n");
539  }
540 
541  if (!_phong)
542  {
543  if (_textured)
544  _strFragmentShaderOut->push_back(" color = diffColor * vColor;\n");
545  else
546  _strFragmentShaderOut->push_back(" color = vColor;\n");
547  }
548  else
549  {
550  // lighting code:
551  std::string::size_type curPos = 0;
552  std::string::size_type newLinePos = strCode.find_first_of('\n');
553  while (newLinePos != std::string::npos)
554  {
555  _strFragmentShaderOut->push_back(strCode.substr(curPos, newLinePos - curPos + 1));
556  curPos = newLinePos + 1;
557  newLinePos = strCode.find_first_of('\n', curPos);
558  }
559  }
560  }
561  else // wireframe:
562  _strFragmentShaderOut->push_back(" vec4 color = VColor;\n");
563 
564  for (unsigned int i = 0; i < sizeof(szFragmentShaderEnd) / sizeof(char*); ++i)
565  {
566  std::string str = szFragmentShaderEnd[i];
567  str += "\n";
568  _strFragmentShaderOut->push_back(str);
569  }
570 
571 
572  // geometry shader:
573  if (_flatShaded)
574  {
575  for (unsigned int i = 0; i < sizeof(szGeometryShaderStart) / sizeof(char*); ++i)
576  {
577  std::string str = szGeometryShaderStart[i];
578  str += "\n";
579  _strGeometryShaderOut->push_back(str);
580  }
581 
582  // lighting code:
583  std::string::size_type curPos = 0;
584  std::string::size_type newLinePos = strCode.find_first_of('\n');
585  while (newLinePos != std::string::npos)
586  {
587  _strGeometryShaderOut->push_back(strCode.substr(curPos, newLinePos - curPos + 1));
588  curPos = newLinePos + 1;
589  newLinePos = strCode.find_first_of('\n', curPos);
590  }
591 
592  for (unsigned int i = 0; i < sizeof(szGeometryShaderEnd) / sizeof(char*); ++i)
593  {
594  std::string str = szGeometryShaderEnd[i];
595  str += "\n";
596  _strGeometryShaderOut->push_back(str);
597  }
598  }
599 
600 
601  // debug output:
602 #ifdef DEPTHPEELING_SHADER_EXPORT
603  FILE* pShaderOut = fopen("peel_vertex.glsl", "wt");
604  for (GLSL::StringList::iterator it = _strVertexShaderOut->begin(); it != _strVertexShaderOut->end(); ++it)
605  fprintf(pShaderOut, it->c_str());
606  fclose(pShaderOut);
607 
608 
609  pShaderOut = fopen("peel_frag.glsl", "wt");
610  for (GLSL::StringList::iterator it = _strFragmentShaderOut->begin(); it != _strFragmentShaderOut->end(); ++it)
611  fprintf(pShaderOut, it->c_str());
612  fclose(pShaderOut);
613 
614  if (_flatShaded)
615  {
616  pShaderOut = fopen("peel_geom.glsl", "wt");
617  for (GLSL::StringList::iterator it = _strGeometryShaderOut->begin(); it != _strGeometryShaderOut->end(); ++it)
618  fprintf(pShaderOut, it->c_str());
619  fclose(pShaderOut);
620  }
621 #endif
622 }
623 
625 
626 template <class Action>
627 bool
628 DepthPeelingPlugin::traverseDrawApplyAction( BaseNode* _node, Action& _action, ACG::SceneGraph::DrawModes::DrawMode _globalDrawMode, int _pass, int _peelPass)
629 {
630  bool ret = true; // process_children flag returned
631 
632  // use nodes drawmode to grab a peeler program with correct shading
633  ACG::SceneGraph::DrawModes::DrawMode dm, dmSave = _node->drawMode();
634  dm = dmSave;
635 
636  if (!dm) return ret;
637 
639  dm = _globalDrawMode;
640 /*
641  if (dm & ACG::SceneGraph::DrawModes::HIDDENLINE)
642  {
643  // hiddenline is accomplished with wireframe in first peel layer only
644  dm &= ~ACG::SceneGraph::DrawModes::HIDDENLINE;
645  dm |= ACG::SceneGraph::DrawModes::WIREFRAME;
646  if (_peelPass > 2)
647  return ret;
648  _node->drawMode(dm);
649  }
650 */
652  {
654  dmShaded &= ~ACG::SceneGraph::DrawModes::WIREFRAME;
655  dmShaded &= ~ACG::SceneGraph::DrawModes::HIDDENLINE;
656 
657  // polygon only draw
658  if (dmShaded)
659  {
660  _node->drawMode(dmShaded); // evil method: change nodes drawmode here, restore it later
661  ret &= traverseDrawApplyAction(_node, _action, _globalDrawMode, _pass, _peelPass);
662  }
663 
664  // wireframe only follows
665  dm &= (~dmShaded);
666  _node->drawMode(dm);
667  }
668 
669  unsigned int shaderIndex = getPeelShaderIndex(dm);
670 
671  // do hiddenline algorithmus manually here
672  GLenum prev_depth = glStateTmp_->depthFunc();
673  if (dm & ACG::SceneGraph::DrawModes::HIDDENLINE)
674  {
675  // manual hiddenline
676 
677  // First:
678  // Render all faces in background color to initialize z-buffer
680 
681  GLSL::Program* peelProg = peelProgs_[PEEL_SHADER_HIDDENLINE];
682  peelProg->use();
683  peelProg->setUniform("DepthBlenderTex", 4);
684  peelProg->setUniform("FrontBlenderTex", 5);
685  peelProg->setUniform("ObjectColor", glStateTmp_->clear_color());
686 
687  ACG::GLState::depthRange(0.01, 1.0);
690  ret &= _action(_node);
693  ACG::GLState::depthRange(0.0, 1.0);
694 
695  // Second
696  // Render the lines. All lines not on the front will be skipped in z-test
698 
699  ACG::GLState::depthFunc(GL_LEQUAL);
700  ACG::GLState::lockDepthFunc();
701 
702  // use wireframe shader now
703  shaderIndex = PEEL_SHADER_WIREFRAME;
704  }
705 
706  GLSL::Program* peelProg = peelProgs_[shaderIndex];
707  peelProg->use();
708  peelProg->setUniform("DepthBlenderTex", 4);
709  peelProg->setUniform("FrontBlenderTex", 5);
710 
711  if (shaderIndex & PEEL_SHADER_FLAT)
712  {
713  // set geomtry shader constants
714  peelProg->setGeometryInputType(GL_TRIANGLES);
715  peelProg->setGeometryOutputType(GL_TRIANGLE_STRIP);
716  peelProg->setGeometryVertexCount(3);
717  }
718  peelProg->setUniform("DiffuseTex", 0);
719 
721  ret &= _action(_node);
723 
724  // restore state
725  _node->drawMode(dmSave);
726 
727  if (dm & ACG::SceneGraph::DrawModes::HIDDENLINE)
728  {
729  ACG::GLState::unlockDepthFunc();
730 
731  //restore depth buffer comparison function
732  ACG::GLState::depthFunc(prev_depth);
733  }
734 
735  return ret;
736 }
737 
739 
740 template <class Action>
741 void
742 DepthPeelingPlugin::traverseDraw( BaseNode* _node, Action& _action, ACG::SceneGraph::DrawModes::DrawMode _globalDrawMode, int _pass, int _peelPass)
743 {
744 
745  // Process node if it exists
746  if (_node) {
747  BaseNode::StatusMode status(_node->status());
748 
749  // If the subtree is hidden, ignore this node and its children while rendering
750  if (status != BaseNode::HideSubtree) {
751 
752  bool process_children(status != BaseNode::HideChildren);
753 
754  // Executes this nodes enter function (if available and active in multipass)
755  if ( _node->multipassStatusActive(_pass) ) {
756  if_has_enter(_action, _node);
757  }
758 
759  // If the node itself is hidden, don't call the action on it.
760  // Additionally check if rendering order is node first. otherwise, we will call it after the children.
761  // And check if it should be called in this rendering pass.
762  if ( (_node->status() != BaseNode::HideNode ) && ( _node->traverseMode() & BaseNode::NodeFirst ) && _node->multipassNodeActive(_pass))
763  process_children &= traverseDrawApplyAction(_node, _action, _globalDrawMode, _pass, _peelPass);
764 
765  if (process_children) {
766 
767  BaseNode::ChildIter cIt, cEnd(_node->childrenEnd());
768 
769  // Process all children
770  for (cIt = _node->childrenBegin(); cIt != cEnd; ++cIt)
771  if (~(*cIt)->traverseMode() & BaseNode::SecondPass)
772  traverseDraw(*cIt, _action, _globalDrawMode, _pass, _peelPass);
773 
774  // Process all children which are second pass
775  for (cIt = _node->childrenBegin(); cIt != cEnd; ++cIt)
776  if ((*cIt)->traverseMode() & BaseNode::SecondPass)
777  traverseDraw(*cIt, _action, _globalDrawMode, _pass, _peelPass);
778 
779  }
780 
781 
782  // If we are in childrenfirst node, the children have been painted andwe now check, if we can draw this node.
783  // If its hidden, ignore it.
784  // If it should not be rendered in this pass, ignore it too.
785  if ( (_node->traverseMode() & BaseNode::ChildrenFirst ) && (_node->status() != BaseNode::HideNode) && _node->multipassNodeActive(_pass) )
786  traverseDrawApplyAction(_node, _action, _globalDrawMode, _pass, _peelPass);
787 
788  // Call the leave function of the node (if available and active in multipass).
789  if ( _node->multipassStatusActive(_pass) )
790  if_has_leave(_action, _node);
791 
792  } // if (status != BaseNode::HideSubtree)
793  } // if(node_)
794 }
795 
796 void DepthPeelingPlugin::drawScenePeelPass(ACG::GLState* _glState, ACG::SceneGraph::DrawModes::DrawMode _drawMode, BaseNode* _sceneGraphRoot, int _peelPass)
797 {
798  ACG::SceneGraph::DrawAction action(_drawMode, *_glState, false);
799 // traverseDraw(_sceneGraphRoot, action, *_glState, _drawMode);
800 
801  // Reset render pass counter
802  _glState->reset_render_pass();
803 
804  // Get max render passes
805  unsigned int max_passes = _glState->max_render_passes();
806 
807  // Render all passes
808  for(unsigned int pass = BaseNode::PASS_1; pass <= (BaseNode::PASS_1 + max_passes); ++pass) {
809 
810  // Traverse scenegraph
811  traverseDraw (_sceneGraphRoot, action, _drawMode, pass, _peelPass);
812  // Increment render pass counter by 1
813  _glState->next_render_pass();
814  }
815 
816  // Reset render pass counter
817  _glState->reset_render_pass();
818 }
819 
821 
823 {
824  ACG::SceneGraph::DrawAction action(_drawMode, *_glState, false);
825  traverse_multipass(_sceneGraphRoot, action, *_glState, _drawMode);
826 }
827 
829 
831 {
832  bool rebuildShaders = false;
833 
835 
836  // peel shader is rebuilt, if a new light is added or a light type changed
837 
838  LightType prevLights[8];
839  unsigned int prevIDs[8];
840  unsigned int prevNum = numLights_;
841 
842  memcpy(prevLights, lightTypes_, sizeof(LightType) * numLights_);
843  memcpy(prevIDs, glLightIDs_, sizeof(unsigned int) * numLights_);
844 
845  numLights_ = 0;
846  traverseLightNodes(sceneGraphRoot);
847 
848  // test for necessary shader recompilation
849  if (numLights_ == prevNum)
850  {
851  // look for any light node changes
852  if (memcmp(prevLights, lightTypes_, sizeof(LightType) * numLights_) ||
853  memcmp(prevIDs, glLightIDs_, sizeof(unsigned int) * numLights_))
854  rebuildShaders = true;
855  }
856  else rebuildShaders = true;
857 
858  if (rebuildShaders)
859  {
860  // delete old shaders and programs
861  for (unsigned int i = 0; i < sizeof(peelShaders_) / sizeof(peelShaders_[0]); ++i)
862  {
863  delete peelShaders_[i]; peelShaders_[i] = 0;
864  }
865 
866  for (unsigned int i = 0; i < sizeof(peelProgs_) / sizeof(peelProgs_[0]); ++i)
867  {
868  delete peelProgs_[i]; peelProgs_[i] = 0;
869  }
870 
871  for (unsigned int i = 0; i < PEEL_NUM_COMBINATIONS; ++i)
872  {
873  GLuint texturedDrawMode = 0, flatDrawMode = 0, phongDrawMode = 0, vertexColorDrawMode = 0, gouraudDrawMode = 0;
874 
875  texturedDrawMode = i & PEEL_SHADER_TEXTURED;
876  flatDrawMode = i & PEEL_SHADER_FLAT;
877  phongDrawMode = i & PEEL_SHADER_PHONG;
878  vertexColorDrawMode = i & PEEL_SHADER_VERTEXCOLORS;
879  gouraudDrawMode = i & PEEL_SHADER_GOURAUD;
880 
881  if (i != PEEL_SHADER_WIREFRAME)
882  {
883  // filter nonsense
884  if (flatDrawMode && phongDrawMode) continue;
885  if (flatDrawMode && gouraudDrawMode) continue;
886  if (phongDrawMode && gouraudDrawMode) continue;
887 
888  if (phongDrawMode + flatDrawMode + gouraudDrawMode == 0) continue;
889  }
890 
891  if (flatDrawMode)
892  {
893  // replace flat shading with gouraud, if geometry shaders are not supported
894  if (!ACG::checkExtensionSupported("GL_ARB_geometry_shader4") && !ACG::checkExtensionSupported("GL_EXT_geometry_shader4"))
895  {
896  flatDrawMode = 0;
897  gouraudDrawMode = 1;
898  }
899  }
900 
901  GLSL::StringList strVertexShader, strFragmentShader, strGeometryShader;
902  generatePeelingShaders(&strVertexShader, &strFragmentShader, &strGeometryShader, texturedDrawMode != 0, flatDrawMode != 0, phongDrawMode != 0, vertexColorDrawMode != 0, i == PEEL_SHADER_WIREFRAME);
903 
904  peelProgs_[i] = new GLSL::Program();
905 
906 
907  GLSL::VertexShader* pVertexSh = new GLSL::VertexShader();
908  pVertexSh->setSource(strVertexShader);
909  pVertexSh->compile();
910  peelShaders_[i*3 + 0] = pVertexSh;
911  peelProgs_[i]->attach(pVertexSh);
912 
913  if (flatDrawMode)
914  {
916  pGeomSh->setSource(strGeometryShader);
917  pGeomSh->compile();
918  peelShaders_[i*3 + 1] = pGeomSh;
919  peelProgs_[i]->attach(pGeomSh);
920  }
921 
923  pFragSh->setSource(strFragmentShader);
924  pFragSh->compile();
925  peelShaders_[i*3 + 2] = pFragSh;
926  peelProgs_[i]->attach(pFragSh);
927 
928  peelProgs_[i]->link();
930 
931 
932 #ifdef DEPTHPEELING_SHADER_EXPORT
933  char szFileName[256];
934  sprintf(szFileName, "peel_vertex_%02u.glsl", i);
935  FILE* pShaderOut = fopen(szFileName, "wt");
936  for (GLSL::StringList::iterator it = strVertexShader.begin(); it != strVertexShader.end(); ++it)
937  fprintf(pShaderOut, it->c_str());
938  fclose(pShaderOut);
939 
940 
941  sprintf(szFileName, "peel_frag%02u.glsl", i);
942  pShaderOut = fopen(szFileName, "wt");
943  for (GLSL::StringList::iterator it = strFragmentShader.begin(); it != strFragmentShader.end(); ++it)
944  fprintf(pShaderOut, it->c_str());
945  fclose(pShaderOut);
946 
947  if (flatDrawMode)
948  {
949  sprintf(szFileName, "peel_geom%02u.glsl", i);
950  pShaderOut = fopen(szFileName, "wt");
951  for (GLSL::StringList::iterator it = strGeometryShader.begin(); it != strGeometryShader.end(); ++it)
952  fprintf(pShaderOut, it->c_str());
953  fclose(pShaderOut);
954  }
955 #endif
956  }
957  }
958 
959 
960  // create a special shader for hiddenline
961  // hiddenline = wireframe + early z cull
962  // the special shader is needed for the z buffer pass
963 
964  const char* szVertexShader[] = {
965  "void main(void)",
966  "{",
967  " gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;",
968  "}"};
969 
970  const char* szFragmentShader[] = {
971  "uniform vec4 ObjectColor;",
972  "uniform sampler2DRect DepthBlenderTex;",
973  "uniform sampler2DRect FrontBlenderTex;",
974  "",
975  "#define MAX_DEPTH 1.0",
976  "",
977  "",
978  "void main(void)",
979  "{",
980  " // window-space depth interpolated linearly in screen space",
981  " float fragDepth = gl_FragCoord.z;",
982  "",
983  " vec2 depthBlender = texture2DRect(DepthBlenderTex, gl_FragCoord.xy).xy;",
984  " vec4 forwardTemp = texture2DRect(FrontBlenderTex, gl_FragCoord.xy);",
985  " ",
986  " // Depths and 1.0-alphaMult always increase",
987  " // so we can use pass-through by default with MAX blending",
988  " gl_FragData[0].xy = depthBlender;",
989  " ",
990  " // Front colors always increase (DST += SRC*ALPHA_MULT)",
991  " // so we can use pass-through by default with MAX blending",
992  " gl_FragData[1] = forwardTemp;",
993  " ",
994  " // Because over blending makes color increase or decrease,",
995  " // we cannot pass-through by default.",
996  " // Each pass, only one fragment writes a color greater than 0",
997  " gl_FragData[2] = vec4(0.0);",
998  "",
999  " float nearestDepth = -depthBlender.x;",
1000  " float farthestDepth = depthBlender.y;",
1001  " float alphaMultiplier = 1.0 - forwardTemp.w;",
1002  "",
1003  " if (fragDepth < nearestDepth || fragDepth > farthestDepth) {",
1004  " // Skip this depth in the peeling algorithm",
1005  " gl_FragData[0].xy = vec2(-MAX_DEPTH);",
1006  " return;",
1007  " }",
1008  " ",
1009  " if (fragDepth > nearestDepth && fragDepth < farthestDepth) {",
1010  " // This fragment needs to be peeled again",
1011  " gl_FragData[0].xy = vec2(-fragDepth, fragDepth);",
1012  " return;",
1013  " }",
1014  " ",
1015  " // If we made it here, this fragment is on the peeled layer from last pass",
1016  " // therefore, we need to shade it, and make sure it is not peeled any farther",
1017  " vec4 color = ObjectColor;",
1018  " gl_FragData[0].xy = vec2(-MAX_DEPTH);",
1019  " ",
1020  " if (fragDepth == nearestDepth) {",
1021  " gl_FragData[1].xyz += color.rgb * color.a * alphaMultiplier;",
1022  " gl_FragData[1].w = 1.0 - alphaMultiplier * (1.0 - color.a);",
1023  " } else {",
1024  " gl_FragData[2] += color;",
1025  " }",
1026  "}"};
1027 
1028  GLSL::StringList strVertexShader, strFragmentShader;
1029  for (unsigned int i = 0; i < sizeof(szVertexShader) / sizeof(char*); ++i)
1030  {
1031  std::string str = szVertexShader[i];
1032  str += "\n";
1033  strVertexShader.push_back(str);
1034  }
1035 
1036  for (unsigned int i = 0; i < sizeof(szFragmentShader) / sizeof(char*); ++i)
1037  {
1038  std::string str = szFragmentShader[i];
1039  str += "\n";
1040  strFragmentShader.push_back(str);
1041  }
1042 
1043  GLSL::Program* peelHiddenLine = peelProgs_[PEEL_SHADER_HIDDENLINE] = new GLSL::Program();
1044 
1045  GLSL::VertexShader* pVertexSh = new GLSL::VertexShader();
1046  pVertexSh->setSource(strVertexShader);
1047  pVertexSh->compile();
1048  peelShaders_[PEEL_SHADER_HIDDENLINE*3 + 0] = pVertexSh;
1049  peelHiddenLine->attach(pVertexSh);
1050 
1051  GLSL::FragmentShader* pFragSh = new GLSL::FragmentShader();
1052  pFragSh->setSource(strFragmentShader);
1053  pFragSh->compile();
1054  peelShaders_[PEEL_SHADER_HIDDENLINE*3 + 2] = pFragSh;
1055  peelHiddenLine->attach(pFragSh);
1056 
1057  peelHiddenLine->link();
1059 }
1060 
1062 
1064 {
1065  if (_drawMode & ACG::SceneGraph::DrawModes::WIREFRAME ||
1067  return PEEL_SHADER_WIREFRAME;
1068 
1070  bool flat = _drawMode & ACG::SceneGraph::DrawModes::SOLID_FLAT_SHADED;
1071  bool phong = _drawMode & ACG::SceneGraph::DrawModes::SOLID_PHONG_SHADED;
1074 
1075  bool gouraud = _drawMode & ACG::SceneGraph::DrawModes::SOLID_SMOOTH_SHADED;
1076 
1077  // fix illegal combinations
1078  if (phong && flat) flat = false;
1079  if (flat && gouraud) gouraud = false;
1080  if (gouraud && phong) phong = false;
1081 
1082  // wireframe, point, etc use gouraud shading
1083  if ((!phong) && (!gouraud) && (!flat)) gouraud = true;
1084 
1085  unsigned int idx = 0;
1086 
1087  if (flat) idx |= PEEL_SHADER_FLAT;
1088  if (gouraud) idx |= PEEL_SHADER_GOURAUD;
1089  if (phong) idx |= PEEL_SHADER_PHONG;
1090  if (vertexColor) idx |= PEEL_SHADER_VERTEXCOLORS;
1091  if (textured) idx |= PEEL_SHADER_TEXTURED;
1092 
1093  return idx;
1094 }
1095 
1096 QString DepthPeelingPlugin::checkOpenGL() {
1097 
1098  if (!ACG::openGLVersion(2, 0))
1099  return QString("Insufficient OpenGL Version! OpenGL 2.0 or higher required");
1100 
1101  // Collect missing extension
1102  QString missing = "";
1103 
1104  if ( !ACG::checkExtensionSupported("GL_ARB_geometry_shader4") )
1105  missing += "Missing Extension GL_ARB_geometry_shader4\n";
1106 
1107  if ( !ACG::checkExtensionSupported("GL_ARB_vertex_program") )
1108  missing += "Missing Extension GL_ARB_vertex_program\n";
1109 
1110  return missing;
1111 }
1112 
1113 
1114 #if QT_VERSION < 0x050000
1115  Q_EXPORT_PLUGIN2( depthpeelingplugin , DepthPeelingPlugin );
1116 #endif
1117 
StatusMode status() const
Get node&#39;s status.
Definition: BaseNode.hh:432
DrawMode POINTS_COLORED
draw colored, but not lighted points (requires point colors)
Definition: DrawModes.cc:80
void next_render_pass()
increment render pass counter
Definition: GLState.hh:993
void attach(PtrConstShader _shader)
Attaches a shader object to the program object.
Definition: GLSLShader.cc:298
ChildIter childrenEnd()
Returns: end-iterator of children.
Definition: BaseNode.hh:329
void setSource(const StringList &source)
Upload the source of the shader.
Definition: GLSLShader.cc:109
std::vector< BaseNode * >::iterator ChildIter
allows to iterate over children
Definition: BaseNode.hh:317
DrawMode SOLID_SMOOTH_SHADED
draw smooth shaded (Gouraud shaded) faces (requires halfedge normals)
Definition: DrawModes.cc:88
DrawMode HIDDENLINE
draw hidden line (2 rendering passes needed)
Definition: DrawModes.cc:86
DrawMode SOLID_FLAT_SHADED
draw flat shaded faces (requires face normals)
Definition: DrawModes.cc:87
bool compile(bool verbose=true)
Compile the shader object.
Definition: GLSLShader.cc:152
void reset_render_pass()
reset render pass counter
Definition: GLState.hh:990
DrawMode DEFAULT
use the default (global) draw mode and not the node&#39;s own.
Definition: DrawModes.cc:78
DrawMode WIREFRAME
draw wireframe
Definition: DrawModes.cc:84
DrawMode SOLID_FACES_COLORED_SMOOTH_SHADED
draw smooth shaded and colored faces (requires vertex normals and face colors)
Definition: DrawModes.cc:101
static void unlockDepthRange()
unlock depth range
Definition: GLState.hh:415
DrawModes::DrawMode drawMode() const
Return the own draw modes of this node.
Definition: BaseNode.hh:461
static void lockProgram()
lock the program
Definition: GLState.hh:632
int numLights_
Number of Lights.
Definition: IRenderer.hh:489
void traverse_multipass(BaseNode *_node, Action &_action, const unsigned int &_pass)
Definition: SceneGraph.hh:260
void link()
Links the shader objects to the program.
Definition: GLSLShader.cc:332
Hide this node and its children.
Definition: BaseNode.hh:429
Execute action on node first and then on its children.
Definition: BaseNode.hh:472
void generatePeelingShaders(GLSL::StringList *_strVertexShaderOut, GLSL::StringList *_strFragmentShaderOut, GLSL::StringList *_strGeometryShaderOut, bool _textured, bool _flatShaded, bool _phong, bool _vertexColor, bool _wireFrame)
peel shader generator based on lights and texture mode
bool multipassNodeActive(const unsigned int _i) const
Get Node status to traverse in a specific pass.
DrawMode SOLID_FACES_COLORED_FLAT_SHADED
draw flat shaded and colored faces (requires face normals and colors)
Definition: DrawModes.cc:100
void use()
Enables the program object for using.
Definition: GLSLShader.cc:351
GLSL vertex shader.
Definition: GLSLShader.hh:101
Draw this node, but hide children.
Definition: BaseNode.hh:427
bool openGLVersion(const int _major, const int _minor)
Definition: gl.cc:95
GLSL geometry shader.
Definition: GLSLShader.hh:130
const GLenum & depthFunc() const
get glDepthFunc() that is supposed to be active
Definition: GLState.cc:937
DrawMode SOLID_TEXTURED
draw textured faces
Definition: DrawModes.cc:94
DrawMode SOLID_FACES_COLORED
draw colored, but not lighted faces using face colors
Definition: DrawModes.cc:90
static void depthRange(GLclampd _zNear, GLclampd _zFar)
replaces glDepthRange, supports locking
Definition: GLState.cc:1728
void getLightSource(LightSource *_light) const
Get the light source parameters.
Definition: LightNode.cc:259
void updatePeelingShaderSet()
regenerates peeling shaders based on light nodes in scenegraph
unsigned int max_render_passes() const
get maximum number of render passes
Definition: GLState.hh:996
DrawMode SOLID_PHONG_SHADED
draw phong shaded faces
Definition: DrawModes.cc:89
void traverseLightNodes(BaseNode *_node)
find all light nodes in the scene
void setGeometryInputType(GLint _type)
Set Type of Geometry.
Definition: GLSLShader.cc:742
static void unlockProgram()
unlock the program
Definition: GLState.hh:634
Hide this node, but draw children.
Definition: BaseNode.hh:425
ChildIter childrenBegin()
Returns: begin-iterator of children.
Definition: BaseNode.hh:325
StatusMode
Status modi.
Definition: BaseNode.hh:420
void setUniform(const char *_name, GLint _value)
Set int uniform to specified value.
Definition: GLSLShader.cc:391
void drawScenePass(ACG::GLState *_glState, ACG::SceneGraph::DrawModes::DrawMode _drawMode, BaseNode *_sceneGraphRoot)
draw the current scene
unsigned int getPeelShaderIndex(ACG::SceneGraph::DrawModes::DrawMode _drawMode)
converts a drawmode to the correct shading program index
bool directional() const
Check if the light source is a directional light source.
Definition: LightNode.cc:133
void drawQuadProj(float _x0=-1.0f, float _y0=1.0f, float _w=2.0f, float _h=2.0f)
draw a quad in projection space (only positions)
Namespace providing different geometric functions concerning angles.
Definition: DBSCANT.cc:51
void setGeometryVertexCount(GLint _numVerticesOut)
Sets the maximum vertex output of the geometry shader.
Definition: GLSLShader.cc:762
void setGeometryOutputType(GLint _type)
Set output type of geometry.
Definition: GLSLShader.cc:752
DrawMode SOLID_POINTS_COLORED
draw colored, but not lighted faces using interpolated vertex colors
Definition: DrawModes.cc:91
Draw node in second pass.
Definition: BaseNode.hh:476
bool multipassStatusActive(const unsigned int _i) const
Get multipass status to traverse in a specific pass.
Execute action the children first and then on this node.
Definition: BaseNode.hh:474
DrawMode SOLID_TEXTURED_SHADED
draw smooth shaded textured faces
Definition: DrawModes.cc:95
bool checkExtensionSupported(const std::string &_extension)
Definition: gl.cc:73
ACG::SceneGraph::BaseNode * getSceneGraphRootNode()
get scenegraph root node
LightType
light type enumeration
GLSL fragment shader.
Definition: GLSLShader.hh:116
unsigned int traverseMode() const
Return how the node should be traversed.
Definition: BaseNode.hh:480
GLSL program class.
Definition: GLSLShader.hh:217
static void lockDepthRange()
lock depth range
Definition: GLState.hh:413
Structure to hold options for one LightSource.
Definition: LightNode.hh:91
void glCheckErrors()
Definition: GLError.hh:105