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