mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-04 18:06:22 +03:00
Classes Aspect_Clayer2d,OpenGl_GrahpicDriver_Layer, Visual3d_Layer, Visual3d_LayerItem, V3d_LayerMgr, V3d_LayerMgrPointer were deleted. Method OpenGl_GraphicDriver::TextSize() was moved to OpenGl_GraphicDriver.cxx. Update V3d/FILES Documentation updated.
1594 lines
50 KiB
C++
1594 lines
50 KiB
C++
// Created on: 2011-09-20
|
|
// Created by: Sergey ZERCHANINOV
|
|
// Copyright (c) 2011-2014 OPEN CASCADE SAS
|
|
//
|
|
// This file is part of Open CASCADE Technology software library.
|
|
//
|
|
// This library is free software; you can redistribute it and/or modify it under
|
|
// the terms of the GNU Lesser General Public License version 2.1 as published
|
|
// by the Free Software Foundation, with special exception defined in the file
|
|
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
|
// distribution for complete text of the license and disclaimer of any warranty.
|
|
//
|
|
// Alternatively, this file may be used under the terms of Open CASCADE
|
|
// commercial license or contractual agreement.
|
|
|
|
#include <OpenGl_GlCore15.hxx>
|
|
#include <OpenGl_ArbFBO.hxx>
|
|
|
|
#include <InterfaceGraphic.hxx>
|
|
|
|
#include <OpenGl_AspectLine.hxx>
|
|
#include <OpenGl_AspectFace.hxx>
|
|
#include <OpenGl_AspectMarker.hxx>
|
|
#include <OpenGl_AspectText.hxx>
|
|
#include <OpenGl_Context.hxx>
|
|
#include <OpenGl_Element.hxx>
|
|
#include <OpenGl_FrameBuffer.hxx>
|
|
#include <OpenGl_Structure.hxx>
|
|
#include <OpenGl_Sampler.hxx>
|
|
#include <OpenGl_ShaderManager.hxx>
|
|
#include <OpenGl_Texture.hxx>
|
|
#include <OpenGl_View.hxx>
|
|
#include <OpenGl_Workspace.hxx>
|
|
|
|
#include <Graphic3d_TextureParams.hxx>
|
|
#include <Graphic3d_GraphicDriver.hxx>
|
|
#include <Graphic3d_TransformUtils.hxx>
|
|
|
|
#if defined(_WIN32) && defined(HAVE_VIDEOCAPTURE)
|
|
#include <OpenGl_AVIWriter.hxx>
|
|
#endif
|
|
|
|
|
|
namespace
|
|
{
|
|
static const TEL_COLOUR THE_WHITE_COLOR = { { 1.0f, 1.0f, 1.0f, 1.0f } };
|
|
static const OpenGl_Vec4 THE_BLACK_COLOR (0.0f, 0.0f, 0.0f, 1.0f);
|
|
|
|
static const OpenGl_AspectLine myDefaultAspectLine;
|
|
static const OpenGl_AspectFace myDefaultAspectFace;
|
|
static const OpenGl_AspectMarker myDefaultAspectMarker;
|
|
static const OpenGl_AspectText myDefaultAspectText;
|
|
|
|
static const OpenGl_TextParam myDefaultTextParam =
|
|
{
|
|
16, Graphic3d_HTA_LEFT, Graphic3d_VTA_BOTTOM
|
|
};
|
|
|
|
static const OpenGl_Matrix myDefaultMatrix =
|
|
{
|
|
{{ 1.0F, 0.0F, 0.0F, 0.0F },
|
|
{ 0.0F, 1.0F, 0.0F, 0.0F },
|
|
{ 0.0F, 0.0F, 1.0F, 0.0F },
|
|
{ 0.0F, 0.0F, 0.0F, 1.0F }}
|
|
};
|
|
|
|
};
|
|
|
|
// =======================================================================
|
|
// function : Init
|
|
// purpose :
|
|
// =======================================================================
|
|
void OpenGl_Material::Init (const OPENGL_SURF_PROP& theProp)
|
|
{
|
|
// ambient component
|
|
if (theProp.color_mask & OPENGL_AMBIENT_MASK)
|
|
{
|
|
const float* aSrcAmb = theProp.isphysic ? theProp.ambcol.rgb : theProp.matcol.rgb;
|
|
Ambient = OpenGl_Vec4 (aSrcAmb[0] * theProp.amb,
|
|
aSrcAmb[1] * theProp.amb,
|
|
aSrcAmb[2] * theProp.amb,
|
|
1.0f);
|
|
}
|
|
else
|
|
{
|
|
Ambient = THE_BLACK_COLOR;
|
|
}
|
|
|
|
// diffusion component
|
|
if (theProp.color_mask & OPENGL_DIFFUSE_MASK)
|
|
{
|
|
const float* aSrcDif = theProp.isphysic ? theProp.difcol.rgb : theProp.matcol.rgb;
|
|
Diffuse = OpenGl_Vec4 (aSrcDif[0] * theProp.diff,
|
|
aSrcDif[1] * theProp.diff,
|
|
aSrcDif[2] * theProp.diff,
|
|
1.0f);
|
|
}
|
|
else
|
|
{
|
|
Diffuse = THE_BLACK_COLOR;
|
|
}
|
|
|
|
// specular component
|
|
if (theProp.color_mask & OPENGL_SPECULAR_MASK)
|
|
{
|
|
const float* aSrcSpe = theProp.isphysic ? theProp.speccol.rgb : THE_WHITE_COLOR.rgb;
|
|
Specular = OpenGl_Vec4 (aSrcSpe[0] * theProp.spec,
|
|
aSrcSpe[1] * theProp.spec,
|
|
aSrcSpe[2] * theProp.spec,
|
|
1.0f);
|
|
}
|
|
else
|
|
{
|
|
Specular = THE_BLACK_COLOR;
|
|
}
|
|
|
|
// emission component
|
|
if (theProp.color_mask & OPENGL_EMISSIVE_MASK)
|
|
{
|
|
const float* aSrcEms = theProp.isphysic ? theProp.emscol.rgb : theProp.matcol.rgb;
|
|
Emission = OpenGl_Vec4 (aSrcEms[0] * theProp.emsv,
|
|
aSrcEms[1] * theProp.emsv,
|
|
aSrcEms[2] * theProp.emsv,
|
|
1.0f);
|
|
}
|
|
else
|
|
{
|
|
Emission = THE_BLACK_COLOR;
|
|
}
|
|
|
|
ChangeShine() = theProp.shine;
|
|
ChangeTransparency() = theProp.trans;
|
|
}
|
|
|
|
// =======================================================================
|
|
// function : OpenGl_Workspace
|
|
// purpose :
|
|
// =======================================================================
|
|
OpenGl_Workspace::OpenGl_Workspace (const Handle(OpenGl_GraphicDriver)& theDriver,
|
|
const CALL_DEF_WINDOW& theCWindow,
|
|
Aspect_RenderingContext theGContext,
|
|
const Handle(OpenGl_Caps)& theCaps,
|
|
const Handle(OpenGl_Context)& theShareCtx)
|
|
: OpenGl_Window (theDriver, theCWindow, theGContext, theCaps, theShareCtx),
|
|
NamedStatus (0),
|
|
HighlightColor (&THE_WHITE_COLOR),
|
|
//
|
|
myHasFboBlit (Standard_True),
|
|
myToFlipOutput (Standard_False),
|
|
//
|
|
myViewId (-1),
|
|
myAntiAliasingMode (3),
|
|
myTransientDrawToFront (Standard_True),
|
|
myBackBufferRestored (Standard_False),
|
|
myIsImmediateDrawn (Standard_False),
|
|
myUseZBuffer (Standard_True),
|
|
myUseDepthWrite (Standard_True),
|
|
myUseGLLight (Standard_True),
|
|
myIsCullingEnabled (Standard_False),
|
|
myFrameCounter (0),
|
|
//
|
|
AspectLine_set (&myDefaultAspectLine),
|
|
AspectLine_applied (NULL),
|
|
AspectFace_set (&myDefaultAspectFace),
|
|
AspectFace_applied (NULL),
|
|
AspectMarker_set (&myDefaultAspectMarker),
|
|
AspectMarker_applied (NULL),
|
|
AspectText_set (&myDefaultAspectText),
|
|
AspectText_applied (NULL),
|
|
TextParam_set (&myDefaultTextParam),
|
|
TextParam_applied (NULL),
|
|
ViewMatrix_applied (&myDefaultMatrix),
|
|
StructureMatrix_applied (&myDefaultMatrix),
|
|
myCullingMode (TelCullUndefined),
|
|
myModelViewMatrix (myDefaultMatrix),
|
|
PolygonOffset_applied (THE_DEFAULT_POFFSET)
|
|
{
|
|
myGlContext->core11fwd->glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
|
|
myMainSceneFbos[0] = new OpenGl_FrameBuffer();
|
|
myMainSceneFbos[1] = new OpenGl_FrameBuffer();
|
|
myImmediateSceneFbos[0] = new OpenGl_FrameBuffer();
|
|
myImmediateSceneFbos[1] = new OpenGl_FrameBuffer();
|
|
|
|
if (!myGlContext->GetResource ("OpenGl_LineAttributes", myLineAttribs))
|
|
{
|
|
// share and register for release once the resource is no longer used
|
|
myLineAttribs = new OpenGl_LineAttributes();
|
|
myGlContext->ShareResource ("OpenGl_LineAttributes", myLineAttribs);
|
|
myLineAttribs->Init (myGlContext);
|
|
}
|
|
|
|
// General initialization of the context
|
|
|
|
#if !defined(GL_ES_VERSION_2_0)
|
|
if (myGlContext->core11 != NULL)
|
|
{
|
|
// Eviter d'avoir les faces mal orientees en noir.
|
|
// Pourrait etre utiliser pour detecter les problemes d'orientation
|
|
glLightModeli ((GLenum )GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
|
|
|
|
// Optimisation pour le Fog et l'antialiasing
|
|
glHint (GL_FOG_HINT, GL_FASTEST);
|
|
glHint (GL_POINT_SMOOTH_HINT, GL_FASTEST);
|
|
}
|
|
|
|
glHint (GL_LINE_SMOOTH_HINT, GL_FASTEST);
|
|
glHint (GL_POLYGON_SMOOTH_HINT, GL_FASTEST);
|
|
#endif
|
|
|
|
// AA mode
|
|
const char* anAaEnv = ::getenv ("CALL_OPENGL_ANTIALIASING_MODE");
|
|
if (anAaEnv != NULL)
|
|
{
|
|
int v;
|
|
if (sscanf (anAaEnv, "%d", &v) > 0) myAntiAliasingMode = v;
|
|
}
|
|
|
|
myDefaultCappingAlgoFilter = new OpenGl_CappingAlgoFilter();
|
|
myNoneCulling.ChangeCullingMode() = TelCullNone;
|
|
myNoneCulling.ChangeEdge() = 0;
|
|
myFrontCulling.ChangeCullingMode() = TelCullBack;
|
|
myFrontCulling.ChangeEdge() = 0;
|
|
}
|
|
|
|
// =======================================================================
|
|
// function : SetActiveView
|
|
// purpose :
|
|
// =======================================================================
|
|
void OpenGl_Workspace::SetActiveView (const Handle(OpenGl_View)& theView,
|
|
const Standard_Integer theViewId)
|
|
{
|
|
myView = theView;
|
|
myViewId = theViewId;
|
|
}
|
|
|
|
// =======================================================================
|
|
// function : SetImmediateModeDrawToFront
|
|
// purpose :
|
|
// =======================================================================
|
|
Standard_Boolean OpenGl_Workspace::SetImmediateModeDrawToFront (const Standard_Boolean theDrawToFrontBuffer)
|
|
{
|
|
const Standard_Boolean aPrevMode = myTransientDrawToFront;
|
|
myTransientDrawToFront = theDrawToFrontBuffer;
|
|
return aPrevMode;
|
|
}
|
|
|
|
inline void nullifyGlResource (Handle(OpenGl_Resource)& theResource,
|
|
const Handle(OpenGl_Context)& theCtx)
|
|
{
|
|
if (!theResource.IsNull())
|
|
{
|
|
theResource->Release (theCtx.operator->());
|
|
theResource.Nullify();
|
|
}
|
|
}
|
|
|
|
// =======================================================================
|
|
// function : ~OpenGl_Workspace
|
|
// purpose :
|
|
// =======================================================================
|
|
OpenGl_Workspace::~OpenGl_Workspace()
|
|
{
|
|
if (!myLineAttribs.IsNull())
|
|
{
|
|
myLineAttribs.Nullify();
|
|
myGlContext->ReleaseResource ("OpenGl_LineAttributes", Standard_True);
|
|
}
|
|
|
|
nullifyGlResource (myMainSceneFbos[0], myGlContext);
|
|
nullifyGlResource (myMainSceneFbos[1], myGlContext);
|
|
nullifyGlResource (myImmediateSceneFbos[0], myGlContext);
|
|
nullifyGlResource (myImmediateSceneFbos[1], myGlContext);
|
|
|
|
myFullScreenQuad .Release (myGlContext.operator->());
|
|
myFullScreenQuadFlip.Release (myGlContext.operator->());
|
|
}
|
|
|
|
// =======================================================================
|
|
// function : Activate
|
|
// purpose :
|
|
// =======================================================================
|
|
Standard_Boolean OpenGl_Workspace::Activate()
|
|
{
|
|
if (!OpenGl_Window::Activate())
|
|
return Standard_False;
|
|
|
|
ViewMatrix_applied = &myDefaultMatrix;
|
|
StructureMatrix_applied = &myDefaultMatrix;
|
|
|
|
ResetAppliedAspect();
|
|
|
|
return Standard_True;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : ResetAppliedAspect
|
|
//purpose : Sets default values of GL parameters in accordance with default aspects
|
|
//=======================================================================
|
|
void OpenGl_Workspace::ResetAppliedAspect()
|
|
{
|
|
myGlContext->BindDefaultVao();
|
|
|
|
NamedStatus = !myTextureBound.IsNull() ? OPENGL_NS_TEXTURE : 0;
|
|
HighlightColor = &THE_WHITE_COLOR;
|
|
AspectLine_set = &myDefaultAspectLine;
|
|
AspectLine_applied = NULL;
|
|
AspectFace_set = &myDefaultAspectFace;
|
|
AspectFace_applied = NULL;
|
|
AspectMarker_set = &myDefaultAspectMarker;
|
|
AspectMarker_applied = NULL;
|
|
AspectText_set = &myDefaultAspectText;
|
|
AspectText_applied = NULL;
|
|
TextParam_set = &myDefaultTextParam;
|
|
TextParam_applied = NULL;
|
|
PolygonOffset_applied = THE_DEFAULT_POFFSET;
|
|
myCullingMode = TelCullUndefined;
|
|
|
|
AspectLine(Standard_True);
|
|
AspectFace(Standard_True);
|
|
AspectMarker(Standard_True);
|
|
AspectText(Standard_True);
|
|
|
|
myGlContext->SetTypeOfLine (myDefaultAspectLine.Type());
|
|
myGlContext->SetLineWidth (myDefaultAspectLine.Width());
|
|
}
|
|
|
|
// =======================================================================
|
|
// function : DisableTexture
|
|
// purpose :
|
|
// =======================================================================
|
|
Handle(OpenGl_Texture) OpenGl_Workspace::DisableTexture()
|
|
{
|
|
if (myTextureBound.IsNull())
|
|
{
|
|
return myTextureBound;
|
|
}
|
|
|
|
const Handle(OpenGl_Sampler)& aSampler = myGlContext->TextureSampler();
|
|
if (!aSampler.IsNull())
|
|
{
|
|
aSampler->Unbind (*myGlContext);
|
|
}
|
|
|
|
#if !defined(GL_ES_VERSION_2_0)
|
|
// reset texture matrix because some code may expect it is identity
|
|
if (myGlContext->core11 != NULL)
|
|
{
|
|
GLint aMatrixMode = GL_TEXTURE;
|
|
glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode);
|
|
glMatrixMode (GL_TEXTURE);
|
|
glLoadIdentity();
|
|
glMatrixMode (aMatrixMode);
|
|
}
|
|
#endif
|
|
|
|
myTextureBound->Unbind (myGlContext);
|
|
switch (myTextureBound->GetTarget())
|
|
{
|
|
#if !defined(GL_ES_VERSION_2_0)
|
|
case GL_TEXTURE_1D:
|
|
{
|
|
if (myGlContext->core11 != NULL)
|
|
{
|
|
if (myTextureBound->GetParams()->GenMode() != GL_NONE)
|
|
{
|
|
glDisable (GL_TEXTURE_GEN_S);
|
|
}
|
|
glDisable (GL_TEXTURE_1D);
|
|
}
|
|
break;
|
|
}
|
|
#endif
|
|
case GL_TEXTURE_2D:
|
|
{
|
|
#if !defined(GL_ES_VERSION_2_0)
|
|
if (myGlContext->core11 != NULL)
|
|
{
|
|
if (myTextureBound->GetParams()->GenMode() != GL_NONE)
|
|
{
|
|
glDisable (GL_TEXTURE_GEN_S);
|
|
glDisable (GL_TEXTURE_GEN_T);
|
|
if (myTextureBound->GetParams()->GenMode() == Graphic3d_TOTM_SPRITE)
|
|
{
|
|
glDisable (GL_POINT_SPRITE);
|
|
}
|
|
}
|
|
glDisable (GL_TEXTURE_2D);
|
|
}
|
|
#endif
|
|
break;
|
|
}
|
|
default: break;
|
|
}
|
|
|
|
Handle(OpenGl_Texture) aPrevTexture = myTextureBound;
|
|
myTextureBound.Nullify();
|
|
return aPrevTexture;
|
|
}
|
|
|
|
// =======================================================================
|
|
// function : setTextureParams
|
|
// purpose :
|
|
// =======================================================================
|
|
void OpenGl_Workspace::setTextureParams (Handle(OpenGl_Texture)& theTexture,
|
|
const Handle(Graphic3d_TextureParams)& theParams)
|
|
{
|
|
const Handle(Graphic3d_TextureParams)& aParams = theParams.IsNull() ? theTexture->GetParams() : theParams;
|
|
if (aParams.IsNull())
|
|
{
|
|
return;
|
|
}
|
|
|
|
#if !defined(GL_ES_VERSION_2_0)
|
|
GLint aMatrixMode = GL_TEXTURE;
|
|
if (myGlContext->core11 != NULL)
|
|
{
|
|
glGetIntegerv (GL_MATRIX_MODE, &aMatrixMode);
|
|
|
|
// setup texture matrix
|
|
glMatrixMode (GL_TEXTURE);
|
|
OpenGl_Mat4 aTextureMat;
|
|
const Graphic3d_Vec2& aScale = aParams->Scale();
|
|
const Graphic3d_Vec2& aTrans = aParams->Translation();
|
|
Graphic3d_TransformUtils::Scale (aTextureMat, aScale.x(), aScale.y(), 1.0f);
|
|
Graphic3d_TransformUtils::Translate (aTextureMat, -aTrans.x(), -aTrans.y(), 0.0f);
|
|
Graphic3d_TransformUtils::Rotate (aTextureMat, -aParams->Rotation(), 0.0f, 0.0f, 1.0f);
|
|
glLoadMatrixf (aTextureMat);
|
|
|
|
GLint anEnvMode = GL_MODULATE; // lighting mode
|
|
if (!aParams->IsModulate())
|
|
{
|
|
anEnvMode = GL_DECAL;
|
|
if (theTexture->GetFormat() == GL_ALPHA
|
|
|| theTexture->GetFormat() == GL_LUMINANCE)
|
|
{
|
|
anEnvMode = GL_REPLACE;
|
|
}
|
|
}
|
|
|
|
// setup generation of texture coordinates
|
|
switch (aParams->GenMode())
|
|
{
|
|
case Graphic3d_TOTM_OBJECT:
|
|
{
|
|
glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
|
|
glTexGenfv (GL_S, GL_OBJECT_PLANE, aParams->GenPlaneS().GetData());
|
|
if (theTexture->GetTarget() != GL_TEXTURE_1D)
|
|
{
|
|
glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
|
|
glTexGenfv (GL_T, GL_OBJECT_PLANE, aParams->GenPlaneT().GetData());
|
|
}
|
|
break;
|
|
}
|
|
case Graphic3d_TOTM_SPHERE:
|
|
{
|
|
glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
|
|
if (theTexture->GetTarget() != GL_TEXTURE_1D)
|
|
{
|
|
glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
|
|
}
|
|
break;
|
|
}
|
|
case Graphic3d_TOTM_EYE:
|
|
{
|
|
myGlContext->WorldViewState.Push();
|
|
|
|
myGlContext->WorldViewState.SetIdentity();
|
|
myGlContext->ApplyWorldViewMatrix();
|
|
|
|
glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
|
|
glTexGenfv (GL_S, GL_EYE_PLANE, aParams->GenPlaneS().GetData());
|
|
|
|
if (theTexture->GetTarget() != GL_TEXTURE_1D)
|
|
{
|
|
glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
|
|
glTexGenfv (GL_T, GL_EYE_PLANE, aParams->GenPlaneT().GetData());
|
|
}
|
|
|
|
myGlContext->WorldViewState.Pop();
|
|
|
|
break;
|
|
}
|
|
case Graphic3d_TOTM_SPRITE:
|
|
{
|
|
if (GetGlContext()->core20fwd != NULL)
|
|
{
|
|
glEnable (GL_POINT_SPRITE);
|
|
glTexEnvi (GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
|
|
anEnvMode = GL_REPLACE;
|
|
GetGlContext()->core15->glPointParameteri (GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
|
|
}
|
|
break;
|
|
}
|
|
case Graphic3d_TOTM_MANUAL:
|
|
default: break;
|
|
}
|
|
|
|
// setup lighting
|
|
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, anEnvMode);
|
|
}
|
|
#endif
|
|
|
|
// get active sampler object to override default texture parameters
|
|
const Handle(OpenGl_Sampler)& aSampler = myGlContext->TextureSampler();
|
|
|
|
// setup texture filtering and wrapping
|
|
//if (theTexture->GetParams() != theParams)
|
|
const GLenum aFilter = (aParams->Filter() == Graphic3d_TOTF_NEAREST) ? GL_NEAREST : GL_LINEAR;
|
|
const GLenum aWrapMode = aParams->IsRepeat() ? GL_REPEAT : myGlContext->TextureWrapClamp();
|
|
switch (theTexture->GetTarget())
|
|
{
|
|
#if !defined(GL_ES_VERSION_2_0)
|
|
case GL_TEXTURE_1D:
|
|
{
|
|
if (aSampler.IsNull() || !aSampler->IsValid())
|
|
{
|
|
glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, aFilter);
|
|
glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, aFilter);
|
|
glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, aWrapMode);
|
|
}
|
|
else
|
|
{
|
|
aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAG_FILTER, aFilter);
|
|
aSampler->SetParameter (*myGlContext, GL_TEXTURE_MIN_FILTER, aFilter);
|
|
aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_S, aWrapMode);
|
|
}
|
|
|
|
break;
|
|
}
|
|
#endif
|
|
case GL_TEXTURE_2D:
|
|
{
|
|
GLenum aFilterMin = aFilter;
|
|
if (theTexture->HasMipmaps())
|
|
{
|
|
aFilterMin = GL_NEAREST_MIPMAP_NEAREST;
|
|
if (aParams->Filter() == Graphic3d_TOTF_BILINEAR)
|
|
{
|
|
aFilterMin = GL_LINEAR_MIPMAP_NEAREST;
|
|
}
|
|
else if (aParams->Filter() == Graphic3d_TOTF_TRILINEAR)
|
|
{
|
|
aFilterMin = GL_LINEAR_MIPMAP_LINEAR;
|
|
}
|
|
|
|
if (myGlContext->extAnis)
|
|
{
|
|
// setup degree of anisotropy filter
|
|
const GLint aMaxDegree = myGlContext->MaxDegreeOfAnisotropy();
|
|
GLint aDegree;
|
|
switch (aParams->AnisoFilter())
|
|
{
|
|
case Graphic3d_LOTA_QUALITY:
|
|
{
|
|
aDegree = aMaxDegree;
|
|
break;
|
|
}
|
|
case Graphic3d_LOTA_MIDDLE:
|
|
{
|
|
aDegree = (aMaxDegree <= 4) ? 2 : (aMaxDegree / 2);
|
|
break;
|
|
}
|
|
case Graphic3d_LOTA_FAST:
|
|
{
|
|
aDegree = 2;
|
|
break;
|
|
}
|
|
case Graphic3d_LOTA_OFF:
|
|
default:
|
|
{
|
|
aDegree = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (aSampler.IsNull() || !aSampler->IsValid())
|
|
{
|
|
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, aDegree);
|
|
}
|
|
else
|
|
{
|
|
aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAX_ANISOTROPY_EXT, aDegree);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (aSampler.IsNull() || !aSampler->IsValid())
|
|
{
|
|
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, aFilterMin);
|
|
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, aFilter);
|
|
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, aWrapMode);
|
|
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, aWrapMode);
|
|
}
|
|
else
|
|
{
|
|
aSampler->SetParameter (*myGlContext, GL_TEXTURE_MIN_FILTER, aFilterMin);
|
|
aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAG_FILTER, aFilter);
|
|
aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_S, aWrapMode);
|
|
aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_T, aWrapMode);
|
|
}
|
|
|
|
break;
|
|
}
|
|
default: break;
|
|
}
|
|
|
|
switch (theTexture->GetTarget())
|
|
{
|
|
#if !defined(GL_ES_VERSION_2_0)
|
|
case GL_TEXTURE_1D:
|
|
{
|
|
if (myGlContext->core11 != NULL)
|
|
{
|
|
if (aParams->GenMode() != Graphic3d_TOTM_MANUAL)
|
|
{
|
|
glEnable (GL_TEXTURE_GEN_S);
|
|
}
|
|
glEnable (GL_TEXTURE_1D);
|
|
}
|
|
break;
|
|
}
|
|
#endif
|
|
case GL_TEXTURE_2D:
|
|
{
|
|
#if !defined(GL_ES_VERSION_2_0)
|
|
if (myGlContext->core11 != NULL)
|
|
{
|
|
if (aParams->GenMode() != Graphic3d_TOTM_MANUAL)
|
|
{
|
|
glEnable (GL_TEXTURE_GEN_S);
|
|
glEnable (GL_TEXTURE_GEN_T);
|
|
}
|
|
glEnable (GL_TEXTURE_2D);
|
|
}
|
|
#endif
|
|
break;
|
|
}
|
|
default: break;
|
|
}
|
|
|
|
#if !defined(GL_ES_VERSION_2_0)
|
|
if (myGlContext->core11 != NULL)
|
|
{
|
|
glMatrixMode (aMatrixMode); // turn back active matrix
|
|
}
|
|
#endif
|
|
theTexture->SetParams (aParams);
|
|
}
|
|
|
|
// =======================================================================
|
|
// function : EnableTexture
|
|
// purpose :
|
|
// =======================================================================
|
|
Handle(OpenGl_Texture) OpenGl_Workspace::EnableTexture (const Handle(OpenGl_Texture)& theTexture,
|
|
const Handle(Graphic3d_TextureParams)& theParams)
|
|
{
|
|
if (theTexture.IsNull() || !theTexture->IsValid())
|
|
{
|
|
return DisableTexture();
|
|
}
|
|
|
|
if (myTextureBound == theTexture
|
|
&& (theParams.IsNull() || theParams == theTexture->GetParams()))
|
|
{
|
|
// already bound
|
|
return myTextureBound;
|
|
}
|
|
|
|
Handle(OpenGl_Texture) aPrevTexture = DisableTexture();
|
|
myTextureBound = theTexture;
|
|
myTextureBound->Bind (myGlContext);
|
|
setTextureParams (myTextureBound, theParams);
|
|
|
|
// If custom sampler object is available it will be
|
|
// used for overriding default texture parameters
|
|
const Handle(OpenGl_Sampler)& aSampler = myGlContext->TextureSampler();
|
|
|
|
if (!aSampler.IsNull() && aSampler->IsValid())
|
|
{
|
|
aSampler->Bind (*myGlContext);
|
|
}
|
|
|
|
return aPrevTexture;
|
|
}
|
|
|
|
// =======================================================================
|
|
// function : bindDefaultFbo
|
|
// purpose :
|
|
// =======================================================================
|
|
void OpenGl_Workspace::bindDefaultFbo (OpenGl_FrameBuffer* theCustomFbo)
|
|
{
|
|
OpenGl_FrameBuffer* anFbo = (theCustomFbo != NULL && theCustomFbo->IsValid())
|
|
? theCustomFbo
|
|
: (!myGlContext->DefaultFrameBuffer().IsNull()
|
|
&& myGlContext->DefaultFrameBuffer()->IsValid()
|
|
? myGlContext->DefaultFrameBuffer().operator->()
|
|
: NULL);
|
|
if (anFbo != NULL)
|
|
{
|
|
anFbo->BindBuffer (myGlContext);
|
|
}
|
|
else
|
|
{
|
|
#if !defined(GL_ES_VERSION_2_0)
|
|
myGlContext->SetReadDrawBuffer (GL_BACK);
|
|
#else
|
|
if (myGlContext->arbFBO != NULL)
|
|
{
|
|
myGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
|
|
}
|
|
#endif
|
|
}
|
|
myGlContext->core11fwd->glViewport (0, 0, myWidth, myHeight);
|
|
}
|
|
|
|
// =======================================================================
|
|
// function : initBlitQuad
|
|
// purpose :
|
|
// =======================================================================
|
|
OpenGl_VertexBuffer* OpenGl_Workspace::initBlitQuad (const Standard_Boolean theToFlip)
|
|
{
|
|
OpenGl_VertexBuffer* aVerts = NULL;
|
|
if (!theToFlip)
|
|
{
|
|
aVerts = &myFullScreenQuad;
|
|
if (!aVerts->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)
|
|
};
|
|
aVerts->Init (myGlContext, 4, 4, aQuad[0].GetData());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
aVerts = &myFullScreenQuadFlip;
|
|
if (!aVerts->IsValid())
|
|
{
|
|
OpenGl_Vec4 aQuad[4] =
|
|
{
|
|
OpenGl_Vec4( 1.0f, -1.0f, 1.0f, 1.0f),
|
|
OpenGl_Vec4( 1.0f, 1.0f, 1.0f, 0.0f),
|
|
OpenGl_Vec4(-1.0f, -1.0f, 0.0f, 1.0f),
|
|
OpenGl_Vec4(-1.0f, 1.0f, 0.0f, 0.0f)
|
|
};
|
|
aVerts->Init (myGlContext, 4, 4, aQuad[0].GetData());
|
|
}
|
|
}
|
|
return aVerts;
|
|
}
|
|
|
|
// =======================================================================
|
|
// function : blitBuffers
|
|
// purpose :
|
|
// =======================================================================
|
|
bool OpenGl_Workspace::blitBuffers (OpenGl_FrameBuffer* theReadFbo,
|
|
OpenGl_FrameBuffer* theDrawFbo,
|
|
const Standard_Boolean theToFlip)
|
|
{
|
|
if (theReadFbo == NULL || myGlContext->IsFeedback())
|
|
{
|
|
return false;
|
|
}
|
|
else if (theReadFbo == theDrawFbo)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
// clear destination before blitting
|
|
if (theDrawFbo != NULL
|
|
&& theDrawFbo->IsValid())
|
|
{
|
|
theDrawFbo->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)
|
|
{
|
|
theReadFbo->BindReadBuffer (myGlContext);
|
|
if (theDrawFbo != NULL
|
|
&& theDrawFbo->IsValid())
|
|
{
|
|
theDrawFbo->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, theReadFbo->GetVPSizeX(), theReadFbo->GetVPSizeY(),
|
|
0, 0, theReadFbo->GetVPSizeX(), theReadFbo->GetVPSizeY(),
|
|
GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
|
|
|
|
if (theDrawFbo != NULL
|
|
&& theDrawFbo->IsValid())
|
|
{
|
|
theDrawFbo->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();
|
|
|
|
OpenGl_VertexBuffer* aVerts = initBlitQuad (theToFlip);
|
|
const Handle(OpenGl_ShaderManager)& aManager = myGlContext->ShaderManager();
|
|
if (aVerts->IsValid()
|
|
&& aManager->BindFboBlitProgram())
|
|
{
|
|
theReadFbo->ColorTexture() ->Bind (myGlContext, GL_TEXTURE0 + 0);
|
|
theReadFbo->DepthStencilTexture()->Bind (myGlContext, GL_TEXTURE0 + 1);
|
|
aVerts->BindVertexAttrib (myGlContext, Graphic3d_TOA_POS);
|
|
|
|
myGlContext->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
|
|
|
|
aVerts->UnbindVertexAttrib (myGlContext, Graphic3d_TOA_POS);
|
|
theReadFbo->DepthStencilTexture()->Unbind (myGlContext, GL_TEXTURE0 + 1);
|
|
theReadFbo->ColorTexture() ->Unbind (myGlContext, GL_TEXTURE0 + 0);
|
|
}
|
|
else
|
|
{
|
|
TCollection_ExtendedString aMsg = TCollection_ExtendedString()
|
|
+ "Error! FBO blitting has failed";
|
|
myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
|
|
GL_DEBUG_TYPE_ERROR_ARB,
|
|
0,
|
|
GL_DEBUG_SEVERITY_HIGH_ARB,
|
|
aMsg);
|
|
myHasFboBlit = Standard_False;
|
|
theReadFbo->Release (myGlContext.operator->());
|
|
return true;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// =======================================================================
|
|
// function : drawStereoPair
|
|
// purpose :
|
|
// =======================================================================
|
|
void OpenGl_Workspace::drawStereoPair (const Graphic3d_CView& theCView)
|
|
{
|
|
OpenGl_FrameBuffer* aPair[2] =
|
|
{
|
|
myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL,
|
|
myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL
|
|
};
|
|
if (aPair[0] == NULL
|
|
|| aPair[1] == NULL
|
|
|| !myTransientDrawToFront)
|
|
{
|
|
aPair[0] = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL;
|
|
aPair[1] = myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL;
|
|
}
|
|
|
|
if (aPair[0] == NULL
|
|
|| aPair[1] == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Standard_Boolean toReverse = theCView.RenderParams.ToReverseStereo;
|
|
const Standard_Boolean isOddY = (theCView.DefWindow.top + theCView.DefWindow.dy) % 2 == 1;
|
|
const Standard_Boolean isOddX = theCView.DefWindow.left % 2 == 1;
|
|
if (isOddY
|
|
&& (theCView.RenderParams.StereoMode == Graphic3d_StereoMode_RowInterlaced
|
|
|| theCView.RenderParams.StereoMode == Graphic3d_StereoMode_ChessBoard))
|
|
{
|
|
toReverse = !toReverse;
|
|
}
|
|
if (isOddX
|
|
&& (theCView.RenderParams.StereoMode == Graphic3d_StereoMode_ColumnInterlaced
|
|
|| theCView.RenderParams.StereoMode == Graphic3d_StereoMode_ChessBoard))
|
|
{
|
|
toReverse = !toReverse;
|
|
}
|
|
|
|
if (toReverse)
|
|
{
|
|
std::swap (aPair[0], aPair[1]);
|
|
}
|
|
|
|
myGlContext->core20fwd->glDepthFunc (GL_ALWAYS);
|
|
myGlContext->core20fwd->glDepthMask (GL_TRUE);
|
|
myGlContext->core20fwd->glEnable (GL_DEPTH_TEST);
|
|
|
|
DisableTexture();
|
|
OpenGl_VertexBuffer* aVerts = initBlitQuad (myToFlipOutput);
|
|
|
|
const Handle(OpenGl_ShaderManager)& aManager = myGlContext->ShaderManager();
|
|
if (aVerts->IsValid()
|
|
&& aManager->BindStereoProgram (theCView.RenderParams.StereoMode))
|
|
{
|
|
if (theCView.RenderParams.StereoMode == Graphic3d_StereoMode_Anaglyph)
|
|
{
|
|
OpenGl_Mat4 aFilterL, aFilterR;
|
|
aFilterL.SetDiagonal (Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
|
|
aFilterR.SetDiagonal (Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
|
|
switch (theCView.RenderParams.AnaglyphFilter)
|
|
{
|
|
case Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple:
|
|
{
|
|
aFilterL.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f));
|
|
aFilterR.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f));
|
|
aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f));
|
|
break;
|
|
}
|
|
case Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized:
|
|
{
|
|
aFilterL.SetRow (0, Graphic3d_Vec4 ( 0.4154f, 0.4710f, 0.16666667f, 0.0f));
|
|
aFilterL.SetRow (1, Graphic3d_Vec4 (-0.0458f, -0.0484f, -0.0257f, 0.0f));
|
|
aFilterL.SetRow (2, Graphic3d_Vec4 (-0.0547f, -0.0615f, 0.0128f, 0.0f));
|
|
aFilterL.SetRow (3, Graphic3d_Vec4 ( 0.0f, 0.0f, 0.0f, 0.0f));
|
|
aFilterR.SetRow (0, Graphic3d_Vec4 (-0.01090909f, -0.03636364f, -0.00606061f, 0.0f));
|
|
aFilterR.SetRow (1, Graphic3d_Vec4 ( 0.37560000f, 0.73333333f, 0.01111111f, 0.0f));
|
|
aFilterR.SetRow (2, Graphic3d_Vec4 (-0.06510000f, -0.12870000f, 1.29710000f, 0.0f));
|
|
aFilterR.SetRow (3, Graphic3d_Vec4 ( 0.0f, 0.0f, 0.0f, 0.0f));
|
|
break;
|
|
}
|
|
case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple:
|
|
{
|
|
aFilterL.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f));
|
|
aFilterL.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f));
|
|
aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f));
|
|
break;
|
|
}
|
|
case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized:
|
|
{
|
|
aFilterL.SetRow (0, Graphic3d_Vec4 ( 1.062f, -0.205f, 0.299f, 0.0f));
|
|
aFilterL.SetRow (1, Graphic3d_Vec4 (-0.026f, 0.908f, 0.068f, 0.0f));
|
|
aFilterL.SetRow (2, Graphic3d_Vec4 (-0.038f, -0.173f, 0.022f, 0.0f));
|
|
aFilterL.SetRow (3, Graphic3d_Vec4 ( 0.0f, 0.0f, 0.0f, 0.0f));
|
|
aFilterR.SetRow (0, Graphic3d_Vec4 (-0.016f, -0.123f, -0.017f, 0.0f));
|
|
aFilterR.SetRow (1, Graphic3d_Vec4 ( 0.006f, 0.062f, -0.017f, 0.0f));
|
|
aFilterR.SetRow (2, Graphic3d_Vec4 ( 0.094f, 0.185f, 0.911f, 0.0f));
|
|
aFilterR.SetRow (3, Graphic3d_Vec4 ( 0.0f, 0.0f, 0.0f, 0.0f));
|
|
break;
|
|
}
|
|
case Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple:
|
|
{
|
|
aFilterR.SetRow (0, Graphic3d_Vec4 (1.0f, 0.0f, 0.0f, 0.0f));
|
|
aFilterL.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f));
|
|
aFilterR.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f));
|
|
break;
|
|
}
|
|
case Graphic3d_RenderingParams::Anaglyph_UserDefined:
|
|
{
|
|
aFilterL = theCView.RenderParams.AnaglyphLeft;
|
|
aFilterR = theCView.RenderParams.AnaglyphRight;
|
|
break;
|
|
}
|
|
}
|
|
myGlContext->ActiveProgram()->SetUniform (myGlContext, "uMultL", aFilterL);
|
|
myGlContext->ActiveProgram()->SetUniform (myGlContext, "uMultR", aFilterR);
|
|
}
|
|
|
|
aPair[0]->ColorTexture()->Bind (myGlContext, GL_TEXTURE0 + 0);
|
|
aPair[1]->ColorTexture()->Bind (myGlContext, GL_TEXTURE0 + 1);
|
|
aVerts->BindVertexAttrib (myGlContext, 0);
|
|
|
|
myGlContext->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
|
|
|
|
aVerts->UnbindVertexAttrib (myGlContext, 0);
|
|
aPair[1]->ColorTexture()->Unbind (myGlContext, GL_TEXTURE0 + 1);
|
|
aPair[0]->ColorTexture()->Unbind (myGlContext, GL_TEXTURE0 + 0);
|
|
}
|
|
else
|
|
{
|
|
TCollection_ExtendedString aMsg = TCollection_ExtendedString()
|
|
+ "Error! Anaglyph has failed";
|
|
myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
|
|
GL_DEBUG_TYPE_ERROR_ARB,
|
|
0,
|
|
GL_DEBUG_SEVERITY_HIGH_ARB,
|
|
aMsg);
|
|
}
|
|
}
|
|
|
|
// =======================================================================
|
|
// function : Redraw
|
|
// purpose :
|
|
// =======================================================================
|
|
void OpenGl_Workspace::Redraw (const Graphic3d_CView& theCView)
|
|
{
|
|
if (!Activate())
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (mySwapInterval != myGlContext->caps->swapInterval)
|
|
{
|
|
mySwapInterval = myGlContext->caps->swapInterval;
|
|
myGlContext->SetSwapInterval (mySwapInterval);
|
|
}
|
|
|
|
++myFrameCounter;
|
|
myIsCullingEnabled = theCView.IsCullingEnabled;
|
|
const Graphic3d_StereoMode aStereoMode = theCView.RenderParams.StereoMode;
|
|
const Handle(Graphic3d_Camera)& aCamera = myView->Camera();
|
|
Graphic3d_Camera::Projection aProjectType = aCamera->ProjectionType();
|
|
|
|
// release pending GL resources
|
|
myGlContext->ReleaseDelayed();
|
|
|
|
// fetch OpenGl context state
|
|
myGlContext->FetchState();
|
|
|
|
OpenGl_FrameBuffer* aFrameBuffer = (OpenGl_FrameBuffer* )theCView.ptrFBO;
|
|
bool toSwap = myGlContext->IsRender()
|
|
&& !myGlContext->caps->buffersNoSwap
|
|
&& aFrameBuffer == NULL;
|
|
|
|
Standard_Integer aSizeX = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeX() : myWidth;
|
|
Standard_Integer aSizeY = aFrameBuffer != NULL ? aFrameBuffer->GetVPSizeY() : myHeight;
|
|
|
|
if ( aFrameBuffer == NULL
|
|
&& !myGlContext->DefaultFrameBuffer().IsNull()
|
|
&& myGlContext->DefaultFrameBuffer()->IsValid())
|
|
{
|
|
aFrameBuffer = myGlContext->DefaultFrameBuffer().operator->();
|
|
}
|
|
|
|
if (myHasFboBlit
|
|
&& (myTransientDrawToFront || aProjectType == Graphic3d_Camera::Projection_Stereo))
|
|
{
|
|
if (myMainSceneFbos[0]->GetVPSizeX() != aSizeX
|
|
|| myMainSceneFbos[0]->GetVPSizeY() != aSizeY)
|
|
{
|
|
// prepare FBOs containing main scene
|
|
// for further blitting and rendering immediate presentations on top
|
|
if (myGlContext->core20fwd != NULL)
|
|
{
|
|
myMainSceneFbos[0]->Init (myGlContext, aSizeX, aSizeY);
|
|
}
|
|
if (!myGlContext->caps->useSystemBuffer && myMainSceneFbos[0]->IsValid())
|
|
{
|
|
myImmediateSceneFbos[0]->InitLazy (myGlContext, aSizeX, aSizeY);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
myMainSceneFbos [0]->Release (myGlContext.operator->());
|
|
myMainSceneFbos [1]->Release (myGlContext.operator->());
|
|
myImmediateSceneFbos[0]->Release (myGlContext.operator->());
|
|
myImmediateSceneFbos[1]->Release (myGlContext.operator->());
|
|
myMainSceneFbos [0]->ChangeViewport (0, 0);
|
|
myMainSceneFbos [1]->ChangeViewport (0, 0);
|
|
myImmediateSceneFbos[0]->ChangeViewport (0, 0);
|
|
myImmediateSceneFbos[1]->ChangeViewport (0, 0);
|
|
}
|
|
|
|
if (aProjectType == Graphic3d_Camera::Projection_Stereo
|
|
&& myMainSceneFbos[0]->IsValid())
|
|
{
|
|
myMainSceneFbos[1]->InitLazy (myGlContext, aSizeX, aSizeY);
|
|
if (!myMainSceneFbos[1]->IsValid())
|
|
{
|
|
// no enough memory?
|
|
aProjectType = Graphic3d_Camera::Projection_Perspective;
|
|
}
|
|
else if (!myTransientDrawToFront)
|
|
{
|
|
//
|
|
}
|
|
else if (!myGlContext->HasStereoBuffers()
|
|
|| aStereoMode != Graphic3d_StereoMode_QuadBuffer)
|
|
{
|
|
myImmediateSceneFbos[0]->InitLazy (myGlContext, aSizeX, aSizeY);
|
|
myImmediateSceneFbos[1]->InitLazy (myGlContext, aSizeX, aSizeY);
|
|
if (!myImmediateSceneFbos[0]->IsValid()
|
|
|| !myImmediateSceneFbos[1]->IsValid())
|
|
{
|
|
aProjectType = Graphic3d_Camera::Projection_Perspective;
|
|
}
|
|
}
|
|
}
|
|
|
|
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* anImmFbos[2] =
|
|
{
|
|
myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL,
|
|
myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL
|
|
};
|
|
|
|
if (!myTransientDrawToFront)
|
|
{
|
|
anImmFbos[0] = aMainFbos[0];
|
|
anImmFbos[1] = aMainFbos[1];
|
|
}
|
|
else if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip
|
|
|| aStereoMode == Graphic3d_StereoMode_QuadBuffer)
|
|
{
|
|
anImmFbos[0] = NULL;
|
|
anImmFbos[1] = NULL;
|
|
}
|
|
|
|
#if !defined(GL_ES_VERSION_2_0)
|
|
myGlContext->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK);
|
|
#endif
|
|
redraw1 (theCView, aMainFbos[0], Graphic3d_Camera::Projection_MonoLeftEye);
|
|
myBackBufferRestored = Standard_True;
|
|
myIsImmediateDrawn = Standard_False;
|
|
#if !defined(GL_ES_VERSION_2_0)
|
|
myGlContext->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK);
|
|
#endif
|
|
if (!redrawImmediate (theCView, aMainFbos[0], aProjectType, anImmFbos[0]))
|
|
{
|
|
toSwap = false;
|
|
}
|
|
else if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip
|
|
&& toSwap)
|
|
{
|
|
myGlContext->SwapBuffers();
|
|
}
|
|
|
|
#if !defined(GL_ES_VERSION_2_0)
|
|
myGlContext->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_RIGHT : GL_BACK);
|
|
#endif
|
|
redraw1 (theCView, aMainFbos[1], Graphic3d_Camera::Projection_MonoRightEye);
|
|
myBackBufferRestored = Standard_True;
|
|
myIsImmediateDrawn = Standard_False;
|
|
if (!redrawImmediate (theCView, aMainFbos[1], aProjectType, anImmFbos[1]))
|
|
{
|
|
toSwap = false;
|
|
}
|
|
|
|
if (anImmFbos[0] != NULL)
|
|
{
|
|
bindDefaultFbo (aFrameBuffer);
|
|
drawStereoPair (theCView);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
OpenGl_FrameBuffer* aMainFbo = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL;
|
|
OpenGl_FrameBuffer* anImmFbo = aFrameBuffer;
|
|
if (!myGlContext->caps->useSystemBuffer && myImmediateSceneFbos[0]->IsValid())
|
|
{
|
|
anImmFbo = myImmediateSceneFbos[0].operator->();
|
|
}
|
|
|
|
#if !defined(GL_ES_VERSION_2_0)
|
|
if (aMainFbo == NULL
|
|
&& aFrameBuffer == NULL)
|
|
{
|
|
myGlContext->SetReadDrawBuffer (GL_BACK);
|
|
}
|
|
#endif
|
|
redraw1 (theCView, aMainFbo != NULL ? aMainFbo : aFrameBuffer, aProjectType);
|
|
myBackBufferRestored = Standard_True;
|
|
myIsImmediateDrawn = Standard_False;
|
|
if (!redrawImmediate (theCView, aMainFbo, aProjectType, anImmFbo))
|
|
{
|
|
toSwap = false;
|
|
}
|
|
|
|
if (anImmFbo != NULL
|
|
&& anImmFbo != aFrameBuffer)
|
|
{
|
|
blitBuffers (anImmFbo, aFrameBuffer, myToFlipOutput);
|
|
}
|
|
}
|
|
|
|
#if defined(_WIN32) && defined(HAVE_VIDEOCAPTURE)
|
|
if (OpenGl_AVIWriter_AllowWriting (theCView.DefWindow.XWindow))
|
|
{
|
|
GLint params[4];
|
|
glGetIntegerv (GL_VIEWPORT, params);
|
|
int nWidth = params[2] & ~0x7;
|
|
int nHeight = params[3] & ~0x7;
|
|
|
|
const int nBitsPerPixel = 24;
|
|
GLubyte* aDumpData = new GLubyte[nWidth * nHeight * nBitsPerPixel / 8];
|
|
|
|
glPixelStorei (GL_PACK_ALIGNMENT, 1);
|
|
glReadPixels (0, 0, nWidth, nHeight, GL_BGR_EXT, GL_UNSIGNED_BYTE, aDumpData);
|
|
OpenGl_AVIWriter_AVIWriter (aDumpData, nWidth, nHeight, nBitsPerPixel);
|
|
delete[] aDumpData;
|
|
}
|
|
#endif
|
|
|
|
// bind default FBO
|
|
bindDefaultFbo();
|
|
|
|
// Swap the buffers
|
|
if (toSwap)
|
|
{
|
|
GetGlContext()->SwapBuffers();
|
|
if (!myMainSceneFbos[0]->IsValid())
|
|
{
|
|
myBackBufferRestored = Standard_False;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
myGlContext->core11fwd->glFlush();
|
|
}
|
|
|
|
// reset render mode state
|
|
myGlContext->FetchState();
|
|
}
|
|
|
|
// =======================================================================
|
|
// function : redraw1
|
|
// purpose :
|
|
// =======================================================================
|
|
void OpenGl_Workspace::redraw1 (const Graphic3d_CView& theCView,
|
|
OpenGl_FrameBuffer* theReadDrawFbo,
|
|
const Graphic3d_Camera::Projection theProjection)
|
|
{
|
|
if (myView.IsNull())
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (theReadDrawFbo != NULL)
|
|
{
|
|
theReadDrawFbo->BindBuffer (myGlContext);
|
|
theReadDrawFbo->SetupViewport (myGlContext);
|
|
}
|
|
else
|
|
{
|
|
myGlContext->core11fwd->glViewport (0, 0, myWidth, myHeight);
|
|
}
|
|
|
|
// request reset of material
|
|
NamedStatus |= OPENGL_NS_RESMAT;
|
|
|
|
myUseZBuffer = Standard_True;
|
|
myUseDepthWrite = Standard_True;
|
|
GLbitfield toClear = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT;
|
|
glDepthFunc (GL_LEQUAL);
|
|
glDepthMask (GL_TRUE);
|
|
glEnable (GL_DEPTH_TEST);
|
|
|
|
#if !defined(GL_ES_VERSION_2_0)
|
|
glClearDepth (1.0);
|
|
#else
|
|
glClearDepthf (1.0f);
|
|
#endif
|
|
|
|
if (NamedStatus & OPENGL_NS_WHITEBACK)
|
|
{
|
|
// set background to white
|
|
glClearColor (1.0f, 1.0f, 1.0f, 1.0f);
|
|
}
|
|
else
|
|
{
|
|
glClearColor (myBgColor.rgb[0], myBgColor.rgb[1], myBgColor.rgb[2], 0.0f);
|
|
}
|
|
|
|
glClear (toClear);
|
|
|
|
Handle(OpenGl_Workspace) aWS (this);
|
|
myView->Render (myPrintContext, aWS, theReadDrawFbo, theProjection, theCView, Standard_False);
|
|
}
|
|
|
|
// =======================================================================
|
|
// function : copyBackToFront
|
|
// purpose :
|
|
// =======================================================================
|
|
void OpenGl_Workspace::copyBackToFront()
|
|
{
|
|
#if !defined(GL_ES_VERSION_2_0)
|
|
|
|
OpenGl_Mat4 aProjectMat;
|
|
Graphic3d_TransformUtils::Ortho2D (aProjectMat,
|
|
0.f, static_cast<GLfloat> (myWidth), 0.f, static_cast<GLfloat> (myHeight));
|
|
|
|
myGlContext->WorldViewState.Push();
|
|
myGlContext->ProjectionState.Push();
|
|
|
|
myGlContext->WorldViewState.SetIdentity();
|
|
myGlContext->ProjectionState.SetCurrent (aProjectMat);
|
|
|
|
myGlContext->ApplyProjectionMatrix();
|
|
myGlContext->ApplyWorldViewMatrix();
|
|
|
|
DisableFeatures();
|
|
|
|
switch (myGlContext->DrawBuffer())
|
|
{
|
|
case GL_BACK_LEFT:
|
|
{
|
|
myGlContext->SetReadBuffer (GL_BACK_LEFT);
|
|
myGlContext->SetDrawBuffer (GL_FRONT_LEFT);
|
|
break;
|
|
}
|
|
case GL_BACK_RIGHT:
|
|
{
|
|
myGlContext->SetReadBuffer (GL_BACK_RIGHT);
|
|
myGlContext->SetDrawBuffer (GL_FRONT_RIGHT);
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
myGlContext->SetReadBuffer (GL_BACK);
|
|
myGlContext->SetDrawBuffer (GL_FRONT);
|
|
break;
|
|
}
|
|
}
|
|
|
|
glRasterPos2i (0, 0);
|
|
glCopyPixels (0, 0, myWidth + 1, myHeight + 1, GL_COLOR);
|
|
//glCopyPixels (0, 0, myWidth + 1, myHeight + 1, GL_DEPTH);
|
|
|
|
EnableFeatures();
|
|
|
|
myGlContext->WorldViewState.Pop();
|
|
myGlContext->ProjectionState.Pop();
|
|
myGlContext->ApplyProjectionMatrix();
|
|
|
|
// read/write from front buffer now
|
|
myGlContext->SetReadBuffer (myGlContext->DrawBuffer());
|
|
#endif
|
|
myIsImmediateDrawn = Standard_False;
|
|
}
|
|
|
|
// =======================================================================
|
|
// function : DisplayCallback
|
|
// purpose :
|
|
// =======================================================================
|
|
void OpenGl_Workspace::DisplayCallback (const Graphic3d_CView& theCView,
|
|
Standard_Integer theReason)
|
|
{
|
|
if (theCView.GDisplayCB == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Aspect_GraphicCallbackStruct aCallData;
|
|
aCallData.reason = theReason;
|
|
aCallData.glContext = myGlContext;
|
|
aCallData.wsID = theCView.WsId;
|
|
aCallData.viewID = theCView.ViewId;
|
|
aCallData.IsCoreProfile = (myGlContext->core11 == NULL);
|
|
theCView.GDisplayCB (theCView.DefWindow.XWindow, theCView.GClientData, &aCallData);
|
|
}
|
|
|
|
// =======================================================================
|
|
// function : RedrawImmediate
|
|
// purpose :
|
|
// =======================================================================
|
|
void OpenGl_Workspace::RedrawImmediate (const Graphic3d_CView& theCView)
|
|
{
|
|
if (!myTransientDrawToFront
|
|
|| !myBackBufferRestored
|
|
|| (myGlContext->caps->buffersNoSwap && !myMainSceneFbos[0]->IsValid()))
|
|
{
|
|
Redraw (theCView);
|
|
return;
|
|
}
|
|
else if (!Activate())
|
|
{
|
|
return;
|
|
}
|
|
|
|
const Handle(Graphic3d_Camera)& aCamera = myView->Camera();
|
|
Graphic3d_Camera::Projection aProjectType = aCamera->ProjectionType();
|
|
OpenGl_FrameBuffer* aFrameBuffer = (OpenGl_FrameBuffer* )theCView.ptrFBO;
|
|
if ( aFrameBuffer == NULL
|
|
&& !myGlContext->DefaultFrameBuffer().IsNull()
|
|
&& myGlContext->DefaultFrameBuffer()->IsValid())
|
|
{
|
|
aFrameBuffer = myGlContext->DefaultFrameBuffer().operator->();
|
|
}
|
|
|
|
const Graphic3d_StereoMode aStereoMode = theCView.RenderParams.StereoMode;
|
|
if (aProjectType == Graphic3d_Camera::Projection_Stereo)
|
|
{
|
|
if (myMainSceneFbos[0]->IsValid()
|
|
&& !myMainSceneFbos[1]->IsValid())
|
|
{
|
|
aProjectType = Graphic3d_Camera::Projection_Perspective;
|
|
}
|
|
}
|
|
|
|
bool toSwap = false;
|
|
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* anImmFbos[2] =
|
|
{
|
|
myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL,
|
|
myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL
|
|
};
|
|
if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip
|
|
|| aStereoMode == Graphic3d_StereoMode_QuadBuffer)
|
|
{
|
|
anImmFbos[0] = NULL;
|
|
anImmFbos[1] = NULL;
|
|
}
|
|
|
|
if (myGlContext->arbFBO != NULL)
|
|
{
|
|
myGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
|
|
}
|
|
#if !defined(GL_ES_VERSION_2_0)
|
|
if (anImmFbos[0] == NULL)
|
|
{
|
|
myGlContext->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK);
|
|
}
|
|
#endif
|
|
toSwap = redrawImmediate (theCView,
|
|
aMainFbos[0],
|
|
Graphic3d_Camera::Projection_MonoLeftEye,
|
|
anImmFbos[0],
|
|
Standard_True) || toSwap;
|
|
if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip
|
|
&& toSwap
|
|
&& !myGlContext->caps->buffersNoSwap)
|
|
{
|
|
myGlContext->SwapBuffers();
|
|
}
|
|
|
|
if (myGlContext->arbFBO != NULL)
|
|
{
|
|
myGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
|
|
}
|
|
#if !defined(GL_ES_VERSION_2_0)
|
|
if (anImmFbos[1] == NULL)
|
|
{
|
|
myGlContext->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_RIGHT : GL_BACK);
|
|
}
|
|
#endif
|
|
toSwap = redrawImmediate (theCView,
|
|
aMainFbos[1],
|
|
Graphic3d_Camera::Projection_MonoRightEye,
|
|
anImmFbos[1],
|
|
Standard_True) || toSwap;
|
|
if (anImmFbos[0] != NULL)
|
|
{
|
|
bindDefaultFbo (aFrameBuffer);
|
|
drawStereoPair (theCView);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
OpenGl_FrameBuffer* aMainFbo = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL;
|
|
OpenGl_FrameBuffer* anImmFbo = aFrameBuffer;
|
|
if (!myGlContext->caps->useSystemBuffer && myImmediateSceneFbos[0]->IsValid())
|
|
{
|
|
anImmFbo = myImmediateSceneFbos[0].operator->();
|
|
}
|
|
#if !defined(GL_ES_VERSION_2_0)
|
|
if (aMainFbo == NULL)
|
|
{
|
|
myGlContext->SetReadDrawBuffer (GL_BACK);
|
|
}
|
|
#endif
|
|
toSwap = redrawImmediate (theCView,
|
|
aMainFbo,
|
|
aProjectType,
|
|
anImmFbo,
|
|
Standard_True) || toSwap;
|
|
if (anImmFbo != NULL
|
|
&& anImmFbo != aFrameBuffer)
|
|
{
|
|
blitBuffers (anImmFbo, aFrameBuffer, myToFlipOutput);
|
|
}
|
|
}
|
|
|
|
// bind default FBO
|
|
bindDefaultFbo();
|
|
|
|
if (toSwap
|
|
&& !myGlContext->caps->buffersNoSwap)
|
|
{
|
|
myGlContext->SwapBuffers();
|
|
}
|
|
else
|
|
{
|
|
myGlContext->core11fwd->glFlush();
|
|
}
|
|
}
|
|
|
|
// =======================================================================
|
|
// function : redrawImmediate
|
|
// purpose :
|
|
// =======================================================================
|
|
bool OpenGl_Workspace::redrawImmediate (const Graphic3d_CView& theCView,
|
|
OpenGl_FrameBuffer* theReadFbo,
|
|
const Graphic3d_Camera::Projection theProjection,
|
|
OpenGl_FrameBuffer* theDrawFbo,
|
|
const Standard_Boolean theIsPartialUpdate)
|
|
{
|
|
GLboolean toCopyBackToFront = GL_FALSE;
|
|
if (!myTransientDrawToFront)
|
|
{
|
|
myBackBufferRestored = Standard_False;
|
|
}
|
|
else if (theReadFbo != NULL
|
|
&& theReadFbo->IsValid()
|
|
&& myGlContext->IsRender())
|
|
{
|
|
if (!blitBuffers (theReadFbo, theDrawFbo))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
else if (theDrawFbo == NULL)
|
|
{
|
|
#if !defined(GL_ES_VERSION_2_0)
|
|
myGlContext->core11fwd->glGetBooleanv (GL_DOUBLEBUFFER, &toCopyBackToFront);
|
|
#endif
|
|
if (toCopyBackToFront)
|
|
{
|
|
if (!myView->HasImmediateStructures()
|
|
&& !theIsPartialUpdate)
|
|
{
|
|
// prefer Swap Buffers within Redraw in compatibility mode (without FBO)
|
|
return true;
|
|
}
|
|
copyBackToFront();
|
|
}
|
|
else
|
|
{
|
|
myBackBufferRestored = Standard_False;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
myBackBufferRestored = Standard_False;
|
|
}
|
|
myIsImmediateDrawn = Standard_True;
|
|
|
|
Handle(OpenGl_Workspace) aWS (this);
|
|
|
|
myUseZBuffer = Standard_True;
|
|
myUseDepthWrite = Standard_True;
|
|
glDepthFunc (GL_LEQUAL);
|
|
glDepthMask (GL_TRUE);
|
|
glEnable (GL_DEPTH_TEST);
|
|
#if !defined(GL_ES_VERSION_2_0)
|
|
glClearDepth (1.0);
|
|
#else
|
|
glClearDepthf (1.0f);
|
|
#endif
|
|
|
|
myView->Render (myPrintContext, aWS, theDrawFbo, theProjection,
|
|
theCView, Standard_True);
|
|
|
|
return !toCopyBackToFront;
|
|
}
|
|
|
|
|
|
// =======================================================================
|
|
// function : CanRender
|
|
// purpose :
|
|
// =======================================================================
|
|
Standard_Boolean OpenGl_RaytraceFilter::CanRender (const OpenGl_Element* theElement)
|
|
{
|
|
Standard_Boolean aPrevFilterResult = Standard_True;
|
|
if (!myPrevRenderFilter.IsNull())
|
|
{
|
|
aPrevFilterResult = myPrevRenderFilter->CanRender (theElement);
|
|
}
|
|
return aPrevFilterResult &&
|
|
!OpenGl_Raytrace::IsRaytracedElement (theElement);
|
|
}
|