aNbSamples = OpenGl_Context::GetPowerOfTwo (aNbSamples, aCtx->MaxMsaaSamples());
}
+ bool toUseOit = myRenderParams.TransparencyMethod == Graphic3d_RTM_BLEND_OIT
+ && checkOitCompatibility (aCtx, aNbSamples > 0);
+
+ const bool toInitImmediateFbo = myTransientDrawToFront
+ && (!aCtx->caps->useSystemBuffer || (toUseOit && HasImmediateStructures()));
+
if ( aFrameBuffer == NULL
&& !aCtx->DefaultFrameBuffer().IsNull()
&& aCtx->DefaultFrameBuffer()->IsValid())
&& (myTransientDrawToFront
|| aProjectType == Graphic3d_Camera::Projection_Stereo
|| aNbSamples != 0
+ || toUseOit
|| aSizeX != aRendSizeX))
{
if (myMainSceneFbos[0]->GetVPSizeX() != aRendSizeX
{
myMainSceneFbos[0]->Init (aCtx, aRendSizeX, aRendSizeY, myFboColorFormat, myFboDepthFormat, aNbSamples);
}
- if (myTransientDrawToFront
- && !aCtx->caps->useSystemBuffer
- && myMainSceneFbos[0]->IsValid())
- {
- myImmediateSceneFbos[0]->InitLazy (aCtx, *myMainSceneFbos[0]);
- }
+ }
+ if (myMainSceneFbos[0]->IsValid() && (toInitImmediateFbo || myImmediateSceneFbos[0]->IsValid()))
+ {
+ myImmediateSceneFbos[0]->InitLazy (aCtx, *myMainSceneFbos[0]);
}
}
else
}
}
+ // create color and coverage accumulation buffers required for OIT algorithm
+ if (toUseOit)
+ {
+ Standard_Integer anFboIt = 0;
+ for (; anFboIt < 2; ++anFboIt)
+ {
+ Handle(OpenGl_FrameBuffer)& aMainSceneFbo = myMainSceneFbos [anFboIt];
+ Handle(OpenGl_FrameBuffer)& aMainSceneFboOit = myMainSceneFbosOit [anFboIt];
+ Handle(OpenGl_FrameBuffer)& anImmediateSceneFbo = myImmediateSceneFbos [anFboIt];
+ Handle(OpenGl_FrameBuffer)& anImmediateSceneFboOit = myImmediateSceneFbosOit[anFboIt];
+ if (aMainSceneFbo->IsValid()
+ && (aMainSceneFboOit->GetVPSizeX() != aRendSizeX
+ || aMainSceneFboOit->GetVPSizeY() != aRendSizeY
+ || aMainSceneFboOit->NbSamples() != aNbSamples))
+ {
+ Standard_Integer aColorConfig = 0;
+ for (;;) // seemly responding to driver limitation (GL_FRAMEBUFFER_UNSUPPORTED)
+ {
+ if (myFboOitColorConfig.IsEmpty())
+ {
+ if (!chooseOitColorConfiguration (aCtx, aColorConfig++, myFboOitColorConfig))
+ {
+ break;
+ }
+ }
+ if (aMainSceneFboOit->Init (aCtx, aRendSizeX, aRendSizeY, myFboOitColorConfig, aMainSceneFbo->DepthStencilTexture(), aNbSamples))
+ {
+ break;
+ }
+ myFboOitColorConfig.Clear();
+ }
+ if (!aMainSceneFboOit->IsValid())
+ {
+ break;
+ }
+ }
+ else if (!aMainSceneFbo->IsValid())
+ {
+ aMainSceneFboOit->Release (aCtx.operator->());
+ aMainSceneFboOit->ChangeViewport (0, 0);
+ }
+
+ if (anImmediateSceneFbo->IsValid()
+ && (anImmediateSceneFboOit->GetVPSizeX() != aRendSizeX
+ || anImmediateSceneFboOit->GetVPSizeY() != aRendSizeY
+ || anImmediateSceneFboOit->NbSamples() != aNbSamples))
+ {
+ if (!anImmediateSceneFboOit->Init (aCtx, aRendSizeX, aRendSizeY, myFboOitColorConfig,
+ anImmediateSceneFbo->DepthStencilTexture(), aNbSamples))
+ {
+ break;
+ }
+ }
+ else if (!anImmediateSceneFbo->IsValid())
+ {
+ anImmediateSceneFboOit->Release (aCtx.operator->());
+ anImmediateSceneFboOit->ChangeViewport (0, 0);
+ }
+ }
+ if (anFboIt == 0) // only the first OIT framebuffer is mandatory
+ {
+ aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
+ "Initialization of float texture framebuffer for use with\n"
+ " blended order-independent transparency rendering algorithm has failed.\n"
+ " Blended order-independent transparency will not be available.\n");
+ if (aNbSamples > 0)
+ {
+ myToDisableOITMSAA = Standard_True;
+ }
+ else
+ {
+ myToDisableOIT = Standard_True;
+ }
+ toUseOit = false;
+ }
+ }
+ if (!toUseOit && myMainSceneFbosOit[0]->IsValid())
+ {
+ myMainSceneFbosOit [0]->Release (aCtx.operator->());
+ myMainSceneFbosOit [1]->Release (aCtx.operator->());
+ myImmediateSceneFbosOit[0]->Release (aCtx.operator->());
+ myImmediateSceneFbosOit[1]->Release (aCtx.operator->());
+ myMainSceneFbosOit [0]->ChangeViewport (0, 0);
+ myMainSceneFbosOit [1]->ChangeViewport (0, 0);
+ myImmediateSceneFbosOit[0]->ChangeViewport (0, 0);
+ myImmediateSceneFbosOit[1]->ChangeViewport (0, 0);
+ }
+
if (aProjectType == Graphic3d_Camera::Projection_Stereo)
{
OpenGl_FrameBuffer* aMainFbos[2] =
myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL,
myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL
};
+ OpenGl_FrameBuffer* aMainFbosOit[2] =
+ {
+ myMainSceneFbosOit[0]->IsValid() ? myMainSceneFbosOit[0].operator->() : NULL,
+ myMainSceneFbosOit[1]->IsValid() ? myMainSceneFbosOit[1].operator->() :
+ myMainSceneFbosOit[0]->IsValid() ? myMainSceneFbosOit[0].operator->() : NULL
+ };
+
OpenGl_FrameBuffer* anImmFbos[2] =
{
myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL,
myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL
};
+ OpenGl_FrameBuffer* anImmFbosOit[2] =
+ {
+ myImmediateSceneFbosOit[0]->IsValid() ? myImmediateSceneFbosOit[0].operator->() : NULL,
+ myImmediateSceneFbosOit[1]->IsValid() ? myImmediateSceneFbosOit[1].operator->() :
+ myImmediateSceneFbosOit[0]->IsValid() ? myImmediateSceneFbosOit[0].operator->() : NULL
+ };
if (!myTransientDrawToFront)
{
- anImmFbos[0] = aMainFbos[0];
- anImmFbos[1] = aMainFbos[1];
+ anImmFbos [0] = aMainFbos [0];
+ anImmFbos [1] = aMainFbos [1];
+ anImmFbosOit[0] = aMainFbosOit[0];
+ anImmFbosOit[1] = aMainFbosOit[1];
}
else if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip
|| aStereoMode == Graphic3d_StereoMode_QuadBuffer)
{
- anImmFbos[0] = NULL;
- anImmFbos[1] = NULL;
+ anImmFbos [0] = NULL;
+ anImmFbos [1] = NULL;
+ anImmFbosOit[0] = NULL;
+ anImmFbosOit[1] = NULL;
}
#if !defined(GL_ES_VERSION_2_0)
aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(),
aMainFbos[0] != NULL ? myRenderParams.RenderResolutionScale : 1.0f);
- redraw (Graphic3d_Camera::Projection_MonoLeftEye, aMainFbos[0]);
+ redraw (Graphic3d_Camera::Projection_MonoLeftEye, aMainFbos[0], aMainFbosOit[0]);
myBackBufferRestored = Standard_True;
myIsImmediateDrawn = Standard_False;
#if !defined(GL_ES_VERSION_2_0)
#endif
aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(),
anImmFbos[0] != NULL ? myRenderParams.RenderResolutionScale : 1.0f);
- if (!redrawImmediate (Graphic3d_Camera::Projection_MonoLeftEye, aMainFbos[0], anImmFbos[0]))
+ if (!redrawImmediate (Graphic3d_Camera::Projection_MonoLeftEye, aMainFbos[0], anImmFbos[0], anImmFbosOit[0]))
{
toSwap = false;
}
aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(),
aMainFbos[1] != NULL ? myRenderParams.RenderResolutionScale : 1.0f);
- redraw (Graphic3d_Camera::Projection_MonoRightEye, aMainFbos[1]);
+ redraw (Graphic3d_Camera::Projection_MonoRightEye, aMainFbos[1], aMainFbosOit[1]);
myBackBufferRestored = Standard_True;
myIsImmediateDrawn = Standard_False;
aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(),
anImmFbos[1] != NULL ? myRenderParams.RenderResolutionScale : 1.0f);
- if (!redrawImmediate (Graphic3d_Camera::Projection_MonoRightEye, aMainFbos[1], anImmFbos[1]))
+ if (!redrawImmediate (Graphic3d_Camera::Projection_MonoRightEye, aMainFbos[1], anImmFbos[1], anImmFbosOit[1]))
{
toSwap = false;
}
}
else
{
- OpenGl_FrameBuffer* aMainFbo = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : aFrameBuffer;
- OpenGl_FrameBuffer* anImmFbo = aFrameBuffer;
- if (!aCtx->caps->useSystemBuffer && myImmediateSceneFbos[0]->IsValid())
+ OpenGl_FrameBuffer* aMainFbo = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : aFrameBuffer;
+ OpenGl_FrameBuffer* aMainFboOit = myMainSceneFbosOit[0]->IsValid() ? myMainSceneFbosOit[0].operator->() : NULL;
+ OpenGl_FrameBuffer* anImmFbo = aFrameBuffer;
+ OpenGl_FrameBuffer* anImmFboOit = NULL;
+ if (!myTransientDrawToFront)
{
- anImmFbo = myImmediateSceneFbos[0].operator->();
+ anImmFbo = aMainFbo;
+ anImmFboOit = aMainFboOit;
}
- if (!myTransientDrawToFront)
+ else if (myImmediateSceneFbos[0]->IsValid())
{
- anImmFbo = aMainFbo;
+ anImmFbo = myImmediateSceneFbos[0].operator->();
+ anImmFboOit = myImmediateSceneFbosOit[0]->IsValid() ? myImmediateSceneFbosOit[0].operator->() : NULL;
}
#if !defined(GL_ES_VERSION_2_0)
#endif
aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(),
aMainFbo != aFrameBuffer ? myRenderParams.RenderResolutionScale : 1.0f);
- redraw (aProjectType, aMainFbo);
+
+ redraw (aProjectType, aMainFbo, aMainFboOit);
myBackBufferRestored = Standard_True;
myIsImmediateDrawn = Standard_False;
aCtx->SetResolution (myRenderParams.Resolution, myRenderParams.ResolutionRatio(),
anImmFbo != aFrameBuffer ? myRenderParams.RenderResolutionScale : 1.0f);
- if (!redrawImmediate (aProjectType, aMainFbo, anImmFbo))
+ if (!redrawImmediate (aProjectType, aMainFbo, anImmFbo, anImmFboOit))
{
toSwap = false;
}
myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL,
myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL
};
+ OpenGl_FrameBuffer* anImmFbosOit[2] =
+ {
+ myImmediateSceneFbosOit[0]->IsValid() ? myImmediateSceneFbosOit[0].operator->() : NULL,
+ myImmediateSceneFbosOit[1]->IsValid() ? myImmediateSceneFbosOit[1].operator->() :
+ myImmediateSceneFbosOit[0]->IsValid() ? myImmediateSceneFbosOit[0].operator->() : NULL
+ };
if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip
|| aStereoMode == Graphic3d_StereoMode_QuadBuffer)
{
- anImmFbos[0] = NULL;
- anImmFbos[1] = NULL;
+ anImmFbos[0] = NULL;
+ anImmFbos[1] = NULL;
+ anImmFbosOit[0] = NULL;
+ anImmFbosOit[1] = NULL;
}
if (aCtx->arbFBO != NULL)
toSwap = redrawImmediate (Graphic3d_Camera::Projection_MonoLeftEye,
aMainFbos[0],
anImmFbos[0],
+ anImmFbosOit[0],
Standard_True) || toSwap;
if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip
&& toSwap
toSwap = redrawImmediate (Graphic3d_Camera::Projection_MonoRightEye,
aMainFbos[1],
anImmFbos[1],
+ anImmFbosOit[1],
Standard_True) || toSwap;
if (anImmFbos[0] != NULL)
{
{
OpenGl_FrameBuffer* aMainFbo = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL;
OpenGl_FrameBuffer* anImmFbo = aFrameBuffer;
- if (!aCtx->caps->useSystemBuffer && myImmediateSceneFbos[0]->IsValid())
+ OpenGl_FrameBuffer* anImmFboOit = NULL;
+ if (myImmediateSceneFbos[0]->IsValid())
{
- anImmFbo = myImmediateSceneFbos[0].operator->();
+ anImmFbo = myImmediateSceneFbos[0].operator->();
+ anImmFboOit = myImmediateSceneFbosOit[0]->IsValid() ? myImmediateSceneFbosOit[0].operator->() : NULL;
}
#if !defined(GL_ES_VERSION_2_0)
if (aMainFbo == NULL)
toSwap = redrawImmediate (aProjectType,
aMainFbo,
anImmFbo,
+ anImmFboOit,
Standard_True) || toSwap;
if (anImmFbo != NULL
&& anImmFbo != aFrameBuffer)
// function : redraw
// purpose :
// =======================================================================
-void OpenGl_View::redraw (const Graphic3d_Camera::Projection theProjection, OpenGl_FrameBuffer* theReadDrawFbo)
+void OpenGl_View::redraw (const Graphic3d_Camera::Projection theProjection,
+ OpenGl_FrameBuffer* theReadDrawFbo,
+ OpenGl_FrameBuffer* theOitAccumFbo)
{
Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
if (theReadDrawFbo != NULL)
glClear (toClear);
- render (theProjection, theReadDrawFbo, Standard_False);
+ render (theProjection, theReadDrawFbo, theOitAccumFbo, Standard_False);
}
// =======================================================================
// purpose :
// =======================================================================
bool OpenGl_View::redrawImmediate (const Graphic3d_Camera::Projection theProjection,
- OpenGl_FrameBuffer* theReadFbo,
- OpenGl_FrameBuffer* theDrawFbo,
- const Standard_Boolean theIsPartialUpdate)
+ OpenGl_FrameBuffer* theReadFbo,
+ OpenGl_FrameBuffer* theDrawFbo,
+ OpenGl_FrameBuffer* theOitAccumFbo,
+ const Standard_Boolean theIsPartialUpdate)
{
Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
GLboolean toCopyBackToFront = GL_FALSE;
glClearDepthf (1.0f);
#endif
- render (theProjection, theDrawFbo, Standard_True);
+ render (theProjection, theDrawFbo, theOitAccumFbo, Standard_True);
return !toCopyBackToFront;
}
//=======================================================================
void OpenGl_View::render (Graphic3d_Camera::Projection theProjection,
OpenGl_FrameBuffer* theOutputFBO,
+ OpenGl_FrameBuffer* theOitAccumFbo,
const Standard_Boolean theToDrawImmediate)
{
// ==================================
myWorkspace->SetEnvironmentTexture (myTextureEnv);
- renderScene (theProjection, theOutputFBO, theToDrawImmediate);
+ renderScene (theProjection, theOutputFBO, theOitAccumFbo, theToDrawImmediate);
myWorkspace->SetEnvironmentTexture (Handle(OpenGl_Texture)());
//=======================================================================
void OpenGl_View::renderStructs (Graphic3d_Camera::Projection theProjection,
OpenGl_FrameBuffer* theReadDrawFbo,
+ OpenGl_FrameBuffer* theOitAccumFbo,
const Standard_Boolean theToDrawImmediate)
{
if ( myZLayers.NbStructures() <= 0 )
if (aCtx->arbFBOBlit != NULL)
{
// Render bottom OSD layer
- myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_Bottom);
+ myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_Bottom, theReadDrawFbo, theOitAccumFbo);
myWorkspace->SetRenderFilter (myRaytraceFilter);
{
}
// Render non-polygonal elements in default layer
- myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_Default);
+ myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_Default, theReadDrawFbo, theOitAccumFbo);
}
myWorkspace->SetRenderFilter (myRaytraceFilter->PrevRenderFilter());
}
raytrace (aSizeX, aSizeY, theProjection, theReadDrawFbo, aCtx);
// Render upper (top and topmost) OpenGL layers
- myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_Upper);
+ myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_Upper, theReadDrawFbo, theOitAccumFbo);
}
}
// mode or in case of ray-tracing failure
if (toRenderGL)
{
- myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_All);
+ myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_All, theReadDrawFbo, theOitAccumFbo);
// Set flag that scene was redrawn by standard pipeline
myWasRedrawnGL = Standard_True;
//=======================================================================
void OpenGl_View::renderScene (Graphic3d_Camera::Projection theProjection,
OpenGl_FrameBuffer* theReadDrawFbo,
+ OpenGl_FrameBuffer* theOitAccumFbo,
const Standard_Boolean theToDrawImmediate)
{
const Handle(OpenGl_Context)& aContext = myWorkspace->GetGlContext();
aContext->ShaderManager()->UpdateClippingState();
}
- renderStructs (theProjection, theReadDrawFbo, theToDrawImmediate);
+ renderStructs (theProjection, theReadDrawFbo, theOitAccumFbo, theToDrawImmediate);
myWorkspace->DisableTexture();
// Apply restored view matrix.
#endif
aCtx->core20fwd->glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
-#if !defined(GL_ES_VERSION_2_0)
if (aCtx->arbFBOBlit != NULL
&& theReadFbo->NbSamples() != 0)
{
}
}
else
-#endif
{
aCtx->core20fwd->glDepthFunc (GL_ALWAYS);
aCtx->core20fwd->glDepthMask (GL_TRUE);
#endif
myIsImmediateDrawn = Standard_False;
}
+
+// =======================================================================
+// function : checkOitCompatibility
+// purpose :
+// =======================================================================
+Standard_Boolean OpenGl_View::checkOitCompatibility (const Handle(OpenGl_Context)& theGlContext,
+ const Standard_Boolean theMSAA)
+{
+ // determine if OIT is supported by current OpenGl context
+ Standard_Boolean& aToDisableOIT = theMSAA ? myToDisableMSAA : myToDisableOIT;
+ if (aToDisableOIT)
+ {
+ return Standard_False;
+ }
+
+ TCollection_ExtendedString aCompatibilityMsg;
+ if (!theGlContext->hasFloatBuffer
+ && !theGlContext->hasHalfFloatBuffer)
+ {
+ aCompatibilityMsg += "OpenGL context does not support floating-point RGBA color buffer format.\n";
+ }
+ if (theMSAA && !theGlContext->hasSampleVariables)
+ {
+ aCompatibilityMsg += "Current version of GLSL does not support built-in sample variables.\n";
+ }
+ if (!theGlContext->hasDrawBuffers)
+ {
+ aCompatibilityMsg += "OpenGL context does not support multiple draw buffers.\n";
+ }
+ if (aCompatibilityMsg.IsEmpty())
+ {
+ return Standard_True;
+ }
+
+ aCompatibilityMsg += " Blended order-independent transparency will not be available.\n";
+ theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
+ GL_DEBUG_TYPE_ERROR,
+ 0,
+ GL_DEBUG_SEVERITY_HIGH,
+ aCompatibilityMsg);
+
+ aToDisableOIT = Standard_True;
+ return Standard_False;
+}
+
+// =======================================================================
+// function : chooseOitColorConfiguration
+// purpose :
+// =======================================================================
+bool OpenGl_View::chooseOitColorConfiguration (const Handle(OpenGl_Context)& theGlContext,
+ const Standard_Integer theConfigIndex,
+ OpenGl_ColorFormats& theFormats)
+{
+ theFormats.Clear();
+ switch (theConfigIndex)
+ {
+ case 0: // choose best applicable color format combination
+ {
+ theFormats.Append (theGlContext->hasHalfFloatBuffer ? GL_RGBA16F : GL_RGBA32F);
+ theFormats.Append (theGlContext->hasHalfFloatBuffer ? GL_R16F : GL_R32F);
+ return true;
+ }
+ case 1: // choose non-optimal applicable color format combination
+ {
+ theFormats.Append (theGlContext->hasHalfFloatBuffer ? GL_RGBA16F : GL_RGBA32F);
+ theFormats.Append (theGlContext->hasHalfFloatBuffer ? GL_RGBA16F : GL_RGBA32F);
+ return true;
+ }
+ }
+ return false; // color combination does not exist
+}