Developer Documentation
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 #include <ACG/GL/acg_glew.hh>
45 #include <cstdio>
46 #include <cstring>
47 #include <iostream>
48 #include <algorithm>
49 #include <QFile>
50 #include <QTextStream>
51 
52 #include <ACG/GL/gl.hh>
53 
54 #include <ACG/GL/IRenderer.hh>
55 
56 #include <ACG/GL/VertexDeclaration.hh>
57 #include <ACG/GL/GLError.hh>
58 
59 #include <ACG/GL/ShaderCache.hh>
60 #include <ACG/GL/ScreenQuad.hh>
61 #include <ACG/GL/FBO.hh>
62 #include <ACG/GL/globjects.hh>
63 
64 
65 
66 namespace ACG
67 {
68 
70 
71 IRenderer::IRenderer()
72 : numLights_(0),
73 renderObjects_(0),
74 depthMapUsed_(false),
75 curViewerID_(0),
76 prevFbo_(0),
77 prevDrawBuffer_(GL_BACK),
78 prevFboSaved_(false),
79 prevVAO_(0),
80 depthCopyShader_(0),
81 errorDetectionLevel_(1),
82 coreProfile_(false),
83 enableLineThicknessGL42_(false)
84 {
85  prevViewport_[0] = 0;
86  prevViewport_[1] = 0;
87  prevViewport_[2] = 0;
88  prevViewport_[3] = 0;
89 
90  // set global ambient scale to default OpenGL value
91  globalLightModelAmbient_ = ACG::Vec3f(0.2f, 0.2f, 0.2f);
92 }
93 
94 
95 IRenderer::~IRenderer()
96 {
97  delete depthCopyShader_;
98 
99  // free depth map fbos
100  for (std::map<int, ACG::FBO*>::iterator it = depthMaps_.begin(); it != depthMaps_.end(); ++it)
101  delete it->second;
102 }
103 
105 {
106  // avoid null-ptr access
107  if (_renderObject->debugName.empty())
108  _renderObject->debugName = "<unnamed>";
109 
110  if (_renderObject->name.empty())
111  _renderObject->name = _renderObject->debugName;
112 
113  // do some more checks for error detection
114  if (!_renderObject->vertexDecl && !_renderObject->vertexArrayObject)
115  std::cout << "error: missing vertex declaration in renderobject: " << _renderObject->debugName << std::endl;
116  else
117  {
118  if (errorDetectionLevel_ > 0)
119  {
120  // commonly encountered rendering errors
121 
122  if (!_renderObject->numIndices)
123  std::cout << "warning: numIndices is 0 in renderobject: " << _renderObject->debugName << std::endl;
124 
125  // Why is my object invisible/black?
126  if (!_renderObject->depthWrite &&
127  !_renderObject->colorWriteMask[0] && !_renderObject->colorWriteMask[1] &&
128  !_renderObject->colorWriteMask[2] && !_renderObject->colorWriteMask[3])
129  std::cout << "warning: depth write and color write disabled in renderobject: " << _renderObject->debugName << std::endl;
130 
131  // Why is gl_PointSize not working in shader?
132 #ifndef GL_PROGRAM_POINT_SIZE
133  if (_renderObject->programPointSize)
134  std::cout << "warning: GL_PROGRAM_POINT_SIZE requested but missing in opengl headers!" << std::endl;
135 #endif
136 
137  if (errorDetectionLevel_ > 1 && _renderObject->shaderDesc.shadeMode == SG_SHADE_UNLIT)
138  {
139  if (_renderObject->emissive.max() < 1e-3f)
140  std::cout << "warning: unlit object rendered with black emissive color: " << _renderObject->debugName << std::endl;
141  else
142  {
143  // rendering with clear color
144 
145  float clearColor[4];
146  glGetFloatv(GL_COLOR_CLEAR_VALUE, clearColor);
147 
148  if (checkEpsilon(clearColor[0] - _renderObject->emissive[0]) &&
149  checkEpsilon(clearColor[1] - _renderObject->emissive[1]) &&
150  checkEpsilon(clearColor[2] - _renderObject->emissive[2]))
151  {
152  std::cout << "warning: unlit object rendered with clear color as emissive color: " << _renderObject->debugName << std::endl;
153  std::cout << " Should this be intentional, disable color writing instead via obj->glColorMask(0,0,0,0)" << std::endl;
154  }
155  }
156  }
157 
158  if (_renderObject->textures().size())
159  {
160  // Why are my textures sampled as black?
161 
162  // mipmap enabled, but no mipmap chain provided?
163 
164  for (std::map<size_t,RenderObject::Texture>::const_iterator it = _renderObject->textures().begin();
165  it != _renderObject->textures().end(); ++it)
166  {
167  if (it->second.type == GL_TEXTURE_BUFFER)
168  continue; // skip texture buffers, for which testing for mipmaps would generate an error
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 
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 
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  auto cur_idx = stack.size() - 1;
462  ACG::SceneGraph::DrawModes::DrawMode nodeDM = cur.node->drawMode();
464  nodeDM = _drawMode;
465 
466  if (!cur.leave) {
467  /*
468  * Stuff that happens before processing cur.node's children.
469  */
470  if ( cur.node->status() != ACG::SceneGraph::BaseNode::HideNode )
471  cur.node->enter(this, *_glState, nodeDM);
472 
473  cur.subtree_index_start = renderObjects_.size();
474 
475  // fetch material (Node itself can be a material node, so we have to
476  // set that in front of the nodes own rendering
478  dynamic_cast<ACG::SceneGraph::MaterialNode*>(cur.node);
479  if (matNode)
480  cur.material = &matNode->material();
481 
482  if (cur.node->status() != ACG::SceneGraph::BaseNode::HideNode)
483  cur.node->getRenderObjects(this, *_glState, nodeDM, cur.material);
484 
485  // keep track of which node added objects
486  size_t numAddedObjects = renderObjects_.size() - renderObjectSource_.size();
487  renderObjectSource_.insert(renderObjectSource_.end(), numAddedObjects, cur.node);
488 
489  auto cur_mat = cur.material; // make a copy so we can avoid use-after-free on stack.push_back
490  // Process children?
491  if (cur.node->status() != ACG::SceneGraph::BaseNode::HideChildren) {
492  // Process all children which are second pass
494  cIt = cur.node->childrenBegin(),
495  cEnd = cur.node->childrenEnd(); cIt != cEnd; ++cIt) {
496  if (((*cIt)->traverseMode() &
498  (*cIt)->status() != ACG::SceneGraph::BaseNode::HideSubtree)
499  stack.emplace_back(*cIt, cur_mat);
500  }
501 
502  // Process all children which are not second pass
504  cIt = cur.node->childrenBegin(),
505  cEnd = cur.node->childrenEnd(); cIt != cEnd; ++cIt) {
506  if ((~(*cIt)->traverseMode() &
508  (*cIt)->status() != ACG::SceneGraph::BaseNode::HideSubtree)
509  stack.emplace_back(*cIt, cur_mat);
510  }
511  }
512 
513  // Next time process the other branch of this if statement.
514  // 'cur' is now invalidated due to push_back, access via stack
515  stack[cur_idx].leave = true;
516 
517  } else {
518  /*
519  * Stuff that happens after processing cur.node's children.
520  */
521  current_subtree_objects_ = RenderObjectRange(
522  renderObjects_.begin() + cur.subtree_index_start,
523  renderObjects_.end());
524 
525  if (cur.node->status() != ACG::SceneGraph::BaseNode::HideNode )
526  cur.node->leave(this, *_glState, nodeDM);
527  stack.pop_back();
528  }
529  }
530 }
531 
533 {
534  // save default VAO
535 #ifdef GL_ARB_vertex_array_object
536  glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &prevVAO_);
537 #endif
538 
539  coreProfile_ = !_glState->compatibilityProfile();
540 
541  // grab view transform from glstate
542  viewMatrix_ = _glState->modelview();
543  camPosWS_ = Vec3f( viewMatrix_(0,3), viewMatrix_(1,3), viewMatrix_(2,3) );
544  camDirWS_ = Vec3f( viewMatrix_(0,2), viewMatrix_(1,2), -viewMatrix_(2,2) ); // mind the z flip
545 
546 // printf("pos: %f %f %f\ndir: %f %f %f\n", camPosWS_[0], camPosWS_[1], camPosWS_[2],
547 // camDirWS_[0], camDirWS_[1], camDirWS_[2]);
548 
549  // First, all render objects get collected.
550  collectRenderObjects(_glState, _drawMode, _scenegraphRoot);
551 
552  // ==========================================================
553  // Sort renderable objects based on their priority
554  // Filter for overlay, lines etc.
555  // ==========================================================
556 
557  size_t numRenderObjects = 0,
558  numOverlayObjects = 0,
559  numLineObjects = 0;
560 
561  for (std::vector<ACG::RenderObject>::const_iterator it = renderObjects_.begin();
562  it != renderObjects_.end(); ++it) {
563  if (!it->overlay && !(it->isDefaultLineObject() && enableLineThicknessGL42_))
564  numRenderObjects++;
565  if (it->overlay)
566  numOverlayObjects++;
567  if (enableLineThicknessGL42_ && it->isDefaultLineObject())
568  numLineObjects++;
569  }
570 
571  /*
572  * Neither clear() nor resize() ever decreases the capacity of
573  * a vector. So it has no adverse impact on performance to clear
574  * the vectors here.
575  */
576  sortedObjects_.clear();
577  sortedObjects_.reserve(numRenderObjects);
578 
579  overlayObjects_.clear();
580  overlayObjects_.reserve(numOverlayObjects);
581 
582  lineGL42Objects_.clear();
583  lineGL42Objects_.reserve(numLineObjects);
584 
585 
586  sortListObjects_.clear();
587  sortListObjects_.reserve(numRenderObjects);
588 
589  sortListOverlays_.clear();
590  sortListOverlays_.reserve(numOverlayObjects);
591 
592  // init sorted objects array
593  for (size_t i = 0; i < renderObjects_.size(); ++i)
594  {
595  if (renderObjects_[i].overlay)
596  {
597  overlayObjects_.push_back(&renderObjects_[i]);
598  sortListOverlays_.push_back(i);
599  }
600  else if (enableLineThicknessGL42_ && numLineObjects && renderObjects_[i].isDefaultLineObject())
601  {
602  renderObjects_[i].shaderDesc.geometryTemplateFile = "Wireframe/gl42/geometry.tpl";
603  renderObjects_[i].shaderDesc.fragmentTemplateFile = "Wireframe/gl42/fragment.tpl";
604 
605  // disable color write to fbo, but allow RenderObject to control depth write
606  renderObjects_[i].glColorMask(0,0,0,0);
607 
608 // sortedObjects_[sceneObjectOffset++] = &renderObjects_[i];
609  lineGL42Objects_.push_back(&renderObjects_[i]);
610  }
611  else
612  {
613  sortedObjects_.push_back(&renderObjects_[i]);
614  sortListObjects_.push_back(i);
615  }
616  }
617 
618  sortRenderObjects();
619 
620 
621  // ---------------------------
622  // Initialize the render state
623  // ---------------------------
624  // gl cleanup
625 
626  if (_glState->compatibilityProfile())
627  {
628  glDisableClientState(GL_VERTEX_ARRAY);
629  glDisableClientState(GL_COLOR_ARRAY);
630  glDisableClientState(GL_NORMAL_ARRAY);
631  glDisableClientState(GL_TEXTURE_COORD_ARRAY);
632  glDisableClientState(GL_INDEX_ARRAY);
633  }
634 
635  glEnable(GL_CULL_FACE);
636  glEnable(GL_DEPTH_TEST);
637  glDepthFunc(GL_LESS);
638  glDepthMask(GL_TRUE);
639 
640  // save active fbo and viewport
641  saveInputFbo();
642 
643 if(_glState->compatibilityProfile())
644 {
645  // get global ambient factor
646  GLfloat lightModelAmbient[4];
647  glGetFloatv(GL_LIGHT_MODEL_AMBIENT, lightModelAmbient);
648  globalLightModelAmbient_ = ACG::Vec3f(lightModelAmbient[0], lightModelAmbient[1], lightModelAmbient[2]);
649 }
650 
651  // search list of render object for objects requiring the scene depth map
652  bool requiresSceneDepths = false;
653 
654  for (size_t i = 0; i < renderObjects_.size(); ++i)
655  {
656  if (renderObjects_[i].depthMapUniformName)
657  requiresSceneDepths = true;
658  }
659 
660  // render scene depth map
661  if (requiresSceneDepths)
662  renderDepthMap(curViewerID_, _glState->viewport_width(), _glState->viewport_height());
663 }
664 
665 
666 
667 void IRenderer::finishRenderingPipeline(bool _drawOverlay)
668 {
669 #ifdef GL_ARB_vertex_array_object
670  glBindVertexArray(prevVAO_);
671 #endif
672 
673  // draw thick lines
674  if (enableLineThicknessGL42_)
675  renderLineThicknessGL42();
676 
677  if (_drawOverlay)
678  {
679  const int numOverlayObj = overlayObjects_.size();
680  // two-pass overlay rendering:
681  // 1. clear depth buffer at pixels of overlay objects
682  // 2. render overlay with correct depth-testing
683 
684  // 1. pass: clear depth to max value at overlay footprint
685  for (int i = 0; i < numOverlayObj; ++i)
686  {
687  RenderObject* obj = getOverlayRenderObject(i);
688 
689  if (obj->depthTest && obj->depthFunc != GL_ALWAYS)
690  {
691  float depthMax = 1.0f;
692 
693  if (obj->depthFunc == GL_GREATER || obj->depthFunc == GL_GEQUAL)
694  depthMax = 0.0f;
695 
696  // save depth setting of renderobject
697  Vec2f depthRange = obj->depthRange;
698  bool depthWrite = obj->depthWrite;
699  GLenum depthFunc = obj->depthFunc;
700 
701  // reset depth to maximal distance by using depth range
702  obj->depthRange = Vec2f(depthMax, depthMax);
703  obj->depthWrite = true;
704  obj->depthFunc = GL_ALWAYS;
705 
706  renderObject(obj);
707 
708  // restore depth setting
709  obj->depthRange = depthRange;
710  obj->depthWrite = depthWrite;
711  obj->depthFunc = depthFunc;
712  }
713 
714  }
715 
716  // 2. render overlay with correct depth-testing
717  for (int i = 0; i < numOverlayObj; ++i)
718  {
719  RenderObject* obj = getOverlayRenderObject(i);
720  renderObject(obj);
721  }
722 
723  }
724 
725 #ifdef GL_ARB_vertex_array_object
726  glBindVertexArray(prevVAO_);
727 #endif
728 
729  for (int i = 0; i < maxClipDistances_; ++i)
730  glDisable(GL_CLIP_DISTANCE0 + i);
731 
732  glDisable(GL_PROGRAM_POINT_SIZE);
733 
734  glDepthMask(1);
735  glColorMask(1,1,1,1);
736 
737  glUseProgram(0);
738 
739  glBindBuffer(GL_ARRAY_BUFFER, 0);
740  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
741 
742  // Renderer check:
743  // Print a warning if the currently active fbo / viewport is not the same as the saved fbo.
744  // Restore to previous fbo and viewport if not done already.
745 
746  GLint curFbo;
747  GLint curViewport[4];
748  GLint curDrawBuf;
749  glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &curFbo);
750  glGetIntegerv(GL_VIEWPORT, curViewport);
751  glGetIntegerv(GL_DRAW_BUFFER, &curDrawBuf);
752 
753  if (curFbo != prevFbo_)
754  {
755  std::cout << "warning: input and output fbo are not the same in renderer implementation" << std::endl;
756  restoreInputFbo();
757  }
758 
759  if (curDrawBuf != prevDrawBuffer_)
760  {
761  std::cout << "warning: input and output draw-buffer are not the same in renderer implementation" << std::endl;
762  restoreInputFbo();
763  }
764 
765  if (curViewport[0] != prevViewport_[0] ||
766  curViewport[1] != prevViewport_[1] ||
767  curViewport[2] != prevViewport_[2] ||
768  curViewport[3] != prevViewport_[3])
769  {
770  std::cout << "warning: input and output viewport are not the same in renderer implementation" << std::endl;
771  restoreInputFbo();
772  }
773 }
774 
775 
777 {
778  // save active fbo
779  saveActiveFbo(&prevFbo_, prevViewport_, &prevDrawBuffer_);
780  prevFboSaved_ = true;
781 }
782 
784 {
785  if (prevFboSaved_)
786  restoreFbo(prevFbo_, prevViewport_, prevDrawBuffer_);
787 }
788 
789 void IRenderer::saveActiveFbo( GLint* _outFboId, GLint* _outViewport, GLint* _outDrawBuffer ) const
790 {
791  // save active fbo
792  glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, _outFboId);
793  glGetIntegerv(GL_VIEWPORT, _outViewport);
794  glGetIntegerv(GL_DRAW_BUFFER, _outDrawBuffer);
795 }
796 
797 void IRenderer::restoreFbo( GLint _fboId, const GLint* _outViewport, GLint _drawBuffer ) const
798 {
799  glBindFramebuffer(GL_FRAMEBUFFER, _fboId);
800  glDrawBuffer(_drawBuffer);
801  glViewport(_outViewport[0], _outViewport[1], _outViewport[2], _outViewport[3]);
802 }
803 
804 void IRenderer::clearInputFbo( const ACG::Vec4f& clearColor )
805 {
806  glClearColor(clearColor[0], clearColor[1], clearColor[2], 1.0f);
807 
808  // glClear will affect the whole back buffer, not only the area in viewport.
809  // Temporarily use glScissor to only clear the viewport area in the back buffer.
810  if (!prevFboSaved_)
811  {
812  GLint oldViewport[4];
813  glGetIntegerv(GL_VIEWPORT, oldViewport);
814  glScissor(oldViewport[0], oldViewport[1], oldViewport[2], oldViewport[3]);
815  }
816  else
817  glScissor(prevViewport_[0], prevViewport_[1], prevViewport_[2], prevViewport_[3]);
818 
819  glEnable(GL_SCISSOR_TEST);
820  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
821 
822  // disable scissors again, draw calls only affect the area in glViewport anyway
823  glDisable(GL_SCISSOR_TEST);
824 }
825 
826 namespace {
827 struct RenderObjectComparator {
828  explicit RenderObjectComparator(const std::vector<ACG::RenderObject>& _vec) : vec_(_vec) {
829  }
830 
831  bool operator() (int a, int b) {
832  return (vec_[a].priority < vec_[b].priority);
833  }
834 
835  const std::vector<ACG::RenderObject>& vec_;
836 };
837 }
838 
840 {
841  size_t numObjs = sortListObjects_.size();
842  size_t numOverlays = sortListOverlays_.size();
843 
844  RenderObjectComparator cmpOp(renderObjects_);
845 
846  std::sort(sortListObjects_.begin(), sortListObjects_.end(), cmpOp);
847  std::sort(sortListOverlays_.begin(), sortListOverlays_.end(), cmpOp);
848 
849  // apply sorting list
850  std::vector<ACG::SceneGraph::BaseNode*> temp;
851  renderObjectSource_.swap(temp);
852 
853 
854  renderObjectSource_.resize(numObjs, 0);
855  overlayObjectSource_.resize(numOverlays, 0);
856 
857  for (size_t i = 0; i < numObjs; ++i)
858  {
859  int objID = sortListObjects_[i];
860  sortedObjects_[i] = &renderObjects_[objID];
861 
862  renderObjectSource_[i] = temp[objID];
863  }
864 
865  for (size_t i = 0; i < numOverlays; ++i)
866  {
867  int objID = sortListOverlays_[i];
868  overlayObjects_[i] = &renderObjects_[objID];
869 
870  overlayObjectSource_[i] = temp[objID];
871  }
872 }
873 
874 
875 
877  GLSL::Program* _prog)
878 {
879  _prog->use();
880 
881 
882 #ifdef GL_ARB_vertex_array_object
883  if (_obj->vertexArrayObject)
884  glBindVertexArray(_obj->vertexArrayObject);
885 #endif
886 
887  if (!_obj->vertexArrayObject)
888  {
890  // NOTE:
891  // always bind buffers before glVertexAttribPointer calls!!
892  // freeze in glDrawElements guaranteed (with no error message whatsoever)
893  glBindBuffer(GL_ARRAY_BUFFER, _obj->vertexBuffer);
894  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _obj->indexBuffer);
895 
896 
897  // activate vertex declaration
898  _obj->vertexDecl->activateShaderPipeline(_prog);
899 
900  }
901 }
902 
903 
905 {
906  // transforms
907  ACG::GLMatrixf mvp = _obj->proj * _obj->modelview;
908  ACG::GLMatrixf mvIT = _obj->modelview;
909  mvIT.invert();
910  mvIT.transpose();
911 
912  _prog->setUniform("g_mWVP", mvp);
913  _prog->setUniform("g_mWV", _obj->modelview);
914  _prog->setUniformMat3("g_mWVIT", mvIT);
915  _prog->setUniform("g_mP", _obj->proj);
916 
917  _prog->setUniform("g_vCamPos", camPosWS_);
918  _prog->setUniform("g_vCamDir", camDirWS_);
919 
920  // material
921 
922  _prog->setUniform("g_cEmissive", _obj->emissive);
923 
924  _prog->setUniform("g_cDiffuse", _obj->diffuse);
925  _prog->setUniform("g_cAmbient", _obj->ambient);
926  _prog->setUniform("g_cSpecular", _obj->specular);
927 
928 
929  float alphaRef = 0.f;
930  if (_obj->alphaTest && _obj->alphaFunc == GL_GREATER) {
931  alphaRef = _obj->alphaRef;
932  }
933  ACG::Vec4f materialParams(_obj->shininess, _obj->alpha, alphaRef, 0.0f);
934  _prog->setUniform("g_vMaterial", materialParams);
935 
936  _prog->setUniform("g_cLightModelAmbient", globalLightModelAmbient_);
937 
938  // Additional Uniforms defined in the render Object
939  if ( !_obj->uniformPool_.empty() )
940  _obj->uniformPool_.bind(_prog);
941 
942  // textures:
943 
944  // maybe consider using bindless textures some time in the future
945  // to get rid of the old and problematic glActiveTexture(), glBindTexture() state machine usage:
946  // https://www.opengl.org/registry/specs/ARB/bindless_texture.txt
947 
948  int maxTextureStage = 0;
949  for (std::map<size_t,RenderObject::Texture>::const_iterator iter = _obj->textures().begin();
950  iter != _obj->textures().end();++iter)
951  {
952  //check for valid texture id
953  const size_t texture_stage = iter->first;
954  const RenderObject::Texture tex = iter->second;
955  if (!tex.id)
956  continue;
957 
958  glActiveTexture(GL_TEXTURE0 + (GLenum)texture_stage);
959  glBindTexture(iter->second.type, tex.id);
960  _prog->setUniform(QString("g_Texture%1").arg(texture_stage).toStdString().c_str(), (int)texture_stage);
961 
962  maxTextureStage = std::max(maxTextureStage, (int)texture_stage);
963  }
964 
965 
966  // scene depth texture
967  if (_obj->depthMapUniformName)
968  {
969  // bind to (hopefully) unused texture stage
970  int depthMapSlot = maxTextureStage + 1;
971 
972  _prog->setUniform(_obj->depthMapUniformName, depthMapSlot);
973  glActiveTexture(GL_TEXTURE0 + depthMapSlot);
974  glBindTexture(GL_TEXTURE_2D, depthMaps_[curViewerID_]->getAttachment(GL_COLOR_ATTACHMENT0));
975  }
976 
977 
978  // lights
979  for (int i = 0; i < numLights_; ++i)
980  {
981  LightData* lgt = lights_ + i;
982 
983  char szUniformName[256];
984 
985  sprintf(szUniformName, "g_cLightDiffuse_%d", i);
986  _prog->setUniform(szUniformName, lgt->diffuse);
987 
988  sprintf(szUniformName, "g_cLightAmbient_%d", i);
989  _prog->setUniform(szUniformName, lgt->ambient);
990 
991  sprintf(szUniformName, "g_cLightSpecular_%d", i);
992  _prog->setUniform(szUniformName, lgt->specular);
993 
994 
995  if (lgt->ltype == ACG::SG_LIGHT_POINT || lgt->ltype == ACG::SG_LIGHT_SPOT)
996  {
997  sprintf(szUniformName, "g_vLightPos_%d", i);
998  _prog->setUniform(szUniformName, lgt->pos);
999 
1000  sprintf(szUniformName, "g_vLightAtten_%d", i);
1001  _prog->setUniform(szUniformName, lgt->atten);
1002  }
1003 
1004  if (lgt->ltype == ACG::SG_LIGHT_DIRECTIONAL || lgt->ltype == ACG::SG_LIGHT_SPOT)
1005  {
1006  sprintf(szUniformName, "g_vLightDir_%d", i);
1007  _prog->setUniform(szUniformName, lgt->dir);
1008  }
1009 
1010  if (lgt->ltype == ACG::SG_LIGHT_SPOT)
1011  {
1012  sprintf(szUniformName, "g_vLightAngleExp_%d", i);
1013  _prog->setUniform(szUniformName, lgt->spotCutoffExponent);
1014  }
1015  }
1016 }
1017 
1019 {
1020  if (_obj->culling)
1021  glEnable(GL_CULL_FACE);
1022  else
1023  glDisable(GL_CULL_FACE);
1024 
1025  if (_obj->blending)
1026  glEnable(GL_BLEND);
1027  else
1028  glDisable(GL_BLEND);
1029 
1030  if (!coreProfile_)
1031  {
1032  if (_obj->alphaTest)
1033  {
1034  glEnable(GL_ALPHA_TEST);
1035  glAlphaFunc(_obj->alphaFunc, _obj->alphaRef);
1036  }
1037  else
1038  glDisable(GL_ALPHA_TEST);
1039  }
1040 
1041  if (_obj->depthTest)
1042  glEnable(GL_DEPTH_TEST);
1043  else
1044  glDisable(GL_DEPTH_TEST);
1045 
1046 
1047  glDepthMask(_obj->depthWrite ? GL_TRUE : GL_FALSE);
1048 
1049  glColorMask(_obj->colorWriteMask[0], _obj->colorWriteMask[1], _obj->colorWriteMask[2], _obj->colorWriteMask[3]);
1050 
1051  glDepthFunc(_obj->depthFunc);
1052 
1053  glDepthRange(_obj->depthRange[0], _obj->depthRange[1]);
1054 
1055  // ACG::GLState::shadeModel(_obj->shadeModel);
1056 
1057  ACG::GLState::blendFunc(_obj->blendSrc, _obj->blendDest);
1058 
1059  if (maxClipDistances_ < 0)
1060  {
1061  glGetIntegerv(GL_MAX_CLIP_DISTANCES, &maxClipDistances_);
1062  maxClipDistances_ = std::min(maxClipDistances_, 32); // clamp to 32 bits
1063  }
1064 
1065  for (int i = 0; i < maxClipDistances_; ++i)
1066  {
1067  if (_obj->clipDistanceMask & (1 << i))
1068  glEnable(GL_CLIP_DISTANCE0 + i);
1069  else
1070  glDisable(GL_CLIP_DISTANCE0 + i);
1071  }
1072 
1073 #ifdef GL_PROGRAM_POINT_SIZE
1074  if (_obj->programPointSize)
1075  glEnable(GL_PROGRAM_POINT_SIZE);
1076  else
1077  glDisable(GL_PROGRAM_POINT_SIZE);
1078 #endif
1079 
1080  glPointSize(_obj->pointSize);
1081 }
1082 
1084 {
1085  if (_obj->numIndices)
1086  {
1087  // indexed drawing?
1088  bool noIndices = true;
1089  if (_obj->indexBuffer || _obj->sysmemIndexBuffer)
1090  noIndices = false;
1091 
1092  glPolygonMode(GL_FRONT_AND_BACK, _obj->fillMode);
1093 
1094  // tessellation info
1095  bool tessellationActive = !(_obj->shaderDesc.tessControlTemplateFile.isEmpty() && _obj->shaderDesc.tessEvaluationTemplateFile.isEmpty());
1096 #ifdef GL_ARB_tessellation_shader
1097  if (tessellationActive)
1098  {
1099  glPatchParameteri(GL_PATCH_VERTICES, _obj->patchVertices);
1100 
1101  if (_obj->shaderDesc.tessControlTemplateFile.isEmpty())
1102  {
1103  glPatchParameterfv(GL_PATCH_DEFAULT_INNER_LEVEL, _obj->patchDefaultInnerLevel.data());
1104  glPatchParameterfv(GL_PATCH_DEFAULT_OUTER_LEVEL, _obj->patchDefaultOuterLevel.data());
1105  }
1106  }
1107 #else
1108  if (tessellationActive)
1109  std::cout << "error: tessellation shaders cannot be used with the outdated glew version" << std::endl;
1110 #endif
1111 
1112  if (noIndices) {
1113  if (_obj->numInstances <= 0)
1114  glDrawArrays(_obj->primitiveMode, _obj->indexOffset, _obj->numIndices);
1115  else
1116  glDrawArraysInstanced(_obj->primitiveMode, _obj->indexOffset, _obj->numIndices, _obj->numInstances);
1117  }
1118  else
1119  {
1120  // ------------------------------------------
1121  // index offset stuff not tested
1122  int indexSize = 0;
1123  switch (_obj->indexType)
1124  {
1125  case GL_UNSIGNED_INT: indexSize = 4; break;
1126  case GL_UNSIGNED_SHORT: indexSize = 2; break;
1127  default: indexSize = 1; break;
1128  }
1129 
1130  if (_obj->numInstances <= 0)
1131  glDrawElements(_obj->primitiveMode, _obj->numIndices, _obj->indexType,
1132  ((const char*)_obj->sysmemIndexBuffer) + _obj->indexOffset * indexSize);
1133  else
1134  glDrawElementsInstanced(_obj->primitiveMode, _obj->numIndices, _obj->indexType,
1135  ((const char*)_obj->sysmemIndexBuffer) + _obj->indexOffset * indexSize, _obj->numInstances);
1136  }
1137  }
1138 }
1139 
1141  GLSL::Program* _prog,
1142  bool _constRenderStates,
1143  const std::vector<unsigned int>* _shaderModifiers)
1144 {
1145  // select shader from cache
1146  GLSL::Program* prog = _prog ? _prog : ACG::ShaderCache::getInstance()->getProgram(&_obj->shaderDesc, _shaderModifiers);
1147 
1148 
1149  bindObjectVBO(_obj, prog);
1150 
1151  // ---------------------------------------
1152  // set shader uniforms
1153 
1154  bindObjectUniforms(_obj, prog);
1155 
1156  // render states
1157 
1158  if (!_constRenderStates)
1159  bindObjectRenderStates(_obj);
1160 
1161  // ----------------------------
1162  // OpenGL draw call
1163 
1164  drawObject(_obj);
1165 
1166 
1168 
1169  if (_obj->vertexDecl)
1170  {
1171  // deactivate vertex declaration to avoid errors
1172  _obj->vertexDecl->deactivateShaderPipeline(prog);
1173  }
1174 
1175 
1176 #ifdef GL_ARB_vertex_array_object
1177  if (_obj->vertexArrayObject)
1178  glBindVertexArray(prevVAO_);
1179 #endif
1180 
1181 }
1182 
1183 
1184 void IRenderer::addLight(const LightData& _light)
1185 {
1186  if (numLights_ < SG_MAX_SHADER_LIGHTS)
1187  {
1188  lights_[numLights_] = _light;
1189 
1190  // normalize direction
1191  if (_light.ltype != SG_LIGHT_POINT)
1192  lights_[numLights_].dir.normalize();
1193 
1194  ++numLights_;
1195  }
1196 }
1197 
1199 {
1200  renderObjectModifiers_.push_back(_mod);
1201 }
1202 
1204 {
1205  for (int i = int(renderObjectModifiers_.size()) - 1; i >= 0; --i)
1206  {
1207  if (renderObjectModifiers_[i] == _mod)
1208  renderObjectModifiers_.erase(renderObjectModifiers_.begin() + i);
1209  }
1210 }
1211 
1213  return sortedObjects_.size();
1214 }
1215 
1217 {
1218  return numLights_;
1219 }
1220 
1221 
1223 {
1224  if (sortedObjects_.empty())
1225  return &renderObjects_[i];
1226 
1227  return sortedObjects_[i];
1228 }
1229 
1231 {
1232  if (overlayObjects_.empty())
1233  return &renderObjects_[i];
1234 
1235  return overlayObjects_[i];
1236 }
1237 
1238 
1240 {
1241  return renderObjectSource_[i];
1242 }
1243 
1245 {
1246  return overlayObjectSource_[i];
1247 }
1248 
1249 
1251 {
1252  if (lineGL42Objects_.empty())
1253  return 0;
1254 
1255  return lineGL42Objects_[i];
1256 }
1257 
1259 {
1260  return &lights_[i];
1261 }
1262 
1263 
1264 void IRenderer::dumpRenderObjectsToFile(const char* _fileName, ACG::RenderObject** _sortedList) const
1265 {
1266  QFile fileOut(_fileName);
1267  if (fileOut.open(QFile::WriteOnly | QFile::Truncate))
1268  {
1269  QTextStream outStrm(&fileOut);
1270  for (int i = 0; i < getNumRenderObjects(); ++i)
1271  {
1272  if (_sortedList)
1273  outStrm << "\n" << _sortedList[i]->toString();
1274  else
1275  outStrm << "\n" << renderObjects_[i].toString();
1276  }
1277 
1278  fileOut.close();
1279  }
1280 }
1281 
1282 
1283 QString IRenderer::dumpCurrentRenderObjectsToString(ACG::RenderObject** _list, bool _outputShaders, std::vector<ACG::ShaderModifier*>* _modifiers) {
1284 
1285  QString objectString;
1286 
1287  QTextStream outStrm(&objectString);
1288 
1289  for (int i = 0; i < getNumRenderObjects(); ++i)
1290  {
1291  const RenderObject* obj = _list ? _list[i] : &renderObjects_[i];
1292 
1293  if (obj) {
1294  outStrm << "\n" << obj->toString();
1295 
1296  if ( _outputShaders ) {
1297 
1298  outStrm << "\n";
1299 
1300  outStrm << obj->shaderDesc.toString();
1301 
1302  ShaderProgGenerator progGen(&(obj->shaderDesc), _modifiers);
1303 
1304  outStrm << "\n---------------------vertex-shader--------------------\n\n";
1305  for (int i = 0; i < progGen.getVertexShaderCode().size(); ++i)
1306  outStrm << progGen.getVertexShaderCode()[i] << "\n";
1307  outStrm << "\n---------------------end-vertex-shader--------------------\n\n";
1308 
1309  if (progGen.hasTessControlShader())
1310  {
1311  outStrm << "\n---------------------tesscontrol-shader--------------------\n\n";
1312  for (int i = 0; i < progGen.getTessControlShaderCode().size(); ++i)
1313  outStrm << progGen.getTessControlShaderCode()[i] << "\n";
1314  outStrm << "\n---------------------end-tesscontrol-shader--------------------\n\n";
1315  }
1316 
1317  if (progGen.hasTessControlShader())
1318  {
1319  outStrm << "\n---------------------tesseval-shader--------------------\n\n";
1320  if (progGen.hasTessEvaluationShader())
1321  for (int i = 0; i < progGen.getTessEvaluationShaderCode().size(); ++i)
1322  outStrm << progGen.getTessEvaluationShaderCode()[i] << "\n";
1323  outStrm << "\n---------------------end-tesseval-shader--------------------\n\n";
1324  }
1325 
1326  if (progGen.hasGeometryShader())
1327  {
1328  outStrm << "\n---------------------geometry-shader--------------------\n\n";
1329  for (int i = 0; i < progGen.getGeometryShaderCode().size(); ++i)
1330  outStrm << progGen.getGeometryShaderCode()[i] << "\n";
1331  outStrm << "\n---------------------end-geometry-shader--------------------\n\n";
1332  }
1333 
1334 
1335  outStrm << "\n---------------------fragment-shader--------------------\n\n";
1336  for (int i = 0; i < progGen.getFragmentShaderCode().size(); ++i)
1337  outStrm << progGen.getFragmentShaderCode()[i] << "\n";
1338  outStrm << "\n---------------------end-fragment-shader--------------------\n\n";
1339  }
1340 
1341  }
1342 
1343  }
1344 
1345  return objectString;
1346 }
1347 
1348 void IRenderer::copyDepthToBackBuffer( GLuint _depthTex, float _scale /*= 1.0f*/ )
1349 {
1350  if (!_depthTex) return;
1351 #ifdef __APPLE__
1352  if(ACG::openGLVersion(3,3))
1353  {
1354  if (!depthCopyShader_)
1355  depthCopyShader_ = GLSL::loadProgram("ScreenQuad/screenquad.glsl", "ScreenQuad/depth_copy_330.glsl");
1356  }
1357  else
1358 #endif
1359  {
1360  if (!depthCopyShader_)
1361  depthCopyShader_ = GLSL::loadProgram("ScreenQuad/screenquad.glsl", "ScreenQuad/depth_copy.glsl");
1362  }
1363 
1364  if (depthCopyShader_)
1365  {
1366  // save important opengl states
1367  GLint curFbo;
1368  GLint curViewport[4];
1369  GLint curDrawBuffer;
1370  saveActiveFbo(&curFbo, curViewport, &curDrawBuffer);
1371 
1372  GLboolean colorMask[4], depthMask;
1373  glGetBooleanv(GL_COLOR_WRITEMASK, colorMask);
1374  glGetBooleanv(GL_DEPTH_WRITEMASK, &depthMask);
1375 
1376  GLboolean depthTestEnable;
1377  GLint depthFunc;
1378  glGetBooleanv(GL_DEPTH_TEST, &depthTestEnable);
1379  glGetIntegerv(GL_DEPTH_FUNC, &depthFunc);
1380 
1381  // write to depth buffer of input fbo
1382  restoreInputFbo();
1383 
1384  depthCopyShader_->use();
1385  depthCopyShader_->setUniform("offset", ACG::Vec2f(0.0f, 0.0f));
1386  depthCopyShader_->setUniform("size", ACG::Vec2f(1.0f, 1.0f));
1387  depthCopyShader_->setUniform("DepthTex", 0); // depth tex at texture slot 0
1388  depthCopyShader_->setUniform("DepthSign", _scale);
1389 
1390  // write to depth buffer only, disable writing to color buffer
1391  glColorMask(0,0,0,0);
1392  glDepthMask(1);
1393 
1394  // depth test enabled + pass always
1395  glEnable(GL_DEPTH_TEST);
1396  glDepthFunc(GL_ALWAYS);
1397 
1398  glActiveTexture(GL_TEXTURE0);
1399  glBindTexture(GL_TEXTURE_2D, _depthTex);
1400 
1401  ACG::ScreenQuad::draw(depthCopyShader_);
1402 
1403 
1404  // restore important opengl states
1405 
1406  restoreFbo(curFbo, curViewport, curDrawBuffer);
1407 
1408  glColorMask(colorMask[0], colorMask[1], colorMask[2], colorMask[3]);
1409  glDepthMask(depthMask);
1410 
1411  if (!depthTestEnable)
1412  glDisable(GL_DEPTH_TEST);
1413 
1414  if (depthFunc != GL_ALWAYS)
1415  glDepthFunc(depthFunc);
1416 
1417  glBindTexture(GL_TEXTURE_2D, 0);
1418  }
1419 }
1420 
1421 
1422 // depth map computation with a modifier
1423 
1424 IRenderer::DepthMapPass IRenderer::DepthMapPass::instance;
1425 
1427 {
1428  _code->push_back("outFragment = gl_FragCoord.zzzz;");
1429 }
1430 
1431 void IRenderer::renderDepthMap(int _viewerID, int _width, int _height)
1432 {
1433  ACG::FBO* fbo = depthMaps_[_viewerID];
1434 
1435  // setup fbo for depth map
1436  if (!fbo)
1437  {
1438  fbo = depthMaps_[_viewerID] = new ACG::FBO();
1439 
1440  fbo->bind();
1441  fbo->attachTexture2D(GL_COLOR_ATTACHMENT0, _width, _height, GL_R32F, GL_RED);
1442  fbo->addDepthBuffer(_width, _height);
1443  }
1444  else
1445  {
1446  fbo->bind();
1447  fbo->resize(_width, _height);
1448  }
1449 
1450  // make sure modifier is registered
1451  ACG::ShaderProgGenerator::registerModifier(&DepthMapPass::instance);
1452 
1453  /* note:
1454  It is possible to directly read the depth buffer if it was attached as a texture.
1455  Then, we would disable the color write mask and just write to the depth buffer in this function.
1456 
1457  However, doing this has shown that the actual depth values written to the depth buffer highly depend on the gpu driver.
1458  Or, at least sampling from a texture with format GL_DEPTH_COMPONENT returns driver dependent values.
1459  For instance, in the amd-gl driver sampling the depth texture returns the value of gl_FragDepth (as expected).
1460  But in the nvidia driver, sampling directly from the depth buffer returns something different!
1461 
1462  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.
1463  */
1464 
1465  fbo->bind();
1466  glDrawBuffer(GL_COLOR_ATTACHMENT0);
1467  glViewport(0, 0, _width, _height);
1468 
1469  // set depth to max
1470  glColorMask(1,1,1,1);
1471  glDepthMask(1);
1472 
1473  glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
1474  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1475 
1476  // render z-prepass
1477  for (int i = 0; i < getNumRenderObjects(); ++i)
1478  {
1479  RenderObject* obj = getRenderObject(i);
1480 
1481  if (obj->inZPrePass)
1482  {
1483  // apply depth map modifier to get the depth pass shader
1484  GLSL::Program* depthPassShader = ShaderCache::getInstance()->getProgram(&obj->shaderDesc, DepthMapPass::instance);
1485 
1486  // temporarily prevent read/write access to the same texture (the depth map)
1487  const char* depthMapUniformName = obj->depthMapUniformName;
1488  obj->depthMapUniformName = 0;
1489 
1490  if (depthMapUniformName)
1491  {
1492  depthPassShader->use();
1493  depthPassShader->setUniform(depthMapUniformName, 0);
1494  glActiveTexture(GL_TEXTURE0);
1495  glBindTexture(GL_TEXTURE_2D, 0);
1496  }
1497 
1498  // we are interested in the depth value only, so temporarily modify the write mask to allow writing to the red channel
1499  // (for instance, an object might not write a color value, but a depth value)
1500  const GLboolean redWriteMask = obj->colorWriteMask[0];
1501  obj->colorWriteMask[0] = obj->depthWrite;
1502 
1503  renderObject(obj, depthPassShader);
1504 
1505  // reset modified render object states
1506  obj->depthMapUniformName = depthMapUniformName;
1507  obj->colorWriteMask[0]= redWriteMask;
1508  }
1509  }
1510 
1511  // restore input fbo state
1512 
1513  fbo->unbind();
1514 
1515  restoreInputFbo();
1516 }
1517 
1518 
1519 void IRenderer::setViewerID(int _viewerID)
1520 {
1521  curViewerID_ = _viewerID;
1522 }
1523 
1524 
1525 void IRenderer::renderLineThicknessGL42()
1526 {
1527 #ifdef GL_ARB_shader_image_load_store
1528  // quad extrusion has depth clipping issue
1529  // GL4.2 method: manually rasterize thick lines into load/store texture, thereby avoiding clipping
1530 
1531  // experimental technique, needs some improvements for rasterization
1532  /* possible improvement:
1533  0. init depth buffer with scene objects
1534  1. extract visible line object (startpos, endpos) into imageBuffer after depth-test in fragment shader
1535  1a. line segment id can be found via atomic counter in geometry shader
1536  1b. use imageAtomicMin/max to find start and end pixel pos of each line segment
1537  atomic ops work with uint only, thus each segment has 4 texels in the imageBuffer, offsets are segmentID * 4 + {0,1,2,3}
1538  2. read imageBuffer in geometry shader and do usual quad extrusion, now without depth testing
1539  => get hw rasterization and msaa
1540  */
1541 
1542  // using image2D does not work: texture always reads 0, even with glGetTexImage2D
1543  // imageBuffer works
1544  // - check with different gpu
1545 
1546  const int numLines = lineGL42Objects_.size();
1547 
1548  // configs
1549  const bool useBufferTexture = true; // imageBuffer or image2D
1550  const bool useIntegerTexture = true; // color as R32U or RGBA32F
1551 
1552 
1553 
1554  if (numLines)
1555  {
1556 
1557  // macro configs for shader
1558  QStringList macros;
1559 
1560  if (useBufferTexture)
1561  macros.push_back("#define IMAGE_BUFFER");
1562  if (useIntegerTexture)
1563  macros.push_back("#define FMT_UINT");
1564 
1565 
1566  // get random access write buffer
1567  // 32bit uint per viewport pixel, stores rgba8
1568  Texture2D* lineColorImg2D = 0;
1569  TextureBuffer* lineColorImgBuf = 0;
1570 
1571  size_t w = static_cast<size_t>(prevViewport_[2]), h = static_cast<size_t>(prevViewport_[3]);
1572  size_t lineBPP = static_cast<size_t>(useIntegerTexture ? 4 : 16); // bytes per pixel
1573 
1574 
1575  if (useBufferTexture)
1576  {
1577  lineColorImgBuf = dynamic_cast<TextureBuffer*>(lineColorBuffers_[curViewerID_]);
1578 
1579  if (!lineColorImgBuf)
1580  {
1581  lineColorImgBuf = new TextureBuffer(GL_TEXTURE0);
1582  lineColorBuffers_[curViewerID_] = lineColorImgBuf;
1583  }
1584 
1585  // resize
1586  if (lineColorImgBuf->getBufferSize() != w * h * lineBPP)
1587  lineColorImgBuf->setBufferData(w*h*lineBPP, 0, GL_R32UI, GL_DYNAMIC_DRAW);
1588  }
1589  else
1590  {
1591  lineColorImg2D = dynamic_cast<Texture2D*>(lineColorBuffers_[curViewerID_]);
1592 
1593  if (!lineColorImg2D)
1594  {
1595  // allocate and store in map
1596  lineColorImg2D = new Texture2D(GL_TEXTURE0);
1597  lineColorBuffers_[curViewerID_] = lineColorImg2D;
1598  }
1599 
1600  // resize
1601  if (lineColorImg2D->getWidth() != static_cast<int>(w) || lineColorImg2D->getHeight() != static_cast<int>(h))
1602  lineColorImg2D->setData(0,
1603  useIntegerTexture ? GL_R32UI : GL_RGBA32F,
1604  w, h,
1605  useIntegerTexture ? GL_RED_INTEGER : GL_RGBA,
1606  useIntegerTexture ? GL_UNSIGNED_INT : GL_FLOAT,
1607  0);
1608  }
1609 
1610 
1611 
1612 
1613 
1614  glViewport(0, 0, w, h);
1615 
1616 
1617 
1618  // ---------------------------
1619  // clear line color buffer
1620 
1621  glColorMask(0,0,0,0);
1622  glDepthMask(0);
1623  glDisable(GL_DEPTH_TEST);
1624 
1625  // image binding is set to slot 0 in shader already
1626  if (useBufferTexture)
1627  lineColorImgBuf->bindAsImage(0, GL_WRITE_ONLY);
1628  else
1629  lineColorImg2D->bindAsImage(0, GL_WRITE_ONLY);
1630 
1631  GLSL::Program* shaderClear = ShaderCache::getInstance()->getProgram("ScreenQuad/screenquad.glsl", "Wireframe/gl42/clear.glsl", &macros);
1632 
1633  shaderClear->use();
1634 // shaderClear->setUniform("offset", Vec2f(0,0));
1635 // shaderClear->setUniform("size", Vec2f(1,1));
1636  shaderClear->setUniform("screenSize", Vec2f(w,h));
1637 
1638  ScreenQuad::draw(shaderClear);
1639 
1640  glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
1641 // GLDebug::dumpTexture2D(lineColorBuf->id(), 0, lineColorBuf->getFormat(), lineColorBuf->getType(), lineBPP*w*h, "c:/dbg/lines_clear.dds");
1642 // GLDebug::dumpBufferData(GL_TEXTURE_BUFFER, lineColorBuf2->getBufferId(), "c:/dbg/lines_clear.bin");
1643 
1644  // ---------------------------
1645  // 1. pass
1646  // render into line color buffer via imageStore,
1647 
1648  for (int i = 0; i < numLines; ++i)
1649  {
1650  RenderObject* obj = getLineGL42RenderObject(i);
1651 
1652  renderObject(obj);
1653  }
1654 
1655  glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
1656 // GLDebug::dumpTexture2D(lineColorBuf->id(), 0, lineColorBuf->getFormat(), lineColorBuf->getType(), lineBPP*w*h, "c:/dbg/lines_image.dds");
1657 // GLDebug::dumpBufferData(GL_TEXTURE_BUFFER, lineColorBuf2->getBufferId(), "c:/dbg/lines_image.bin");
1658 
1659 
1660  // ---------------------------
1661  // 2. pass
1662  // composition of line colors and fbo
1663 
1664  restoreInputFbo();
1665 
1666  // image binding is set to slot 0 in shader already
1667  if (useBufferTexture)
1668  lineColorImgBuf->bindAsImage(0, GL_READ_ONLY);
1669  else
1670  lineColorImg2D->bindAsImage(0, GL_READ_ONLY);
1671 
1672 
1673  glColorMask(1,1,1,1);
1674  glDisable(GL_DEPTH_TEST);
1675 
1676  // enable alpha blending
1677  glEnable(GL_BLEND);
1678  ACG::GLState::blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1679 
1680  GLSL::Program* shaderComposite = ShaderCache::getInstance()->getProgram("ScreenQuad/screenquad.glsl", "Wireframe/gl42/composite.glsl", &macros);
1681 
1682  shaderComposite->use();
1683 // shaderComposite->setUniform("offset", Vec2f(0,0));
1684 // shaderComposite->setUniform("size", Vec2f(1,1));
1685  shaderComposite->setUniform("screenSize", Vec2f(w,h));
1686 
1687  ScreenQuad::draw(shaderComposite);
1688 
1689 
1690  }
1691 #endif
1692 }
1693 
1695 {
1696  if (Texture::supportsImageLoadStore() && Texture::supportsTextureBuffer())
1697  enableLineThicknessGL42_ = _enable;
1698 }
1699 
1701 {
1702  errorDetectionLevel_ = std::max(_level, 0); // clamp to [0,n]
1703 }
1704 
1706 {
1707  return errorDetectionLevel_;
1708 }
1709 
1710 } // namespace ACG end
1711 
bool invert()
matrix inversion (returns true on success)
static ShaderCache * getInstance()
Return instance of the ShaderCache singleton.
Definition: ShaderCache.cc:84
Draw this node, but hide children.
Definition: BaseNode.hh:396
void traverseRenderableNodes(ACG::GLState *_glState, ACG::SceneGraph::DrawModes::DrawMode _drawMode, ACG::SceneGraph::BaseNode &_node, const ACG::SceneGraph::Material &_mat)
Scene graph traversal for render object collection.
Definition: IRenderer.cc:447
bool hasTessControlShader() const
check whether there is a tess-control shader present
Namespace providing different geometric functions concerning angles.
GLMatrixd proj
Projection transform.
static unsigned int registerModifier(ShaderModifier *_modifier)
Shader modifiers have to be registered before they can be used. They also must remain allocated for t...
int getNumLights() const
Get the number of current light sources.
Definition: IRenderer.cc:1216
virtual QString dumpCurrentRenderObjectsToString(ACG::RenderObject **_list=0, bool _outputShaders=false, std::vector< ACG::ShaderModifier *> *_modifiers=0)
Outputs the current render objects to the string.
Definition: IRenderer.cc:1283
void setLineThicknessRenderingGL42(bool _enable)
Definition: IRenderer.cc:1694
GLSL::Program * getProgram(const ShaderGenDesc *_desc, const std::vector< unsigned int > &_mods)
Query a dynamically generated program from cache.
Definition: ShaderCache.cc:102
bool inZPrePass
Specify whether this object should be rendered in a z-prepass.
int getErrorDetectionLevel() const
Get error detection level.
Definition: IRenderer.cc:1705
void addDepthBuffer(GLuint _width, GLuint _height)
function to add a depth renderbuffer to the fbo
Definition: FBO.cc:350
virtual void addRenderObjectModifier(RenderObjectModifier *_mod)
Callback for the scenegraph nodes, which adds a render object modifier to the renderer via this funct...
Definition: IRenderer.cc:1198
void ambientColor(const Vec4f &_a)
set the ambient color.
LightData * getLight(int i)
Get light by index.
Definition: IRenderer.cc:1258
bool hasGeometryShader() const
check whether there is a geometry shader present
Draw node in second pass.
Definition: BaseNode.hh:445
virtual void removeRenderObjectModifier(RenderObjectModifier *_mod)
Callback for the scenegraph nodes, which removes a render object modifier from the renderer...
Definition: IRenderer.cc:1203
virtual void clearInputFbo(const ACG::Vec4f &_clearColor)
Clear input Fbo.
Definition: IRenderer.cc:804
static int maxClipDistances_
max number of clip distance outputs in a vertex shader
Definition: IRenderer.hh:580
GLenum primitiveMode
Primitive type.
void setViewerID(int _viewerID)
Set currently active viewer id.
Definition: IRenderer.cc:1519
VectorT< float, 3 > Vec3f
Definition: VectorT.hh:119
const char * depthMapUniformName
Uniform name of the depth map in the used shader.
void deactivateShaderPipeline(GLSL::Program *_prog) const
ACG::SceneGraph::BaseNode * getOverlayRenderObjectNode(int i)
Get node that emitted the render object in the sorted list by index (only overlay objects) ...
Definition: IRenderer.cc:1244
unsigned int patchVertices
patch size if primitiveMode is GL_PATCHES for rendering with tessellation shaders ...
void modifyFragmentEndCode(QStringList *_code)
Append code the the fragment shader.
Definition: IRenderer.cc:1426
virtual void bindObjectUniforms(ACG::RenderObject *_obj, GLSL::Program *_prog)
Binding Uniforms (Second state function)
Definition: IRenderer.cc:904
virtual void collectRenderObjects(ACG::GLState *_glState, ACG::SceneGraph::DrawModes::DrawMode _drawMode, ACG::SceneGraph::BaseNode *_sceneGraphRoot)
Traverse the scenegraph to collect render information.
Definition: IRenderer.cc:402
int viewport_width() const
get viewport width
Definition: GLState.hh:822
virtual void addLight(const LightData &_light)
Callback for the scenegraph nodes, which send new lights to the renderer via this function...
Definition: IRenderer.cc:1184
GLMatrixd modelview
Modelview transform.
Hide this node, but draw children.
Definition: BaseNode.hh:394
void specularColor(const Vec4f &_s)
set the specular color
auto normalize() -> decltype(*this/=std::declval< VectorT< S, DIM >>().norm())
Definition: Vector11T.hh:429
bool empty() const
returns if the pool is empty
Definition: UniformPool.cc:95
GLuint getProgramId()
Returns opengl id.
Definition: GLSLShader.cc:376
Hide this node and its children.
Definition: BaseNode.hh:398
Scalar * data()
access to Scalar array
Definition: Vector11T.hh:195
Vec2f depthRange
glDepthRange: (znear, zmax)
void diffuseColor(const Vec4f &_d)
set the diffuse color.
Interface class between scenegraph and renderer.
Definition: RenderObject.hh:98
bool isDefaultLineObject() const
Test if the object is rendered with one of the default line thickness methods.
Vec3f diffuse
material definitions
GLSL program class.
Definition: GLSLShader.hh:211
static void blendFunc(GLenum _sfactor, GLenum _dfactor)
replaces glBlendFunc, supports locking
Definition: GLState.hh:307
bool bind()
bind the fbo and sets it as rendertarget
Definition: FBO.cc:458
void transpose()
transpose matrix
virtual void bindObjectRenderStates(ACG::RenderObject *_obj)
Binding Render state (Third state function)
Definition: IRenderer.cc:1018
virtual void drawObject(ACG::RenderObject *_obj)
Executes the opengl draw call for one object (Fourth function)
Definition: IRenderer.cc:1083
void activateShaderPipeline(GLSL::Program *_prog) const
int getNumRenderObjects() const
Get the number of collected render objects (not including overlay objects or gl4.2 line objects) ...
Definition: IRenderer.cc:1212
DrawMode DEFAULT
use the default (global) draw mode and not the node&#39;s own.
Definition: DrawModes.cc:72
virtual void renderDepthMap(int _viewerID, int _width, int _height)
Render the depth map of the scene.
Definition: IRenderer.cc:1431
GLenum depthFunc
GL_LESS, GL_LEQUAL, GL_GREATER ..
virtual void sortRenderObjects()
Sort the renderobjects by priority.
Definition: IRenderer.cc:839
Interface for modifying render objects.
ACG::RenderObject * getOverlayRenderObject(int i)
Get render objects in the sorted list by index (only overlay objects)
Definition: IRenderer.cc:1230
VectorT< float, 2 > Vec2f
Definition: VectorT.hh:102
unsigned int indexOffset
Offset to first index in the index buffer or vertex buffer respectively.
unsigned int internalFlags_
may be used internally by the renderer
void resize(GLsizei _width, GLsizei _height, bool _forceResize=false)
resize function (if textures created by this class)
Definition: FBO.cc:550
void baseColor(const Vec4f &_c)
set the base color (Sets the baseColor which is the same as the emission(const Vec4f& _c) ) ...
bool hasTessEvaluationShader() const
check whether there is a tess-evaluation shader present
GLuint vertexBuffer
VBO, IBO ids, ignored if VAO is provided.
virtual void prepareRenderingPipeline(ACG::GLState *_glState, ACG::SceneGraph::DrawModes::DrawMode _drawMode, ACG::SceneGraph::BaseNode *_scenegraphRoot)
Prepares renderer and OpenGL for any draw-related calls including.
Definition: IRenderer.cc:532
int viewport_height() const
get viewport height
Definition: GLState.hh:824
GLuint vertexArrayObject
Use vertex array object.
void attachTexture2D(GLenum _attachment, GLsizei _width, GLsizei _height, GLuint _internalFmt, GLenum _format, GLint _wrapMode=GL_CLAMP_TO_EDGE, GLint _minFilter=GL_NEAREST, GLint _magFilter=GL_NEAREST)
function to attach a texture to fbo
Definition: FBO.cc:207
void unbind()
unbind fbo, go to normal rendering mode
Definition: FBO.cc:481
const QStringList & getTessEvaluationShaderCode()
Returns generated tessellation control shader code.
virtual void restoreFbo(GLint _fboId, const GLint *_outViewport, GLint _drawBuffer) const
Restore a previously saved input Fbo configuration (fbo id + viewport)
Definition: IRenderer.cc:797
const QStringList & getTessControlShaderCode()
Returns generated vertex shader code.
virtual void addRenderObject(RenderObject *_renderObject)
Callback for the scenegraph nodes, which send new render objects via this function.
Definition: IRenderer.cc:104
GLenum alphaFunc
GL_LESS, GL_LEQUAL, GL_GREATER ..
unsigned int numIndices
Number indices to render.
ACG::RenderObject * getRenderObject(int i)
Get render objects in the sorted list by index (not including overlay objects)
Definition: IRenderer.cc:1222
void setUniformMat3(const char *_name, const ACG::GLMatrixf &_value, bool _transposed=false)
Set 3x3fMatrix uniform to specified value.
Definition: GLSLShader.cc:663
Definition: FBO.hh:71
const GLMatrixd & modelview() const
get modelview matrix
Definition: GLState.hh:791
void glCheckErrors()
Definition: GLError.hh:96
virtual void finishRenderingPipeline(bool _drawOverlay=true)
Draw overlay objects and reset OpenGL state.
Definition: IRenderer.cc:667
ACG::RenderObject * getLineGL42RenderObject(int i)
Get render objects in the sorted list by index (only line objects rendered with gl4.2)
Definition: IRenderer.cc:1250
ACG::SceneGraph::BaseNode * getRenderObjectNode(int i)
Get node that emitted the render object in the sorted list by index (not including overlay objects) ...
Definition: IRenderer.cc:1239
const QStringList & getVertexShaderCode()
Returns generated vertex shader code.
ShaderGenDesc shaderDesc
Drawmode and other shader params.
static void draw(GLSL::Program *_prog=0)
Draw the screen quad.
Definition: ScreenQuad.cc:138
std::string name
Name for logging.
GLuint indexBuffer
Use vertex array object.
const QStringList & getFragmentShaderCode()
Returns generated fragment shader code.
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:1076
Texture to be used.
GLenum indexType
Index element type.
ACG::SceneGraph::Material & material()
Get material object reference.
virtual void copyDepthToBackBuffer(GLuint _depthTex, float _scale=1.0f)
Copy texture to depth buffer.
Definition: IRenderer.cc:1348
virtual void saveActiveFbo(GLint *_outFboId, GLint *_outViewport, GLint *_outDrawBuffer) const
Save active Fbo configuration (fbo id + viewport)
Definition: IRenderer.cc:789
virtual void restoreInputFbo()
Restore the previously saved input Fbo configuration (fbo id + viewport)
Definition: IRenderer.cc:783
QString toString() const
convert ShaderGenDesc to string format for debugging
const VertexElement * findElementByUsage(VERTEX_USAGE _usage) const
virtual void saveInputFbo()
Save input Fbo configuration (fbo id + viewport)
Definition: IRenderer.cc:776
QString toString() const
void setErrorDetectionLevel(int _level)
Control error detection for checking render objects.
Definition: IRenderer.cc:1700
bool isDefaultPointObject() const
Test if the object is rendered with one of the default point extension methods.
virtual void bindObjectVBO(ACG::RenderObject *_obj, GLSL::Program *_prog)
Binding VBOs (First state function)
Definition: IRenderer.cc:876
const void * sysmemIndexBuffer
Use system memory index buffer.
virtual void renderObject(ACG::RenderObject *_obj, GLSL::Program *_prog=0, bool _constRenderStates=false, const std::vector< unsigned int > *_shaderModifiers=0)
Render one renderobject.
Definition: IRenderer.cc:1140
GLenum blendDest
glBlendFunc: GL_SRC_ALPHA, GL_ZERO, GL_ONE, GL_ONE_MINUS_SRC_ALPHA ...
void shininess(float _s)
set shininess
const QStringList & getGeometryShaderCode()
Returns generated tessellation evaluation shader code.
std::vector< BaseNode * >::iterator ChildIter
allows to iterate over children
Definition: BaseNode.hh:286
const VertexDeclaration * vertexDecl
Defines the vertex buffer layout, ignored if VAO is provided.
void setUniform(const char *_name, GLint _value)
Set int uniform to specified value.
Definition: GLSLShader.cc:385
void bind(PtrProgram _prog) const
Send all stored uniforms to program.
Definition: UniformPool.cc:116
void dumpRenderObjectsToFile(const char *_fileName, ACG::RenderObject **_sortedList=0) const
Debugging function to dump list of render objects into a file.
Definition: IRenderer.cc:1264
void use()
Enables the program object for using.
Definition: GLSLShader.cc:345
Scalar max() const
return the maximal component
Definition: Vector11T.hh:493
StatusMode status() const
Get node&#39;s status.
Definition: BaseNode.hh:401
bool openGLVersion(const int _major, const int _minor, bool _verbose)
Definition: gl.cc:129