Developer Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
IRenderer.cc
1 /*===========================================================================*\
2  * *
3  * OpenFlipper *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39  * *
40 \*===========================================================================*/
41 
42 /*===========================================================================*\
43  * *
44  * $Revision$ *
45  * $Author$ *
46  * $Date$ *
47  * *
48 \*===========================================================================*/
49 
50 #include <ACG/GL/acg_glew.hh>
51 #include <cstdio>
52 #include <cstring>
53 #include <iostream>
54 #include <algorithm>
55 #include <QFile>
56 #include <QTextStream>
57 
58 #include <ACG/GL/gl.hh>
59 
60 #include <ACG/GL/IRenderer.hh>
61 
62 #include <ACG/GL/VertexDeclaration.hh>
63 #include <ACG/GL/GLError.hh>
64 
65 #include <ACG/GL/ShaderCache.hh>
66 #include <ACG/GL/ScreenQuad.hh>
67 #include <ACG/GL/FBO.hh>
68 #include <ACG/GL/globjects.hh>
69 
70 
71 
72 namespace ACG
73 {
74 
76 
77 IRenderer::IRenderer()
78 : numLights_(0),
79 renderObjects_(0),
80 depthMapUsed_(false),
81 curViewerID_(0),
82 prevFbo_(0),
83 prevDrawBuffer_(GL_BACK),
84 prevFboSaved_(false),
85 depthCopyShader_(0),
86 errorDetectionLevel_(1),
87 enableLineThicknessGL42_(false)
88 {
89  prevViewport_[0] = 0;
90  prevViewport_[1] = 0;
91  prevViewport_[2] = 0;
92  prevViewport_[3] = 0;
93 
94  // set global ambient scale to default OpenGL value
95  globalLightModelAmbient_ = ACG::Vec3f(0.2f, 0.2f, 0.2f);
96 }
97 
98 
99 IRenderer::~IRenderer()
100 {
101  delete depthCopyShader_;
102 
103  // free depth map fbos
104  for (std::map<int, ACG::FBO*>::iterator it = depthMaps_.begin(); it != depthMaps_.end(); ++it)
105  delete it->second;
106 }
107 
109 {
110  // avoid null-ptr access
111  if (!_renderObject->debugName)
112  _renderObject->debugName = "<unnamed>";
113 
114  if (_renderObject->name.empty())
115  _renderObject->name = _renderObject->debugName;
116 
117  // do some more checks for error detection
118  if (!_renderObject->vertexDecl && !_renderObject->vertexArrayObject)
119  std::cout << "error: missing vertex declaration in renderobject: " << _renderObject->debugName << std::endl;
120  else
121  {
122  if (errorDetectionLevel_ > 0)
123  {
124  // commonly encountered rendering errors
125 
126  if (!_renderObject->numIndices)
127  std::cout << "warning: numIndices is 0 in renderobject: " << _renderObject->debugName << std::endl;
128 
129  // Why is my object invisible/black?
130  if (!_renderObject->depthWrite &&
131  !_renderObject->colorWriteMask[0] && !_renderObject->colorWriteMask[1] &&
132  !_renderObject->colorWriteMask[2] && !_renderObject->colorWriteMask[3])
133  std::cout << "warning: depth write and color write disabled in renderobject: " << _renderObject->debugName << std::endl;
134 
135  if (errorDetectionLevel_ > 1 && _renderObject->shaderDesc.shadeMode == SG_SHADE_UNLIT)
136  {
137  if (_renderObject->emissive.max() < 1e-3f)
138  std::cout << "warning: unlit object rendered with black emissive color: " << _renderObject->debugName << std::endl;
139  else
140  {
141  // rendering with clear color
142 
143  float clearColor[4];
144  glGetFloatv(GL_COLOR_CLEAR_VALUE, clearColor);
145 
146  if (checkEpsilon(clearColor[0] - _renderObject->emissive[0]) &&
147  checkEpsilon(clearColor[1] - _renderObject->emissive[1]) &&
148  checkEpsilon(clearColor[2] - _renderObject->emissive[2]))
149  {
150  std::cout << "warning: unlit object rendered with clear color as emissive color: " << _renderObject->debugName << std::endl;
151  std::cout << " Should this be intentional, disable color writing instead via obj->glColorMask(0,0,0,0)" << std::endl;
152  }
153  }
154  }
155 
156  if (_renderObject->textures().size())
157  {
158  // Why are my textures sampled as black?
159 
160  // mipmap enabled, but no mipmap chain provided?
161 
162  for (std::map<size_t,RenderObject::Texture>::const_iterator it = _renderObject->textures().begin();
163  it != _renderObject->textures().end(); ++it)
164  {
165 #ifdef GL_ARB_texture_buffer_object
166  if (it->second.type == GL_TEXTURE_BUFFER)
167  continue; // skip texture buffers, for which testing for mipmaps would generate an error
168 #endif
169 
170  glBindTexture(it->second.type, it->second.id);
171 
172  GLint minFilter = GL_NONE;
173  glGetTexParameteriv(it->second.type, GL_TEXTURE_MIN_FILTER, &minFilter);
174 
175  if (minFilter == GL_NEAREST_MIPMAP_LINEAR ||
176  minFilter == GL_NEAREST_MIPMAP_NEAREST ||
177  minFilter == GL_LINEAR_MIPMAP_LINEAR ||
178  minFilter == GL_LINEAR_MIPMAP_NEAREST)
179  {
180  GLint maxLevel = 0;
181  glGetTexParameteriv(it->second.type, GL_TEXTURE_MAX_LEVEL, &maxLevel);
182 
183  GLint texWidth = 0;
184  glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &texWidth);
185 
186  GLint maxLod = -1;
187  for (GLint lod = 0; lod < maxLevel && maxLod < 0; ++lod)
188  {
189  GLint lodWidth;
190  glGetTexLevelParameteriv(GL_TEXTURE_2D, lod, GL_TEXTURE_WIDTH, &lodWidth);
191 
192  if (lodWidth <= 0 || lodWidth == GL_INVALID_VALUE)
193  maxLod = lod-1;
194  }
195 
196  if (maxLod <= 0 && texWidth > 1)
197  {
198  std::cout << "warning: texture is sampled with mipmapping, but no mipchain is present: " << _renderObject->debugName << " texid: " << it->second.id << std::endl;
199  std::cout << " automatically disabling mipmapping!!" << std::endl;
200 
201  GLint correctedFilter = GL_LINEAR;
202 
203  if (minFilter == GL_NEAREST_MIPMAP_LINEAR ||
204  minFilter == GL_LINEAR_MIPMAP_LINEAR)
205  correctedFilter = GL_LINEAR;
206  else
207  correctedFilter = GL_NEAREST;
208 
209  glTexParameteri(it->second.type, GL_TEXTURE_MIN_FILTER, correctedFilter);
210  }
211  }
212  }
213 
214  }
215 
216  if (errorDetectionLevel_ > 1)
217  {
218  // Why is there nothing written to the depth-buffer?
219  // this might very well be intentional, so put it in higher level
220 
221  if (_renderObject->depthWrite && !_renderObject->depthTest)
222  {
223  std::cout << "warning: trying to write to depth buffer with depth-testing disabled does not work in: " << _renderObject->debugName << std::endl;
224  std::cout << " If depth-writing was intended, enable depth-testing and set depth-func to GL_ALWAYS" << std::endl;
225  }
226  }
227 
228  if (!_renderObject->vertexArrayObject)
229  {
230  // Why are there gl errors and/or nothing gets drawn?
231  if (_renderObject->shaderDesc.shadeMode != SG_SHADE_UNLIT)
232  {
233  // check for normals
234  if (!_renderObject->vertexDecl->findElementByUsage(VERTEX_USAGE_NORMAL))
235  std::cout << "warning: missing normals for lighting in renderobject: " << _renderObject->debugName << std::endl
236  << " Set shadeMode to SG_SHADE_UNLIT or provide normals!" << std::endl;
237  }
238 
239  if (_renderObject->shaderDesc.textured())
240  {
241  // check for texcoords
243  std::cout << "warning: missing texcoords for textured mode in renderobject: " << _renderObject->debugName << std::endl;
244  }
245 
246  if (_renderObject->shaderDesc.vertexColors)
247  {
248  // check for vertex colors
249  if (!_renderObject->vertexDecl->findElementByUsage(VERTEX_USAGE_COLOR))
250  std::cout << "warning: missing colors for vertexcolor mode in renderobject: " << _renderObject->debugName << std::endl;
251  }
252  }
253 
254 
255  // Why is alpha blending not work?
256  if (fabsf(_renderObject->alpha - 1.0f) > 1e-3f && !(_renderObject->alphaTest || _renderObject->blending))
257  std::cout << "warning: alpha value != 1 but no alpha blending or testing enabled in renderobject: " << _renderObject->debugName << std::endl;
258 
259 
260 #ifdef GL_ARB_tessellation_shader
261  // Trying to render with tessellation shaders?
262  const bool tessellationActive = !_renderObject->shaderDesc.tessControlTemplateFile.isEmpty() || !_renderObject->shaderDesc.tessEvaluationTemplateFile.isEmpty();
263  bool tryToFixPatchInfo = false;
264  if (tessellationActive && _renderObject->primitiveMode != GL_PATCHES)
265  {
266  std::cout << "error: tessellation shaders are not used with GL_PATCHES primitiveType in renderobject: " << _renderObject->debugName << std::endl;
267  tryToFixPatchInfo = true;
268  }
269 
270  if (tessellationActive && !_renderObject->patchVertices)
271  {
272  std::cout << "error: undefined patch size for tessellation in renderobject: " << _renderObject->debugName << std::endl;
273  tryToFixPatchInfo = true;
274  }
275 
276  if (tryToFixPatchInfo)
277  {
278  if (_renderObject->primitiveMode == GL_POINTS)
279  {
280  _renderObject->primitiveMode = GL_PATCHES;
281  _renderObject->patchVertices = 1;
282  std::cout << "warning: attempting to draw with patchVertices = 1 for tessellation in renderobject: " << _renderObject->debugName << std::endl;
283  }
284  else if (_renderObject->primitiveMode == GL_LINES)
285  {
286  _renderObject->primitiveMode = GL_PATCHES;
287  _renderObject->patchVertices = 2;
288  std::cout << "warning: attempting to draw with patchVertices = 2 for tessellation in renderobject: " << _renderObject->debugName << std::endl;
289  }
290  else if (_renderObject->primitiveMode == GL_TRIANGLES)
291  {
292  _renderObject->primitiveMode = GL_PATCHES;
293  _renderObject->patchVertices = 3;
294  std::cout << "warning: attempting to draw with patchVertices = 3 for tessellation in renderobject: " << _renderObject->debugName << std::endl;
295  }
296  else if (_renderObject->primitiveMode == GL_QUADS)
297  {
298  _renderObject->primitiveMode = GL_PATCHES;
299  _renderObject->patchVertices = 4;
300  std::cout << "warning: attempting to draw with patchVertices = 4 for tessellation in renderobject: " << _renderObject->debugName << std::endl;
301  }
302  }
303 
304 #endif
305  }
306 
307 
308  renderObjects_.push_back(*_renderObject);
309 
310 
311  ACG::RenderObject* p = &renderObjects_.back();
312 
313  // apply modifiers
314  size_t numMods = renderObjectModifiers_.size();
315  for (size_t i = 0; i < numMods; ++i)
316  {
317  if (renderObjectModifiers_[i])
318  renderObjectModifiers_[i]->apply(p);
319  }
320 
321  if (!p->shaderDesc.numLights)
322  p->shaderDesc.numLights = numLights_;
323 
324  else if (p->shaderDesc.numLights < 0 || p->shaderDesc.numLights >= SG_MAX_SHADER_LIGHTS)
325  p->shaderDesc.numLights = 0;
326 
327  p->internalFlags_ = 0;
328 
329  // precompile shader
330 #ifdef GL_VERSION_3_2
332 #endif
333 
334 
335  // check primitive type and geometry shader
336  if (errorDetectionLevel_ > 1 && p->shaderDesc.geometryTemplateFile.length())
337  {
338 #ifdef GL_VERSION_3_2
339  GLint geomInputType = 0;
340  glGetProgramiv(shaderProg->getProgramId(), GL_GEOMETRY_INPUT_TYPE, &geomInputType);
341 
342 
343  if (geomInputType != GLint(p->primitiveMode))
344  {
345 
346  switch (geomInputType)
347  {
348  case GL_POINTS: std::cout << "warning: primitive mode is incompatible with points-geometryshader in renderobject: " << _renderObject->debugName << std::endl; break;
349 
350  case GL_LINES:
351  {
352  if (p->primitiveMode != GL_LINE_STRIP && p->primitiveMode != GL_LINE_LOOP)
353  std::cout << "warning: primitive mode is incompatible with lines-geometryshader in renderobject: " << _renderObject->debugName << std::endl;
354  } break;
355 
356  case GL_LINES_ADJACENCY:
357  {
358  if (p->primitiveMode != GL_LINE_STRIP_ADJACENCY)
359  std::cout << "warning: primitive mode is incompatible with lines_adjacency-geometryshader in renderobject: " << _renderObject->debugName << std::endl;
360  } break;
361 
362  case GL_TRIANGLES:
363  {
364  if (p->primitiveMode != GL_TRIANGLE_STRIP && p->primitiveMode != GL_TRIANGLE_FAN)
365  std::cout << "warning: primitive mode is incompatible with triangles-geometryshader in renderobject: " << _renderObject->debugName << std::endl;
366  } break;
367 
368  case GL_TRIANGLES_ADJACENCY:
369  {
370  if (p->primitiveMode != GL_TRIANGLE_STRIP_ADJACENCY)
371  std::cout << "warning: primitive mode is incompatible with triangles_adjacency-geometryshader in renderobject: " << _renderObject->debugName << std::endl;
372  } break;
373 
374  default: std::cout << "warning: unknown input_type for geometryshader in renderobject: " << _renderObject->debugName << std::endl;
375  }
376 
377 
378 
379  }
380 
381 
382 #else
383  if (_renderObject->isDefaultLineObject())
384  {
385  if (_renderObject->primitiveMode != GL_LINES && _renderObject->primitiveMode != GL_LINE_STRIP && _renderObject->primitiveMode != GL_LINE_LOOP)
386  std::cout << "warning: primitive mode is incompatible with lines-geometryshader in renderobject: " << _renderObject->debugName << std::endl;
387  }
388  else if (_renderObject->isDefaultPointObject())
389  {
390  if (_renderObject->primitiveMode != GL_POINTS)
391  std::cout << "warning: primitive mode is incompatible with points-geometryshader in renderobject: " << _renderObject->debugName << std::endl;
392  }
393 #endif
394  }
395 
396  }
397 }
398 
399 
400 
401 
402 void IRenderer::collectRenderObjects( ACG::GLState* _glState, ACG::SceneGraph::DrawModes::DrawMode _drawMode, ACG::SceneGraph::BaseNode* _sceneGraphRoot )
403 {
404  // collect light sources
405 // collectLightNodes(_sceneGraphRoot);
406  numLights_ = 0; // reset light counter
407 
408 // // flush render objects
409 // for (size_t i = 0; i < renderObjects_.size(); ++i)
410 // {
411 // renderObjects_[i].uniformPool_.clear();
412 // }
413  renderObjects_.clear();
414 
415  if (!_sceneGraphRoot) return;
416 
417  // default material needed
419  defMat.baseColor(ACG::Vec4f(0.0f, 0.0f, 0.0f, 1.0f));
420  defMat.ambientColor(ACG::Vec4f(0.2f, 0.2f, 0.2f, 1.0f));
421  defMat.diffuseColor(ACG::Vec4f(0.6f, 0.6f, 0.6f, 1.0f));
422  defMat.specularColor(ACG::Vec4f(0.0f, 0.0f, 0.0f, 1.0f));
423  defMat.shininess(1.0f);
424  // defMat.alphaValue(1.0f);
425 
426  // collect renderables
427  traverseRenderableNodes(_glState, _drawMode, *_sceneGraphRoot, defMat);
428 }
429 
430 
432 namespace {
433 class ScenegraphTraversalStackEl {
434  public:
435  ScenegraphTraversalStackEl(ACG::SceneGraph::BaseNode *_node,
436  const ACG::SceneGraph::Material *_material) :
437  node(_node), material(_material),
438  subtree_index_start(0), leave(false) {}
439 
441  const ACG::SceneGraph::Material* material;
442  size_t subtree_index_start;
443  bool leave;
444 };
445 }
446 
447 void IRenderer::traverseRenderableNodes( ACG::GLState* _glState, ACG::SceneGraph::DrawModes::DrawMode _drawMode, ACG::SceneGraph::BaseNode &_node, const ACG::SceneGraph::Material &_mat )
448 {
449  renderObjectSource_.clear();
450  overlayObjectSource_.clear();
451 
453  return;
454 
455  std::vector<ScenegraphTraversalStackEl> stack;
456  // That's roughly the minimum size every scenegraph requries.
457  stack.reserve(32);
458  stack.push_back(ScenegraphTraversalStackEl(&_node, &_mat));
459  while (!stack.empty()) {
460  ScenegraphTraversalStackEl &cur = stack.back();
461  ACG::SceneGraph::DrawModes::DrawMode nodeDM = cur.node->drawMode();
463  nodeDM = _drawMode;
464 
465  if (!cur.leave) {
466  /*
467  * Stuff that happens before processing cur.node's children.
468  */
469  if ( cur.node->status() != ACG::SceneGraph::BaseNode::HideNode )
470  cur.node->enter(this, *_glState, nodeDM);
471 
472  cur.subtree_index_start = renderObjects_.size();
473 
474  // fetch material (Node itself can be a material node, so we have to
475  // set that in front of the nodes own rendering
477  dynamic_cast<ACG::SceneGraph::MaterialNode*>(cur.node);
478  if (matNode)
479  cur.material = &matNode->material();
480 
481  if (cur.node->status() != ACG::SceneGraph::BaseNode::HideNode)
482  cur.node->getRenderObjects(this, *_glState, nodeDM, cur.material);
483 
484  // keep track of which node added objects
485  size_t numAddedObjects = renderObjects_.size() - renderObjectSource_.size();
486  renderObjectSource_.insert(renderObjectSource_.end(), numAddedObjects, cur.node);
487 
488  // Process children?
489  if (cur.node->status() != ACG::SceneGraph::BaseNode::HideChildren) {
490  // Process all children which are second pass
492  cIt = cur.node->childrenBegin(),
493  cEnd = cur.node->childrenEnd(); cIt != cEnd; ++cIt) {
494  if (((*cIt)->traverseMode() &
496  (*cIt)->status() != ACG::SceneGraph::BaseNode::HideSubtree)
497  stack.push_back(ScenegraphTraversalStackEl(*cIt, cur.material));
498  }
499 
500  // Process all children which are not second pass
502  cIt = cur.node->childrenBegin(),
503  cEnd = cur.node->childrenEnd(); cIt != cEnd; ++cIt) {
504  if ((~(*cIt)->traverseMode() &
506  (*cIt)->status() != ACG::SceneGraph::BaseNode::HideSubtree)
507  stack.push_back(ScenegraphTraversalStackEl(*cIt, cur.material));
508  }
509  }
510 
511  // Next time process the other branch of this if statement.
512  cur.leave = true;
513 
514  } else {
515  /*
516  * Stuff that happens after processing cur.node's children.
517  */
518  current_subtree_objects_ = RenderObjectRange(
519  renderObjects_.begin() + cur.subtree_index_start,
520  renderObjects_.end());
521 
522  if (cur.node->status() != ACG::SceneGraph::BaseNode::HideNode )
523  cur.node->leave(this, *_glState, nodeDM);
524  stack.pop_back();
525  }
526  }
527 }
528 
529 void IRenderer::prepareRenderingPipeline(ACG::GLState* _glState, ACG::SceneGraph::DrawModes::DrawMode _drawMode, ACG::SceneGraph::BaseNode* _scenegraphRoot)
530 {
531  // grab view transform from glstate
532  viewMatrix_ = _glState->modelview();
533  camPosWS_ = Vec3f( viewMatrix_(0,3), viewMatrix_(1,3), viewMatrix_(2,3) );
534  camDirWS_ = Vec3f( viewMatrix_(0,2), viewMatrix_(1,2), -viewMatrix_(2,2) ); // mind the z flip
535 
536 // printf("pos: %f %f %f\ndir: %f %f %f\n", camPosWS_[0], camPosWS_[1], camPosWS_[2],
537 // camDirWS_[0], camDirWS_[1], camDirWS_[2]);
538 
539  // First, all render objects get collected.
540  collectRenderObjects(_glState, _drawMode, _scenegraphRoot);
541 
542  // ==========================================================
543  // Sort renderable objects based on their priority
544  // Filter for overlay, lines etc.
545  // ==========================================================
546 
547  size_t numRenderObjects = 0,
548  numOverlayObjects = 0,
549  numLineObjects = 0;
550 
551  for (std::vector<ACG::RenderObject>::const_iterator it = renderObjects_.begin();
552  it != renderObjects_.end(); ++it) {
553  if (!it->overlay && !(it->isDefaultLineObject() && enableLineThicknessGL42_))
554  numRenderObjects++;
555  if (it->overlay)
556  numOverlayObjects++;
557  if (enableLineThicknessGL42_ && it->isDefaultLineObject())
558  numLineObjects++;
559  }
560 
561  /*
562  * Neither clear() nor resize() ever decreases the capacity of
563  * a vector. So it has no adverse impact on performance to clear
564  * the vectors here.
565  */
566  sortedObjects_.clear();
567  sortedObjects_.reserve(numRenderObjects);
568 
569  overlayObjects_.clear();
570  overlayObjects_.reserve(numOverlayObjects);
571 
572  lineGL42Objects_.clear();
573  lineGL42Objects_.reserve(numLineObjects);
574 
575 
576  sortListObjects_.clear();
577  sortListObjects_.reserve(numRenderObjects);
578 
579  sortListOverlays_.clear();
580  sortListOverlays_.reserve(numOverlayObjects);
581 
582  // init sorted objects array
583  for (size_t i = 0; i < renderObjects_.size(); ++i)
584  {
585  if (renderObjects_[i].overlay)
586  {
587  overlayObjects_.push_back(&renderObjects_[i]);
588  sortListOverlays_.push_back(i);
589  }
590  else if (enableLineThicknessGL42_ && numLineObjects && renderObjects_[i].isDefaultLineObject())
591  {
592  renderObjects_[i].shaderDesc.geometryTemplateFile = "Wireframe/gl42/geometry.tpl";
593  renderObjects_[i].shaderDesc.fragmentTemplateFile = "Wireframe/gl42/fragment.tpl";
594 
595  // disable color write to fbo, but allow RenderObject to control depth write
596  renderObjects_[i].glColorMask(0,0,0,0);
597 
598 // sortedObjects_[sceneObjectOffset++] = &renderObjects_[i];
599  lineGL42Objects_.push_back(&renderObjects_[i]);
600  }
601  else
602  {
603  sortedObjects_.push_back(&renderObjects_[i]);
604  sortListObjects_.push_back(i);
605  }
606  }
607 
608  sortRenderObjects();
609 
610 
611  // ---------------------------
612  // Initialize the render state
613  // ---------------------------
614  // gl cleanup
615 
616  glDisableClientState(GL_VERTEX_ARRAY);
617  glDisableClientState(GL_COLOR_ARRAY);
618  glDisableClientState(GL_NORMAL_ARRAY);
619  glDisableClientState(GL_TEXTURE_COORD_ARRAY);
620  glDisableClientState(GL_INDEX_ARRAY);
621 
622 
623  glEnable(GL_CULL_FACE);
624  glEnable(GL_DEPTH_TEST);
625  glDepthFunc(GL_LESS);
626  glDepthMask(GL_TRUE);
627 
628  // save active fbo and viewport
629  saveInputFbo();
630 
631 
632  // get global ambient factor
633  GLfloat lightModelAmbient[4];
634  glGetFloatv(GL_LIGHT_MODEL_AMBIENT, lightModelAmbient);
635  globalLightModelAmbient_ = ACG::Vec3f(lightModelAmbient[0], lightModelAmbient[1], lightModelAmbient[2]);
636 
637 
638  // search list of render object for objects requiring the scene depth map
639  bool requiresSceneDepths = false;
640 
641  for (size_t i = 0; i < renderObjects_.size(); ++i)
642  {
643  if (renderObjects_[i].depthMapUniformName)
644  requiresSceneDepths = true;
645  }
646 
647  // render scene depth map
648  if (requiresSceneDepths)
649  renderDepthMap(curViewerID_, _glState->viewport_width(), _glState->viewport_height());
650 }
651 
652 
653 
654 void IRenderer::finishRenderingPipeline(bool _drawOverlay)
655 {
656 #ifdef GL_ARB_vertex_array_object
657  glBindVertexArray(0);
658 #endif
659 
660  // draw thick lines
661  if (enableLineThicknessGL42_)
662  renderLineThicknessGL42();
663 
664  if (_drawOverlay)
665  {
666  const int numOverlayObj = overlayObjects_.size();
667  // two-pass overlay rendering:
668  // 1. clear depth buffer at pixels of overlay objects
669  // 2. render overlay with correct depth-testing
670 
671  // 1. pass: clear depth to max value at overlay footprint
672  for (int i = 0; i < numOverlayObj; ++i)
673  {
674  RenderObject* obj = getOverlayRenderObject(i);
675 
676  if (obj->depthTest && obj->depthFunc != GL_ALWAYS)
677  {
678  float depthMax = 1.0f;
679 
680  if (obj->depthFunc == GL_GREATER || obj->depthFunc == GL_GEQUAL)
681  depthMax = 0.0f;
682 
683  // save depth setting of renderobject
684  Vec2f depthRange = obj->depthRange;
685  bool depthWrite = obj->depthWrite;
686  GLenum depthFunc = obj->depthFunc;
687 
688  // reset depth to maximal distance by using depth range
689  obj->depthRange = Vec2f(depthMax, depthMax);
690  obj->depthWrite = true;
691  obj->depthFunc = GL_ALWAYS;
692 
693  renderObject(obj);
694 
695  // restore depth setting
696  obj->depthRange = depthRange;
697  obj->depthWrite = depthWrite;
698  obj->depthFunc = depthFunc;
699  }
700 
701  }
702 
703  // 2. render overlay with correct depth-testing
704  for (int i = 0; i < numOverlayObj; ++i)
705  {
706  RenderObject* obj = getOverlayRenderObject(i);
707  renderObject(obj);
708  }
709 
710  }
711 
712 #ifdef GL_ARB_vertex_array_object
713  glBindVertexArray(0);
714 #endif
715 
716  for (int i = 0; i < maxClipDistances_; ++i)
717  glDisable(GL_CLIP_DISTANCE0 + i);
718 
719  glDepthMask(1);
720  glColorMask(1,1,1,1);
721 
722  glUseProgram(0);
723 
724  glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
725  glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
726 
727  // Renderer check:
728  // Print a warning if the currently active fbo / viewport is not the same as the saved fbo.
729  // Restore to previous fbo and viewport if not done already.
730 
731  GLint curFbo;
732  GLint curViewport[4];
733  GLint curDrawBuf;
734  glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &curFbo);
735  glGetIntegerv(GL_VIEWPORT, curViewport);
736  glGetIntegerv(GL_DRAW_BUFFER, &curDrawBuf);
737 
738  if (curFbo != prevFbo_)
739  {
740  std::cout << "warning: input and output fbo are not the same in renderer implementation" << std::endl;
741  restoreInputFbo();
742  }
743 
744  if (curDrawBuf != prevDrawBuffer_)
745  {
746  std::cout << "warning: input and output draw-buffer are not the same in renderer implementation" << std::endl;
747  restoreInputFbo();
748  }
749 
750  if (curViewport[0] != prevViewport_[0] ||
751  curViewport[1] != prevViewport_[1] ||
752  curViewport[2] != prevViewport_[2] ||
753  curViewport[3] != prevViewport_[3])
754  {
755  std::cout << "warning: input and output viewport are not the same in renderer implementation" << std::endl;
756  restoreInputFbo();
757  }
758 }
759 
760 
761 void IRenderer::saveInputFbo()
762 {
763  // save active fbo
764  saveActiveFbo(&prevFbo_, prevViewport_, &prevDrawBuffer_);
765  prevFboSaved_ = true;
766 }
767 
768 void IRenderer::restoreInputFbo()
769 {
770  if (prevFboSaved_)
771  restoreFbo(prevFbo_, prevViewport_, prevDrawBuffer_);
772 }
773 
774 void IRenderer::saveActiveFbo( GLint* _outFboId, GLint* _outViewport, GLint* _outDrawBuffer ) const
775 {
776  // save active fbo
777  glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, _outFboId);
778  glGetIntegerv(GL_VIEWPORT, _outViewport);
779  glGetIntegerv(GL_DRAW_BUFFER, _outDrawBuffer);
780 }
781 
782 void IRenderer::restoreFbo( GLint _fboId, const GLint* _outViewport, GLint _drawBuffer ) const
783 {
784  glBindFramebuffer(GL_FRAMEBUFFER, _fboId);
785  glDrawBuffer(_drawBuffer);
786  glViewport(_outViewport[0], _outViewport[1], _outViewport[2], _outViewport[3]);
787 }
788 
789 void IRenderer::clearInputFbo( const ACG::Vec4f& clearColor )
790 {
791  glClearColor(clearColor[0], clearColor[1], clearColor[2], 1.0f);
792 
793  // glClear will affect the whole back buffer, not only the area in viewport.
794  // Temporarily use glScissor to only clear the viewport area in the back buffer.
795  if (!prevFboSaved_)
796  {
797  GLint oldViewport[4];
798  glGetIntegerv(GL_VIEWPORT, oldViewport);
799  glScissor(oldViewport[0], oldViewport[1], oldViewport[2], oldViewport[3]);
800  }
801  else
802  glScissor(prevViewport_[0], prevViewport_[1], prevViewport_[2], prevViewport_[3]);
803 
804  glEnable(GL_SCISSOR_TEST);
805  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
806 
807  // disable scissors again, draw calls only affect the area in glViewport anyway
808  glDisable(GL_SCISSOR_TEST);
809 }
810 
811 namespace {
812 struct RenderObjectComparator {
813  RenderObjectComparator(const std::vector<ACG::RenderObject>& _vec) : vec_(_vec) {
814  }
815 
816  bool operator() (int a, int b) {
817  return (vec_[a].priority < vec_[b].priority);
818  }
819 
820  const std::vector<ACG::RenderObject>& vec_;
821 };
822 }
823 
824 void IRenderer::sortRenderObjects()
825 {
826  size_t numObjs = sortListObjects_.size();
827  size_t numOverlays = sortListOverlays_.size();
828 
829  RenderObjectComparator cmpOp(renderObjects_);
830 
831  std::sort(sortListObjects_.begin(), sortListObjects_.end(), cmpOp);
832  std::sort(sortListOverlays_.begin(), sortListOverlays_.end(), cmpOp);
833 
834  // apply sorting list
835  std::vector<ACG::SceneGraph::BaseNode*> temp;
836  renderObjectSource_.swap(temp);
837 
838 
839  renderObjectSource_.resize(numObjs, 0);
840  overlayObjectSource_.resize(numOverlays, 0);
841 
842  for (size_t i = 0; i < numObjs; ++i)
843  {
844  int objID = sortListObjects_[i];
845  sortedObjects_[i] = &renderObjects_[objID];
846 
847  renderObjectSource_[i] = temp[objID];
848  }
849 
850  for (size_t i = 0; i < numOverlays; ++i)
851  {
852  int objID = sortListOverlays_[i];
853  overlayObjects_[i] = &renderObjects_[objID];
854 
855  overlayObjectSource_[i] = temp[objID];
856  }
857 }
858 
859 
860 
861 void IRenderer::bindObjectVBO(ACG::RenderObject* _obj,
862  GLSL::Program* _prog)
863 {
864  _prog->use();
865 
866 
867 #ifdef GL_ARB_vertex_array_object
868  glBindVertexArray(_obj->vertexArrayObject);
869 #endif
870 
871  if (!_obj->vertexArrayObject)
872  {
874  // NOTE:
875  // always bind buffers before glVertexAttribPointer calls!!
876  // freeze in glDrawElements guaranteed (with no error message whatsoever)
877  glBindBufferARB(GL_ARRAY_BUFFER_ARB, _obj->vertexBuffer);
878  glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, _obj->indexBuffer);
879 
880 
881  // activate vertex declaration
882  _obj->vertexDecl->activateShaderPipeline(_prog);
883 
884  }
885 }
886 
887 
888 void IRenderer::bindObjectUniforms( ACG::RenderObject* _obj, GLSL::Program* _prog )
889 {
890  // transforms
891  ACG::GLMatrixf mvp = _obj->proj * _obj->modelview;
892  ACG::GLMatrixf mvIT = _obj->modelview;
893  mvIT.invert();
894  mvIT.transpose();
895 
896  _prog->setUniform("g_mWVP", mvp);
897  _prog->setUniform("g_mWV", _obj->modelview);
898  _prog->setUniformMat3("g_mWVIT", mvIT);
899  _prog->setUniform("g_mP", _obj->proj);
900 
901  _prog->setUniform("g_vCamPos", camPosWS_);
902  _prog->setUniform("g_vCamDir", camDirWS_);
903 
904  // material
905 
906  _prog->setUniform("g_cEmissive", _obj->emissive);
907 
908  _prog->setUniform("g_cDiffuse", _obj->diffuse);
909  _prog->setUniform("g_cAmbient", _obj->ambient);
910  _prog->setUniform("g_cSpecular", _obj->specular);
911 
912  ACG::Vec4f materialParams(_obj->shininess, _obj->alpha, 0.0f, 0.0f);
913  _prog->setUniform("g_vMaterial", materialParams);
914 
915  _prog->setUniform("g_cLightModelAmbient", globalLightModelAmbient_);
916 
917  // Additional Uniforms defined in the render Object
918  if ( !_obj->uniformPool_.empty() )
919  _obj->uniformPool_.bind(_prog);
920 
921  // textures:
922 
923  // maybe consider using bindless textures some time in the future
924  // to get rid of the old and problematic glActiveTexture(), glBindTexture() state machine usage:
925  // https://www.opengl.org/registry/specs/ARB/bindless_texture.txt
926 
927  int maxTextureStage = 0;
928  for (std::map<size_t,RenderObject::Texture>::const_iterator iter = _obj->textures().begin();
929  iter != _obj->textures().end();++iter)
930  {
931  //check for valid texture id
932  const size_t texture_stage = iter->first;
933  const RenderObject::Texture tex = iter->second;
934  if (!tex.id)
935  continue;
936 
937  glActiveTexture(GL_TEXTURE0 + (GLenum)texture_stage);
938  glBindTexture(iter->second.type, tex.id);
939  _prog->setUniform(QString("g_Texture%1").arg(texture_stage).toStdString().c_str(), (int)texture_stage);
940 
941  maxTextureStage = std::max(maxTextureStage, (int)texture_stage);
942  }
943 
944 
945  // scene depth texture
946  if (_obj->depthMapUniformName)
947  {
948  // bind to (hopefully) unused texture stage
949  int depthMapSlot = maxTextureStage + 1;
950 
951  _prog->setUniform(_obj->depthMapUniformName, depthMapSlot);
952  glActiveTexture(GL_TEXTURE0 + depthMapSlot);
953  glBindTexture(GL_TEXTURE_2D, depthMaps_[curViewerID_]->getAttachment(GL_COLOR_ATTACHMENT0));
954  }
955 
956 
957  // lights
958  for (int i = 0; i < numLights_; ++i)
959  {
960  LightData* lgt = lights_ + i;
961 
962  char szUniformName[256];
963 
964  sprintf(szUniformName, "g_cLightDiffuse_%d", i);
965  _prog->setUniform(szUniformName, lgt->diffuse);
966 
967  sprintf(szUniformName, "g_cLightAmbient_%d", i);
968  _prog->setUniform(szUniformName, lgt->ambient);
969 
970  sprintf(szUniformName, "g_cLightSpecular_%d", i);
971  _prog->setUniform(szUniformName, lgt->specular);
972 
973 
974  if (lgt->ltype == ACG::SG_LIGHT_POINT || lgt->ltype == ACG::SG_LIGHT_SPOT)
975  {
976  sprintf(szUniformName, "g_vLightPos_%d", i);
977  _prog->setUniform(szUniformName, lgt->pos);
978 
979  sprintf(szUniformName, "g_vLightAtten_%d", i);
980  _prog->setUniform(szUniformName, lgt->atten);
981  }
982 
983  if (lgt->ltype == ACG::SG_LIGHT_DIRECTIONAL || lgt->ltype == ACG::SG_LIGHT_SPOT)
984  {
985  sprintf(szUniformName, "g_vLightDir_%d", i);
986  _prog->setUniform(szUniformName, lgt->dir);
987  }
988 
989  if (lgt->ltype == ACG::SG_LIGHT_SPOT)
990  {
991  sprintf(szUniformName, "g_vLightAngleExp_%d", i);
992  _prog->setUniform(szUniformName, lgt->spotCutoffExponent);
993  }
994  }
995 }
996 
997 void IRenderer::bindObjectRenderStates(ACG::RenderObject* _obj)
998 {
999  if (_obj->culling)
1000  glEnable(GL_CULL_FACE);
1001  else
1002  glDisable(GL_CULL_FACE);
1003 
1004  if (_obj->blending)
1005  glEnable(GL_BLEND);
1006  else
1007  glDisable(GL_BLEND);
1008 
1009  if (_obj->alphaTest)
1010  {
1011  glEnable(GL_ALPHA_TEST);
1012  glAlphaFunc(_obj->alphaFunc, _obj->alphaRef);
1013  }
1014  else
1015  glDisable(GL_ALPHA_TEST);
1016 
1017  if (_obj->depthTest)
1018  glEnable(GL_DEPTH_TEST);
1019  else
1020  glDisable(GL_DEPTH_TEST);
1021 
1022 
1023  glDepthMask(_obj->depthWrite ? GL_TRUE : GL_FALSE);
1024 
1025  glColorMask(_obj->colorWriteMask[0], _obj->colorWriteMask[1], _obj->colorWriteMask[2], _obj->colorWriteMask[3]);
1026 
1027  glDepthFunc(_obj->depthFunc);
1028 
1029  glDepthRange(_obj->depthRange[0], _obj->depthRange[1]);
1030 
1031  // ACG::GLState::shadeModel(_obj->shadeModel);
1032 
1033  ACG::GLState::blendFunc(_obj->blendSrc, _obj->blendDest);
1034 
1035  if (maxClipDistances_ < 0)
1036  {
1037  glGetIntegerv(GL_MAX_CLIP_DISTANCES, &maxClipDistances_);
1038  maxClipDistances_ = std::min(maxClipDistances_, 32); // clamp to 32 bits
1039  }
1040 
1041  for (int i = 0; i < maxClipDistances_; ++i)
1042  {
1043  if (_obj->clipDistanceMask & (1 << i))
1044  glEnable(GL_CLIP_DISTANCE0 + i);
1045  else
1046  glDisable(GL_CLIP_DISTANCE0 + i);
1047  }
1048 }
1049 
1050 void IRenderer::drawObject(ACG::RenderObject* _obj)
1051 {
1052  if (_obj->numIndices)
1053  {
1054  // indexed drawing?
1055  bool noIndices = true;
1056  if (_obj->indexBuffer || _obj->sysmemIndexBuffer)
1057  noIndices = false;
1058 
1059  glPolygonMode(GL_FRONT_AND_BACK, _obj->fillMode);
1060 
1061  // tessellation info
1062  bool tessellationActive = !(_obj->shaderDesc.tessControlTemplateFile.isEmpty() && _obj->shaderDesc.tessEvaluationTemplateFile.isEmpty());
1063 #ifdef GL_ARB_tessellation_shader
1064  if (tessellationActive)
1065  {
1066  glPatchParameteri(GL_PATCH_VERTICES, _obj->patchVertices);
1067 
1068  if (_obj->shaderDesc.tessControlTemplateFile.isEmpty())
1069  {
1070  glPatchParameterfv(GL_PATCH_DEFAULT_INNER_LEVEL, _obj->patchDefaultInnerLevel.data());
1071  glPatchParameterfv(GL_PATCH_DEFAULT_OUTER_LEVEL, _obj->patchDefaultOuterLevel.data());
1072  }
1073  }
1074 #else
1075  if (tessellationActive)
1076  std::cout << "error: tessellation shaders cannot be used with the outdated glew version" << std::endl;
1077 #endif
1078 
1079  if (noIndices) {
1080  if (_obj->numInstances <= 0)
1081  glDrawArrays(_obj->primitiveMode, _obj->indexOffset, _obj->numIndices);
1082  else
1083  glDrawArraysInstanced(_obj->primitiveMode, _obj->indexOffset, _obj->numIndices, _obj->numInstances);
1084  }
1085  else
1086  {
1087  // ------------------------------------------
1088  // index offset stuff not tested
1089  int indexSize = 0;
1090  switch (_obj->indexType)
1091  {
1092  case GL_UNSIGNED_INT: indexSize = 4; break;
1093  case GL_UNSIGNED_SHORT: indexSize = 2; break;
1094  default: indexSize = 1; break;
1095  }
1096 
1097  if (_obj->numInstances <= 0)
1098  glDrawElements(_obj->primitiveMode, _obj->numIndices, _obj->indexType,
1099  ((const char*)_obj->sysmemIndexBuffer) + _obj->indexOffset * indexSize);
1100  else
1101  glDrawElementsInstanced(_obj->primitiveMode, _obj->numIndices, _obj->indexType,
1102  ((const char*)_obj->sysmemIndexBuffer) + _obj->indexOffset * indexSize, _obj->numInstances);
1103  }
1104  }
1105 }
1106 
1107 void IRenderer::renderObject(ACG::RenderObject* _obj,
1108  GLSL::Program* _prog,
1109  bool _constRenderStates,
1110  const std::vector<unsigned int>* _shaderModifiers)
1111 {
1112  // select shader from cache
1113  GLSL::Program* prog = _prog ? _prog : ACG::ShaderCache::getInstance()->getProgram(&_obj->shaderDesc, _shaderModifiers);
1114 
1115 
1116  bindObjectVBO(_obj, prog);
1117 
1118  // ---------------------------------------
1119  // set shader uniforms
1120 
1121  bindObjectUniforms(_obj, prog);
1122 
1123  // render states
1124 
1125  if (!_constRenderStates)
1126  bindObjectRenderStates(_obj);
1127 
1128  // ----------------------------
1129  // OpenGL draw call
1130 
1131  drawObject(_obj);
1132 
1133 
1135 
1136  if (_obj->vertexDecl)
1137  {
1138  // deactivate vertex declaration to avoid errors
1139  _obj->vertexDecl->deactivateShaderPipeline(prog);
1140  }
1141 
1142 
1143 #ifdef GL_ARB_vertex_array_object
1144  if (_obj->vertexArrayObject)
1145  glBindVertexArray(0);
1146 #endif
1147 
1148 }
1149 
1150 
1151 void IRenderer::addLight(const LightData& _light)
1152 {
1153  if (numLights_ < SG_MAX_SHADER_LIGHTS)
1154  {
1155  lights_[numLights_] = _light;
1156 
1157  // normalize direction
1158  if (_light.ltype != SG_LIGHT_POINT)
1159  lights_[numLights_].dir.normalize();
1160 
1161  ++numLights_;
1162  }
1163 }
1164 
1165 void IRenderer::addRenderObjectModifier(RenderObjectModifier* _mod)
1166 {
1167  renderObjectModifiers_.push_back(_mod);
1168 }
1169 
1170 void IRenderer::removeRenderObjectModifier(RenderObjectModifier* _mod)
1171 {
1172  for (int i = int(renderObjectModifiers_.size()) - 1; i >= 0; --i)
1173  {
1174  if (renderObjectModifiers_[i] == _mod)
1175  renderObjectModifiers_.erase(renderObjectModifiers_.begin() + i);
1176  }
1177 }
1178 
1179 int IRenderer::getNumRenderObjects() const {
1180  return sortedObjects_.size();
1181 }
1182 
1183 int IRenderer::getNumLights() const
1184 {
1185  return numLights_;
1186 }
1187 
1188 
1189 ACG::RenderObject* IRenderer::getRenderObject( int i )
1190 {
1191  if (sortedObjects_.empty())
1192  return &renderObjects_[i];
1193 
1194  return sortedObjects_[i];
1195 }
1196 
1197 ACG::RenderObject* IRenderer::getOverlayRenderObject( int i )
1198 {
1199  if (overlayObjects_.empty())
1200  return &renderObjects_[i];
1201 
1202  return overlayObjects_[i];
1203 }
1204 
1205 
1206 ACG::SceneGraph::BaseNode* IRenderer::getRenderObjectNode( int i )
1207 {
1208  return renderObjectSource_[i];
1209 }
1210 
1211 ACG::SceneGraph::BaseNode* IRenderer::getOverlayRenderObjectNode( int i )
1212 {
1213  return overlayObjectSource_[i];
1214 }
1215 
1216 
1217 ACG::RenderObject* IRenderer::getLineGL42RenderObject( int i )
1218 {
1219  if (lineGL42Objects_.empty())
1220  return 0;
1221 
1222  return lineGL42Objects_[i];
1223 }
1224 
1225 IRenderer::LightData* IRenderer::getLight( int i )
1226 {
1227  return &lights_[i];
1228 }
1229 
1230 
1231 void IRenderer::dumpRenderObjectsToFile(const char* _fileName, ACG::RenderObject** _sortedList) const
1232 {
1233  QFile fileOut(_fileName);
1234  if (fileOut.open(QFile::WriteOnly | QFile::Truncate))
1235  {
1236  QTextStream outStrm(&fileOut);
1237  for (int i = 0; i < getNumRenderObjects(); ++i)
1238  {
1239  if (_sortedList)
1240  outStrm << "\n" << _sortedList[i]->toString();
1241  else
1242  outStrm << "\n" << renderObjects_[i].toString();
1243  }
1244 
1245  fileOut.close();
1246  }
1247 }
1248 
1249 
1250 QString IRenderer::dumpCurrentRenderObjectsToString(ACG::RenderObject** _list, bool _outputShaders, std::vector<ACG::ShaderModifier*>* _modifiers) {
1251 
1252  QString objectString;
1253 
1254  QTextStream outStrm(&objectString);
1255 
1256  for (int i = 0; i < getNumRenderObjects(); ++i)
1257  {
1258  const RenderObject* obj = _list ? _list[i] : &renderObjects_[i];
1259 
1260  if (obj) {
1261  outStrm << "\n" << obj->toString();
1262 
1263  if ( _outputShaders ) {
1264 
1265  outStrm << "\n";
1266 
1267  outStrm << obj->shaderDesc.toString();
1268 
1269  ShaderProgGenerator progGen(&(obj->shaderDesc), _modifiers);
1270 
1271  outStrm << "\n---------------------vertex-shader--------------------\n\n";
1272  for (int i = 0; i < progGen.getVertexShaderCode().size(); ++i)
1273  outStrm << progGen.getVertexShaderCode()[i] << "\n";
1274  outStrm << "\n---------------------end-vertex-shader--------------------\n\n";
1275 
1276  if (progGen.hasTessControlShader())
1277  {
1278  outStrm << "\n---------------------tesscontrol-shader--------------------\n\n";
1279  for (int i = 0; i < progGen.getTessControlShaderCode().size(); ++i)
1280  outStrm << progGen.getTessControlShaderCode()[i] << "\n";
1281  outStrm << "\n---------------------end-tesscontrol-shader--------------------\n\n";
1282  }
1283 
1284  if (progGen.hasTessControlShader())
1285  {
1286  outStrm << "\n---------------------tesseval-shader--------------------\n\n";
1287  if (progGen.hasTessEvaluationShader())
1288  for (int i = 0; i < progGen.getTessEvaluationShaderCode().size(); ++i)
1289  outStrm << progGen.getTessEvaluationShaderCode()[i] << "\n";
1290  outStrm << "\n---------------------end-tesseval-shader--------------------\n\n";
1291  }
1292 
1293  if (progGen.hasGeometryShader())
1294  {
1295  outStrm << "\n---------------------geometry-shader--------------------\n\n";
1296  for (int i = 0; i < progGen.getGeometryShaderCode().size(); ++i)
1297  outStrm << progGen.getGeometryShaderCode()[i] << "\n";
1298  outStrm << "\n---------------------end-geometry-shader--------------------\n\n";
1299  }
1300 
1301 
1302  outStrm << "\n---------------------fragment-shader--------------------\n\n";
1303  for (int i = 0; i < progGen.getFragmentShaderCode().size(); ++i)
1304  outStrm << progGen.getFragmentShaderCode()[i] << "\n";
1305  outStrm << "\n---------------------end-fragment-shader--------------------\n\n";
1306  }
1307 
1308  }
1309 
1310  }
1311 
1312  return objectString;
1313 }
1314 
1315 void IRenderer::copyDepthToBackBuffer( GLuint _depthTex, float _scale /*= 1.0f*/ )
1316 {
1317  if (!_depthTex) return;
1318 
1319  if (!depthCopyShader_)
1320  depthCopyShader_ = GLSL::loadProgram("ScreenQuad/screenquad.glsl", "ScreenQuad/depth_copy.glsl");
1321 
1322 
1323  if (depthCopyShader_)
1324  {
1325  // save important opengl states
1326  GLint curFbo;
1327  GLint curViewport[4];
1328  GLint curDrawBuffer;
1329  saveActiveFbo(&curFbo, curViewport, &curDrawBuffer);
1330 
1331  GLboolean colorMask[4], depthMask;
1332  glGetBooleanv(GL_COLOR_WRITEMASK, colorMask);
1333  glGetBooleanv(GL_DEPTH_WRITEMASK, &depthMask);
1334 
1335  GLboolean depthTestEnable;
1336  GLint depthFunc;
1337  glGetBooleanv(GL_DEPTH_TEST, &depthTestEnable);
1338  glGetIntegerv(GL_DEPTH_FUNC, &depthFunc);
1339 
1340  // write to depth buffer of input fbo
1341  restoreInputFbo();
1342 
1343  depthCopyShader_->use();
1344  depthCopyShader_->setUniform("offset", ACG::Vec2f(0.0f, 0.0f));
1345  depthCopyShader_->setUniform("size", ACG::Vec2f(1.0f, 1.0f));
1346  depthCopyShader_->setUniform("DepthTex", 0); // depth tex at texture slot 0
1347  depthCopyShader_->setUniform("DepthSign", _scale);
1348 
1349  // write to depth buffer only, disable writing to color buffer
1350  glColorMask(0,0,0,0);
1351  glDepthMask(1);
1352 
1353  // depth test enabled + pass always
1354  glEnable(GL_DEPTH_TEST);
1355  glDepthFunc(GL_ALWAYS);
1356 
1357  glActiveTexture(GL_TEXTURE0);
1358  glBindTexture(GL_TEXTURE_2D, _depthTex);
1359 
1360  ACG::ScreenQuad::draw(depthCopyShader_);
1361 
1362 
1363  // restore important opengl states
1364 
1365  restoreFbo(curFbo, curViewport, curDrawBuffer);
1366 
1367  glColorMask(colorMask[0], colorMask[1], colorMask[2], colorMask[3]);
1368  glDepthMask(depthMask);
1369 
1370  if (!depthTestEnable)
1371  glDisable(GL_DEPTH_TEST);
1372 
1373  if (depthFunc != GL_ALWAYS)
1374  glDepthFunc(depthFunc);
1375 
1376  glBindTexture(GL_TEXTURE_2D, 0);
1377  }
1378 }
1379 
1380 
1381 // depth map computation with a modifier
1382 
1383 IRenderer::DepthMapPass IRenderer::DepthMapPass::instance;
1384 
1385 void IRenderer::DepthMapPass::modifyFragmentEndCode(QStringList* _code)
1386 {
1387  _code->push_back("outFragment = gl_FragCoord.zzzz;");
1388 }
1389 
1390 void IRenderer::renderDepthMap(int _viewerID, int _width, int _height)
1391 {
1392  ACG::FBO* fbo = depthMaps_[_viewerID];
1393 
1394  // setup fbo for depth map
1395  if (!fbo)
1396  {
1397  fbo = depthMaps_[_viewerID] = new ACG::FBO();
1398 
1399  fbo->bind();
1400  fbo->attachTexture2D(GL_COLOR_ATTACHMENT0, _width, _height, GL_R32F, GL_RED);
1401  fbo->addDepthBuffer(_width, _height);
1402  }
1403  else
1404  {
1405  fbo->bind();
1406  fbo->resize(_width, _height);
1407  }
1408 
1409  // make sure modifier is registered
1410  ACG::ShaderProgGenerator::registerModifier(&DepthMapPass::instance);
1411 
1412  /* note:
1413  It is possible to directly read the depth buffer if it was attached as a texture.
1414  Then, we would disable the color write mask and just write to the depth buffer in this function.
1415 
1416  However, doing this has shown that the actual depth values written to the depth buffer highly depend on the gpu driver.
1417  Or, at least sampling from a texture with format GL_DEPTH_COMPONENT returns driver dependent values.
1418  For instance, in the amd-gl driver sampling the depth texture returns the value of gl_FragDepth (as expected).
1419  But in the nvidia driver, sampling directly from the depth buffer returns something different!
1420 
1421  Therefore we render the value of gl_FragDepth to a custom floating-point texture bound to a color slot in order to get driver independent behavior.
1422  */
1423 
1424  fbo->bind();
1425  glDrawBuffer(GL_COLOR_ATTACHMENT0);
1426  glViewport(0, 0, _width, _height);
1427 
1428  // set depth to max
1429  glColorMask(1,1,1,1);
1430  glDepthMask(1);
1431 
1432  glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
1433  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1434 
1435  // render z-prepass
1436  for (int i = 0; i < getNumRenderObjects(); ++i)
1437  {
1438  RenderObject* obj = getRenderObject(i);
1439 
1440  if (obj->inZPrePass)
1441  {
1442  // apply depth map modifier to get the depth pass shader
1443  GLSL::Program* depthPassShader = ShaderCache::getInstance()->getProgram(&obj->shaderDesc, DepthMapPass::instance);
1444 
1445  // temporarily prevent read/write access to the same texture (the depth map)
1446  const char* depthMapUniformName = obj->depthMapUniformName;
1447  obj->depthMapUniformName = 0;
1448 
1449  if (depthMapUniformName)
1450  {
1451  depthPassShader->use();
1452  depthPassShader->setUniform(depthMapUniformName, 0);
1453  glActiveTexture(GL_TEXTURE0);
1454  glBindTexture(GL_TEXTURE_2D, 0);
1455  }
1456 
1457  // we are interested in the depth value only, so temporarily modify the write mask to allow writing to the red channel
1458  // (for instance, an object might not write a color value, but a depth value)
1459  const GLboolean redWriteMask = obj->colorWriteMask[0];
1460  obj->colorWriteMask[0] = obj->depthWrite;
1461 
1462  renderObject(obj, depthPassShader);
1463 
1464  // reset modified render object states
1465  obj->depthMapUniformName = depthMapUniformName;
1466  obj->colorWriteMask[0]= redWriteMask;
1467  }
1468  }
1469 
1470  // restore input fbo state
1471 
1472  fbo->unbind();
1473 
1474  restoreInputFbo();
1475 }
1476 
1477 
1478 void IRenderer::setViewerID(int _viewerID)
1479 {
1480  curViewerID_ = _viewerID;
1481 }
1482 
1483 
1484 void IRenderer::renderLineThicknessGL42()
1485 {
1486 #ifdef GL_ARB_shader_image_load_store
1487  // quad extrusion has depth clipping issue
1488  // GL4.2 method: manually rasterize thick lines into load/store texture, thereby avoiding clipping
1489 
1490  // experimental technique, needs some improvements for rasterization
1491  /* possible improvement:
1492  0. init depth buffer with scene objects
1493  1. extract visible line object (startpos, endpos) into imageBuffer after depth-test in fragment shader
1494  1a. line segment id can be found via atomic counter in geometry shader
1495  1b. use imageAtomicMin/max to find start and end pixel pos of each line segment
1496  atomic ops work with uint only, thus each segment has 4 texels in the imageBuffer, offsets are segmentID * 4 + {0,1,2,3}
1497  2. read imageBuffer in geometry shader and do usual quad extrusion, now without depth testing
1498  => get hw rasterization and msaa
1499  */
1500 
1501  // using image2D does not work: texture always reads 0, even with glGetTexImage2D
1502  // imageBuffer works
1503  // - check with different gpu
1504 
1505  const int numLines = lineGL42Objects_.size();
1506 
1507  // configs
1508  const bool useBufferTexture = true; // imageBuffer or image2D
1509  const bool useIntegerTexture = true; // color as R32U or RGBA32F
1510 
1511 
1512 
1513  if (numLines)
1514  {
1515 
1516  // macro configs for shader
1517  QStringList macros;
1518 
1519  if (useBufferTexture)
1520  macros.push_back("#define IMAGE_BUFFER");
1521  if (useIntegerTexture)
1522  macros.push_back("#define FMT_UINT");
1523 
1524 
1525  // get random access write buffer
1526  // 32bit uint per viewport pixel, stores rgba8
1527  Texture2D* lineColorImg2D = 0;
1528  TextureBuffer* lineColorImgBuf = 0;
1529 
1530  size_t w = static_cast<size_t>(prevViewport_[2]), h = static_cast<size_t>(prevViewport_[3]);
1531  size_t lineBPP = static_cast<size_t>(useIntegerTexture ? 4 : 16); // bytes per pixel
1532 
1533 
1534  if (useBufferTexture)
1535  {
1536  lineColorImgBuf = dynamic_cast<TextureBuffer*>(lineColorBuffers_[curViewerID_]);
1537 
1538  if (!lineColorImgBuf)
1539  {
1540  lineColorImgBuf = new TextureBuffer(GL_TEXTURE0);
1541  lineColorBuffers_[curViewerID_] = lineColorImgBuf;
1542  }
1543 
1544  // resize
1545  if (lineColorImgBuf->getBufferSize() != w * h * lineBPP)
1546  lineColorImgBuf->setBufferData(w*h*lineBPP, 0, GL_R32UI, GL_DYNAMIC_DRAW);
1547  }
1548  else
1549  {
1550  lineColorImg2D = dynamic_cast<Texture2D*>(lineColorBuffers_[curViewerID_]);
1551 
1552  if (!lineColorImg2D)
1553  {
1554  // allocate and store in map
1555  lineColorImg2D = new Texture2D(GL_TEXTURE0);
1556  lineColorBuffers_[curViewerID_] = lineColorImg2D;
1557  }
1558 
1559  // resize
1560  if (lineColorImg2D->getWidth() != static_cast<int>(w) || lineColorImg2D->getHeight() != static_cast<int>(h))
1561  lineColorImg2D->setData(0,
1562  useIntegerTexture ? GL_R32UI : GL_RGBA32F,
1563  w, h,
1564  useIntegerTexture ? GL_RED_INTEGER : GL_RGBA,
1565  useIntegerTexture ? GL_UNSIGNED_INT : GL_FLOAT,
1566  0);
1567  }
1568 
1569 
1570 
1571 
1572 
1573  glViewport(0, 0, w, h);
1574 
1575 
1576 
1577  // ---------------------------
1578  // clear line color buffer
1579 
1580  glColorMask(0,0,0,0);
1581  glDepthMask(0);
1582  glDisable(GL_DEPTH_TEST);
1583 
1584  // image binding is set to slot 0 in shader already
1585  if (useBufferTexture)
1586  lineColorImgBuf->bindAsImage(0, GL_WRITE_ONLY);
1587  else
1588  lineColorImg2D->bindAsImage(0, GL_WRITE_ONLY);
1589 
1590  GLSL::Program* shaderClear = ShaderCache::getInstance()->getProgram("ScreenQuad/screenquad.glsl", "Wireframe/gl42/clear.glsl", &macros);
1591 
1592  shaderClear->use();
1593 // shaderClear->setUniform("offset", Vec2f(0,0));
1594 // shaderClear->setUniform("size", Vec2f(1,1));
1595  shaderClear->setUniform("screenSize", Vec2f(w,h));
1596 
1597  ScreenQuad::draw(shaderClear);
1598 
1599  glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
1600 // GLDebug::dumpTexture2D(lineColorBuf->id(), 0, lineColorBuf->getFormat(), lineColorBuf->getType(), lineBPP*w*h, "c:/dbg/lines_clear.dds");
1601 // GLDebug::dumpBufferData(GL_TEXTURE_BUFFER, lineColorBuf2->getBufferId(), "c:/dbg/lines_clear.bin");
1602 
1603  // ---------------------------
1604  // 1. pass
1605  // render into line color buffer via imageStore,
1606 
1607  for (int i = 0; i < numLines; ++i)
1608  {
1609  RenderObject* obj = getLineGL42RenderObject(i);
1610 
1611  renderObject(obj);
1612  }
1613 
1614  glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
1615 // GLDebug::dumpTexture2D(lineColorBuf->id(), 0, lineColorBuf->getFormat(), lineColorBuf->getType(), lineBPP*w*h, "c:/dbg/lines_image.dds");
1616 // GLDebug::dumpBufferData(GL_TEXTURE_BUFFER, lineColorBuf2->getBufferId(), "c:/dbg/lines_image.bin");
1617 
1618 
1619  // ---------------------------
1620  // 2. pass
1621  // composition of line colors and fbo
1622 
1623  restoreInputFbo();
1624 
1625  // image binding is set to slot 0 in shader already
1626  if (useBufferTexture)
1627  lineColorImgBuf->bindAsImage(0, GL_READ_ONLY);
1628  else
1629  lineColorImg2D->bindAsImage(0, GL_READ_ONLY);
1630 
1631 
1632  glColorMask(1,1,1,1);
1633  glDisable(GL_DEPTH_TEST);
1634 
1635  // enable alpha blending
1636  glEnable(GL_BLEND);
1637  ACG::GLState::blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1638 
1639  GLSL::Program* shaderComposite = ShaderCache::getInstance()->getProgram("ScreenQuad/screenquad.glsl", "Wireframe/gl42/composite.glsl", &macros);
1640 
1641  shaderComposite->use();
1642 // shaderComposite->setUniform("offset", Vec2f(0,0));
1643 // shaderComposite->setUniform("size", Vec2f(1,1));
1644  shaderComposite->setUniform("screenSize", Vec2f(w,h));
1645 
1646  ScreenQuad::draw(shaderComposite);
1647 
1648 
1649  }
1650 #endif
1651 }
1652 
1653 void IRenderer::setLineThicknessRenderingGL42( bool _enable )
1654 {
1655  if (Texture::supportsImageLoadStore() && Texture::supportsTextureBuffer())
1656  enableLineThicknessGL42_ = _enable;
1657 }
1658 
1659 void IRenderer::setErrorDetectionLevel( int _level )
1660 {
1661  errorDetectionLevel_ = std::max(_level, 0); // clamp to [0,n]
1662 }
1663 
1664 int IRenderer::getErrorDetectionLevel() const
1665 {
1666  return errorDetectionLevel_;
1667 }
1668 
1669 } // namespace ACG end
1670 
bool isDefaultLineObject() const
Test if the object is rendered with one of the default line thickness methods.
GLSL::Program * depthCopyShader_
shader copies depth of the first front layer to the back buffer
Definition: IRenderer.hh:564
int viewport_width() const
get viewport width
Definition: GLState.hh:825
Texture to be used.
bool isDefaultPointObject() const
Test if the object is rendered with one of the default point extension methods.
static void draw(GLSL::Program *_prog=0)
Draw the screen quad.
Definition: ScreenQuad.cc:147
bool invert()
matrix inversion (returns true on success)
Definition: Matrix4x4T.cc:297
GLenum indexType
Index element type.
void specularColor(const Vec4f &_s)
set the specular color
int numLights_
Number of Lights.
Definition: IRenderer.hh:497
bool hasTessControlShader() const
check whether there is a tess-control shader present
const QStringList & getGeometryShaderCode()
Returns generated tessellation evaluation shader code.
GLenum alphaFunc
GL_LESS, GL_LEQUAL, GL_GREATER ..
void ambientColor(const Vec4f &_a)
set the ambient color.
static ShaderCache * getInstance()
Return instance of the ShaderCache singleton.
Definition: ShaderCache.cc:90
Hide this node and its children.
Definition: BaseNode.hh:429
const QStringList & getTessControlShaderCode()
Returns generated vertex shader code.
Namespace providing different geometric functions concerning angles.
Definition: DBSCANT.cc:51
std::vector< ACG::RenderObjectModifier * > renderObjectModifiers_
active render object modifiers
Definition: IRenderer.hh:521
GLuint vertexArrayObject
Use vertex array object.
bool empty() const
returns if the pool is empty
Definition: UniformPool.cc:100
GLenum depthFunc
GL_LESS, GL_LEQUAL, GL_GREATER ..
void unbind()
unbind fbo, go to normal rendering mode
Definition: FBO.cc:474
void glCheckErrors()
Definition: GLError.hh:105
bool hasTessEvaluationShader() const
check whether there is a tess-evaluation shader present
unsigned int patchVertices
patch size if primitiveMode is GL_PATCHES for rendering with tessellation shaders ...
bool inZPrePass
Specify whether this object should be rendered in a z-prepass.
const void * sysmemIndexBuffer
Use system memory index buffer.
void setUniformMat3(const char *_name, const ACG::GLMatrixf &_value, bool _transposed=false)
Set 3x3fMatrix uniform to specified value.
Definition: GLSLShader.cc:669
void transpose()
transpose matrix
Definition: Matrix4x4T.cc:272
static void blendFunc(GLenum _sfactor, GLenum _dfactor)
replaces glBlendFunc, supports locking
Definition: GLState.hh:314
void diffuseColor(const Vec4f &_d)
set the diffuse color.
GLMatrixd proj
Projection transform.
std::vector< BaseNode * >::iterator ChildIter
allows to iterate over children
Definition: BaseNode.hh:317
void setUniform(const char *_name, GLint _value)
Set int uniform to specified value.
Definition: GLSLShader.cc:391
const VertexElement * findElementByUsage(VERTEX_USAGE _usage) const
void attachTexture2D(GLenum _attachment, GLsizei _width, GLsizei _height, GLuint _internalFmt, GLenum _format, GLint _wrapMode=GL_CLAMP, GLint _minFilter=GL_NEAREST, GLint _magFilter=GL_NEAREST)
function to attach a texture to fbo
Definition: FBO.cc:200
Vec3f diffuse
material definitions
int errorDetectionLevel_
error-detection level for checking render objects
Definition: IRenderer.hh:567
Draw this node, but hide children.
Definition: BaseNode.hh:427
VectorT< float, 3 > Vec3f
Definition: VectorT.hh:125
Draw node in second pass.
Definition: BaseNode.hh:476
static int maxClipDistances_
max number of clip distance outputs in a vertex shader
Definition: IRenderer.hh:570
virtual void addRenderObject(RenderObject *_renderObject)
Callback for the scenegraph nodes, which send new render objects via this function.
Definition: IRenderer.cc:108
GLSL::Program * getProgram(const ShaderGenDesc *_desc, const std::vector< unsigned int > &_mods)
Query a dynamically generated program from cache.
Definition: ShaderCache.cc:108
GLMatrixd modelview
Modelview transform.
Definition: FBO.hh:83
void addDepthBuffer(GLuint _width, GLuint _height)
function to add a depth renderbuffer to the fbo
Definition: FBO.cc:343
bool bind()
bind the fbo and sets it as rendertarget
Definition: FBO.cc:451
void activateShaderPipeline(GLSL::Program *_prog) const
QString toString() const
convert ShaderGenDesc to string format for debugging
Interface for modifying render objects.
QString toString() const
Vec2f depthRange
glDepthRange: (znear, zmax)
std::map< int, ACG::FBO * > depthMaps_
Definition: IRenderer.hh:534
GLuint vertexBuffer
VBO, IBO ids, ignored if VAO is provided.
const QStringList & getTessEvaluationShaderCode()
Returns generated tessellation control shader code.
GLSL program class.
Definition: GLSLShader.hh:217
void baseColor(const Vec4f &_c)
set the base color
std::vector< ACG::RenderObject > renderObjects_
array of renderobjects, filled by addRenderObject()
Definition: IRenderer.hh:507
std::string name
Name for logging.
int viewport_height() const
get viewport height
Definition: GLState.hh:827
const VertexDeclaration * vertexDecl
Defines the vertex buffer layout, ignored if VAO is provided.
bool hasGeometryShader() const
check whether there is a geometry shader present
const GLMatrixd & modelview() const
get modelview matrix
Definition: GLState.hh:794
void deactivateShaderPipeline(GLSL::Program *_prog) const
Hide this node, but draw children.
Definition: BaseNode.hh:425
unsigned int numIndices
Number indices to render.
GLenum blendDest
glBlendFunc: GL_SRC_ALPHA, GL_ZERO, GL_ONE, GL_ONE_MINUS_SRC_ALPHA ...
unsigned int internalFlags_
may be used internally by the renderer
DrawMode DEFAULT
use the default (global) draw mode and not the node's own.
Definition: DrawModes.cc:78
void shininess(float _s)
set shininess
StatusMode status() const
Get node's status.
Definition: BaseNode.hh:432
const QStringList & getFragmentShaderCode()
Returns generated fragment shader code.
Interface class between scenegraph and renderer.
void use()
Enables the program object for using.
Definition: GLSLShader.cc:351
void bind(PtrProgram _prog) const
Send all stored uniforms to program.
Definition: UniformPool.cc:108
const QStringList & getVertexShaderCode()
Returns generated vertex shader code.
GLenum primitiveMode
Primitive type.
static unsigned int registerModifier(ShaderModifier *_modifier)
Shader modifiers have to be registered before they can be used. They also must remain allocated for t...
const char * depthMapUniformName
Uniform name of the depth map in the used shader.
void resize(GLsizei _width, GLsizei _height, bool _forceResize=false)
resize function (if textures created by this class)
Definition: FBO.cc:543
GLSL::PtrProgram loadProgram(const char *vertexShaderFile, const char *tessControlShaderFile, const char *tessEvaluationShaderFile, const char *geometryShaderFile, const char *fragmentShaderFile, const GLSL::StringList *macros, bool verbose)
Definition: GLSLShader.cc:1082
ACG::SceneGraph::Material & material()
Get material object reference.
unsigned int indexOffset
Offset to first index in the index buffer or vertex buffer respectively.
GLuint getProgramId()
Returns opengl id.
Definition: GLSLShader.cc:382
GLuint indexBuffer
Use vertex array object.
ShaderGenDesc shaderDesc
Drawmode and other shader params.