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
69 int IRenderer::maxClipDistances_ = -1;
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
104 void IRenderer::addRenderObject(ACG::RenderObject* _renderObject)
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
242 if (!_renderObject->vertexDecl->findElementByUsage(VERTEX_USAGE_TEXCOORD))
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
331 GLSL::Program* shaderProg = ACG::ShaderCache::getInstance()->getProgram(&p->shaderDesc);
332 #endif
333
334
335 // check primitive type and geometry shader
336 if (errorDetectionLevel_ > 1 && p->shaderDesc.geometryTemplateFile.length())
337 {
338 #ifdef GL_VERSION_3_2
339 GLint geomInputType = 0;
340 glGetProgramiv(shaderProg->getProgramId(), GL_GEOMETRY_INPUT_TYPE, &geomInputType);
341
342
343 if (geomInputType != GLint(p->primitiveMode))
344 {
345
346 switch (geomInputType)
347 {
348 case GL_POINTS: std::cout << "warning: primitive mode is incompatible with points-geometryshader in renderobject: " << _renderObject->debugName << std::endl; break;
349
350 case GL_LINES:
351 {
352 if (p->primitiveMode != GL_LINE_STRIP && p->primitiveMode != GL_LINE_LOOP)
353 std::cout << "warning: primitive mode is incompatible with lines-geometryshader in renderobject: " << _renderObject->debugName << std::endl;
354 } break;
355
356 case GL_LINES_ADJACENCY:
357 {
358 if (p->primitiveMode != GL_LINE_STRIP_ADJACENCY)
359 std::cout << "warning: primitive mode is incompatible with lines_adjacency-geometryshader in renderobject: " << _renderObject->debugName << std::endl;
360 } break;
361
362 case GL_TRIANGLES:
363 {
364 if (p->primitiveMode != GL_TRIANGLE_STRIP && p->primitiveMode != GL_TRIANGLE_FAN)
365 std::cout << "warning: primitive mode is incompatible with triangles-geometryshader in renderobject: " << _renderObject->debugName << std::endl;
366 } break;
367
368 case GL_TRIANGLES_ADJACENCY:
369 {
370 if (p->primitiveMode != GL_TRIANGLE_STRIP_ADJACENCY)
371 std::cout << "warning: primitive mode is incompatible with triangles_adjacency-geometryshader in renderobject: " << _renderObject->debugName << std::endl;
372 } break;
373
374 default: std::cout << "warning: unknown input_type for geometryshader in renderobject: " << _renderObject->debugName << std::endl;
375 }
376
377
378
379 }
380
381
382 #else
383 if (_renderObject->isDefaultLineObject())
384 {
385 if (_renderObject->primitiveMode != GL_LINES && _renderObject->primitiveMode != GL_LINE_STRIP && _renderObject->primitiveMode != GL_LINE_LOOP)
386 std::cout << "warning: primitive mode is incompatible with lines-geometryshader in renderobject: " << _renderObject->debugName << std::endl;
387 }
388 else if (_renderObject->isDefaultPointObject())
389 {
390 if (_renderObject->primitiveMode != GL_POINTS)
391 std::cout << "warning: primitive mode is incompatible with points-geometryshader in renderobject: " << _renderObject->debugName << std::endl;
392 }
393 #endif
394 }
395
396 }
397 }
398
399
400
401
402 void IRenderer::collectRenderObjects( ACG::GLState* _glState, ACG::SceneGraph::DrawModes::DrawMode _drawMode, ACG::SceneGraph::BaseNode* _sceneGraphRoot )
403 {
404 // collect light sources
405 // collectLightNodes(_sceneGraphRoot);
406 numLights_ = 0; // reset light counter
407
408 // // flush render objects
409 // for (size_t i = 0; i < renderObjects_.size(); ++i)
410 // {
411 // renderObjects_[i].uniformPool_.clear();
412 // }
413 renderObjects_.clear();
414
415 if (!_sceneGraphRoot) return;
416
417 // default material needed
418 ACG::SceneGraph::Material defMat;
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
440 ACG::SceneGraph::BaseNode *node;
441 const ACG::SceneGraph::Material* material;
442 size_t subtree_index_start;
443 bool leave;
444 };
445 }
446
447 void IRenderer::traverseRenderableNodes( ACG::GLState* _glState, ACG::SceneGraph::DrawModes::DrawMode _drawMode, ACG::SceneGraph::BaseNode &_node, const ACG::SceneGraph::Material &_mat )
448 {
449 renderObjectSource_.clear();
450 overlayObjectSource_.clear();
451
452 if (_node.status() == ACG::SceneGraph::BaseNode::HideSubtree)
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();
463 if (nodeDM == ACG::SceneGraph::DrawModes::DEFAULT)
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
477 ACG::SceneGraph::MaterialNode* matNode =
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
493 for (ACG::SceneGraph::BaseNode::ChildIter
494 cIt = cur.node->childrenBegin(),
495 cEnd = cur.node->childrenEnd(); cIt != cEnd; ++cIt) {
496 if (((*cIt)->traverseMode() &
497 ACG::SceneGraph::BaseNode::SecondPass) &&
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
503 for (ACG::SceneGraph::BaseNode::ChildIter
504 cIt = cur.node->childrenBegin(),
505 cEnd = cur.node->childrenEnd(); cIt != cEnd; ++cIt) {
506 if ((~(*cIt)->traverseMode() &
507 ACG::SceneGraph::BaseNode::SecondPass) &&
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
532 void IRenderer::prepareRenderingPipeline(ACG::GLState* _glState, ACG::SceneGraph::DrawModes::DrawMode _drawMode, ACG::SceneGraph::BaseNode* _scenegraphRoot)
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
776 void IRenderer::saveInputFbo()
777 {
778 // save active fbo
779 saveActiveFbo(&prevFbo_, prevViewport_, &prevDrawBuffer_);
780 prevFboSaved_ = true;
781 }
782
783 void IRenderer::restoreInputFbo()
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
839 void IRenderer::sortRenderObjects()
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
876 void IRenderer::bindObjectVBO(ACG::RenderObject* _obj,
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
904 void IRenderer::bindObjectUniforms( ACG::RenderObject* _obj, GLSL::Program* _prog )
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
1018 void IRenderer::bindObjectRenderStates(ACG::RenderObject* _obj)
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
1083 void IRenderer::drawObject(ACG::RenderObject* _obj)
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
1140 void IRenderer::renderObject(ACG::RenderObject* _obj,
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
1167 ACG::glCheckErrors();
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
1198 void IRenderer::addRenderObjectModifier(RenderObjectModifier* _mod)
1199 {
1200 renderObjectModifiers_.push_back(_mod);
1201 }
1202
1203 void IRenderer::removeRenderObjectModifier(RenderObjectModifier* _mod)
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
1212 int IRenderer::getNumRenderObjects() const {
1213 return sortedObjects_.size();
1214 }
1215
1216 int IRenderer::getNumLights() const
1217 {
1218 return numLights_;
1219 }
1220
1221
1222 ACG::RenderObject* IRenderer::getRenderObject( int i )
1223 {
1224 if (sortedObjects_.empty())
1225 return &renderObjects_[i];
1226
1227 return sortedObjects_[i];
1228 }
1229
1230 ACG::RenderObject* IRenderer::getOverlayRenderObject( int i )
1231 {
1232 if (overlayObjects_.empty())
1233 return &renderObjects_[i];
1234
1235 return overlayObjects_[i];
1236 }
1237
1238
1239 ACG::SceneGraph::BaseNode* IRenderer::getRenderObjectNode( int i )
1240 {
1241 return renderObjectSource_[i];
1242 }
1243
1244 ACG::SceneGraph::BaseNode* IRenderer::getOverlayRenderObjectNode( int i )
1245 {
1246 return overlayObjectSource_[i];
1247 }
1248
1249
1250 ACG::RenderObject* IRenderer::getLineGL42RenderObject( int i )
1251 {
1252 if (lineGL42Objects_.empty())
1253 return 0;
1254
1255 return lineGL42Objects_[i];
1256 }
1257
1258 IRenderer::LightData* IRenderer::getLight( int i )
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
1426 void IRenderer::DepthMapPass::modifyFragmentEndCode(QStringList* _code)
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
1694 void IRenderer::setLineThicknessRenderingGL42( bool _enable )
1695 {
1696 if (Texture::supportsImageLoadStore() && Texture::supportsTextureBuffer())
1697 enableLineThicknessGL42_ = _enable;
1698 }
1699
1700 void IRenderer::setErrorDetectionLevel( int _level )
1701 {
1702 errorDetectionLevel_ = std::max(_level, 0); // clamp to [0,n]
1703 }
1704
1705 int IRenderer::getErrorDetectionLevel() const
1706 {
1707 return errorDetectionLevel_;
1708 }
1709
1710 } // namespace ACG end
1711
ACG::Matrix4x4T::invert
bool invert()
matrix inversion (returns true on success)
Definition: Matrix4x4T_impl.hh:291
ACG::ShaderCache::getInstance
static ShaderCache * getInstance()
Return instance of the ShaderCache singleton.
Definition: ShaderCache.cc:84
ACG::SceneGraph::BaseNode::HideChildren
Draw this node, but hide children.
Definition: BaseNode.hh:396
ACG::IRenderer::traverseRenderableNodes
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
ACG::ShaderProgGenerator::hasTessControlShader
bool hasTessControlShader() const
check whether there is a tess-control shader present
Definition: ShaderGenerator.cc:2497
ACG
Namespace providing different geometric functions concerning angles.
Definition: BaseObjectData.hh:68
ACG::RenderObject::proj
GLMatrixd proj
Projection transform.
Definition: RenderObject.hh:141
ACG::ShaderProgGenerator::registerModifier
static unsigned int registerModifier(ShaderModifier *_modifier)
Shader modifiers have to be registered before they can be used. They also must remain allocated for t...
Definition: ShaderGenerator.cc:2457
ACG::IRenderer::getNumLights
int getNumLights() const
Get the number of current light sources.
Definition: IRenderer.cc:1216
ACG::IRenderer::dumpCurrentRenderObjectsToString
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
ACG::IRenderer::setLineThicknessRenderingGL42
void setLineThicknessRenderingGL42(bool _enable)
Definition: IRenderer.cc:1694
ACG::ShaderCache::getProgram
GLSL::Program * getProgram(const ShaderGenDesc *_desc, const std::vector< unsigned int > &_mods)
Query a dynamically generated program from cache.
Definition: ShaderCache.cc:102
ACG::ShaderProgGenerator
Definition: ShaderGenerator.hh:1189
ACG::RenderObject::inZPrePass
bool inZPrePass
Specify whether this object should be rendered in a z-prepass.
Definition: RenderObject.hh:291
ACG::IRenderer::getErrorDetectionLevel
int getErrorDetectionLevel() const
Get error detection level.
Definition: IRenderer.cc:1705
ACG::FBO::addDepthBuffer
void addDepthBuffer(GLuint _width, GLuint _height)
function to add a depth renderbuffer to the fbo
Definition: FBO.cc:350
ACG::IRenderer::addRenderObjectModifier
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
ACG::SceneGraph::Material::ambientColor
void ambientColor(const Vec4f &_a)
set the ambient color.
Definition: MaterialNode.hh:175
ACG::IRenderer::getLight
LightData * getLight(int i)
Get light by index.
Definition: IRenderer.cc:1258
ACG::ShaderProgGenerator::hasGeometryShader
bool hasGeometryShader() const
check whether there is a geometry shader present
Definition: ShaderGenerator.cc:2492
ACG::SceneGraph::BaseNode::SecondPass
Draw node in second pass.
Definition: BaseNode.hh:445
ACG::IRenderer::removeRenderObjectModifier
virtual void removeRenderObjectModifier(RenderObjectModifier *_mod)
Callback for the scenegraph nodes, which removes a render object modifier from the renderer...
Definition: IRenderer.cc:1203
ACG::IRenderer::clearInputFbo
virtual void clearInputFbo(const ACG::Vec4f &_clearColor)
Clear input Fbo.
Definition: IRenderer.cc:804
ACG::IRenderer::maxClipDistances_
static int maxClipDistances_
max number of clip distance outputs in a vertex shader
Definition: IRenderer.hh:580
ACG::RenderObject::primitiveMode
GLenum primitiveMode
Primitive type.
Definition: RenderObject.hh:182
ACG::IRenderer::setViewerID
void setViewerID(int _viewerID)
Set currently active viewer id.
Definition: IRenderer.cc:1519
ACG::Vec3f
VectorT< float, 3 > Vec3f
Definition: VectorT.hh:119
ACG::RenderObject::depthMapUniformName
const char * depthMapUniformName
Uniform name of the depth map in the used shader.
Definition: RenderObject.hh:302
ACG::VertexDeclaration::deactivateShaderPipeline
void deactivateShaderPipeline(GLSL::Program *_prog) const
Definition: VertexDeclaration.cc:486
ACG::IRenderer::getOverlayRenderObjectNode
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
ACG::RenderObject::patchVertices
unsigned int patchVertices
patch size if primitiveMode is GL_PATCHES for rendering with tessellation shaders ...
Definition: RenderObject.hh:185
ACG::IRenderer::DepthMapPass::modifyFragmentEndCode
void modifyFragmentEndCode(QStringList *_code)
Append code the the fragment shader.
Definition: IRenderer.cc:1426
ACG::IRenderer::bindObjectUniforms
virtual void bindObjectUniforms(ACG::RenderObject *_obj, GLSL::Program *_prog)
Binding Uniforms (Second state function)
Definition: IRenderer.cc:904
ACG::IRenderer::collectRenderObjects
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
ACG::GLState::viewport_width
int viewport_width() const
get viewport width
Definition: GLState.hh:822
ACG::IRenderer::addLight
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
ACG::RenderObject::modelview
GLMatrixd modelview
Modelview transform.
Definition: RenderObject.hh:138
ACG::SceneGraph::BaseNode::HideNode
Hide this node, but draw children.
Definition: BaseNode.hh:394
ACG::SceneGraph::Material::specularColor
void specularColor(const Vec4f &_s)
set the specular color
Definition: MaterialNode.hh:185
OpenMesh::VectorT::normalize
auto normalize() -> decltype(*this/=std::declval< VectorT< S, DIM >>().norm())
Definition: Vector11T.hh:429
GLSL::UniformPool::empty
bool empty() const
returns if the pool is empty
Definition: UniformPool.cc:95
GLSL::Program::getProgramId
GLuint getProgramId()
Returns opengl id.
Definition: GLSLShader.cc:376
ACG::SceneGraph::BaseNode::HideSubtree
Hide this node and its children.
Definition: BaseNode.hh:398
OpenMesh::VectorT::data
Scalar * data()
access to Scalar array
Definition: Vector11T.hh:195
ACG::RenderObject::depthRange
Vec2f depthRange
glDepthRange: (znear, zmax)
Definition: RenderObject.hh:249
ACG::VERTEX_USAGE_COLOR
"inColor"
Definition: VertexDeclaration.hh:68
ACG::SceneGraph::Material::diffuseColor
void diffuseColor(const Vec4f &_d)
set the diffuse color.
Definition: MaterialNode.hh:180
ACG::SceneGraph::MaterialNode
Definition: MaterialNode.hh:338
ACG::RenderObject
Interface class between scenegraph and renderer.
Definition: RenderObject.hh:98
ACG::RenderObject::isDefaultLineObject
bool isDefaultLineObject() const
Test if the object is rendered with one of the default line thickness methods.
Definition: RenderObject.cc:472
ACG::RenderObject::diffuse
Vec3f diffuse
material definitions
Definition: RenderObject.hh:274
GLSL::Program
GLSL program class.
Definition: GLSLShader.hh:211
ACG::GLState::blendFunc
static void blendFunc(GLenum _sfactor, GLenum _dfactor)
replaces glBlendFunc, supports locking
Definition: GLState.hh:307
ACG::FBO::bind
bool bind()
bind the fbo and sets it as rendertarget
Definition: FBO.cc:458
ACG::Matrix4x4T::transpose
void transpose()
transpose matrix
Definition: Matrix4x4T_impl.hh:266
ACG::IRenderer::bindObjectRenderStates
virtual void bindObjectRenderStates(ACG::RenderObject *_obj)
Binding Render state (Third state function)
Definition: IRenderer.cc:1018
ACG::IRenderer::drawObject
virtual void drawObject(ACG::RenderObject *_obj)
Executes the opengl draw call for one object (Fourth function)
Definition: IRenderer.cc:1083
ACG::VertexDeclaration::activateShaderPipeline
void activateShaderPipeline(GLSL::Program *_prog) const
Definition: VertexDeclaration.cc:429
ACG::IRenderer::getNumRenderObjects
int getNumRenderObjects() const
Get the number of collected render objects (not including overlay objects or gl4.2 line objects) ...
Definition: IRenderer.cc:1212
ACG::SceneGraph::DrawModes::DEFAULT
DrawMode DEFAULT
use the default (global) draw mode and not the node&#39;s own.
Definition: DrawModes.cc:72
ACG::IRenderer::renderDepthMap
virtual void renderDepthMap(int _viewerID, int _width, int _height)
Render the depth map of the scene.
Definition: IRenderer.cc:1431
ACG::GLState
Definition: GLState.hh:213
ACG::Texture2D
Definition: globjects.hh:391
ACG::RenderObject::depthFunc
GLenum depthFunc
GL_LESS, GL_LEQUAL, GL_GREATER ..
Definition: RenderObject.hh:240
ACG::IRenderer::sortRenderObjects
virtual void sortRenderObjects()
Sort the renderobjects by priority.
Definition: IRenderer.cc:839
ACG::RenderObject::numInstances
GLsizei numInstances
Definition: RenderObject.hh:204
ACG::RenderObjectModifier
Interface for modifying render objects.
Definition: RenderObject.hh:540
ACG::IRenderer::getOverlayRenderObject
ACG::RenderObject * getOverlayRenderObject(int i)
Get render objects in the sorted list by index (only overlay objects)
Definition: IRenderer.cc:1230
ACG::Vec2f
VectorT< float, 2 > Vec2f
Definition: VectorT.hh:102
ACG::RenderObject::indexOffset
unsigned int indexOffset
Offset to first index in the index buffer or vertex buffer respectively.
Definition: RenderObject.hh:191
ACG::RenderObject::internalFlags_
unsigned int internalFlags_
may be used internally by the renderer
Definition: RenderObject.hh:364
ACG::FBO::resize
void resize(GLsizei _width, GLsizei _height, bool _forceResize=false)
resize function (if textures created by this class)
Definition: FBO.cc:550
ACG::SceneGraph::Material::baseColor
void baseColor(const Vec4f &_c)
set the base color (Sets the baseColor which is the same as the emission(const Vec4f& _c) ) ...
Definition: MaterialNode.hh:165
ACG::IRenderer::LightData
Definition: IRenderer.hh:104
ACG::ShaderProgGenerator::hasTessEvaluationShader
bool hasTessEvaluationShader() const
check whether there is a tess-evaluation shader present
Definition: ShaderGenerator.cc:2502
ACG::GLMatrixT< float >
ACG::TextureBuffer
Definition: globjects.hh:513
ACG::RenderObject::vertexBuffer
GLuint vertexBuffer
VBO, IBO ids, ignored if VAO is provided.
Definition: RenderObject.hh:162
ACG::IRenderer::prepareRenderingPipeline
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
ACG::GLState::viewport_height
int viewport_height() const
get viewport height
Definition: GLState.hh:824
ACG::RenderObject::vertexArrayObject
GLuint vertexArrayObject
Use vertex array object.
Definition: RenderObject.hh:158
ACG::FBO::attachTexture2D
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
ACG::FBO::unbind
void unbind()
unbind fbo, go to normal rendering mode
Definition: FBO.cc:481
ACG::ShaderProgGenerator::getTessEvaluationShaderCode
const QStringList & getTessEvaluationShaderCode()
Returns generated tessellation control shader code.
Definition: ShaderGenerator.cc:2249
ACG::IRenderer::restoreFbo
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
ACG::SceneGraph::DrawModes::DrawMode
Specifies a DrawMode.
Definition: DrawModes.hh:288
ACG::ShaderProgGenerator::getTessControlShaderCode
const QStringList & getTessControlShaderCode()
Returns generated vertex shader code.
Definition: ShaderGenerator.cc:2244
ACG::IRenderer::addRenderObject
virtual void addRenderObject(RenderObject *_renderObject)
Callback for the scenegraph nodes, which send new render objects via this function.
Definition: IRenderer.cc:104
ACG::SceneGraph::Material
Definition: MaterialNode.hh:79
ACG::IRenderer::DepthMapPass
Definition: IRenderer.hh:368
ACG::RenderObject::alphaFunc
GLenum alphaFunc
GL_LESS, GL_LEQUAL, GL_GREATER ..
Definition: RenderObject.hh:243
ACG::RenderObject::numIndices
unsigned int numIndices
Number indices to render.
Definition: RenderObject.hh:188
ACG::IRenderer::getRenderObject
ACG::RenderObject * getRenderObject(int i)
Get render objects in the sorted list by index (not including overlay objects)
Definition: IRenderer.cc:1222
GLSL::Program::setUniformMat3
void setUniformMat3(const char *_name, const ACG::GLMatrixf &_value, bool _transposed=false)
Set 3x3fMatrix uniform to specified value.
Definition: GLSLShader.cc:663
ACG::FBO
Definition: FBO.hh:71
ACG::GLState::modelview
const GLMatrixd & modelview() const
get modelview matrix
Definition: GLState.hh:791
ACG::glCheckErrors
void glCheckErrors()
Definition: GLError.hh:96
ACG::IRenderer::finishRenderingPipeline
virtual void finishRenderingPipeline(bool _drawOverlay=true)
Draw overlay objects and reset OpenGL state.
Definition: IRenderer.cc:667
ACG::IRenderer::getLineGL42RenderObject
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::IRenderer::getRenderObjectNode
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
ACG::ShaderProgGenerator::getVertexShaderCode
const QStringList & getVertexShaderCode()
Returns generated vertex shader code.
Definition: ShaderGenerator.cc:2239
ACG::RenderObject::shaderDesc
ShaderGenDesc shaderDesc
Drawmode and other shader params.
Definition: RenderObject.hh:225
ACG::ScreenQuad::draw
static void draw(GLSL::Program *_prog=0)
Draw the screen quad.
Definition: ScreenQuad.cc:138
ACG::SceneGraph::BaseNode
Definition: BaseNode.hh:104
ACG::RenderObject::name
std::string name
Name for logging.
Definition: RenderObject.hh:121
ACG::RenderObject::indexBuffer
GLuint indexBuffer
Use vertex array object.
Definition: RenderObject.hh:162
ACG::ShaderProgGenerator::getFragmentShaderCode
const QStringList & getFragmentShaderCode()
Returns generated fragment shader code.
Definition: ShaderGenerator.cc:2259
OpenMesh::VectorT
Definition: Vector11T.hh:83
GLSL::loadProgram
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
ACG::RenderObject::Texture
Texture to be used.
Definition: RenderObject.hh:313
ACG::RenderObject::indexType
GLenum indexType
Index element type.
Definition: RenderObject.hh:197
ACG::SceneGraph::MaterialNode::material
ACG::SceneGraph::Material & material()
Get material object reference.
Definition: MaterialNode.hh:575
ACG::IRenderer::copyDepthToBackBuffer
virtual void copyDepthToBackBuffer(GLuint _depthTex, float _scale=1.0f)
Copy texture to depth buffer.
Definition: IRenderer.cc:1348
ACG::IRenderer::saveActiveFbo
virtual void saveActiveFbo(GLint *_outFboId, GLint *_outViewport, GLint *_outDrawBuffer) const
Save active Fbo configuration (fbo id + viewport)
Definition: IRenderer.cc:789
ACG::IRenderer::restoreInputFbo
virtual void restoreInputFbo()
Restore the previously saved input Fbo configuration (fbo id + viewport)
Definition: IRenderer.cc:783
ACG::ShaderGenDesc::toString
QString toString() const
convert ShaderGenDesc to string format for debugging
Definition: ShaderGenerator.cc:2733
ACG::VertexDeclaration::findElementByUsage
const VertexElement * findElementByUsage(VERTEX_USAGE _usage) const
Definition: VertexDeclaration.cc:534
ACG::IRenderer::saveInputFbo
virtual void saveInputFbo()
Save input Fbo configuration (fbo id + viewport)
Definition: IRenderer.cc:776
ACG::RenderObject::toString
QString toString() const
Definition: RenderObject.cc:239
ACG::VERTEX_USAGE_NORMAL
"inNormal"
Definition: VertexDeclaration.hh:66
ACG::IRenderer::setErrorDetectionLevel
void setErrorDetectionLevel(int _level)
Control error detection for checking render objects.
Definition: IRenderer.cc:1700
ACG::RenderObject::isDefaultPointObject
bool isDefaultPointObject() const
Test if the object is rendered with one of the default point extension methods.
Definition: RenderObject.cc:493
ACG::IRenderer::bindObjectVBO
virtual void bindObjectVBO(ACG::RenderObject *_obj, GLSL::Program *_prog)
Binding VBOs (First state function)
Definition: IRenderer.cc:876
ACG::RenderObject::sysmemIndexBuffer
const void * sysmemIndexBuffer
Use system memory index buffer.
Definition: RenderObject.hh:173
ACG::IRenderer::renderObject
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
ACG::RenderObject::blendDest
GLenum blendDest
glBlendFunc: GL_SRC_ALPHA, GL_ZERO, GL_ONE, GL_ONE_MINUS_SRC_ALPHA ...
Definition: RenderObject.hh:247
ACG::SceneGraph::Material::shininess
void shininess(float _s)
set shininess
Definition: MaterialNode.hh:204
ACG::ShaderProgGenerator::getGeometryShaderCode
const QStringList & getGeometryShaderCode()
Returns generated tessellation evaluation shader code.
Definition: ShaderGenerator.cc:2254
ACG::SceneGraph::BaseNode::ChildIter
std::vector< BaseNode * >::iterator ChildIter
allows to iterate over children
Definition: BaseNode.hh:286
ACG::RenderObject::vertexDecl
const VertexDeclaration * vertexDecl
Defines the vertex buffer layout, ignored if VAO is provided.
Definition: RenderObject.hh:208
GLSL::Program::setUniform
void setUniform(const char *_name, GLint _value)
Set int uniform to specified value.
Definition: GLSLShader.cc:385
GLSL::UniformPool::bind
void bind(PtrProgram _prog) const
Send all stored uniforms to program.
Definition: UniformPool.cc:116
ACG::IRenderer::RenderObjectRange
Definition: IRenderer.hh:120
ACG::IRenderer::dumpRenderObjectsToFile
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
GLSL::Program::use
void use()
Enables the program object for using.
Definition: GLSLShader.cc:345
ACG::VERTEX_USAGE_TEXCOORD
"inTexCoord"
Definition: VertexDeclaration.hh:67
OpenMesh::VectorT::max
Scalar max() const
return the maximal component
Definition: Vector11T.hh:493
ACG::SceneGraph::BaseNode::status
StatusMode status() const
Get node&#39;s status.
Definition: BaseNode.hh:401
ACG::openGLVersion
bool openGLVersion(const int _major, const int _minor, bool _verbose)
Definition: gl.cc:129