44 #include <ACG/GL/acg_glew.hh> 50 #include <QTextStream> 52 #include <ACG/GL/gl.hh> 54 #include <ACG/GL/IRenderer.hh> 56 #include <ACG/GL/VertexDeclaration.hh> 57 #include <ACG/GL/GLError.hh> 59 #include <ACG/GL/ShaderCache.hh> 60 #include <ACG/GL/ScreenQuad.hh> 61 #include <ACG/GL/FBO.hh> 62 #include <ACG/GL/globjects.hh> 71 IRenderer::IRenderer()
77 prevDrawBuffer_(GL_BACK),
81 errorDetectionLevel_(1),
83 enableLineThicknessGL42_(false)
91 globalLightModelAmbient_ =
ACG::Vec3f(0.2f, 0.2f, 0.2f);
95 IRenderer::~IRenderer()
97 delete depthCopyShader_;
100 for (std::map<int, ACG::FBO*>::iterator it = depthMaps_.begin(); it != depthMaps_.end(); ++it)
107 if (_renderObject->debugName.empty())
108 _renderObject->debugName =
"<unnamed>";
110 if (_renderObject->
name.empty())
111 _renderObject->
name = _renderObject->debugName;
115 std::cout <<
"error: missing vertex declaration in renderobject: " << _renderObject->debugName << std::endl;
118 if (errorDetectionLevel_ > 0)
123 std::cout <<
"warning: numIndices is 0 in renderobject: " << _renderObject->debugName << std::endl;
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;
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;
137 if (errorDetectionLevel_ > 1 && _renderObject->
shaderDesc.shadeMode == SG_SHADE_UNLIT)
139 if (_renderObject->emissive.
max() < 1e-3f)
140 std::cout <<
"warning: unlit object rendered with black emissive color: " << _renderObject->debugName << std::endl;
146 glGetFloatv(GL_COLOR_CLEAR_VALUE, clearColor);
148 if (checkEpsilon(clearColor[0] - _renderObject->emissive[0]) &&
149 checkEpsilon(clearColor[1] - _renderObject->emissive[1]) &&
150 checkEpsilon(clearColor[2] - _renderObject->emissive[2]))
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;
158 if (_renderObject->textures().size())
164 for (std::map<size_t,RenderObject::Texture>::const_iterator it = _renderObject->textures().begin();
165 it != _renderObject->textures().end(); ++it)
167 if (it->second.type == GL_TEXTURE_BUFFER)
170 glBindTexture(it->second.type, it->second.id);
172 GLint minFilter = GL_NONE;
173 glGetTexParameteriv(it->second.type, GL_TEXTURE_MIN_FILTER, &minFilter);
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)
181 glGetTexParameteriv(it->second.type, GL_TEXTURE_MAX_LEVEL, &maxLevel);
184 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &texWidth);
187 for (GLint lod = 0; lod < maxLevel && maxLod < 0; ++lod)
190 glGetTexLevelParameteriv(GL_TEXTURE_2D, lod, GL_TEXTURE_WIDTH, &lodWidth);
192 if (lodWidth <= 0 || lodWidth == GL_INVALID_VALUE)
196 if (maxLod <= 0 && texWidth > 1)
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;
201 GLint correctedFilter = GL_LINEAR;
203 if (minFilter == GL_NEAREST_MIPMAP_LINEAR ||
204 minFilter == GL_LINEAR_MIPMAP_LINEAR)
205 correctedFilter = GL_LINEAR;
207 correctedFilter = GL_NEAREST;
209 glTexParameteri(it->second.type, GL_TEXTURE_MIN_FILTER, correctedFilter);
216 if (errorDetectionLevel_ > 1)
221 if (_renderObject->depthWrite && !_renderObject->depthTest)
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;
231 if (_renderObject->
shaderDesc.shadeMode != SG_SHADE_UNLIT)
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;
243 std::cout <<
"warning: missing texcoords for textured mode in renderobject: " << _renderObject->debugName << std::endl;
250 std::cout <<
"warning: missing colors for vertexcolor mode in renderobject: " << _renderObject->debugName << std::endl;
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;
260 #ifdef GL_ARB_tessellation_shader 262 const bool tessellationActive = !_renderObject->
shaderDesc.tessControlTemplateFile.isEmpty() || !_renderObject->
shaderDesc.tessEvaluationTemplateFile.isEmpty();
263 bool tryToFixPatchInfo =
false;
264 if (tessellationActive && _renderObject->
primitiveMode != GL_PATCHES)
266 std::cout <<
"error: tessellation shaders are not used with GL_PATCHES primitiveType in renderobject: " << _renderObject->debugName << std::endl;
267 tryToFixPatchInfo =
true;
272 std::cout <<
"error: undefined patch size for tessellation in renderobject: " << _renderObject->debugName << std::endl;
273 tryToFixPatchInfo =
true;
276 if (tryToFixPatchInfo)
282 std::cout <<
"warning: attempting to draw with patchVertices = 1 for tessellation in renderobject: " << _renderObject->debugName << std::endl;
288 std::cout <<
"warning: attempting to draw with patchVertices = 2 for tessellation in renderobject: " << _renderObject->debugName << std::endl;
294 std::cout <<
"warning: attempting to draw with patchVertices = 3 for tessellation in renderobject: " << _renderObject->debugName << std::endl;
300 std::cout <<
"warning: attempting to draw with patchVertices = 4 for tessellation in renderobject: " << _renderObject->debugName << std::endl;
308 renderObjects_.push_back(*_renderObject);
314 size_t numMods = renderObjectModifiers_.size();
315 for (
size_t i = 0; i < numMods; ++i)
317 if (renderObjectModifiers_[i])
318 renderObjectModifiers_[i]->apply(p);
330 #ifdef GL_VERSION_3_2 336 if (errorDetectionLevel_ > 1 && p->
shaderDesc.geometryTemplateFile.length())
338 #ifdef GL_VERSION_3_2 339 GLint geomInputType = 0;
340 glGetProgramiv(shaderProg->
getProgramId(), GL_GEOMETRY_INPUT_TYPE, &geomInputType);
346 switch (geomInputType)
348 case GL_POINTS: std::cout <<
"warning: primitive mode is incompatible with points-geometryshader in renderobject: " << _renderObject->debugName << std::endl;
break;
353 std::cout <<
"warning: primitive mode is incompatible with lines-geometryshader in renderobject: " << _renderObject->debugName << std::endl;
356 case GL_LINES_ADJACENCY:
359 std::cout <<
"warning: primitive mode is incompatible with lines_adjacency-geometryshader in renderobject: " << _renderObject->debugName << std::endl;
365 std::cout <<
"warning: primitive mode is incompatible with triangles-geometryshader in renderobject: " << _renderObject->debugName << std::endl;
368 case GL_TRIANGLES_ADJACENCY:
371 std::cout <<
"warning: primitive mode is incompatible with triangles_adjacency-geometryshader in renderobject: " << _renderObject->debugName << std::endl;
374 default: std::cout <<
"warning: unknown input_type for geometryshader in renderobject: " << _renderObject->debugName << std::endl;
386 std::cout <<
"warning: primitive mode is incompatible with lines-geometryshader in renderobject: " << _renderObject->debugName << std::endl;
391 std::cout <<
"warning: primitive mode is incompatible with points-geometryshader in renderobject: " << _renderObject->debugName << std::endl;
413 renderObjects_.clear();
415 if (!_sceneGraphRoot)
return;
427 traverseRenderableNodes(_glState, _drawMode, *_sceneGraphRoot, defMat);
433 class ScenegraphTraversalStackEl {
437 node(_node), material(_material),
438 subtree_index_start(0), leave(
false) {}
442 size_t subtree_index_start;
449 renderObjectSource_.clear();
450 overlayObjectSource_.clear();
455 std::vector<ScenegraphTraversalStackEl> stack;
458 stack.push_back(ScenegraphTraversalStackEl(&_node, &_mat));
459 while (!stack.empty()) {
460 ScenegraphTraversalStackEl &cur = stack.back();
461 auto cur_idx = stack.size() - 1;
471 cur.node->enter(
this, *_glState, nodeDM);
473 cur.subtree_index_start = renderObjects_.size();
480 cur.material = &matNode->
material();
483 cur.node->getRenderObjects(
this, *_glState, nodeDM, cur.material);
486 size_t numAddedObjects = renderObjects_.size() - renderObjectSource_.size();
487 renderObjectSource_.insert(renderObjectSource_.end(), numAddedObjects, cur.node);
489 auto cur_mat = cur.material;
494 cIt = cur.node->childrenBegin(),
495 cEnd = cur.node->childrenEnd(); cIt != cEnd; ++cIt) {
496 if (((*cIt)->traverseMode() &
499 stack.emplace_back(*cIt, cur_mat);
504 cIt = cur.node->childrenBegin(),
505 cEnd = cur.node->childrenEnd(); cIt != cEnd; ++cIt) {
506 if ((~(*cIt)->traverseMode() &
509 stack.emplace_back(*cIt, cur_mat);
515 stack[cur_idx].leave =
true;
522 renderObjects_.begin() + cur.subtree_index_start,
523 renderObjects_.end());
526 cur.node->leave(
this, *_glState, nodeDM);
535 #ifdef GL_ARB_vertex_array_object 536 glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &prevVAO_);
539 coreProfile_ = !_glState->compatibilityProfile();
543 camPosWS_ =
Vec3f( viewMatrix_(0,3), viewMatrix_(1,3), viewMatrix_(2,3) );
544 camDirWS_ =
Vec3f( viewMatrix_(0,2), viewMatrix_(1,2), -viewMatrix_(2,2) );
550 collectRenderObjects(_glState, _drawMode, _scenegraphRoot);
557 size_t numRenderObjects = 0,
558 numOverlayObjects = 0,
561 for (std::vector<ACG::RenderObject>::const_iterator it = renderObjects_.begin();
562 it != renderObjects_.end(); ++it) {
563 if (!it->overlay && !(it->isDefaultLineObject() && enableLineThicknessGL42_))
567 if (enableLineThicknessGL42_ && it->isDefaultLineObject())
576 sortedObjects_.clear();
577 sortedObjects_.reserve(numRenderObjects);
579 overlayObjects_.clear();
580 overlayObjects_.reserve(numOverlayObjects);
582 lineGL42Objects_.clear();
583 lineGL42Objects_.reserve(numLineObjects);
586 sortListObjects_.clear();
587 sortListObjects_.reserve(numRenderObjects);
589 sortListOverlays_.clear();
590 sortListOverlays_.reserve(numOverlayObjects);
593 for (
size_t i = 0; i < renderObjects_.size(); ++i)
595 if (renderObjects_[i].overlay)
597 overlayObjects_.push_back(&renderObjects_[i]);
598 sortListOverlays_.push_back(i);
600 else if (enableLineThicknessGL42_ && numLineObjects && renderObjects_[i].isDefaultLineObject())
602 renderObjects_[i].shaderDesc.geometryTemplateFile =
"Wireframe/gl42/geometry.tpl";
603 renderObjects_[i].shaderDesc.fragmentTemplateFile =
"Wireframe/gl42/fragment.tpl";
606 renderObjects_[i].glColorMask(0,0,0,0);
609 lineGL42Objects_.push_back(&renderObjects_[i]);
613 sortedObjects_.push_back(&renderObjects_[i]);
614 sortListObjects_.push_back(i);
626 if (_glState->compatibilityProfile())
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);
635 glEnable(GL_CULL_FACE);
636 glEnable(GL_DEPTH_TEST);
637 glDepthFunc(GL_LESS);
638 glDepthMask(GL_TRUE);
643 if(_glState->compatibilityProfile())
646 GLfloat lightModelAmbient[4];
647 glGetFloatv(GL_LIGHT_MODEL_AMBIENT, lightModelAmbient);
648 globalLightModelAmbient_ =
ACG::Vec3f(lightModelAmbient[0], lightModelAmbient[1], lightModelAmbient[2]);
652 bool requiresSceneDepths =
false;
654 for (
size_t i = 0; i < renderObjects_.size(); ++i)
656 if (renderObjects_[i].depthMapUniformName)
657 requiresSceneDepths =
true;
661 if (requiresSceneDepths)
669 #ifdef GL_ARB_vertex_array_object 670 glBindVertexArray(prevVAO_);
674 if (enableLineThicknessGL42_)
675 renderLineThicknessGL42();
679 const int numOverlayObj = overlayObjects_.size();
685 for (
int i = 0; i < numOverlayObj; ++i)
689 if (obj->depthTest && obj->
depthFunc != GL_ALWAYS)
691 float depthMax = 1.0f;
698 bool depthWrite = obj->depthWrite;
703 obj->depthWrite =
true;
710 obj->depthWrite = depthWrite;
717 for (
int i = 0; i < numOverlayObj; ++i)
725 #ifdef GL_ARB_vertex_array_object 726 glBindVertexArray(prevVAO_);
729 for (
int i = 0; i < maxClipDistances_; ++i)
730 glDisable(GL_CLIP_DISTANCE0 + i);
732 glDisable(GL_PROGRAM_POINT_SIZE);
735 glColorMask(1,1,1,1);
739 glBindBuffer(GL_ARRAY_BUFFER, 0);
740 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
747 GLint curViewport[4];
749 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &curFbo);
750 glGetIntegerv(GL_VIEWPORT, curViewport);
751 glGetIntegerv(GL_DRAW_BUFFER, &curDrawBuf);
753 if (curFbo != prevFbo_)
755 std::cout <<
"warning: input and output fbo are not the same in renderer implementation" << std::endl;
759 if (curDrawBuf != prevDrawBuffer_)
761 std::cout <<
"warning: input and output draw-buffer are not the same in renderer implementation" << std::endl;
765 if (curViewport[0] != prevViewport_[0] ||
766 curViewport[1] != prevViewport_[1] ||
767 curViewport[2] != prevViewport_[2] ||
768 curViewport[3] != prevViewport_[3])
770 std::cout <<
"warning: input and output viewport are not the same in renderer implementation" << std::endl;
779 saveActiveFbo(&prevFbo_, prevViewport_, &prevDrawBuffer_);
780 prevFboSaved_ =
true;
786 restoreFbo(prevFbo_, prevViewport_, prevDrawBuffer_);
792 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, _outFboId);
793 glGetIntegerv(GL_VIEWPORT, _outViewport);
794 glGetIntegerv(GL_DRAW_BUFFER, _outDrawBuffer);
799 glBindFramebuffer(GL_FRAMEBUFFER, _fboId);
800 glDrawBuffer(_drawBuffer);
801 glViewport(_outViewport[0], _outViewport[1], _outViewport[2], _outViewport[3]);
806 glClearColor(clearColor[0], clearColor[1], clearColor[2], 1.0f);
812 GLint oldViewport[4];
813 glGetIntegerv(GL_VIEWPORT, oldViewport);
814 glScissor(oldViewport[0], oldViewport[1], oldViewport[2], oldViewport[3]);
817 glScissor(prevViewport_[0], prevViewport_[1], prevViewport_[2], prevViewport_[3]);
819 glEnable(GL_SCISSOR_TEST);
820 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
823 glDisable(GL_SCISSOR_TEST);
827 struct RenderObjectComparator {
828 explicit RenderObjectComparator(
const std::vector<ACG::RenderObject>& _vec) : vec_(_vec) {
831 bool operator() (
int a,
int b) {
832 return (vec_[a].priority < vec_[b].priority);
835 const std::vector<ACG::RenderObject>& vec_;
841 size_t numObjs = sortListObjects_.size();
842 size_t numOverlays = sortListOverlays_.size();
844 RenderObjectComparator cmpOp(renderObjects_);
846 std::sort(sortListObjects_.begin(), sortListObjects_.end(), cmpOp);
847 std::sort(sortListOverlays_.begin(), sortListOverlays_.end(), cmpOp);
850 std::vector<ACG::SceneGraph::BaseNode*> temp;
851 renderObjectSource_.swap(temp);
854 renderObjectSource_.resize(numObjs, 0);
855 overlayObjectSource_.resize(numOverlays, 0);
857 for (
size_t i = 0; i < numObjs; ++i)
859 int objID = sortListObjects_[i];
860 sortedObjects_[i] = &renderObjects_[objID];
862 renderObjectSource_[i] = temp[objID];
865 for (
size_t i = 0; i < numOverlays; ++i)
867 int objID = sortListOverlays_[i];
868 overlayObjects_[i] = &renderObjects_[objID];
870 overlayObjectSource_[i] = temp[objID];
882 #ifdef GL_ARB_vertex_array_object 894 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _obj->
indexBuffer);
922 _prog->
setUniform(
"g_cEmissive", _obj->emissive);
925 _prog->
setUniform(
"g_cAmbient", _obj->ambient);
926 _prog->
setUniform(
"g_cSpecular", _obj->specular);
929 float alphaRef = 0.f;
930 if (_obj->alphaTest && _obj->
alphaFunc == GL_GREATER) {
931 alphaRef = _obj->alphaRef;
933 ACG::Vec4f materialParams(_obj->shininess, _obj->alpha, alphaRef, 0.0f);
934 _prog->
setUniform(
"g_vMaterial", materialParams);
936 _prog->
setUniform(
"g_cLightModelAmbient", globalLightModelAmbient_);
939 if ( !_obj->uniformPool_.
empty() )
940 _obj->uniformPool_.
bind(_prog);
948 int maxTextureStage = 0;
949 for (std::map<size_t,RenderObject::Texture>::const_iterator iter = _obj->textures().begin();
950 iter != _obj->textures().end();++iter)
953 const size_t texture_stage = iter->first;
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);
962 maxTextureStage = std::max(maxTextureStage, (
int)texture_stage);
970 int depthMapSlot = maxTextureStage + 1;
973 glActiveTexture(GL_TEXTURE0 + depthMapSlot);
974 glBindTexture(GL_TEXTURE_2D, depthMaps_[curViewerID_]->getAttachment(GL_COLOR_ATTACHMENT0));
979 for (
int i = 0; i < numLights_; ++i)
983 char szUniformName[256];
985 sprintf(szUniformName,
"g_cLightDiffuse_%d", i);
986 _prog->
setUniform(szUniformName, lgt->diffuse);
988 sprintf(szUniformName,
"g_cLightAmbient_%d", i);
989 _prog->
setUniform(szUniformName, lgt->ambient);
991 sprintf(szUniformName,
"g_cLightSpecular_%d", i);
992 _prog->
setUniform(szUniformName, lgt->specular);
995 if (lgt->ltype == ACG::SG_LIGHT_POINT || lgt->ltype == ACG::SG_LIGHT_SPOT)
997 sprintf(szUniformName,
"g_vLightPos_%d", i);
1000 sprintf(szUniformName,
"g_vLightAtten_%d", i);
1001 _prog->
setUniform(szUniformName, lgt->atten);
1004 if (lgt->ltype == ACG::SG_LIGHT_DIRECTIONAL || lgt->ltype == ACG::SG_LIGHT_SPOT)
1006 sprintf(szUniformName,
"g_vLightDir_%d", i);
1010 if (lgt->ltype == ACG::SG_LIGHT_SPOT)
1012 sprintf(szUniformName,
"g_vLightAngleExp_%d", i);
1013 _prog->
setUniform(szUniformName, lgt->spotCutoffExponent);
1021 glEnable(GL_CULL_FACE);
1023 glDisable(GL_CULL_FACE);
1028 glDisable(GL_BLEND);
1032 if (_obj->alphaTest)
1034 glEnable(GL_ALPHA_TEST);
1035 glAlphaFunc(_obj->
alphaFunc, _obj->alphaRef);
1038 glDisable(GL_ALPHA_TEST);
1041 if (_obj->depthTest)
1042 glEnable(GL_DEPTH_TEST);
1044 glDisable(GL_DEPTH_TEST);
1047 glDepthMask(_obj->depthWrite ? GL_TRUE : GL_FALSE);
1049 glColorMask(_obj->colorWriteMask[0], _obj->colorWriteMask[1], _obj->colorWriteMask[2], _obj->colorWriteMask[3]);
1059 if (maxClipDistances_ < 0)
1061 glGetIntegerv(GL_MAX_CLIP_DISTANCES, &maxClipDistances_);
1062 maxClipDistances_ = std::min(maxClipDistances_, 32);
1065 for (
int i = 0; i < maxClipDistances_; ++i)
1067 if (_obj->clipDistanceMask & (1 << i))
1068 glEnable(GL_CLIP_DISTANCE0 + i);
1070 glDisable(GL_CLIP_DISTANCE0 + i);
1073 #ifdef GL_PROGRAM_POINT_SIZE 1074 if (_obj->programPointSize)
1075 glEnable(GL_PROGRAM_POINT_SIZE);
1077 glDisable(GL_PROGRAM_POINT_SIZE);
1080 glPointSize(_obj->pointSize);
1088 bool noIndices =
true;
1092 glPolygonMode(GL_FRONT_AND_BACK, _obj->fillMode);
1095 bool tessellationActive = !(_obj->
shaderDesc.tessControlTemplateFile.isEmpty() && _obj->
shaderDesc.tessEvaluationTemplateFile.isEmpty());
1096 #ifdef GL_ARB_tessellation_shader 1097 if (tessellationActive)
1101 if (_obj->
shaderDesc.tessControlTemplateFile.isEmpty())
1103 glPatchParameterfv(GL_PATCH_DEFAULT_INNER_LEVEL, _obj->patchDefaultInnerLevel.
data());
1104 glPatchParameterfv(GL_PATCH_DEFAULT_OUTER_LEVEL, _obj->patchDefaultOuterLevel.
data());
1108 if (tessellationActive)
1109 std::cout <<
"error: tessellation shaders cannot be used with the outdated glew version" << std::endl;
1125 case GL_UNSIGNED_INT: indexSize = 4;
break;
1126 case GL_UNSIGNED_SHORT: indexSize = 2;
break;
1127 default: indexSize = 1;
break;
1142 bool _constRenderStates,
1143 const std::vector<unsigned int>* _shaderModifiers)
1149 bindObjectVBO(_obj, prog);
1154 bindObjectUniforms(_obj, prog);
1158 if (!_constRenderStates)
1159 bindObjectRenderStates(_obj);
1176 #ifdef GL_ARB_vertex_array_object 1178 glBindVertexArray(prevVAO_);
1186 if (numLights_ < SG_MAX_SHADER_LIGHTS)
1188 lights_[numLights_] = _light;
1191 if (_light.ltype != SG_LIGHT_POINT)
1200 renderObjectModifiers_.push_back(_mod);
1205 for (
int i =
int(renderObjectModifiers_.size()) - 1; i >= 0; --i)
1207 if (renderObjectModifiers_[i] == _mod)
1208 renderObjectModifiers_.erase(renderObjectModifiers_.begin() + i);
1213 return sortedObjects_.size();
1224 if (sortedObjects_.empty())
1225 return &renderObjects_[i];
1227 return sortedObjects_[i];
1232 if (overlayObjects_.empty())
1233 return &renderObjects_[i];
1235 return overlayObjects_[i];
1241 return renderObjectSource_[i];
1246 return overlayObjectSource_[i];
1252 if (lineGL42Objects_.empty())
1255 return lineGL42Objects_[i];
1266 QFile fileOut(_fileName);
1267 if (fileOut.open(QFile::WriteOnly | QFile::Truncate))
1269 QTextStream outStrm(&fileOut);
1270 for (
int i = 0; i < getNumRenderObjects(); ++i)
1273 outStrm <<
"\n" << _sortedList[i]->
toString();
1275 outStrm <<
"\n" << renderObjects_[i].toString();
1285 QString objectString;
1287 QTextStream outStrm(&objectString);
1289 for (
int i = 0; i < getNumRenderObjects(); ++i)
1291 const RenderObject* obj = _list ? _list[i] : &renderObjects_[i];
1294 outStrm <<
"\n" << obj->
toString();
1296 if ( _outputShaders ) {
1304 outStrm <<
"\n---------------------vertex-shader--------------------\n\n";
1307 outStrm <<
"\n---------------------end-vertex-shader--------------------\n\n";
1311 outStrm <<
"\n---------------------tesscontrol-shader--------------------\n\n";
1314 outStrm <<
"\n---------------------end-tesscontrol-shader--------------------\n\n";
1319 outStrm <<
"\n---------------------tesseval-shader--------------------\n\n";
1323 outStrm <<
"\n---------------------end-tesseval-shader--------------------\n\n";
1328 outStrm <<
"\n---------------------geometry-shader--------------------\n\n";
1331 outStrm <<
"\n---------------------end-geometry-shader--------------------\n\n";
1335 outStrm <<
"\n---------------------fragment-shader--------------------\n\n";
1338 outStrm <<
"\n---------------------end-fragment-shader--------------------\n\n";
1345 return objectString;
1350 if (!_depthTex)
return;
1354 if (!depthCopyShader_)
1355 depthCopyShader_ =
GLSL::loadProgram(
"ScreenQuad/screenquad.glsl",
"ScreenQuad/depth_copy_330.glsl");
1360 if (!depthCopyShader_)
1361 depthCopyShader_ =
GLSL::loadProgram(
"ScreenQuad/screenquad.glsl",
"ScreenQuad/depth_copy.glsl");
1364 if (depthCopyShader_)
1368 GLint curViewport[4];
1369 GLint curDrawBuffer;
1370 saveActiveFbo(&curFbo, curViewport, &curDrawBuffer);
1372 GLboolean colorMask[4], depthMask;
1373 glGetBooleanv(GL_COLOR_WRITEMASK, colorMask);
1374 glGetBooleanv(GL_DEPTH_WRITEMASK, &depthMask);
1376 GLboolean depthTestEnable;
1378 glGetBooleanv(GL_DEPTH_TEST, &depthTestEnable);
1379 glGetIntegerv(GL_DEPTH_FUNC, &depthFunc);
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);
1388 depthCopyShader_->setUniform(
"DepthSign", _scale);
1391 glColorMask(0,0,0,0);
1395 glEnable(GL_DEPTH_TEST);
1396 glDepthFunc(GL_ALWAYS);
1398 glActiveTexture(GL_TEXTURE0);
1399 glBindTexture(GL_TEXTURE_2D, _depthTex);
1406 restoreFbo(curFbo, curViewport, curDrawBuffer);
1408 glColorMask(colorMask[0], colorMask[1], colorMask[2], colorMask[3]);
1409 glDepthMask(depthMask);
1411 if (!depthTestEnable)
1412 glDisable(GL_DEPTH_TEST);
1414 if (depthFunc != GL_ALWAYS)
1415 glDepthFunc(depthFunc);
1417 glBindTexture(GL_TEXTURE_2D, 0);
1428 _code->push_back(
"outFragment = gl_FragCoord.zzzz;");
1433 ACG::FBO* fbo = depthMaps_[_viewerID];
1438 fbo = depthMaps_[_viewerID] =
new ACG::FBO();
1441 fbo->
attachTexture2D(GL_COLOR_ATTACHMENT0, _width, _height, GL_R32F, GL_RED);
1447 fbo->
resize(_width, _height);
1466 glDrawBuffer(GL_COLOR_ATTACHMENT0);
1467 glViewport(0, 0, _width, _height);
1470 glColorMask(1,1,1,1);
1473 glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
1474 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1477 for (
int i = 0; i < getNumRenderObjects(); ++i)
1490 if (depthMapUniformName)
1492 depthPassShader->
use();
1493 depthPassShader->
setUniform(depthMapUniformName, 0);
1494 glActiveTexture(GL_TEXTURE0);
1495 glBindTexture(GL_TEXTURE_2D, 0);
1500 const GLboolean redWriteMask = obj->colorWriteMask[0];
1501 obj->colorWriteMask[0] = obj->depthWrite;
1503 renderObject(obj, depthPassShader);
1507 obj->colorWriteMask[0]= redWriteMask;
1521 curViewerID_ = _viewerID;
1525 void IRenderer::renderLineThicknessGL42()
1527 #ifdef GL_ARB_shader_image_load_store 1546 const int numLines = lineGL42Objects_.size();
1549 const bool useBufferTexture =
true;
1550 const bool useIntegerTexture =
true;
1560 if (useBufferTexture)
1561 macros.push_back(
"#define IMAGE_BUFFER");
1562 if (useIntegerTexture)
1563 macros.push_back(
"#define FMT_UINT");
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);
1575 if (useBufferTexture)
1577 lineColorImgBuf =
dynamic_cast<TextureBuffer*
>(lineColorBuffers_[curViewerID_]);
1579 if (!lineColorImgBuf)
1582 lineColorBuffers_[curViewerID_] = lineColorImgBuf;
1586 if (lineColorImgBuf->getBufferSize() != w * h * lineBPP)
1587 lineColorImgBuf->setBufferData(w*h*lineBPP, 0, GL_R32UI, GL_DYNAMIC_DRAW);
1591 lineColorImg2D =
dynamic_cast<Texture2D*
>(lineColorBuffers_[curViewerID_]);
1593 if (!lineColorImg2D)
1596 lineColorImg2D =
new Texture2D(GL_TEXTURE0);
1597 lineColorBuffers_[curViewerID_] = lineColorImg2D;
1601 if (lineColorImg2D->getWidth() !=
static_cast<int>(w) || lineColorImg2D->getHeight() !=
static_cast<int>(h))
1602 lineColorImg2D->setData(0,
1603 useIntegerTexture ? GL_R32UI : GL_RGBA32F,
1605 useIntegerTexture ? GL_RED_INTEGER : GL_RGBA,
1606 useIntegerTexture ? GL_UNSIGNED_INT : GL_FLOAT,
1614 glViewport(0, 0, w, h);
1621 glColorMask(0,0,0,0);
1623 glDisable(GL_DEPTH_TEST);
1626 if (useBufferTexture)
1627 lineColorImgBuf->bindAsImage(0, GL_WRITE_ONLY);
1629 lineColorImg2D->bindAsImage(0, GL_WRITE_ONLY);
1640 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
1648 for (
int i = 0; i < numLines; ++i)
1655 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
1667 if (useBufferTexture)
1668 lineColorImgBuf->bindAsImage(0, GL_READ_ONLY);
1670 lineColorImg2D->bindAsImage(0, GL_READ_ONLY);
1673 glColorMask(1,1,1,1);
1674 glDisable(GL_DEPTH_TEST);
1682 shaderComposite->
use();
1696 if (Texture::supportsImageLoadStore() && Texture::supportsTextureBuffer())
1697 enableLineThicknessGL42_ = _enable;
1702 errorDetectionLevel_ = std::max(_level, 0);
1707 return errorDetectionLevel_;
virtual void renderObject(ACG::RenderObject *_obj, GLSL::Program *_prog=0, bool _constRenderStates=false, const std::vector< unsigned int > *_shaderModifiers=0)
Render one renderobject.
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.
GLenum indexType
Index element type.
virtual void bindObjectVBO(ACG::RenderObject *_obj, GLSL::Program *_prog)
Binding VBOs (First state function)
void resize(GLsizei _width, GLsizei _height, bool _forceResize=false)
resize function (if textures created by this class)
ACG::RenderObject * getLineGL42RenderObject(int i)
Get render objects in the sorted list by index (only line objects rendered with gl4.2)
virtual void bindObjectRenderStates(ACG::RenderObject *_obj)
Binding Render state (Third state function)
bool inZPrePass
Specify whether this object should be rendered in a z-prepass.
virtual void sortRenderObjects()
Sort the renderobjects by priority.
const QStringList & getTessEvaluationShaderCode()
Returns generated tessellation control shader code.
static void draw(GLSL::Program *_prog=0)
Draw the screen quad.
bool hasTessControlShader() const
check whether there is a tess-control shader present
void use()
Enables the program object for using.
virtual void removeRenderObjectModifier(RenderObjectModifier *_mod)
Callback for the scenegraph nodes, which removes a render object modifier from the renderer...
int viewport_width() const
get viewport width
VectorT< float, 2 > Vec2f
int getNumRenderObjects() const
Get the number of collected render objects (not including overlay objects or gl4.2 line objects) ...
Namespace providing different geometric functions concerning angles.
virtual QString dumpCurrentRenderObjectsToString(ACG::RenderObject **_list=0, bool _outputShaders=false, std::vector< ACG::ShaderModifier *> *_modifiers=0)
Outputs the current render objects to the string.
virtual void bindObjectUniforms(ACG::RenderObject *_obj, GLSL::Program *_prog)
Binding Uniforms (Second state function)
Interface for modifying render objects.
void transpose()
transpose matrix
void setErrorDetectionLevel(int _level)
Control error detection for checking render objects.
virtual void renderDepthMap(int _viewerID, int _width, int _height)
Render the depth map of the scene.
void setLineThicknessRenderingGL42(bool _enable)
void baseColor(const Vec4f &_c)
set the base color (Sets the baseColor which is the same as the emission(const Vec4f& _c) ) ...
ACG::RenderObject * getRenderObject(int i)
Get render objects in the sorted list by index (not including overlay objects)
virtual void collectRenderObjects(ACG::GLState *_glState, ACG::SceneGraph::DrawModes::DrawMode _drawMode, ACG::SceneGraph::BaseNode *_sceneGraphRoot)
Traverse the scenegraph to collect render information.
const QStringList & getTessControlShaderCode()
Returns generated vertex shader code.
GLenum depthFunc
GL_LESS, GL_LEQUAL, GL_GREATER ..
const QStringList & getFragmentShaderCode()
Returns generated fragment shader code.
void unbind()
unbind fbo, go to normal rendering mode
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.
virtual void addLight(const LightData &_light)
Callback for the scenegraph nodes, which send new lights to the renderer via this function...
ShaderGenDesc shaderDesc
Drawmode and other shader params.
Draw node in second pass.
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
void deactivateShaderPipeline(GLSL::Program *_prog) const
LightData * getLight(int i)
Get light by index.
virtual void drawObject(ACG::RenderObject *_obj)
Executes the opengl draw call for one object (Fourth function)
void addDepthBuffer(GLuint _width, GLuint _height)
function to add a depth renderbuffer to the fbo
Hide this node and its children.
std::string name
Name for logging.
GLuint vertexBuffer
VBO, IBO ids, ignored if VAO is provided.
GLMatrixd proj
Projection transform.
unsigned int internalFlags_
may be used internally by the renderer
bool hasTessEvaluationShader() const
check whether there is a tess-evaluation shader present
GLuint getProgramId()
Returns opengl id.
StatusMode status() const
Get node's status.
GLenum primitiveMode
Primitive type.
virtual void clearInputFbo(const ACG::Vec4f &_clearColor)
Clear input Fbo.
Scalar * data()
access to Scalar array
Vec2f depthRange
glDepthRange: (znear, zmax)
bool invert()
matrix inversion (returns true on success)
void ambientColor(const Vec4f &_a)
set the ambient color.
const char * depthMapUniformName
Uniform name of the depth map in the used shader.
static int maxClipDistances_
max number of clip distance outputs in a vertex shader
void diffuseColor(const Vec4f &_d)
set the diffuse color.
GLSL::PtrProgram loadProgram(const char *vertexShaderFile, const char *tessControlShaderFile, const char *tessEvaluationShaderFile, const char *geometryShaderFile, const char *fragmentShaderFile, const GLSL::StringList *macros, bool verbose)
DrawMode DEFAULT
use the default (global) draw mode and not the node's own.
Scalar max() const
return the maximal component
VectorT< float, 3 > Vec3f
virtual void restoreInputFbo()
Restore the previously saved input Fbo configuration (fbo id + viewport)
static ShaderCache * getInstance()
Return instance of the ShaderCache singleton.
Vec3f diffuse
material definitions
virtual void restoreFbo(GLint _fboId, const GLint *_outViewport, GLint _drawBuffer) const
Restore a previously saved input Fbo configuration (fbo id + viewport)
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.
virtual void saveInputFbo()
Save input Fbo configuration (fbo id + viewport)
GLuint indexBuffer
Use vertex array object.
virtual void copyDepthToBackBuffer(GLuint _depthTex, float _scale=1.0f)
Copy texture to depth buffer.
int viewport_height() const
get viewport height
GLSL::Program * getProgram(const ShaderGenDesc *_desc, const std::vector< unsigned int > &_mods)
Query a dynamically generated program from cache.
void setUniform(const char *_name, GLint _value)
Set int uniform to specified value.
bool openGLVersion(const int _major, const int _minor, bool _verbose)
virtual void saveActiveFbo(GLint *_outFboId, GLint *_outViewport, GLint *_outDrawBuffer) const
Save active Fbo configuration (fbo id + viewport)
bool bind()
bind the fbo and sets it as rendertarget
const VertexDeclaration * vertexDecl
Defines the vertex buffer layout, ignored if VAO is provided.
virtual void finishRenderingPipeline(bool _drawOverlay=true)
Draw overlay objects and reset OpenGL state.
int getErrorDetectionLevel() const
Get error detection level.
static void blendFunc(GLenum _sfactor, GLenum _dfactor)
replaces glBlendFunc, supports locking
virtual void addRenderObjectModifier(RenderObjectModifier *_mod)
Callback for the scenegraph nodes, which adds a render object modifier to the renderer via this funct...
std::vector< BaseNode * >::iterator ChildIter
allows to iterate over children
unsigned int numIndices
Number indices to render.
GLuint vertexArrayObject
Use vertex array object.
const QStringList & getGeometryShaderCode()
Returns generated tessellation evaluation shader code.
virtual void addRenderObject(RenderObject *_renderObject)
Callback for the scenegraph nodes, which send new render objects via this function.
GLenum alphaFunc
GL_LESS, GL_LEQUAL, GL_GREATER ..
ACG::SceneGraph::BaseNode * getOverlayRenderObjectNode(int i)
Get node that emitted the render object in the sorted list by index (only overlay objects) ...
ACG::SceneGraph::BaseNode * getRenderObjectNode(int i)
Get node that emitted the render object in the sorted list by index (not including overlay objects) ...
void setUniformMat3(const char *_name, const ACG::GLMatrixf &_value, bool _transposed=false)
Set 3x3fMatrix uniform to specified value.
QString toString() const
convert ShaderGenDesc to string format for debugging
bool isDefaultPointObject() const
Test if the object is rendered with one of the default point extension methods.
Draw this node, but hide children.
void specularColor(const Vec4f &_s)
set the specular color
int getNumLights() const
Get the number of current light sources.
const GLMatrixd & modelview() const
get modelview matrix
static unsigned int registerModifier(ShaderModifier *_modifier)
Shader modifiers have to be registered before they can be used. They also must remain allocated for t...
const void * sysmemIndexBuffer
Use system memory index buffer.
const QStringList & getVertexShaderCode()
Returns generated vertex shader code.
ACG::RenderObject * getOverlayRenderObject(int i)
Get render objects in the sorted list by index (only overlay objects)
void activateShaderPipeline(GLSL::Program *_prog) const
Hide this node, but draw children.
const VertexElement * findElementByUsage(VERTEX_USAGE _usage) const
bool hasGeometryShader() const
check whether there is a geometry shader present
void setViewerID(int _viewerID)
Set currently active viewer id.
GLenum blendDest
glBlendFunc: GL_SRC_ALPHA, GL_ZERO, GL_ONE, GL_ONE_MINUS_SRC_ALPHA ...
bool isDefaultLineObject() const
Test if the object is rendered with one of the default line thickness methods.
auto normalize() -> decltype(*this/=std::declval< VectorT< S, DIM >>().norm())
Interface class between scenegraph and renderer.
void dumpRenderObjectsToFile(const char *_fileName, ACG::RenderObject **_sortedList=0) const
Debugging function to dump list of render objects into a file.
ACG::SceneGraph::Material & material()
Get material object reference.
unsigned int indexOffset
Offset to first index in the index buffer or vertex buffer respectively.
void shininess(float _s)
set shininess
GLMatrixd modelview
Modelview transform.