44#include <ACG/GL/acg_glew.hh>
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>
77prevDrawBuffer_(GL_BACK),
81errorDetectionLevel_(1),
83enableLineThicknessGL42_(false)
91 globalLightModelAmbient_ =
ACG::Vec3f(0.2f, 0.2f, 0.2f);
95IRenderer::~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);
336 if (errorDetectionLevel_ > 1 && p->
shaderDesc.geometryTemplateFile.length())
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);
433class 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);
643if(_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)
667void IRenderer::finishRenderingPipeline(
bool _drawOverlay)
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;
776void IRenderer::saveInputFbo()
779 saveActiveFbo(&prevFbo_, prevViewport_, &prevDrawBuffer_);
780 prevFboSaved_ =
true;
783void IRenderer::restoreInputFbo()
786 restoreFbo(prevFbo_, prevViewport_, prevDrawBuffer_);
789void IRenderer::saveActiveFbo( GLint* _outFboId, GLint* _outViewport, GLint* _outDrawBuffer )
const
792 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, _outFboId);
793 glGetIntegerv(GL_VIEWPORT, _outViewport);
794 glGetIntegerv(GL_DRAW_BUFFER, _outDrawBuffer);
797void IRenderer::restoreFbo( GLint _fboId,
const GLint* _outViewport, GLint _drawBuffer )
const
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);
827struct 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_;
839void IRenderer::sortRenderObjects()
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 auto idx_str = std::to_string(i);
985 _prog->
setUniform((
"g_cLightDiffuse_" + idx_str).c_str(), lgt->diffuse);
986 _prog->
setUniform((
"g_cLightAmbient_" + idx_str).c_str(), lgt->ambient);
987 _prog->
setUniform((
"g_cLightSpecular_" + idx_str).c_str(), lgt->specular);
989 if (lgt->ltype == ACG::SG_LIGHT_POINT || lgt->ltype == ACG::SG_LIGHT_SPOT)
991 _prog->
setUniform((
"g_vLightPos_" + idx_str).c_str(), lgt->pos);
992 _prog->
setUniform((
"g_vLightAtten_" + idx_str).c_str(), lgt->atten);
995 if (lgt->ltype == ACG::SG_LIGHT_DIRECTIONAL || lgt->ltype == ACG::SG_LIGHT_SPOT)
997 _prog->
setUniform((
"g_vLightDir_" + idx_str).c_str(), lgt->dir);
1000 if (lgt->ltype == ACG::SG_LIGHT_SPOT)
1002 _prog->
setUniform((
"g_vLightAngleExp_" + idx_str).c_str(), lgt->spotCutoffExponent);
1010 glEnable(GL_CULL_FACE);
1012 glDisable(GL_CULL_FACE);
1017 glDisable(GL_BLEND);
1021 if (_obj->alphaTest)
1023 glEnable(GL_ALPHA_TEST);
1024 glAlphaFunc(_obj->
alphaFunc, _obj->alphaRef);
1027 glDisable(GL_ALPHA_TEST);
1030 if (_obj->depthTest)
1031 glEnable(GL_DEPTH_TEST);
1033 glDisable(GL_DEPTH_TEST);
1036 glDepthMask(_obj->depthWrite ? GL_TRUE : GL_FALSE);
1038 glColorMask(_obj->colorWriteMask[0], _obj->colorWriteMask[1], _obj->colorWriteMask[2], _obj->colorWriteMask[3]);
1048 if (maxClipDistances_ < 0)
1050 glGetIntegerv(GL_MAX_CLIP_DISTANCES, &maxClipDistances_);
1051 maxClipDistances_ = std::min(maxClipDistances_, 32);
1054 for (
int i = 0; i < maxClipDistances_; ++i)
1056 if (_obj->clipDistanceMask & (1 << i))
1057 glEnable(GL_CLIP_DISTANCE0 + i);
1059 glDisable(GL_CLIP_DISTANCE0 + i);
1062#ifdef GL_PROGRAM_POINT_SIZE
1063 if (_obj->programPointSize)
1064 glEnable(GL_PROGRAM_POINT_SIZE);
1066 glDisable(GL_PROGRAM_POINT_SIZE);
1069 glPointSize(_obj->pointSize);
1077 bool noIndices =
true;
1081 glPolygonMode(GL_FRONT_AND_BACK, _obj->fillMode);
1084 bool tessellationActive = !(_obj->
shaderDesc.tessControlTemplateFile.isEmpty() && _obj->
shaderDesc.tessEvaluationTemplateFile.isEmpty());
1085#ifdef GL_ARB_tessellation_shader
1086 if (tessellationActive)
1090 if (_obj->
shaderDesc.tessControlTemplateFile.isEmpty())
1092 glPatchParameterfv(GL_PATCH_DEFAULT_INNER_LEVEL, _obj->patchDefaultInnerLevel.
data());
1093 glPatchParameterfv(GL_PATCH_DEFAULT_OUTER_LEVEL, _obj->patchDefaultOuterLevel.
data());
1097 if (tessellationActive)
1098 std::cout <<
"error: tessellation shaders cannot be used with the outdated glew version" << std::endl;
1114 case GL_UNSIGNED_INT: indexSize = 4;
break;
1115 case GL_UNSIGNED_SHORT: indexSize = 2;
break;
1116 default: indexSize = 1;
break;
1131 bool _constRenderStates,
1132 const std::vector<unsigned int>* _shaderModifiers)
1138 bindObjectVBO(_obj, prog);
1143 bindObjectUniforms(_obj, prog);
1147 if (!_constRenderStates)
1148 bindObjectRenderStates(_obj);
1165#ifdef GL_ARB_vertex_array_object
1167 glBindVertexArray(prevVAO_);
1175 if (numLights_ < SG_MAX_SHADER_LIGHTS)
1177 lights_[numLights_] = _light;
1180 if (_light.ltype != SG_LIGHT_POINT)
1189 renderObjectModifiers_.push_back(_mod);
1194 for (
int i =
int(renderObjectModifiers_.size()) - 1; i >= 0; --i)
1196 if (renderObjectModifiers_[i] == _mod)
1197 renderObjectModifiers_.erase(renderObjectModifiers_.begin() + i);
1201int IRenderer::getNumRenderObjects()
const {
1202 return sortedObjects_.size();
1205int IRenderer::getNumLights()
const
1213 if (sortedObjects_.empty())
1214 return &renderObjects_[i];
1216 return sortedObjects_[i];
1221 if (overlayObjects_.empty())
1222 return &renderObjects_[i];
1224 return overlayObjects_[i];
1230 return renderObjectSource_[i];
1235 return overlayObjectSource_[i];
1241 if (lineGL42Objects_.empty())
1244 return lineGL42Objects_[i];
1253void IRenderer::dumpRenderObjectsToFile(
const char* _fileName,
ACG::RenderObject** _sortedList)
const
1255 QFile fileOut(_fileName);
1256 if (fileOut.open(QFile::WriteOnly | QFile::Truncate))
1258 QTextStream outStrm(&fileOut);
1259 for (
int i = 0; i < getNumRenderObjects(); ++i)
1262 outStrm <<
"\n" << _sortedList[i]->
toString();
1264 outStrm <<
"\n" << renderObjects_[i].toString();
1272QString IRenderer::dumpCurrentRenderObjectsToString(
ACG::RenderObject** _list,
bool _outputShaders, std::vector<ACG::ShaderModifier*>* _modifiers) {
1274 QString objectString;
1276 QTextStream outStrm(&objectString);
1278 for (
int i = 0; i < getNumRenderObjects(); ++i)
1280 const RenderObject* obj = _list ? _list[i] : &renderObjects_[i];
1283 outStrm <<
"\n" << obj->
toString();
1285 if ( _outputShaders ) {
1293 outStrm <<
"\n---------------------vertex-shader--------------------\n\n";
1296 outStrm <<
"\n---------------------end-vertex-shader--------------------\n\n";
1300 outStrm <<
"\n---------------------tesscontrol-shader--------------------\n\n";
1303 outStrm <<
"\n---------------------end-tesscontrol-shader--------------------\n\n";
1308 outStrm <<
"\n---------------------tesseval-shader--------------------\n\n";
1312 outStrm <<
"\n---------------------end-tesseval-shader--------------------\n\n";
1317 outStrm <<
"\n---------------------geometry-shader--------------------\n\n";
1320 outStrm <<
"\n---------------------end-geometry-shader--------------------\n\n";
1324 outStrm <<
"\n---------------------fragment-shader--------------------\n\n";
1327 outStrm <<
"\n---------------------end-fragment-shader--------------------\n\n";
1334 return objectString;
1337void IRenderer::copyDepthToBackBuffer( GLuint _depthTex,
float _scale )
1339 if (!_depthTex)
return;
1343 if (!depthCopyShader_)
1344 depthCopyShader_ =
GLSL::loadProgram(
"ScreenQuad/screenquad.glsl",
"ScreenQuad/depth_copy_330.glsl");
1349 if (!depthCopyShader_)
1350 depthCopyShader_ =
GLSL::loadProgram(
"ScreenQuad/screenquad.glsl",
"ScreenQuad/depth_copy.glsl");
1353 if (depthCopyShader_)
1357 GLint curViewport[4];
1358 GLint curDrawBuffer;
1359 saveActiveFbo(&curFbo, curViewport, &curDrawBuffer);
1361 GLboolean colorMask[4], depthMask;
1362 glGetBooleanv(GL_COLOR_WRITEMASK, colorMask);
1363 glGetBooleanv(GL_DEPTH_WRITEMASK, &depthMask);
1365 GLboolean depthTestEnable;
1367 glGetBooleanv(GL_DEPTH_TEST, &depthTestEnable);
1368 glGetIntegerv(GL_DEPTH_FUNC, &depthFunc);
1373 depthCopyShader_->use();
1374 depthCopyShader_->setUniform(
"offset",
ACG::Vec2f(0.0f, 0.0f));
1375 depthCopyShader_->setUniform(
"size",
ACG::Vec2f(1.0f, 1.0f));
1376 depthCopyShader_->setUniform(
"DepthTex", 0);
1377 depthCopyShader_->setUniform(
"DepthSign", _scale);
1380 glColorMask(0,0,0,0);
1384 glEnable(GL_DEPTH_TEST);
1385 glDepthFunc(GL_ALWAYS);
1387 glActiveTexture(GL_TEXTURE0);
1388 glBindTexture(GL_TEXTURE_2D, _depthTex);
1395 restoreFbo(curFbo, curViewport, curDrawBuffer);
1397 glColorMask(colorMask[0], colorMask[1], colorMask[2], colorMask[3]);
1398 glDepthMask(depthMask);
1400 if (!depthTestEnable)
1401 glDisable(GL_DEPTH_TEST);
1403 if (depthFunc != GL_ALWAYS)
1404 glDepthFunc(depthFunc);
1406 glBindTexture(GL_TEXTURE_2D, 0);
1415void IRenderer::DepthMapPass::modifyFragmentEndCode(QStringList* _code)
1417 _code->push_back(
"outFragment = gl_FragCoord.zzzz;");
1420void IRenderer::renderDepthMap(
int _viewerID,
int _width,
int _height)
1422 ACG::FBO* fbo = depthMaps_[_viewerID];
1427 fbo = depthMaps_[_viewerID] =
new ACG::FBO();
1430 fbo->
attachTexture2D(GL_COLOR_ATTACHMENT0, _width, _height, GL_R32F, GL_RED);
1436 fbo->
resize(_width, _height);
1455 glDrawBuffer(GL_COLOR_ATTACHMENT0);
1456 glViewport(0, 0, _width, _height);
1459 glColorMask(1,1,1,1);
1462 glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
1463 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1466 for (
int i = 0; i < getNumRenderObjects(); ++i)
1473 GLSL::Program* depthPassShader = ShaderCache::getInstance()->getProgram(&obj->
shaderDesc, DepthMapPass::instance);
1479 if (depthMapUniformName)
1481 depthPassShader->
use();
1482 depthPassShader->
setUniform(depthMapUniformName, 0);
1483 glActiveTexture(GL_TEXTURE0);
1484 glBindTexture(GL_TEXTURE_2D, 0);
1489 const GLboolean redWriteMask = obj->colorWriteMask[0];
1490 obj->colorWriteMask[0] = obj->depthWrite;
1492 renderObject(obj, depthPassShader);
1496 obj->colorWriteMask[0]= redWriteMask;
1508void IRenderer::setViewerID(
int _viewerID)
1510 curViewerID_ = _viewerID;
1514void IRenderer::renderLineThicknessGL42()
1516#ifdef GL_ARB_shader_image_load_store
1535 const int numLines = lineGL42Objects_.size();
1538 const bool useBufferTexture =
true;
1539 const bool useIntegerTexture =
true;
1549 if (useBufferTexture)
1550 macros.push_back(
"#define IMAGE_BUFFER");
1551 if (useIntegerTexture)
1552 macros.push_back(
"#define FMT_UINT");
1560 size_t w =
static_cast<size_t>(prevViewport_[2]), h =
static_cast<size_t>(prevViewport_[3]);
1561 size_t lineBPP =
static_cast<size_t>(useIntegerTexture ? 4 : 16);
1564 if (useBufferTexture)
1566 lineColorImgBuf =
dynamic_cast<TextureBuffer*
>(lineColorBuffers_[curViewerID_]);
1568 if (!lineColorImgBuf)
1571 lineColorBuffers_[curViewerID_] = lineColorImgBuf;
1575 if (lineColorImgBuf->getBufferSize() != w * h * lineBPP)
1576 lineColorImgBuf->setBufferData(w*h*lineBPP, 0, GL_R32UI, GL_DYNAMIC_DRAW);
1580 lineColorImg2D =
dynamic_cast<Texture2D*
>(lineColorBuffers_[curViewerID_]);
1582 if (!lineColorImg2D)
1585 lineColorImg2D =
new Texture2D(GL_TEXTURE0);
1586 lineColorBuffers_[curViewerID_] = lineColorImg2D;
1590 if (lineColorImg2D->getWidth() !=
static_cast<int>(w) || lineColorImg2D->getHeight() !=
static_cast<int>(h))
1591 lineColorImg2D->setData(0,
1592 useIntegerTexture ? GL_R32UI : GL_RGBA32F,
1594 useIntegerTexture ? GL_RED_INTEGER : GL_RGBA,
1595 useIntegerTexture ? GL_UNSIGNED_INT : GL_FLOAT,
1603 glViewport(0, 0, w, h);
1610 glColorMask(0,0,0,0);
1612 glDisable(GL_DEPTH_TEST);
1615 if (useBufferTexture)
1616 lineColorImgBuf->bindAsImage(0, GL_WRITE_ONLY);
1618 lineColorImg2D->bindAsImage(0, GL_WRITE_ONLY);
1620 GLSL::Program* shaderClear = ShaderCache::getInstance()->getProgram(
"ScreenQuad/screenquad.glsl",
"Wireframe/gl42/clear.glsl", ¯os);
1627 ScreenQuad::draw(shaderClear);
1629 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
1637 for (
int i = 0; i < numLines; ++i)
1639 RenderObject* obj = getLineGL42RenderObject(i);
1644 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
1656 if (useBufferTexture)
1657 lineColorImgBuf->bindAsImage(0, GL_READ_ONLY);
1659 lineColorImg2D->bindAsImage(0, GL_READ_ONLY);
1662 glColorMask(1,1,1,1);
1663 glDisable(GL_DEPTH_TEST);
1669 GLSL::Program* shaderComposite = ShaderCache::getInstance()->getProgram(
"ScreenQuad/screenquad.glsl",
"Wireframe/gl42/composite.glsl", ¯os);
1671 shaderComposite->
use();
1676 ScreenQuad::draw(shaderComposite);
1683void IRenderer::setLineThicknessRenderingGL42(
bool _enable )
1685 if (Texture::supportsImageLoadStore() && Texture::supportsTextureBuffer())
1686 enableLineThicknessGL42_ = _enable;
1689void IRenderer::setErrorDetectionLevel(
int _level )
1691 errorDetectionLevel_ = std::max(_level, 0);
1694int IRenderer::getErrorDetectionLevel()
const
1696 return errorDetectionLevel_;
void resize(GLsizei _width, GLsizei _height, bool _forceResize=false)
resize function (if textures created by this class)
bool bind()
bind the fbo and sets it as rendertarget
void addDepthBuffer(GLuint _width, GLuint _height)
function to add a depth renderbuffer to the fbo
void unbind()
unbind fbo, go to normal rendering mode
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
const GLMatrixd & modelview() const
get modelview matrix
int viewport_width() const
get viewport width
static void blendFunc(GLenum _sfactor, GLenum _dfactor)
replaces glBlendFunc, supports locking
int viewport_height() const
get viewport height
static int maxClipDistances_
max number of clip distance outputs in a vertex shader
bool invert()
matrix inversion (returns true on success)
void transpose()
transpose matrix
Interface for modifying render objects.
@ HideNode
Hide this node, but draw children.
@ HideChildren
Draw this node, but hide children.
@ HideSubtree
Hide this node and its children.
@ SecondPass
Draw node in second pass.
std::vector< BaseNode * >::iterator ChildIter
allows to iterate over children
StatusMode status() const
Get node's status.
ACG::SceneGraph::Material & material()
Get material object reference.
void shininess(float _s)
set shininess
void baseColor(const Vec4f &_c)
set the base color (Sets the baseColor which is the same as the emission(const Vec4f& _c) )
void specularColor(const Vec4f &_s)
set the specular color
void ambientColor(const Vec4f &_a)
set the ambient color.
void diffuseColor(const Vec4f &_d)
set the diffuse color.
static void draw(GLSL::Program *_prog=0)
Draw the screen quad.
static ShaderCache * getInstance()
Return instance of the ShaderCache singleton.
GLSL::Program * getProgram(const ShaderGenDesc *_desc, const std::vector< unsigned int > &_mods)
Query a dynamically generated program from cache.
QString toString() const
convert ShaderGenDesc to string format for debugging
const QStringList & getTessEvaluationShaderCode()
Returns generated tessellation control shader code.
const QStringList & getTessControlShaderCode()
Returns generated vertex shader code.
bool hasTessEvaluationShader() const
check whether there is a tess-evaluation shader present
const QStringList & getGeometryShaderCode()
Returns generated tessellation evaluation shader code.
bool hasGeometryShader() const
check whether there is a geometry shader present
bool hasTessControlShader() const
check whether there is a tess-control shader present
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 QStringList & getFragmentShaderCode()
Returns generated fragment shader code.
const QStringList & getVertexShaderCode()
Returns generated vertex shader code.
void deactivateShaderPipeline(GLSL::Program *_prog) const
const VertexElement * findElementByUsage(VERTEX_USAGE _usage) const
void activateShaderPipeline(GLSL::Program *_prog) const
GLuint getProgramId()
Returns opengl id.
void setUniformMat3(const char *_name, const ACG::GLMatrixf &_value, bool _transposed=false)
Set 3x3fMatrix uniform to specified value.
void use()
Enables the program object for using.
void setUniform(const char *_name, GLint _value)
Set int uniform to specified value.
Scalar * data()
access to Scalar array
Scalar max() const
return the maximal component
auto normalize() -> decltype(*this/=std::declval< VectorT< S, DIM > >().norm())
DrawMode DEFAULT
use the default (global) draw mode and not the node's own.
Namespace providing different geometric functions concerning angles.
bool openGLVersion(const int _major, const int _minor, bool _verbose)
VectorT< float, 3 > Vec3f
@ VERTEX_USAGE_NORMAL
"inNormal"
@ VERTEX_USAGE_COLOR
"inColor"
@ VERTEX_USAGE_TEXCOORD
"inTexCoord"
GLSL::PtrProgram loadProgram(const char *vertexShaderFile, const char *tessControlShaderFile, const char *tessEvaluationShaderFile, const char *geometryShaderFile, const char *fragmentShaderFile, const GLSL::StringList *macros, bool verbose)
Interface class between scenegraph and renderer.
const char * depthMapUniformName
Uniform name of the depth map in the used shader.
Vec3f diffuse
material definitions
ShaderGenDesc shaderDesc
Drawmode and other shader params.
bool isDefaultLineObject() const
Test if the object is rendered with one of the default line thickness methods.
GLuint vertexArrayObject
Use vertex array object.
const VertexDeclaration * vertexDecl
Defines the vertex buffer layout, ignored if VAO is provided.
const void * sysmemIndexBuffer
Use system memory index buffer.
GLuint indexBuffer
Use vertex array object.
unsigned int numIndices
Number indices to render.
GLMatrixd modelview
Modelview transform.
GLMatrixd proj
Projection transform.
std::string name
Name for logging.
bool inZPrePass
Specify whether this object should be rendered in a z-prepass.
unsigned int indexOffset
Offset to first index in the index buffer or vertex buffer respectively.
GLuint vertexBuffer
VBO, IBO ids, ignored if VAO is provided.
bool isDefaultPointObject() const
Test if the object is rendered with one of the default point extension methods.
GLenum primitiveMode
Primitive type.
GLenum alphaFunc
GL_LESS, GL_LEQUAL, GL_GREATER ..
unsigned int patchVertices
patch size if primitiveMode is GL_PATCHES for rendering with tessellation shaders
GLenum blendDest
glBlendFunc: GL_SRC_ALPHA, GL_ZERO, GL_ONE, GL_ONE_MINUS_SRC_ALPHA ...
unsigned int internalFlags_
may be used internally by the renderer
Vec2f depthRange
glDepthRange: (znear, zmax)
GLenum indexType
Index element type.
GLenum depthFunc
GL_LESS, GL_LEQUAL, GL_GREATER ..