From: kgv Date: Tue, 23 Dec 2014 19:50:47 +0000 (+0300) Subject: 0025091: Visualization - use FBO for layer with immediate objects X-Git-Url: http://git.dev.opencascade.org/gitweb/?a=commitdiff_plain;h=36b459e7e814956dae361c1e3415a2a984cf9303;p=occt-copy.git 0025091: Visualization - use FBO for layer with immediate objects --- diff --git a/src/OpenGl/OpenGl_FrameBuffer.cxx b/src/OpenGl/OpenGl_FrameBuffer.cxx index 4d45461cd0..6b8cd97363 100644 --- a/src/OpenGl/OpenGl_FrameBuffer.cxx +++ b/src/OpenGl/OpenGl_FrameBuffer.cxx @@ -176,6 +176,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_Structure.cxx b/src/OpenGl/OpenGl_Structure.cxx index a4013e8b5d..c567017efb 100644 --- a/src/OpenGl/OpenGl_Structure.cxx +++ b/src/OpenGl/OpenGl_Structure.cxx @@ -73,10 +73,10 @@ public: const Handle(OpenGl_Texture) aPrevTexture = theWorkspace->DisableTexture(); glDisable (GL_LIGHTING); - if ((theWorkspace->NamedStatus & OPENGL_NS_IMMEDIATE) != 0) + /**if ((theWorkspace->NamedStatus & OPENGL_NS_IMMEDIATE) != 0) { glDepthMask (GL_FALSE); - } + }*/ // Use highlight colors theWorkspace->GetGlContext()->core11->glColor3fv ((theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) ? theWorkspace->HighlightColor->rgb : anAspectLine->Color().rgb); diff --git a/src/OpenGl/OpenGl_Workspace.cxx b/src/OpenGl/OpenGl_Workspace.cxx index c737d42a66..1d2b049c25 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 @@ -180,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)) { @@ -235,6 +237,12 @@ OpenGl_Workspace::~OpenGl_Workspace() myGlContext->ReleaseResource ("OpenGl_LineAttributes", Standard_True); } + if (!myResultFBO.IsNull()) + { + myResultFBO->Release (myGlContext.operator->()); + myResultFBO.Nullify(); + } + ReleaseRaytraceResources(); } @@ -650,6 +658,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->ImmediateStructures().IsEmpty() + || myResultFBO->IsValid(); + myToRedrawGL = Standard_True; if (theCView.RenderParams.Method == Graphic3d_RM_RAYTRACING && myComputeInitStatus != OpenGl_RT_FAIL) @@ -663,9 +687,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(); @@ -685,13 +706,13 @@ void OpenGl_Workspace::Redraw (const Graphic3d_CView& theCView, redraw1 (theCView, anEmptyCLayer, anEmptyCLayer, 0); myOpenGlFBO->UnbindBuffer (aGlCtx); - const Standard_Boolean isImmediate = !myView->ImmediateStructures().IsEmpty(); 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); @@ -703,16 +724,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->ImmediateStructures().IsEmpty(); 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; @@ -896,7 +920,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()) { @@ -907,7 +932,8 @@ void OpenGl_Workspace::RedrawImmediate (const Graphic3d_CView& theCView, #if !defined(GL_ES_VERSION_2_0) glGetBooleanv (GL_DOUBLEBUFFER, &isDoubleBuffer); #endif - if (myView->ImmediateStructures().IsEmpty()) + if (myView->ImmediateStructures().IsEmpty() + && !myResultFBO->IsValid()) { if (theToForce || !myIsImmediateDrawn) @@ -929,7 +955,36 @@ void OpenGl_Workspace::RedrawImmediate (const Graphic3d_CView& theCView, return; } - if (isDoubleBuffer && myTransientDrawToFront) + if (myResultFBO->IsValid()) + { + if (!myBackBufferRestored) + { + Redraw (theCView, theCUnderLayer, theCOverLayer); + return; + } + + myResultFBO->BindReadBuffer (myGlContext); + if (theTargetFBO != NULL) + { + theTargetFBO->BindDrawBuffer (myGlContext); + } + else + { + myGlContext->arbFBO->glBindFramebuffer (GL_DRAW_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); + } + myGlContext->arbFBO->glBlitFramebuffer (0, 0, myResultFBO->GetVPSizeX(), myResultFBO->GetVPSizeY(), + 0, 0, myResultFBO->GetVPSizeX(), myResultFBO->GetVPSizeY(), + GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); + if (theTargetFBO != NULL) + { + theTargetFBO->BindBuffer (myGlContext); + } + else + { + myGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER); + } + } + else if (isDoubleBuffer && myTransientDrawToFront) { if (!myBackBufferRestored) { @@ -946,8 +1001,11 @@ void OpenGl_Workspace::RedrawImmediate (const Graphic3d_CView& theCView, myIsImmediateDrawn = Standard_True; NamedStatus |= OPENGL_NS_IMMEDIATE; - ///glDisable (GL_LIGHTING); - glDisable (GL_DEPTH_TEST); + + ///glDisable (GL_DEPTH_TEST); + glDepthFunc (GL_LEQUAL); + glDepthMask (GL_TRUE); + glEnable (GL_DEPTH_TEST); Handle(OpenGl_Workspace) aWS (this); for (OpenGl_SequenceOfStructure::Iterator anIter (myView->ImmediateStructures()); @@ -969,7 +1027,14 @@ void OpenGl_Workspace::RedrawImmediate (const Graphic3d_CView& theCView, NamedStatus &= ~OPENGL_NS_IMMEDIATE; - if (isDoubleBuffer && myTransientDrawToFront) + if (myResultFBO->IsValid()) + { + if (theTargetFBO == NULL) + { + myGlContext->SwapBuffers(); + } + } + else if (isDoubleBuffer && myTransientDrawToFront) { glFlush(); MakeBackBufCurrent(); diff --git a/src/OpenGl/OpenGl_Workspace.hxx b/src/OpenGl/OpenGl_Workspace.hxx index 5d02e15610..43d2c3eab7 100644 --- a/src/OpenGl/OpenGl_Workspace.hxx +++ b/src/OpenGl/OpenGl_Workspace.hxx @@ -160,7 +160,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*/) { @@ -642,6 +643,8 @@ protected: //! @name fields related to ray-tracing //! Framebuffer (FBO) for pre-raytrace rendering by OpenGL. Handle(OpenGl_FrameBuffer) myOpenGlFBO; + Handle(OpenGl_FrameBuffer) myResultFBO; + //! State of OpenGL view. Standard_Size myViewModificationStatus; //! State of OpenGL layer list.