diff --git a/src/Graphic3d/Graphic3d_ShaderProgram.hxx b/src/Graphic3d/Graphic3d_ShaderProgram.hxx index 112d1a0145..44fc43efba 100755 --- a/src/Graphic3d/Graphic3d_ShaderProgram.hxx +++ b/src/Graphic3d/Graphic3d_ShaderProgram.hxx @@ -61,6 +61,18 @@ public: //! Returns unique ID used to manage resource in graphic driver. const TCollection_AsciiString& GetId() const { return myID; } + //! Returns GLSL header (version code and extensions). + const TCollection_AsciiString& Header() const { return myHeader; } + + //! Setup GLSL header containing language version code and used extensions. + //! Will be prepended to the very beginning of the source code. + //! Example: + //! @code + //! #version 300 es + //! #extension GL_ARB_bindless_texture : require + //! @endcode + void SetHeader (const TCollection_AsciiString& theHeader) { myHeader = theHeader; } + //! Attaches shader object to the program object. Standard_EXPORT Standard_Boolean AttachShader (const Handle(Graphic3d_ShaderObject)& theShader); @@ -96,6 +108,7 @@ private: TCollection_AsciiString myID; //!< The unique identifier of program object. Graphic3d_ShaderObjectList myShaderObjects; //!< the list of attached shader objects. Graphic3d_ShaderVariableList myVariables; //!< the list of custom uniform variables. + TCollection_AsciiString myHeader; //!< GLSL header with version code and used extensions }; diff --git a/src/OpenGl/OpenGl_ArbFBO.hxx b/src/OpenGl/OpenGl_ArbFBO.hxx index 8e67351e93..bfac84aa27 100644 --- a/src/OpenGl/OpenGl_ArbFBO.hxx +++ b/src/OpenGl/OpenGl_ArbFBO.hxx @@ -48,4 +48,13 @@ struct OpenGl_ArbFBO : protected OpenGl_GlFunctions }; +//! FBO blit is available in OpenGL 3.0+. +//! Moved out from OpenGl_ArbFBO since it is unavailable in OpenGL ES 2.0. +struct OpenGl_ArbFBOBlit : protected OpenGl_GlFunctions +{ + + using OpenGl_GlFunctions::glBlitFramebuffer; + +}; + #endif // _OpenGl_ArbFBO_H__ diff --git a/src/OpenGl/OpenGl_Context.cxx b/src/OpenGl/OpenGl_Context.cxx index 247c189f02..3f47492ff7 100644 --- a/src/OpenGl/OpenGl_Context.cxx +++ b/src/OpenGl/OpenGl_Context.cxx @@ -95,6 +95,7 @@ OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps) arbIns (NULL), arbDbg (NULL), arbFBO (NULL), + arbFBOBlit (NULL), extGS (NULL), extBgra(Standard_False), extAnis(Standard_False), @@ -877,6 +878,7 @@ void OpenGl_Context::init() arbIns = NULL; arbDbg = NULL; arbFBO = NULL; + arbFBOBlit = NULL; extGS = NULL; #if defined(GL_ES_VERSION_2_0) @@ -902,7 +904,12 @@ void OpenGl_Context::init() core20 = (OpenGl_GlCore20* )(&(*myFuncs)); core20fwd = (OpenGl_GlCore20Fwd* )(&(*myFuncs)); core15fwd = (OpenGl_GlCore15Fwd* )(&(*myFuncs)); - arbFBO = (OpenGl_ArbFBO* )(&(*myFuncs)); + arbFBO = (OpenGl_ArbFBO* )(&(*myFuncs)); + } + if (IsGlGreaterEqual (3, 0) + && FindProc ("glBlitFramebuffer", myFuncs->glBlitFramebuffer)) + { + arbFBOBlit = (OpenGl_ArbFBOBlit* )(&(*myFuncs)); } hasHighp = CheckExtension ("OES_fragment_precision_high"); @@ -1762,7 +1769,8 @@ void OpenGl_Context::init() // initialize FBO extension (ARB) if (hasFBO) { - arbFBO = (OpenGl_ArbFBO* )(&(*myFuncs)); + arbFBO = (OpenGl_ArbFBO* )(&(*myFuncs)); + arbFBOBlit = (OpenGl_ArbFBOBlit* )(&(*myFuncs)); extPDS = Standard_True; // extension for EXT, but part of ARB } diff --git a/src/OpenGl/OpenGl_Context.hxx b/src/OpenGl/OpenGl_Context.hxx index 1510e5b94a..187a918c67 100644 --- a/src/OpenGl/OpenGl_Context.hxx +++ b/src/OpenGl/OpenGl_Context.hxx @@ -45,6 +45,7 @@ struct OpenGl_ArbTBO; struct OpenGl_ArbIns; struct OpenGl_ArbDbg; struct OpenGl_ArbFBO; +struct OpenGl_ArbFBOBlit; struct OpenGl_ExtGS; struct OpenGl_ArbTexBindless; @@ -522,6 +523,7 @@ public: //! @name extensions OpenGl_ArbIns* arbIns; //!< GL_ARB_draw_instanced OpenGl_ArbDbg* arbDbg; //!< GL_ARB_debug_output OpenGl_ArbFBO* arbFBO; //!< GL_ARB_framebuffer_object + OpenGl_ArbFBOBlit* arbFBOBlit; //!< glBlitFramebuffer function, moved out from OpenGl_ArbFBO structure for compatibility with OpenGL ES 2.0 OpenGl_ExtGS* extGS; //!< GL_EXT_geometry_shader4 Standard_Boolean extBgra; //!< GL_EXT_bgra or GL_EXT_texture_format_BGRA8888 on OpenGL ES Standard_Boolean extAnis; //!< GL_EXT_texture_filter_anisotropic diff --git a/src/OpenGl/OpenGl_FrameBuffer.cxx b/src/OpenGl/OpenGl_FrameBuffer.cxx index 4d45461cd0..6304afdee4 100644 --- a/src/OpenGl/OpenGl_FrameBuffer.cxx +++ b/src/OpenGl/OpenGl_FrameBuffer.cxx @@ -20,22 +20,6 @@ IMPLEMENT_STANDARD_HANDLE (OpenGl_FrameBuffer, OpenGl_Resource) IMPLEMENT_STANDARD_RTTIEXT(OpenGl_FrameBuffer, OpenGl_Resource) -static inline bool isOddNumber (const GLsizei theNumber) -{ - return theNumber & 0x01; -} - -static inline GLsizei getEvenNumber (const GLsizei theNumber) -{ - return isOddNumber (theNumber) ? (theNumber + 1) : theNumber; -} - -//! Notice - 0 is not power of two here -static inline bool isPowerOfTwo (const GLsizei theNumber) -{ - return !(theNumber & (theNumber - 1)); -} - // ======================================================================= // function : OpenGl_FrameBuffer // purpose : @@ -176,6 +160,24 @@ void OpenGl_FrameBuffer::BindBuffer (const Handle(OpenGl_Context)& theGlCtx) theGlCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, myGlFBufferId); } +// ======================================================================= +// function : BindDrawBuffer +// purpose : +// ======================================================================= +void OpenGl_FrameBuffer::BindDrawBuffer (const Handle(OpenGl_Context)& theGlCtx) +{ + theGlCtx->arbFBO->glBindFramebuffer (GL_DRAW_FRAMEBUFFER, myGlFBufferId); +} + +// ======================================================================= +// function : BindReadBuffer +// purpose : +// ======================================================================= +void OpenGl_FrameBuffer::BindReadBuffer (const Handle(OpenGl_Context)& theGlCtx) +{ + theGlCtx->arbFBO->glBindFramebuffer (GL_READ_FRAMEBUFFER, myGlFBufferId); +} + // ======================================================================= // function : UnbindBuffer // purpose : diff --git a/src/OpenGl/OpenGl_FrameBuffer.hxx b/src/OpenGl/OpenGl_FrameBuffer.hxx index 3a4eeb4530..b091e50aae 100644 --- a/src/OpenGl/OpenGl_FrameBuffer.hxx +++ b/src/OpenGl/OpenGl_FrameBuffer.hxx @@ -92,9 +92,15 @@ public: Standard_EXPORT void ChangeViewport (const GLsizei theVPSizeX, const GLsizei theVPSizeY); - //! Bind frame buffer (to render into the texture). + //! Bind frame buffer for drawing and reading (to render into the texture). Standard_EXPORT virtual void BindBuffer (const Handle(OpenGl_Context)& theGlCtx); + //! Bind frame buffer for drawing GL_DRAW_FRAMEBUFFER (to render into the texture). + Standard_EXPORT virtual void BindDrawBuffer (const Handle(OpenGl_Context)& theGlCtx); + + //! Bind frame buffer for reading GL_READ_FRAMEBUFFER + Standard_EXPORT virtual void BindReadBuffer (const Handle(OpenGl_Context)& theGlCtx); + //! Unbind frame buffer. Standard_EXPORT virtual void UnbindBuffer (const Handle(OpenGl_Context)& theGlCtx); diff --git a/src/OpenGl/OpenGl_GlFunctions.hxx b/src/OpenGl/OpenGl_GlFunctions.hxx index 79d2b2fbd1..1cc3f037cb 100644 --- a/src/OpenGl/OpenGl_GlFunctions.hxx +++ b/src/OpenGl/OpenGl_GlFunctions.hxx @@ -95,6 +95,9 @@ #define GL_UNSIGNED_INT_24_8 0x84FA #define GL_DEPTH24_STENCIL8 0x88F0 + #define GL_READ_FRAMEBUFFER 0x8CA8 + #define GL_DRAW_FRAMEBUFFER 0x8CA9 + // GL_EXT_texture_filter_anisotropic #define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE #define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF @@ -688,6 +691,11 @@ public: //! @name OpenGL ES 2.0 ::glVertexAttribPointer (index, size, type, normalized, stride, pointer); } +public: //! @name OpenGL ES 3.0 + + typedef void (*glBlitFramebuffer_t)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); + glBlitFramebuffer_t glBlitFramebuffer; + #else // OpenGL ES vs. desktop public: //! @name OpenGL 1.2 diff --git a/src/OpenGl/OpenGl_ShaderManager.cxx b/src/OpenGl/OpenGl_ShaderManager.cxx index e00d2e4e23..b63be61e45 100644 --- a/src/OpenGl/OpenGl_ShaderManager.cxx +++ b/src/OpenGl/OpenGl_ShaderManager.cxx @@ -234,6 +234,7 @@ void OpenGl_ShaderManager::clear() myFlatPrograms = OpenGl_SetOfShaderPrograms(); myMapOfLightPrograms.Clear(); myFontProgram.Nullify(); + myBlitProgram.Nullify(); switchLightPrograms(); } @@ -1030,6 +1031,69 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFont() return Standard_True; } +// ======================================================================= +// function : prepareStdProgramFboBlit +// purpose : +// ======================================================================= +Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFboBlit() +{ + Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram(); + TCollection_AsciiString aSrcVert = + EOL"THE_SHADER_OUT vec2 TexCoord;" + EOL"void main()" + EOL"{" + EOL" TexCoord = occVertex.zw;" + EOL" gl_Position = vec4(occVertex.x, occVertex.y, 0.0, 1.0);" + EOL"}"; + + TCollection_AsciiString aSrcFrag = + EOL"uniform sampler2D uColorSampler;" + EOL"uniform sampler2D uDepthSampler;" + EOL + EOL"THE_SHADER_IN vec2 TexCoord;" + EOL + EOL"void main()" + EOL"{" + EOL" gl_FragDepth = occTexture2D (uDepthSampler, TexCoord).r;" + EOL" occFragColor = occTexture2D (uColorSampler, TexCoord);" + EOL"}"; + +#if defined(GL_ES_VERSION_2_0) + if (myContext->IsGlGreaterEqual (3, 0)) + { + aProgramSrc->SetHeader ("#version 300 es"); + } + else + { + // there is no way to draw into depth buffer + aSrcFrag = + EOL"uniform sampler2D uColorSampler;" + EOL + EOL"THE_SHADER_IN vec2 TexCoord;" + EOL + EOL"void main()" + EOL"{" + EOL" occFragColor = occTexture2D (uColorSampler, TexCoord);" + EOL"}"; + } +#endif + + aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert)); + aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag)); + TCollection_AsciiString aKey; + if (!Create (aProgramSrc, aKey, myBlitProgram)) + { + myBlitProgram = new OpenGl_ShaderProgram(); // just mark as invalid + return Standard_False; + } + + myContext->BindProgram (myBlitProgram); + myBlitProgram->SetSampler (myContext, "uColorSampler", 0); + myBlitProgram->SetSampler (myContext, "uDepthSampler", 1); + myContext->BindProgram (NULL); + return Standard_True; +} + // ======================================================================= // function : prepareStdProgramFlat // purpose : diff --git a/src/OpenGl/OpenGl_ShaderManager.hxx b/src/OpenGl/OpenGl_ShaderManager.hxx index d4ab02ce46..adab135d22 100644 --- a/src/OpenGl/OpenGl_ShaderManager.hxx +++ b/src/OpenGl/OpenGl_ShaderManager.hxx @@ -145,6 +145,17 @@ public: return bindProgramWithState (myFontProgram, theAspect); } + //! Bind program for FBO blit operation. + Standard_Boolean BindFboBlitProgram() + { + if (myBlitProgram.IsNull()) + { + prepareStdProgramFboBlit(); + } + return !myBlitProgram.IsNull() + && myContext->BindProgram (myBlitProgram); + } + public: //! Returns current state of OCCT light sources. @@ -292,6 +303,9 @@ protected: //! Prepare standard GLSL program for textured font. Standard_EXPORT Standard_Boolean prepareStdProgramFont(); + //! Prepare standard GLSL program for FBO blit operation. + Standard_EXPORT Standard_Boolean prepareStdProgramFboBlit(); + //! Prepare standard GLSL program without lighting. Standard_EXPORT Standard_Boolean prepareStdProgramFlat (Handle(OpenGl_ShaderProgram)& theProgram, const Standard_Integer theBits); @@ -331,6 +345,7 @@ protected: Handle(OpenGl_SetOfShaderPrograms) myLightPrograms; //!< pointer to active lighting programs matrix OpenGl_SetOfShaderPrograms myFlatPrograms; //!< programs matrix without lighting Handle(OpenGl_ShaderProgram) myFontProgram; //!< standard program for textured text + Handle(OpenGl_ShaderProgram) myBlitProgram; //!< standard program for FBO blit emulation OpenGl_MapOfShaderPrograms myMapOfLightPrograms; //!< map of lighting programs depending on shading model and lights configuration OpenGl_Context* myContext; //!< OpenGL context diff --git a/src/OpenGl/OpenGl_ShaderProgram.cxx b/src/OpenGl/OpenGl_ShaderProgram.cxx index a539ac7aa8..d88dc092bf 100755 --- a/src/OpenGl/OpenGl_ShaderProgram.cxx +++ b/src/OpenGl/OpenGl_ShaderProgram.cxx @@ -155,6 +155,10 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)& return Standard_False; } + TCollection_AsciiString aHeader = !myProxy.IsNull() && !myProxy->Header().IsEmpty() + ? (myProxy->Header() + "\n") + : TCollection_AsciiString(); + TCollection_AsciiString aDeclarations; aDeclFile.Open (OSD_ReadOnly, OSD_Protection()); aDeclFile.Read (aDeclarations, (int)aDeclFile.Size()); @@ -216,7 +220,7 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)& { case Graphic3d_TOS_VERTEX: { - aSource = TCollection_AsciiString ("#define VERTEX_SHADER\n") + aSource; + aSource = aHeader + TCollection_AsciiString ("#define VERTEX_SHADER\n") + aSource; break; } case Graphic3d_TOS_FRAGMENT: @@ -225,7 +229,7 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)& TCollection_AsciiString aPrefix (theCtx->hasHighp ? "precision highp float;\n" : "precision mediump float;\n"); - aSource = aPrefix + aSource; + aSource = aHeader + aPrefix + aSource; #endif break; } @@ -644,7 +648,7 @@ Standard_Boolean OpenGl_ShaderProgram::SetAttributeName (const Handle(OpenGl_Con theCtx->core20fwd->glBindAttribLocation (myProgramID, theIndex, theName); return Standard_True; } - + // ======================================================================= // function : SetAttribute // purpose : diff --git a/src/OpenGl/OpenGl_View_2.cxx b/src/OpenGl/OpenGl_View_2.cxx index 7980367b15..9fe7f64585 100644 --- a/src/OpenGl/OpenGl_View_2.cxx +++ b/src/OpenGl/OpenGl_View_2.cxx @@ -306,8 +306,8 @@ void OpenGl_View::Render (const Handle(OpenGl_PrinterContext)& thePrintContext, myBVHSelector.SetViewVolume (myCamera); } - const Handle(OpenGl_ShaderManager) aManager = aContext->ShaderManager(); - const Standard_Boolean isSameView = aManager->IsSameView (this); // force camera state update when needed + const Handle(OpenGl_ShaderManager)& aManager = aContext->ShaderManager(); + const Standard_Boolean isSameView = aManager->IsSameView (this); // force camera state update when needed if (StateInfo (myCurrLightSourceState, aManager->LightSourceState().Index()) != myLastLightSourceState) { aManager->UpdateLightSourceStateTo (&myLights); diff --git a/src/OpenGl/OpenGl_Workspace.cxx b/src/OpenGl/OpenGl_Workspace.cxx index c0e1d1a827..80e6ff1366 100644 --- a/src/OpenGl/OpenGl_Workspace.cxx +++ b/src/OpenGl/OpenGl_Workspace.cxx @@ -14,6 +14,7 @@ // commercial license or contractual agreement. #include +#include #include @@ -26,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -179,6 +181,7 @@ OpenGl_Workspace::OpenGl_Workspace (const Handle(OpenGl_GraphicDriver)& theDrive PolygonOffset_applied (THE_DEFAULT_POFFSET) { myGlContext->core11fwd->glPixelStorei (GL_UNPACK_ALIGNMENT, 1); + myResultFBO = new OpenGl_FrameBuffer(); if (!myGlContext->GetResource ("OpenGl_LineAttributes", myLineAttribs)) { @@ -234,6 +237,16 @@ OpenGl_Workspace::~OpenGl_Workspace() myGlContext->ReleaseResource ("OpenGl_LineAttributes", Standard_True); } + if (!myResultFBO.IsNull()) + { + myResultFBO->Release (myGlContext.operator->()); + myResultFBO.Nullify(); + } + if (myFullScreenQuad.IsValid()) + { + myFullScreenQuad.Release (myGlContext.operator->()); + } + ReleaseRaytraceResources(); } @@ -655,6 +668,22 @@ void OpenGl_Workspace::Redraw (const Graphic3d_CView& theCView, aGlCtx->core11fwd->glViewport (0, 0, myWidth, myHeight); } + Standard_Integer aSizeX = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeX() : myWidth; + Standard_Integer aSizeY = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeY() : myHeight; + + if (myResultFBO->GetVPSizeX() != aSizeX + || myResultFBO->GetVPSizeY() != aSizeY) + { + myResultFBO->Init (aGlCtx, aSizeX, aSizeY); + } + if (myResultFBO->IsValid()) + { + myResultFBO->SetupViewport (aGlCtx); + } + + const Standard_Boolean isImmediate = myView->HasImmediateStructures() + || myResultFBO->IsValid(); + myToRedrawGL = Standard_True; if (theCView.RenderParams.Method == Graphic3d_RM_RAYTRACING && myComputeInitStatus != OpenGl_RT_FAIL) @@ -668,9 +697,6 @@ void OpenGl_Workspace::Redraw (const Graphic3d_CView& theCView, myRaytraceFilter->SetPrevRenderFilter (aRenderFilter); SetRenderFilter (myRaytraceFilter); - Standard_Integer aSizeX = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeX() : myWidth; - Standard_Integer aSizeY = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeY() : myHeight; - if (myOpenGlFBO.IsNull()) { myOpenGlFBO = new OpenGl_FrameBuffer(); @@ -690,13 +716,13 @@ void OpenGl_Workspace::Redraw (const Graphic3d_CView& theCView, redraw1 (theCView, anEmptyCLayer, anEmptyCLayer, 0); myOpenGlFBO->UnbindBuffer (aGlCtx); - const Standard_Boolean isImmediate = myView->HasImmediateStructures(); Raytrace (theCView, aSizeX, aSizeY, isImmediate ? 0 : toSwap, - theCOverLayer, theCUnderLayer, aFrameBuffer); + theCOverLayer, theCUnderLayer, + myResultFBO->IsValid() ? myResultFBO.operator->() : aFrameBuffer); if (isImmediate) { - RedrawImmediate (theCView, theCUnderLayer, theCOverLayer, Standard_True); + RedrawImmediate (theCView, theCUnderLayer, theCOverLayer, Standard_True, aFrameBuffer); } SetRenderFilter (aRenderFilter); @@ -708,16 +734,19 @@ void OpenGl_Workspace::Redraw (const Graphic3d_CView& theCView, if (myToRedrawGL) { // draw entire frame using normal OpenGL pipeline - if (aFrameBuffer != NULL) + if (myResultFBO->IsValid()) + { + myResultFBO->BindBuffer (aGlCtx); + } + else if (aFrameBuffer != NULL) { aFrameBuffer->BindBuffer (aGlCtx); } - const Standard_Boolean isImmediate = myView->HasImmediateStructures(); redraw1 (theCView, theCUnderLayer, theCOverLayer, isImmediate ? 0 : toSwap); if (isImmediate) { - RedrawImmediate (theCView, theCUnderLayer, theCOverLayer, Standard_True); + RedrawImmediate (theCView, theCUnderLayer, theCOverLayer, Standard_True, aFrameBuffer); } theCView.WasRedrawnGL = Standard_True; @@ -902,7 +931,8 @@ void OpenGl_Workspace::DisplayCallback (const Graphic3d_CView& theCView, void OpenGl_Workspace::RedrawImmediate (const Graphic3d_CView& theCView, const Aspect_CLayer2d& theCUnderLayer, const Aspect_CLayer2d& theCOverLayer, - const Standard_Boolean theToForce) + const Standard_Boolean theToForce, + OpenGl_FrameBuffer* theTargetFBO) { if (!Activate()) { @@ -913,7 +943,8 @@ void OpenGl_Workspace::RedrawImmediate (const Graphic3d_CView& theCView, #if !defined(GL_ES_VERSION_2_0) glGetBooleanv (GL_DOUBLEBUFFER, &isDoubleBuffer); #endif - if (!myView->HasImmediateStructures()) + if (!myView->HasImmediateStructures() + && !myResultFBO->IsValid()) { if (theToForce || !myIsImmediateDrawn) @@ -935,7 +966,94 @@ void OpenGl_Workspace::RedrawImmediate (const Graphic3d_CView& theCView, return; } - if (isDoubleBuffer && myTransientDrawToFront) + if (myResultFBO->IsValid() + && myGlContext->IsRender()) + { + if (!myBackBufferRestored) + { + Redraw (theCView, theCUnderLayer, theCOverLayer); + return; + } + + // clear destination before blitting + if (theTargetFBO != NULL) + { + theTargetFBO->BindBuffer (myGlContext); + } + else + { + myGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); + } + #if !defined(GL_ES_VERSION_2_0) + myGlContext->core20fwd->glClearDepth (1.0); + #else + myGlContext->core20fwd->glClearDepthf (1.0f); + #endif + myGlContext->core20fwd->glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + + /*#if !defined(GL_ES_VERSION_2_0) + if (myGlContext->arbFBOBlit != NULL) + { + myResultFBO->BindReadBuffer (myGlContext); + if (theTargetFBO != NULL) + { + theTargetFBO->BindDrawBuffer (myGlContext); + } + else + { + myGlContext->arbFBO->glBindFramebuffer (GL_DRAW_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); + } + // we don't copy stencil buffer here... does it matter for performance? + myGlContext->arbFBOBlit->glBlitFramebuffer (0, 0, myResultFBO->GetVPSizeX(), myResultFBO->GetVPSizeY(), + 0, 0, myResultFBO->GetVPSizeX(), myResultFBO->GetVPSizeY(), + GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); + + if (theTargetFBO != NULL) + { + theTargetFBO->BindBuffer (myGlContext); + } + else + { + myGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); + } + } + else + #endif*/ + { + myGlContext->core20fwd->glDepthFunc (GL_ALWAYS); + myGlContext->core20fwd->glDepthMask (GL_TRUE); + myGlContext->core20fwd->glEnable (GL_DEPTH_TEST); + + DisableTexture(); + if (!myFullScreenQuad.IsValid()) + { + OpenGl_Vec4 aQuad[4] = + { + OpenGl_Vec4( 1.0f, -1.0f, 1.0f, 0.0f), + OpenGl_Vec4( 1.0f, 1.0f, 1.0f, 1.0f), + OpenGl_Vec4(-1.0f, -1.0f, 0.0f, 0.0f), + OpenGl_Vec4(-1.0f, 1.0f, 0.0f, 1.0f) + }; + myFullScreenQuad.Init (myGlContext, 4, 4, aQuad[0].GetData()); + } + + const Handle(OpenGl_ShaderManager)& aManager = myGlContext->ShaderManager(); + if (myFullScreenQuad.IsValid() + && aManager->BindFboBlitProgram()) + { + myResultFBO->ColorTexture() ->Bind (myGlContext, GL_TEXTURE0 + 0); + myResultFBO->DepthStencilTexture()->Bind (myGlContext, GL_TEXTURE0 + 1); + myFullScreenQuad.BindVertexAttrib (myGlContext, 0); + + myGlContext->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4); + + myFullScreenQuad.UnbindVertexAttrib (myGlContext, 0); + myResultFBO->DepthStencilTexture()->Unbind (myGlContext, GL_TEXTURE0 + 1); + myResultFBO->ColorTexture() ->Unbind (myGlContext, GL_TEXTURE0 + 0); + } + } + } + else if (isDoubleBuffer && myTransientDrawToFront) { if (!myBackBufferRestored) { @@ -994,7 +1112,16 @@ void OpenGl_Workspace::RedrawImmediate (const Graphic3d_CView& theCView, aStructure->Render (aWS); } - if (isDoubleBuffer && myTransientDrawToFront) + if (myResultFBO->IsValid()) + { + if (theTargetFBO == NULL + && myGlContext->IsRender() + && !myGlContext->caps->buffersNoSwap) + { + myGlContext->SwapBuffers(); + } + } + else if (isDoubleBuffer && myTransientDrawToFront) { glFlush(); MakeBackBufCurrent(); diff --git a/src/OpenGl/OpenGl_Workspace.hxx b/src/OpenGl/OpenGl_Workspace.hxx index 54509757b6..2c8523f664 100644 --- a/src/OpenGl/OpenGl_Workspace.hxx +++ b/src/OpenGl/OpenGl_Workspace.hxx @@ -152,7 +152,8 @@ public: void RedrawImmediate (const Graphic3d_CView& theCView, const Aspect_CLayer2d& theCUnderLayer, const Aspect_CLayer2d& theCOverLayer, - const Standard_Boolean theToForce = Standard_False); + const Standard_Boolean theToForce = Standard_False, + OpenGl_FrameBuffer* theTargetFBO = NULL); void Invalidate (const Graphic3d_CView& /*theCView*/) { @@ -626,6 +627,12 @@ protected: //! @name fields related to ray-tracing //! Framebuffer (FBO) for pre-raytrace rendering by OpenGL. Handle(OpenGl_FrameBuffer) myOpenGlFBO; + //! Framebuffer stores cached main presentation of the view (without presentation of immediate layers). + Handle(OpenGl_FrameBuffer) myResultFBO; + + //! Vertices for full-screen quad rendering. + OpenGl_VertexBuffer myFullScreenQuad; + //! State of OpenGL view. Standard_Size myViewModificationStatus; //! State of OpenGL layer list. diff --git a/src/Shaders/Declarations.glsl b/src/Shaders/Declarations.glsl index 15f88375f2..8b6ec4b222 100644 --- a/src/Shaders/Declarations.glsl +++ b/src/Shaders/Declarations.glsl @@ -18,12 +18,31 @@ #define THE_MAX_LIGHTS 8 #define THE_MAX_CLIP_PLANES 8 +// compatibility macros +#if (__VERSION__ >= 130) + #define THE_ATTRIBUTE in + #define THE_SHADER_IN in + #define THE_SHADER_OUT out + #define THE_OUT out + #define occTexture2D texture +#else + #define THE_ATTRIBUTE attribute + #define THE_SHADER_IN varying + #define THE_SHADER_OUT varying + #define THE_OUT + #define occTexture2D texture2D +#endif + // Vertex attributes #ifdef VERTEX_SHADER - attribute vec4 occVertex; - attribute vec3 occNormal; - attribute vec4 occTexCoord; - attribute vec4 occVertColor; + THE_ATTRIBUTE vec4 occVertex; + THE_ATTRIBUTE vec3 occNormal; + THE_ATTRIBUTE vec4 occTexCoord; + THE_ATTRIBUTE vec4 occVertColor; +#elif (__VERSION__ >= 130) + out vec4 occFragColor; +#else + #define occFragColor gl_FragColor #endif // Matrix state diff --git a/tests/3rdparty/end b/tests/3rdparty/end index a818ecc36c..c816e7efca 100755 --- a/tests/3rdparty/end +++ b/tests/3rdparty/end @@ -1,3 +1,4 @@ +vglinfo vdump $imagedir/${test_image}.png puts "" diff --git a/tests/mesh/end b/tests/mesh/end index 0f8acd80f6..b9ed015721 100644 --- a/tests/mesh/end +++ b/tests/mesh/end @@ -190,6 +190,7 @@ if { [info exists test_image ] == 0 } { } if { [string compare $command "shading"] == 0 } { + vglinfo vdump $imagedir/${test_image}.png } else { isos 0