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