#include <Graphic3d_GraphicDriver.hxx>
#include <Graphic3d_ShaderObject.hxx>
#include <Graphic3d_ShaderProgram.hxx>
+#include <OSD_Directory.hxx>
+#include <OSD_Environment.hxx>
+#include <OSD_File.hxx>
+#include <OSD_Path.hxx>
namespace
{
IMPLEMENT_STANDARD_HANDLE (Graphic3d_ShaderProgram, Standard_Transient)
IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ShaderProgram, Standard_Transient)
+// =======================================================================
+// function : ShadersFolder
+// purpose :
+// =======================================================================
+const TCollection_AsciiString& Graphic3d_ShaderProgram::ShadersFolder()
+{
+ static Standard_Boolean THE_IS_DEFINED = Standard_False;
+ static TCollection_AsciiString THE_SHADERS_FOLDER;
+ if (!THE_IS_DEFINED)
+ {
+ THE_IS_DEFINED = Standard_True;
+ OSD_Environment aDirEnv ("CSF_ShadersDirectory");
+ THE_SHADERS_FOLDER = aDirEnv.Value();
+ if (THE_SHADERS_FOLDER.IsEmpty())
+ {
+ OSD_Environment aCasRootEnv ("CASROOT");
+ THE_SHADERS_FOLDER = aCasRootEnv.Value();
+ if (!THE_SHADERS_FOLDER.IsEmpty())
+ {
+ THE_SHADERS_FOLDER += "/src/Shaders";
+ }
+ }
+
+ if (THE_SHADERS_FOLDER.IsEmpty())
+ {
+ std::cerr << "Both environment variables CSF_ShadersDirectory and CASROOT are undefined!\n"
+ << "At least one should be defined to use standard GLSL programs.\n";
+ Standard_Failure::Raise ("CSF_ShadersDirectory and CASROOT are undefined");
+ return THE_SHADERS_FOLDER;
+ }
+
+ const OSD_Path aDirPath (THE_SHADERS_FOLDER);
+ OSD_Directory aDir (aDirPath);
+ const TCollection_AsciiString aProgram = THE_SHADERS_FOLDER + "/Declarations.glsl";
+ OSD_File aProgramFile (aProgram);
+ if (!aDir.Exists()
+ || !aProgramFile.Exists())
+ {
+ std::cerr << "Standard GLSL programs are not found in: " << THE_SHADERS_FOLDER.ToCString() << std::endl;
+ Standard_Failure::Raise ("CSF_ShadersDirectory or CASROOT is set incorrectly");
+ return THE_SHADERS_FOLDER;
+ }
+ }
+ return THE_SHADERS_FOLDER;
+}
+
// =======================================================================
// function : Graphic3d_ShaderProgram
// purpose : Creates new empty program object
+ TCollection_AsciiString (Standard_Atomic_Increment (&THE_PROGRAM_OBJECT_COUNTER));
}
+// =======================================================================
+// function : Graphic3d_ShaderProgram
+// purpose :
+// =======================================================================
+Graphic3d_ShaderProgram::Graphic3d_ShaderProgram (const Graphic3d_ShaderProgram::ShaderName theName)
+{
+ const TCollection_AsciiString& aShadersRoot = Graphic3d_ShaderProgram::ShadersFolder();
+ switch (theName)
+ {
+ case ShaderName_Phong:
+ {
+ myID = TCollection_AsciiString ("Graphic3d_ShaderProgram_Phong");
+ const TCollection_AsciiString aSrcVert = aShadersRoot + "/PhongShading.vs";
+ const TCollection_AsciiString aSrcFrag = aShadersRoot + "/PhongShading.fs";
+
+ if (!aSrcVert.IsEmpty()
+ && !OSD_File (aSrcVert).Exists())
+ {
+ Standard_Failure::Raise ("Graphic3d_ShaderProgram, PhongShading.vs is not found");
+ return;
+ }
+ if (!aSrcFrag.IsEmpty()
+ && !OSD_File (aSrcFrag).Exists())
+ {
+ Standard_Failure::Raise ("Graphic3d_ShaderProgram, PhongShading.fs is not found");
+ return;
+ }
+
+ AttachShader (Graphic3d_ShaderObject::CreateFromFile (Graphic3d_TOS_VERTEX, aSrcVert));
+ AttachShader (Graphic3d_ShaderObject::CreateFromFile (Graphic3d_TOS_FRAGMENT, aSrcFrag));
+ break;
+ }
+ case ShaderName_UNKNOWN:
+ default:
+ {
+ Standard_Failure::Raise ("Graphic3d_ShaderProgram, unknown program name");
+ break;
+ }
+ }
+}
+
// =======================================================================
// function : ~Graphic3d_ShaderProgram
// purpose : Releases resources of program object
//! This class is responsible for managing shader programs.
class Graphic3d_ShaderProgram : public Standard_Transient
{
+
+public:
+
+ //! The list of built-in GLSL programs
+ enum ShaderName
+ {
+ ShaderName_UNKNOWN, //!< undefined program
+ ShaderName_Phong //!< per-pixel lighting (Phong shading)
+ };
+
public:
//! Creates new empty program object.
Standard_EXPORT Graphic3d_ShaderProgram();
+ //! Creates program object from pre-defined shaders.
+ //! Raises Standard_Failure exception if shader resources are unavailable.
+ Standard_EXPORT Graphic3d_ShaderProgram (const Graphic3d_ShaderProgram::ShaderName theName);
+
//! Releases resources of program object.
Standard_EXPORT virtual ~Graphic3d_ShaderProgram();
//! Removes all custom uniform variables from the program.
Standard_EXPORT void ClearVariables();
+public:
+
+ //! The path to GLSL programs determined from CSF_ShadersDirectory or CASROOT environment variables.
+ //! @return the root folder with default GLSL programs.
+ Standard_EXPORT static const TCollection_AsciiString& ShadersFolder();
+
public:
DEFINE_STANDARD_RTTI (Graphic3d_ShaderProgram)
if (VarName.IsEmpty())
{
- std::cerr << " CSF_MDTVTexturesDirectory and CASROOT not setted\n";
- std::cerr << " one of these variable are mandatory to use this functionality\n";
- Standard_Failure::Raise ("CSF_MDTVTexturesDirectory and CASROOT not setted");
+ std::cerr << "Both environment variables CSF_MDTVTexturesDirectory and CASROOT are undefined!\n"
+ << "At least one should be defined to use standard Textures.\n";
+ Standard_Failure::Raise ("CSF_MDTVTexturesDirectory and CASROOT are undefined");
return VarName;
}
myTexture = theAspect.Texture.TextureMap;
const TCollection_AsciiString& aTextureKey = myTexture.IsNull() ? THE_EMPTY_KEY : myTexture->GetId();
-
if (aTextureKey.IsEmpty() || myResources.TextureId != aTextureKey)
{
myResources.ResetTexture();
myShaderProgram = theAspect.ShaderProgram;
const TCollection_AsciiString& aShaderKey = myShaderProgram.IsNull() ? THE_EMPTY_KEY : myShaderProgram->GetId();
-
if (aShaderKey.IsEmpty() || myResources.ShaderProgramId != aShaderKey)
{
myResources.ResetShader();
myResources.TextureId.Clear();
myResources.ResetTexture();
- if (!myResources.ShaderProgram.IsNull() && !theContext.IsNull())
+ if (!myResources.ShaderProgram.IsNull()
+ && !theContext.IsNull())
{
- theContext->ShaderManager()->Unregister (myResources.ShaderProgram);
+ theContext->ShaderManager()->Unregister (myResources.ShaderProgramId,
+ myResources.ShaderProgram);
}
myResources.ShaderProgramId.Clear();
myResources.ResetShader();
// function : BuildShader
// purpose :
// =======================================================================
-void OpenGl_AspectFace::Resources::BuildShader (const Handle(OpenGl_Workspace)& theWS,
+void OpenGl_AspectFace::Resources::BuildShader (const Handle(OpenGl_Workspace)& theWS,
const Handle(Graphic3d_ShaderProgram)& theShader)
{
const Handle(OpenGl_Context)& aContext = theWS->GetGlContext();
-
if (!aContext->IsGlGreaterEqual (2, 0))
+ {
return;
+ }
// release old shader program resources
if (!ShaderProgram.IsNull())
{
- aContext->ShaderManager()->Unregister (ShaderProgram);
+ aContext->ShaderManager()->Unregister (ShaderProgramId, ShaderProgram);
}
-
- ShaderProgramId = theShader.IsNull() ? THE_EMPTY_KEY : theShader->GetId();
-
- if (!theShader.IsNull())
+ if (theShader.IsNull())
{
- if (!aContext->GetResource<Handle(OpenGl_ShaderProgram)> (ShaderProgramId, ShaderProgram))
- {
- ShaderProgram = aContext->ShaderManager()->Create (theShader);
- if (!ShaderProgramId.IsEmpty())
- {
- aContext->ShareResource (ShaderProgramId, ShaderProgram);
- }
- }
- }
- else
- {
- ShaderProgram.Nullify();
+ return;
}
+
+ aContext->ShaderManager()->Create (theShader, ShaderProgramId, ShaderProgram);
}
myShaderProgram = theAspect.ShaderProgram;
const TCollection_AsciiString& aShaderKey = myShaderProgram.IsNull() ? THE_EMPTY_KEY : myShaderProgram->GetId();
-
if (aShaderKey.IsEmpty() || myResources.ShaderProgramId != aShaderKey)
{
myResources.ResetShader();
// =======================================================================
void OpenGl_AspectLine::Release (const Handle(OpenGl_Context)& theContext)
{
- if (!myResources.ShaderProgram.IsNull() && !theContext.IsNull())
+ if (!myResources.ShaderProgram.IsNull()
+ && !theContext.IsNull())
{
- theContext->ShaderManager()->Unregister (myResources.ShaderProgram);
+ theContext->ShaderManager()->Unregister (myResources.ShaderProgramId,
+ myResources.ShaderProgram);
}
myResources.ShaderProgramId.Clear();
myResources.ResetShader();
// function : BuildShader
// purpose :
// =======================================================================
-void OpenGl_AspectLine::Resources::BuildShader (const Handle(OpenGl_Workspace)& theWS,
+void OpenGl_AspectLine::Resources::BuildShader (const Handle(OpenGl_Workspace)& theWS,
const Handle(Graphic3d_ShaderProgram)& theShader)
{
const Handle(OpenGl_Context)& aContext = theWS->GetGlContext();
-
if (!aContext->IsGlGreaterEqual (2, 0))
+ {
return;
+ }
// release old shader program resources
if (!ShaderProgram.IsNull())
{
- aContext->ShaderManager()->Unregister (ShaderProgram);
- }
-
- ShaderProgramId = theShader.IsNull() ? THE_EMPTY_KEY : theShader->GetId();
-
- if (!theShader.IsNull())
- {
- if (!aContext->GetResource<Handle(OpenGl_ShaderProgram)> (ShaderProgramId, ShaderProgram))
- {
- ShaderProgram = aContext->ShaderManager()->Create (theShader);
- if (!ShaderProgramId.IsEmpty())
- {
- aContext->ShareResource (ShaderProgramId, ShaderProgram);
- }
- }
+ aContext->ShaderManager()->Unregister (ShaderProgramId, ShaderProgram);
}
- else
+ if (theShader.IsNull())
{
- ShaderProgram.Nullify();
+ return;
}
+
+ aContext->ShaderManager()->Create (theShader, ShaderProgramId, ShaderProgram);
}
if (!myResources.ShaderProgram.IsNull() && !theCtx.IsNull())
{
- theCtx->ShaderManager()->Unregister (myResources.ShaderProgram);
+ theCtx->ShaderManager()->Unregister (myResources.ShaderProgramId,
+ myResources.ShaderProgram);
}
myResources.ShaderProgramId.Clear();
myResources.ResetShader();
// function : BuildShader
// purpose :
// =======================================================================
-void OpenGl_AspectMarker::Resources::BuildShader (const Handle(OpenGl_Workspace)& theWS,
+void OpenGl_AspectMarker::Resources::BuildShader (const Handle(OpenGl_Workspace)& theWS,
const Handle(Graphic3d_ShaderProgram)& theShader)
{
const Handle(OpenGl_Context)& aContext = theWS->GetGlContext();
-
if (!aContext->IsGlGreaterEqual (2, 0))
+ {
return;
+ }
// release old shader program resources
if (!ShaderProgram.IsNull())
{
- aContext->ShaderManager()->Unregister (ShaderProgram);
- }
-
- ShaderProgramId = theShader.IsNull() ? THE_EMPTY_KEY : theShader->GetId();
-
- if (!theShader.IsNull())
- {
- if (!aContext->GetResource<Handle(OpenGl_ShaderProgram)> (ShaderProgramId, ShaderProgram))
- {
- ShaderProgram = aContext->ShaderManager()->Create (theShader);
- if (!ShaderProgramId.IsEmpty())
- {
- aContext->ShareResource (ShaderProgramId, ShaderProgram);
- }
- }
+ aContext->ShaderManager()->Unregister (ShaderProgramId, ShaderProgram);
}
- else
+ if (theShader.IsNull())
{
- ShaderProgram.Nullify();
+ return;
}
+
+ aContext->ShaderManager()->Create (theShader, ShaderProgramId, ShaderProgram);
}
// =======================================================================
// =======================================================================
void OpenGl_AspectText::Release (const Handle(OpenGl_Context)& theContext)
{
- if (!myResources.ShaderProgram.IsNull() && !theContext.IsNull())
+ if (!myResources.ShaderProgram.IsNull()
+ && !theContext.IsNull())
{
- theContext->ShaderManager()->Unregister (myResources.ShaderProgram);
+ theContext->ShaderManager()->Unregister (myResources.ShaderProgramId,
+ myResources.ShaderProgram);
}
myResources.ShaderProgramId.Clear();
myResources.ResetShader();
// function : BuildShader
// purpose :
// =======================================================================
-void OpenGl_AspectText::Resources::BuildShader (const Handle(OpenGl_Workspace)& theWS,
+void OpenGl_AspectText::Resources::BuildShader (const Handle(OpenGl_Workspace)& theWS,
const Handle(Graphic3d_ShaderProgram)& theShader)
{
const Handle(OpenGl_Context)& aContext = theWS->GetGlContext();
-
if (!aContext->IsGlGreaterEqual (2, 0))
+ {
return;
+ }
// release old shader program resources
if (!ShaderProgram.IsNull())
{
- aContext->ShaderManager()->Unregister (ShaderProgram);
+ aContext->ShaderManager()->Unregister (ShaderProgramId, ShaderProgram);
}
-
- ShaderProgramId = theShader.IsNull() ? THE_EMPTY_KEY : theShader->GetId();
-
- if (!theShader.IsNull())
+ if (theShader.IsNull())
{
- if (!aContext->GetResource<Handle(OpenGl_ShaderProgram)> (ShaderProgramId, ShaderProgram))
- {
- ShaderProgram = aContext->ShaderManager()->Create (theShader);
- if (!ShaderProgramId.IsEmpty())
- {
- aContext->ShareResource (ShaderProgramId, ShaderProgram);
- }
- }
- }
- else
- {
- ShaderProgram.Nullify();
+ return;
}
+
+ aContext->ShaderManager()->Create (theShader, ShaderProgramId, ShaderProgram);
}
glDisableClientState (GL_VERTEX_ARRAY);
glDisableClientState (GL_TEXTURE_COORD_ARRAY);
- theWorkspace->SetStructureMatrix (aModelMatrix);
+ theWorkspace->SetStructureMatrix (aModelMatrix, true);
theWorkspace->SetAspectFace (aFaceAspect);
// set delayed resource release
OpenGl_Caps::OpenGl_Caps()
: vboDisable (Standard_False),
pntSpritesDisable (Standard_False),
+ keepArrayData (Standard_False),
contextStereo (Standard_False),
#ifdef DEB
contextDebug (Standard_True),
contextDebug (Standard_False),
#endif
contextNoAccel (Standard_False),
- keepArrayData (Standard_False)
+ glslWarnings (Standard_False)
{
//
}
{
vboDisable = theCopy.vboDisable;
pntSpritesDisable = theCopy.pntSpritesDisable;
+ keepArrayData = theCopy.keepArrayData;
contextStereo = theCopy.contextStereo;
contextDebug = theCopy.contextDebug;
contextNoAccel = theCopy.contextNoAccel;
+ glslWarnings = theCopy.glslWarnings;
return *this;
}
Standard_Boolean vboDisable; //!< flag permits VBO usage, will significantly affect performance (OFF by default)
Standard_Boolean pntSpritesDisable; //!< flag permits Point Sprites usage, will significantly affect performance (OFF by default)
+ Standard_Boolean keepArrayData; //!< Disables freeing CPU memory after building VBOs (OFF by default)
public: //! @name context creation parameters
*/
Standard_Boolean contextNoAccel;
- /**
- * Disables freeing CPU memory after building VBOs.
- *
- * OFF by default.
- */
- Standard_Boolean keepArrayData;
+public: //! @name flags to activate verbose output
+
+ //! Print GLSL program compilation/linkage warnings, if any. OFF by default.
+ Standard_Boolean glslWarnings;
public: //! @name class methods
// release shared resources if any
if (((const Handle(Standard_Transient)& )mySharedResources)->GetRefCount() <= 1)
{
+ myShaderManager.Nullify();
for (NCollection_DataMap<TCollection_AsciiString, Handle(OpenGl_Resource)>::Iterator anIter (*mySharedResources);
anIter.More(); anIter.Next())
{
anIter.Value()->Release (this);
}
}
+ else
+ {
+ myShaderManager->SetContext (NULL);
+ }
mySharedResources.Nullify();
myDelayed.Nullify();
mySharedResources = theShareCtx->mySharedResources;
myDelayed = theShareCtx->myDelayed;
myReleaseQueue = theShareCtx->myReleaseQueue;
+ myShaderManager = theShareCtx->myShaderManager;
}
}
// however some drivers (Intel etc.) may FAIL doing this for unknown reason
if (IsCurrent())
{
+ myShaderManager->SetContext (this);
return Standard_True;
}
else if (wglMakeCurrent ((HDC )myWindowDC, (HGLRC )myGContext) != TRUE)
return Standard_False;
}
#endif
+ myShaderManager->SetContext (this);
return Standard_True;
}
class OpenGl_Structure;
class OpenGl_Text;
+//! Tool class to implement consistent state counter
+//! for objects inside the same driver instance.
+class OpenGl_StateCounter
+{
+public:
+
+ OpenGl_StateCounter() : myCounter (0) { }
+
+ Standard_Size Increment() { return ++myCounter; }
+
+private:
+
+ Standard_Size myCounter;
+};
+
//! This class defines an OpenGl graphic driver <br>
class OpenGl_GraphicDriver : public Graphic3d_GraphicDriver
{
OpenGl_UserDrawCallback_t myUserDrawCallback;
OpenGl_Text* myTempText; //!< variable for compatibility (drawing text in layers)
+public:
+
+ OpenGl_StateCounter* GetStateCounter() const { return &myStateCounter; }
+
+private:
+
+ mutable OpenGl_StateCounter myStateCounter;
+
};
#endif //_OpenGl_GraphicDriver_HeaderFile
Handle(OpenGl_Context) aShareCtx = GetSharedContext();
Handle(OpenGl_Workspace) aWS = new OpenGl_Workspace (myGlDisplay, theCView.DefWindow, theCView.GContext, myCaps, aShareCtx);
- Handle(OpenGl_View) aView = new OpenGl_View (theCView.Context);
+ Handle(OpenGl_View) aView = new OpenGl_View (theCView.Context, &myStateCounter);
myMapOfWS .Bind (theCView.WsId, aWS);
myMapOfView.Bind (theCView.ViewId, aView);
// function : Create
// purpose : Creates new shader program
// =======================================================================
-Handle(OpenGl_ShaderProgram) OpenGl_ShaderManager::Create (const Handle(Graphic3d_ShaderProgram)& theProxyProgram)
+void OpenGl_ShaderManager::Create (const Handle(Graphic3d_ShaderProgram)& theProxy,
+ TCollection_AsciiString& theShareKey,
+ Handle(OpenGl_ShaderProgram)& theProgram)
{
- if (theProxyProgram.IsNull())
+ theProgram.Nullify();
+ if (theProxy.IsNull())
{
- return NULL;
+ return;
}
-
- Handle(OpenGl_ShaderProgram) aProgram = new OpenGl_ShaderProgram (theProxyProgram);
- if (!aProgram->Initialize (myContext, theProxyProgram->ShaderObjects()))
+
+ theShareKey = theProxy->GetId();
+ if (myContext->GetResource<Handle(OpenGl_ShaderProgram)> (theShareKey, theProgram))
{
- return NULL;
+ theProgram->Share();
+ return;
}
-
- myProgramList.Append (aProgram);
- return aProgram;
+ theProgram = new OpenGl_ShaderProgram (theProxy);
+ if (!theProgram->Initialize (myContext, theProxy->ShaderObjects()))
+ {
+ theProgram->Release (myContext);
+ theShareKey.Clear();
+ theProgram.Nullify();
+ return;
+ }
+
+ myProgramList.Append (theProgram);
+ myContext->ShareResource (theShareKey, theProgram);
}
// =======================================================================
// function : Unregister
// purpose : Removes specified shader program from the manager
// =======================================================================
-void OpenGl_ShaderManager::Unregister (Handle(OpenGl_ShaderProgram)& theProgram)
+void OpenGl_ShaderManager::Unregister (TCollection_AsciiString& theShareKey,
+ Handle(OpenGl_ShaderProgram)& theProgram)
{
for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next())
{
if (anIt.Value() == theProgram)
{
+ if (!theProgram->UnShare())
+ {
+ theShareKey.Clear();
+ theProgram.Nullify();
+ return;
+ }
+
myProgramList.Remove (anIt);
+ myMaterialStates.UnBind (theProgram);
break;
}
}
//! Releases resources of shader manager.
Standard_EXPORT virtual ~OpenGl_ShaderManager();
- //! Creates new shader program.
- Standard_EXPORT Handle(OpenGl_ShaderProgram) Create (const Handle(Graphic3d_ShaderProgram)& theProxyProgram = NULL);
+ //! Creates new shader program or re-use shared instance.
+ //! @param theProxy [IN] program definition
+ //! @param theShareKey [OUT] sharing key
+ //! @param theProgram [OUT] OpenGL program
+ Standard_EXPORT void Create (const Handle(Graphic3d_ShaderProgram)& theProxy,
+ TCollection_AsciiString& theShareKey,
+ Handle(OpenGl_ShaderProgram)& theProgram);
//! Unregisters specified shader program.
- Standard_EXPORT void Unregister (Handle(OpenGl_ShaderProgram)& theProgram);
+ Standard_EXPORT void Unregister (TCollection_AsciiString& theShareKey,
+ Handle(OpenGl_ShaderProgram)& theProgram);
//! Returns list of registered shader programs.
Standard_EXPORT const OpenGl_ShaderProgramList& ShaderPrograms() const;
//! Pushes current state of OCCT graphics parameters to specified program.
Standard_EXPORT void PushState (const Handle(OpenGl_ShaderProgram)& theProgram) const;
+public:
+
+ //! Overwrites context
+ void SetContext (OpenGl_Context* theCtx)
+ {
+ myContext = theCtx;
+ }
+
protected:
OpenGl_ShaderProgramList myProgramList; //!< The list of shader programs
// =======================================================================
OpenGl_ShaderProgram::OpenGl_ShaderProgram (const Handle(Graphic3d_ShaderProgram)& theProxy)
: myProgramID (NO_PROGRAM),
- myProxy (theProxy)
+ myProxy (theProxy),
+ myShareCount(1)
{
memset (myCurrentState, 0, sizeof (myCurrentState));
for (GLint aVar = 0; aVar < OpenGl_OCCT_NUMBER_OF_STATE_VARIABLES; ++aVar)
return Standard_False;
}
- GLchar *aShaderDir = getenv ("CSF_ShadersDirectory");
- if (aShaderDir == NULL)
- {
- TCollection_ExtendedString aMsg = "Error! Failed to get OCCT shaders directory";
-
- theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
- GL_DEBUG_TYPE_ERROR_ARB,
- 0,
- GL_DEBUG_SEVERITY_HIGH_ARB,
- aMsg);
-
- return Standard_False;
- }
-
- OSD_File aDeclFile (TCollection_AsciiString (aShaderDir) + "/Declarations.glsl");
+ OSD_File aDeclFile (Graphic3d_ShaderProgram::ShadersFolder() + "/Declarations.glsl");
if (!aDeclFile.Exists())
{
- TCollection_ExtendedString aMsg = "Error! Failed to load OCCT shader declarations file";
-
+ const TCollection_ExtendedString aMsg = "Error! Failed to load OCCT shader declarations file";
theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
GL_DEBUG_TYPE_ERROR_ARB,
0,
GL_DEBUG_SEVERITY_HIGH_ARB,
aMsg);
-
return Standard_False;
}
{
if (!anIter.Value()->IsDone())
{
- TCollection_ExtendedString aMsg = "Error! Failed to get shader source";
-
+ const TCollection_ExtendedString aMsg = "Error! Failed to get shader source";
theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
GL_DEBUG_TYPE_ERROR_ARB,
0,
GL_DEBUG_SEVERITY_HIGH_ARB,
aMsg);
-
return Standard_False;
}
if (aShader.IsNull())
{
TCollection_ExtendedString aMsg = "Error! Unsupported shader type";
-
theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
GL_DEBUG_TYPE_ERROR_ARB,
0,
GL_DEBUG_SEVERITY_HIGH_ARB,
aMsg);
-
return Standard_False;
}
if (!aShader->Create (theCtx))
{
+ aShader->Release (theCtx.operator->());
return Standard_False;
}
TCollection_AsciiString aSource = aDeclarations + anIter.Value()->Source();
-
if (anIter.Value()->Type() == Graphic3d_TOS_VERTEX)
{
aSource = TCollection_AsciiString ("#define VERTEX_SHADER\n") + aSource;
if (!aShader->LoadSource (theCtx, aSource))
{
- TCollection_ExtendedString aMsg = "Error! Failed to set shader source";
-
+ const TCollection_ExtendedString aMsg = "Error! Failed to set shader source";
theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
GL_DEBUG_TYPE_ERROR_ARB,
0,
GL_DEBUG_SEVERITY_HIGH_ARB,
aMsg);
-
+ aShader->Release (theCtx.operator->());
return Standard_False;
}
if (!aShader->Compile (theCtx))
{
- TCollection_ExtendedString aMsg = "Error! Failed to compile shader object";
-
+ TCollection_AsciiString aLog;
+ aShader->FetchInfoLog (theCtx, aLog);
+ if (aLog.IsEmpty())
+ {
+ aLog = "Compilation log is empty.";
+ }
theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
GL_DEBUG_TYPE_ERROR_ARB,
0,
GL_DEBUG_SEVERITY_HIGH_ARB,
- aMsg);
-
- if (theCtx->caps->contextDebug)
+ TCollection_ExtendedString ("Failed to compile shader object. Compilation log:\n") + aLog);
+ aShader->Release (theCtx.operator->());
+ return Standard_False;
+ }
+ else if (theCtx->caps->glslWarnings)
+ {
+ TCollection_AsciiString aLog;
+ aShader->FetchInfoLog (theCtx, aLog);
+ if (!aLog.IsEmpty()
+ && !aLog.IsEqual ("No errors.\n"))
{
- TCollection_AsciiString aLog;
- aShader->FetchInfoLog (theCtx, aLog);
- if (!aLog.IsEmpty())
- {
- std::cout << aLog.ToCString() << std::endl << std::flush;
- }
- else
- {
- std::cout << "Information log is empty" << std::endl;
- }
+ theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
+ GL_DEBUG_TYPE_PORTABILITY_ARB,
+ 0,
+ GL_DEBUG_SEVERITY_LOW_ARB,
+ TCollection_ExtendedString ("Shader compilation log:\n") + aLog);
}
-
- return Standard_False;
}
if (!AttachShader (theCtx, aShader))
{
+ aShader->Release (theCtx.operator->());
return Standard_False;
}
}
if (!Link (theCtx))
{
- TCollection_ExtendedString aMsg = "Error! Failed to link program object";
-
+ TCollection_AsciiString aLog;
+ FetchInfoLog (theCtx, aLog);
+ if (aLog.IsEmpty())
+ {
+ aLog = "Linker log is empty.";
+ }
theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
GL_DEBUG_TYPE_ERROR_ARB,
0,
GL_DEBUG_SEVERITY_HIGH_ARB,
- aMsg);
-
- if (theCtx->caps->contextDebug)
+ TCollection_ExtendedString ("Failed to link program object! Linker log:\n"));
+ return Standard_False;
+ }
+ else if (theCtx->caps->glslWarnings)
+ {
+ TCollection_AsciiString aLog;
+ FetchInfoLog (theCtx, aLog);
+ if (!aLog.IsEmpty()
+ && !aLog.IsEqual ("No errors.\n"))
{
- TCollection_AsciiString aLog;
- FetchInfoLog (theCtx, aLog);
- if (!aLog.IsEmpty())
- {
- std::cout << aLog.ToCString() << std::endl;
- }
- else
- {
- std::cout << "Information log is empty" << std::endl;
- }
+ theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
+ GL_DEBUG_TYPE_PORTABILITY_ARB,
+ 0,
+ GL_DEBUG_SEVERITY_LOW_ARB,
+ TCollection_ExtendedString ("GLSL linker log:\n") + aLog);
}
-
- return Standard_False;
}
return Standard_True;
protected:
- GLuint myProgramID; //! Handle of OpenGL shader program
- OpenGl_ShaderList myShaderObjects; //! List of attached shader objects
- Handle(Graphic3d_ShaderProgram) myProxy; //! Proxy shader program (from application layer)
+ //! Increments counter of users.
+ //! Used by OpenGl_ShaderManager.
+ void Share()
+ {
+ ++myShareCount;
+ }
+
+ //! Decrements counter of users.
+ //! Used by OpenGl_ShaderManager.
+ //! @return true when there are no more users of this program has been left
+ bool UnShare()
+ {
+ return --myShareCount == 0;
+ }
+
+protected:
+
+ GLuint myProgramID; //!< Handle of OpenGL shader program
+ OpenGl_ShaderList myShaderObjects; //!< List of attached shader objects
+ Handle(Graphic3d_ShaderProgram) myProxy; //!< Proxy shader program (from application layer)
+ Standard_Integer myShareCount; //!< program users count, initialized with 1 (already shared by one user)
protected:
// purpose or non-infringement. Please see the License for the specific terms
// and conditions governing the rights and limitations under the License.
-
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <OpenGl_Display.hxx>
#include <OpenGl_GlCore11.hxx>
#include <OpenGl_GraduatedTrihedron.hxx>
+#include <OpenGl_GraphicDriver.hxx>
#include <OpenGl_ShaderManager.hxx>
#include <OpenGl_Texture.hxx>
#include <OpenGl_Trihedron.hxx>
/*----------------------------------------------------------------------*/
-OpenGl_View::OpenGl_View (const CALL_DEF_VIEWCONTEXT &AContext)
+OpenGl_View::OpenGl_View (const CALL_DEF_VIEWCONTEXT &AContext,
+ OpenGl_StateCounter* theCounter)
: mySurfaceDetail(Visual3d_TOD_NONE),
myBackfacing(0),
myBgTexture(myDefaultBgTexture),
myAntiAliasing(Standard_False),
myTransPers(&myDefaultTransPers),
myIsTransPers(Standard_False),
- myOrientationChanged (Standard_True),
- myViewMappingChanged (Standard_True),
- myLightSourcesChanged (Standard_True)
+ myStateCounter (theCounter),
+ myLastOrientationState (0, 0),
+ myLastViewMappingState (0, 0),
+ myLastLightSourceState (0, 0)
{
// Initialize matrices
memcpy(myOrientationMatrix,myDefaultMatrix,sizeof(Tmatrix3));
break;
}
+ myCurrOrientationState = myStateCounter->Increment(); // <-- delete after merge with camera
+ myCurrViewMappingState = myStateCounter->Increment(); // <-- delete after merge with camera
+ myCurrLightSourceState = myStateCounter->Increment();
+
#ifdef HAVE_OPENCL
myModificationState = 1; // initial state
#endif
myLights.Append(rep);
}
- myLightSourcesChanged = Standard_True;
+ myCurrLightSourceState = myStateCounter->Increment();
}
/*----------------------------------------------------------------------*/
if (!err_ind)
myExtra.map = Map;
- myViewMappingChanged = Standard_True;
+ myCurrViewMappingState = myStateCounter->Increment();
}
/*----------------------------------------------------------------------*/
myExtra.scaleFactors[2] = ScaleFactors[2];
}
- myOrientationChanged = Standard_True;
+ myCurrOrientationState = myStateCounter->Increment();
}
/*----------------------------------------------------------------------*/
#include <OpenGl_Light.hxx>
#include <Handle_OpenGl_Context.hxx>
+#include <Handle_OpenGl_GraphicDriver.hxx>
#include <Handle_OpenGl_Display.hxx>
#include <Handle_OpenGl_Workspace.hxx>
#include <Handle_OpenGl_View.hxx>
class OpenGl_Structure;
class OpenGl_Trihedron;
class Handle(OpenGl_PrinterContext);
+class OpenGl_StateCounter;
class OpenGl_View : public MMgt_TShared
{
public:
- OpenGl_View (const CALL_DEF_VIEWCONTEXT &AContext);
+ OpenGl_View (const CALL_DEF_VIEWCONTEXT &AContext, OpenGl_StateCounter* theCounter);
virtual ~OpenGl_View ();
void ReleaseGlResources (const Handle(OpenGl_Context)& theCtx);
const TEL_TRANSFORM_PERSISTENCE *myTransPers;
Standard_Boolean myIsTransPers;
- //! Modification flags.
- Standard_Boolean myOrientationChanged;
- Standard_Boolean myViewMappingChanged;
- Standard_Boolean myLightSourcesChanged;
+ OpenGl_StateCounter* myStateCounter;
+
+ Standard_Size myCurrOrientationState; // <-- delete it after merge with new camera
+ Standard_Size myCurrViewMappingState; // <-- delete it after merge with new camera
+ Standard_Size myCurrLightSourceState;
+
+ typedef std::pair<Standard_Size, Standard_Size> StateInfo;
+
+ StateInfo myLastOrientationState;
+ StateInfo myLastViewMappingState;
+ StateInfo myLastLightSourceState;
#ifdef HAVE_OPENCL
Standard_Size myModificationState;
}
// Set OCCT state uniform variables
-
- if (!aContext->ShaderManager()->IsEmpty())
+ const Handle(OpenGl_ShaderManager) aManager = aContext->ShaderManager();
+ if (StateInfo (myCurrLightSourceState, aManager->LightSourceState().Index()) != myLastLightSourceState)
{
- if (myLightSourcesChanged)
- {
- aContext->ShaderManager()->UpdateLightSourceStateTo (&myLights);
- myLightSourcesChanged = Standard_False;
- }
-
- if (myViewMappingChanged)
- {
- aContext->ShaderManager()->UpdateProjectionStateTo (myMappingMatrix);
- myViewMappingChanged = Standard_False;
- }
-
- if (myOrientationChanged)
- {
- aContext->ShaderManager()->UpdateWorldViewStateTo (myOrientationMatrix);
- myOrientationChanged = Standard_False;
- }
-
- if (aContext->ShaderManager()->ModelWorldState().Index() == 0)
- {
- Tmatrix3 aModelWorldState = { { 1.f, 0.f, 0.f, 0.f },
- { 0.f, 1.f, 0.f, 0.f },
- { 0.f, 0.f, 1.f, 0.f },
- { 0.f, 0.f, 0.f, 1.f } };
-
- aContext->ShaderManager()->UpdateModelWorldStateTo (aModelWorldState);
- }
+ aManager->UpdateLightSourceStateTo (&myLights);
+ myLastLightSourceState = StateInfo (myCurrLightSourceState, aManager->LightSourceState().Index());
+ }
+ if (StateInfo (myCurrViewMappingState, aManager->ProjectionState().Index()) != myLastViewMappingState)
+ {
+ aManager->UpdateProjectionStateTo (myMappingMatrix);
+ myLastViewMappingState = StateInfo (myCurrViewMappingState, aManager->ProjectionState().Index());
+ }
+ if (StateInfo (myCurrOrientationState, aManager->WorldViewState().Index()) != myLastOrientationState)
+ {
+ aManager->UpdateWorldViewStateTo (myOrientationMatrix);
+ myLastOrientationState = StateInfo (myCurrOrientationState, aManager->WorldViewState().Index());
+ }
+ if (aManager->ModelWorldState().Index() == 0)
+ {
+ Tmatrix3 aModelWorldState = { { 1.f, 0.f, 0.f, 0.f },
+ { 0.f, 1.f, 0.f, 0.f },
+ { 0.f, 0.f, 1.f, 0.f },
+ { 0.f, 0.f, 0.f, 1.f } };
+
+ aManager->UpdateModelWorldStateTo (aModelWorldState);
}
/////////////////////////////////////////////////////////////////////////////
}
}
- if (!aContext->ShaderManager()->IsEmpty())
+ if (!aManager->IsEmpty())
{
- aContext->ShaderManager()->UpdateClippingState();
+ aManager->UpdateClippingState();
}
}
aContext->ChangeClipping().RemoveAll();
- if (!aContext->ShaderManager()->IsEmpty())
+ if (!aManager->IsEmpty())
{
- aContext->ShaderManager()->ResetMaterialStates();
- aContext->ShaderManager()->RevertClippingState();
+ aManager->ResetMaterialStates();
+ aManager->RevertClippingState();
+
+ // We need to disable (unbind) all shaders programs to ensure
+ // that all objects without specified aspect will be drawn
+ // correctly (such as background)
+ OpenGl_ShaderProgram::Unbind (aContext);
}
// display global trihedron
if (!myGlContext->ShaderManager()->IsEmpty())
{
if (aRevert)
- myGlContext->ShaderManager()->UpdateModelWorldStateTo (lmat.mat);
- else
+ {
myGlContext->ShaderManager()->RevertModelWorldStateTo (lmat.mat);
+ }
+ else
+ {
+ myGlContext->ShaderManager()->UpdateModelWorldStateTo (lmat.mat);
+ }
}
return StructureMatrix_old;
--- /dev/null
+// Created on: 2013-10-10
+// Created by: Denis BOGOLEPOV
+// Copyright (c) 2013 OPEN CASCADE SAS
+//
+// The content of this file is subject to the Open CASCADE Technology Public
+// License Version 6.5 (the "License"). You may not use the content of this file
+// except in compliance with the License. Please obtain a copy of the License
+// at http://www.opencascade.org and read it completely before using this file.
+//
+// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
+// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
+//
+// The Original Code and all software distributed under the License is
+// distributed on an "AS IS" basis, without warranty of any kind, and the
+// Initial Developer hereby disclaims all such warranties, including without
+// limitation, any warranties of merchantability, fitness for a particular
+// purpose or non-infringement. Please see the License for the specific terms
+// and conditions governing the rights and limitations under the License.
+
+//! Direction to the viewer.
+varying vec3 View;
+
+//! Vertex normal in view space.
+varying vec3 Normal;
+
+//! Vertex position in view space.
+varying vec4 Position;
+
+
+//! Ambient contribution of light sources.
+vec3 Ambient;
+
+//! Diffuse contribution of light sources.
+vec3 Diffuse;
+
+//! Specular contribution of light sources.
+vec3 Specular;
+
+
+// =======================================================================
+// function : AmbientLight
+// purpose : Computes contribution of OCCT pure ambient light source
+// =======================================================================
+void AmbientLight (in int theIndex)
+{
+ Ambient += occLightSources[theIndex].Ambient;
+}
+
+// =======================================================================
+// function : PointLight
+// purpose : Computes contribution of OCCT isotropic point light source
+// =======================================================================
+void PointLight (in int theIndex,
+ in vec3 theNormal,
+ in vec3 theView,
+ in vec3 thePoint)
+{
+ vec3 aLight = occLightSources[theIndex].Position;
+ if (occLightSources[theIndex].Head == 0)
+ {
+ aLight = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aLight, 1.0));
+ }
+ aLight -= thePoint;
+
+ float aDist = length (aLight);
+ aLight = aLight * (1.0 / aDist);
+
+ float anAttenuation = 1.0 / (occLightSources[theIndex].ConstAttenuation +
+ occLightSources[theIndex].LinearAttenuation * aDist);
+
+ vec3 aHalf = normalize (aLight + theView);
+
+ float aNdotL = max (0.0, dot (theNormal, aLight));
+ float aNdotH = max (0.0, dot (theNormal, aHalf));
+
+ float aSpecl = 0.0;
+ if (aNdotL > 0.0)
+ {
+ aSpecl = pow (aNdotH, occFrontMaterial.Shininess);
+ }
+
+ Ambient += occLightSources[theIndex].Ambient * anAttenuation;
+ Diffuse += occLightSources[theIndex].Diffuse * aNdotL * anAttenuation;
+ Specular += occLightSources[theIndex].Specular * aSpecl * anAttenuation;
+}
+
+// =======================================================================
+// function : DirectionalLight
+// purpose : Computes contribution of OCCT directional light source
+// =======================================================================
+void DirectionalLight (in int theIndex,
+ in vec3 theNormal,
+ in vec3 theView)
+{
+ vec3 aLight = normalize (occLightSources[theIndex].Position);
+
+ if (occLightSources[theIndex].Head == 0)
+ {
+ aLight = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aLight, 0.0));
+ }
+
+ vec3 aHalf = normalize (aLight + theView);
+
+ float aNdotL = max (0.0, dot (theNormal, aLight));
+ float aNdotH = max (0.0, dot (theNormal, aHalf));
+
+ float aSpecl = 0.0;
+
+ if (aNdotL > 0.0)
+ {
+ aSpecl = pow (aNdotH, occFrontMaterial.Shininess);
+ }
+
+ Ambient += occLightSources[theIndex].Ambient;
+ Diffuse += occLightSources[theIndex].Diffuse * aNdotL;
+ Specular += occLightSources[theIndex].Specular * aSpecl;
+}
+
+// =======================================================================
+// function : ComputeLighting
+// purpose : Computes illumination from OCCT light sources
+// =======================================================================
+vec4 ComputeLighting (in vec3 theNormal,
+ in vec3 theView,
+ in vec4 thePoint)
+{
+ // Clear the light intensity accumulators
+ Ambient = vec3 (0.0);
+ Diffuse = vec3 (0.0);
+ Specular = vec3 (0.0);
+
+ vec3 aPoint = thePoint.xyz / thePoint.w;
+
+ for (int anIndex = 0; anIndex < occLightSourcesCount; ++anIndex)
+ {
+ occLightSource light = occLightSources[anIndex];
+
+ if (light.Type == occAmbientLight)
+ {
+ AmbientLight (anIndex);
+ }
+ else if (light.Type == occDirectLight)
+ {
+ DirectionalLight (anIndex, theNormal, theView);
+ }
+ else if (light.Type == occPointLight)
+ {
+ PointLight (anIndex, theNormal, theView, aPoint);
+ }
+ else if (light.Type == occSpotLight)
+ {
+ /* Not implemented */
+ }
+ }
+
+ return vec4 (Ambient, 1.0) * occFrontMaterial.Ambient +
+ vec4 (Diffuse, 1.0) * occFrontMaterial.Diffuse +
+ vec4 (Specular, 1.0) * occFrontMaterial.Specular;
+}
+
+// =======================================================================
+// function : main
+// purpose : Entry point to the fragment shader
+// =======================================================================
+void main()
+{
+ gl_FragColor = ComputeLighting (normalize (Normal),
+ normalize (View),
+ Position);
+}
--- /dev/null
+// Created on: 2013-10-10
+// Created by: Denis BOGOLEPOV
+// Copyright (c) 2013 OPEN CASCADE SAS
+//
+// The content of this file is subject to the Open CASCADE Technology Public
+// License Version 6.5 (the "License"). You may not use the content of this file
+// except in compliance with the License. Please obtain a copy of the License
+// at http://www.opencascade.org and read it completely before using this file.
+//
+// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
+// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
+//
+// The Original Code and all software distributed under the License is
+// distributed on an "AS IS" basis, without warranty of any kind, and the
+// Initial Developer hereby disclaims all such warranties, including without
+// limitation, any warranties of merchantability, fitness for a particular
+// purpose or non-infringement. Please see the License for the specific terms
+// and conditions governing the rights and limitations under the License.
+
+//! Direction to the viewer.
+varying vec3 View;
+
+//! Vertex normal in view space.
+varying vec3 Normal;
+
+//! Vertex position in view space.
+varying vec4 Position;
+
+// =======================================================================
+// function : TransformNormal
+// purpose : Computes the normal in view space
+// =======================================================================
+vec3 TransformNormal (in vec3 theNormal)
+{
+ vec4 aResult = occWorldViewMatrixInverseTranspose *
+ occModelWorldMatrixInverseTranspose * vec4 (theNormal, 0.0);
+
+ return normalize (aResult.xyz);
+}
+
+// =======================================================================
+// function : main
+// purpose : Entry point to the vertex shader
+// =======================================================================
+void main()
+{
+ // Compute vertex position in the view space
+ Position = occWorldViewMatrix * occModelWorldMatrix * occVertex;
+
+ // Compute vertex normal in the view space
+ Normal = TransformNormal (occNormal);
+
+ // Note: The specified view vector is absolutely correct only for the orthogonal
+ // projection. For perspective projection it will be approximate, but it is in
+ // good agreement with the OpenGL calculations
+ View = vec3 (0.0, 0.0, 1.0);
+
+ // Do fixed functionality vertex transform
+ gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;
+}
#include <TopLoc_Location.hxx>
#include <TopTools_HArray1OfShape.hxx>
#include <TColStd_HArray1OfTransient.hxx>
-#include <OSD_Directory.hxx>
-#include <OSD_File.hxx>
-#include <OSD_Path.hxx>
#include <OSD_Timer.hxx>
#include <Geom_Axis2Placement.hxx>
#include <Geom_Axis1Placement.hxx>
#include <AIS_ListIteratorOfListOfInteractive.hxx>
#include <Aspect_InteriorStyle.hxx>
#include <Graphic3d_AspectFillArea3d.hxx>
-#include <Graphic3d_TextureRoot.hxx>
#include <Graphic3d_AspectLine3d.hxx>
-#include <Graphic3d_ShaderObject.hxx>
-#include <Graphic3d_ShaderProgram.hxx>
+#include <Graphic3d_TextureRoot.hxx>
#include <Image_AlienPixMap.hxx>
#include <Prs3d_ShadingAspect.hxx>
#include <Prs3d_IsoAspect.hxx>
return 0;
}
-//==============================================================================
-//function : VShaderProg
-//purpose : Sets the pair of vertex and fragment shaders for the object
-//==============================================================================
-static Standard_Integer VShaderProg (Draw_Interpretor& /*theDI*/,
- Standard_Integer theArgNb,
- const char** theArgVec)
-{
- Handle(AIS_InteractiveContext) anAISContext = ViewerTest::GetAISContext();
- if (anAISContext.IsNull())
- {
- std::cerr << "Use 'vinit' command before " << theArgVec[0] << "\n";
- return 1;
- }
-
- if (theArgNb < 3)
- {
- std::cerr << theArgVec[0] <<" syntax error: lack of arguments - Type 'help vshaderprog\n";
- return 1;
- }
-
- const TCollection_AsciiString aShapeName = theArgVec[1];
- if (!GetMapOfAIS().IsBound2 (aShapeName))
- {
- std::cerr << theArgVec[0] << ": Use 'vdisplay' before\n";
- return 1;
- }
-
- Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast (GetMapOfAIS().Find2 (aShapeName));
- if (anIO.IsNull())
- {
- std::cerr << "Shape " << aShapeName.ToCString() << " does not exist\n";
- return 1;
- }
-
- Handle(Graphic3d_ShaderProgram) aProgram = new Graphic3d_ShaderProgram();
- const TCollection_AsciiString aVertexSource (theArgVec[2]);
- if (!aVertexSource.IsEmpty() && !OSD_File(aVertexSource).Exists())
- {
- std::cerr << "Non-existing vertex shader source\n";
- return 1;
- }
-
- TCollection_AsciiString aFragmentSource (theArgVec[3]);
- if (!aFragmentSource.IsEmpty() && !OSD_File(aFragmentSource).Exists())
- {
- std::cerr << "Non-existing fragment shader source\n";
- return 1;
- }
-
- aProgram->AttachShader (Graphic3d_ShaderObject::CreateFromFile (Graphic3d_TOS_VERTEX, aVertexSource));
- aProgram->AttachShader (Graphic3d_ShaderObject::CreateFromFile (Graphic3d_TOS_FRAGMENT, aFragmentSource));
- anIO->Attributes()->ShadingAspect()->Aspect()->SetShaderProgram (aProgram);
-
- anAISContext->Redisplay (anIO);
- return 0;
-}
-
//==============================================================================
//function : VDisplay2
//author : ege
or 'vtexture NameOfShape IdOfTexture' (0<=IdOfTexture<=20)' to use predefined textures\n ",
__FILE__,VTexture,group);
- theCommands.Add("vshaderprog",
- "'vshaderprog NameOfShape VertexShaderFile FragmentShaderFile'",
- __FILE__,VShaderProg,group);
-
theCommands.Add("vtexscale",
"'vtexscale NameOfShape ScaleU ScaleV' \n \
or 'vtexscale NameOfShape ScaleUV' \n \
#include <ViewerTest.hxx>
+#include <AIS_Drawer.hxx>
#include <AIS_InteractiveContext.hxx>
#include <AIS_InteractiveObject.hxx>
#include <Draw.hxx>
#include <Draw_Interpretor.hxx>
#include <Graphic3d_Group.hxx>
+#include <Graphic3d_ShaderObject.hxx>
+#include <Graphic3d_ShaderProgram.hxx>
#include <OpenGl_ArbVBO.hxx>
#include <OpenGl_AspectFace.hxx>
#include <OpenGl_AspectLine.hxx>
#include <OpenGl_GlCore20.hxx>
#include <OpenGl_GraphicDriver.hxx>
#include <OpenGl_Workspace.hxx>
+#include <OSD_Environment.hxx>
+#include <OSD_File.hxx>
#include <Prs3d_Presentation.hxx>
#include <Prs3d_Root.hxx>
+#include <Prs3d_ShadingAspect.hxx>
#include <Select3D_SensitiveCurve.hxx>
#include <SelectMgr_EntityOwner.hxx>
#include <SelectMgr_Selection.hxx>
-#include <V3d_Viewer.hxx>
#include <TCollection_AsciiString.hxx>
#include <V3d_View.hxx>
+#include <V3d_Viewer.hxx>
#include <Visual3d_View.hxx>
+#include <ViewerTest_DoubleMapOfInteractiveAndName.hxx>
+#include <ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName.hxx>
extern Standard_Boolean VDisplayAISObject (const TCollection_AsciiString& theName,
const Handle(AIS_InteractiveObject)& theAISObj,
Standard_Boolean theReplaceIfExists = Standard_True);
+extern ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS();
//=======================================================================
//function : VUserDraw
return 0;
}
+
+//==============================================================================
+//function : VShaderProg
+//purpose : Sets the pair of vertex and fragment shaders for the object
+//==============================================================================
+static Standard_Integer VShaderProg (Draw_Interpretor& /*theDI*/,
+ Standard_Integer theArgNb,
+ const char** theArgVec)
+{
+ Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
+ if (aCtx.IsNull())
+ {
+ std::cerr << "Use 'vinit' command before " << theArgVec[0] << "\n";
+ return 1;
+ }
+ else if (theArgNb < 2)
+ {
+ std::cerr << theArgVec[0] << " syntax error: lack of arguments\n";
+ return 1;
+ }
+
+ TCollection_AsciiString aLastArg (theArgVec[theArgNb - 1]);
+ aLastArg.UpperCase();
+ const Standard_Boolean toTurnOff = aLastArg == "OFF";
+ Standard_Integer anArgsNb = theArgNb - 1;
+ Handle(Graphic3d_ShaderProgram) aProgram;
+ if (!toTurnOff
+ && aLastArg == "PHONG")
+ {
+ aProgram = new Graphic3d_ShaderProgram (Graphic3d_ShaderProgram::ShaderName_Phong);
+ }
+ if (!toTurnOff
+ && aProgram.IsNull())
+ {
+ if (theArgNb < 3)
+ {
+ std::cerr << theArgVec[0] << " syntax error: lack of arguments\n";
+ return 1;
+ }
+
+ const TCollection_AsciiString aSrcVert = theArgVec[theArgNb - 2];
+ const TCollection_AsciiString aSrcFrag = theArgVec[theArgNb - 1];
+ if (!aSrcVert.IsEmpty()
+ && !OSD_File (aSrcVert).Exists())
+ {
+ std::cerr << "Non-existing vertex shader source\n";
+ return 1;
+ }
+ if (!aSrcFrag.IsEmpty()
+ && !OSD_File (aSrcFrag).Exists())
+ {
+ std::cerr << "Non-existing fragment shader source\n";
+ return 1;
+ }
+
+ aProgram = new Graphic3d_ShaderProgram();
+ aProgram->AttachShader (Graphic3d_ShaderObject::CreateFromFile (Graphic3d_TOS_VERTEX, aSrcVert));
+ aProgram->AttachShader (Graphic3d_ShaderObject::CreateFromFile (Graphic3d_TOS_FRAGMENT, aSrcFrag));
+ anArgsNb = theArgNb - 2;
+ }
+
+ Handle(AIS_InteractiveObject) anIO;
+ if (anArgsNb <= 1
+ || *theArgVec[1] == '*')
+ {
+ for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
+ anIter.More(); anIter.Next())
+ {
+ anIO = Handle(AIS_InteractiveObject)::DownCast (anIter.Key1());
+ if (!anIO.IsNull())
+ {
+ anIO->Attributes()->ShadingAspect()->Aspect()->SetShaderProgram (aProgram);
+ aCtx->Redisplay (anIO, Standard_False);
+ }
+ }
+ aCtx->UpdateCurrentViewer();
+ return 0;
+ }
+
+ for (Standard_Integer anArgIter = 1; anArgIter < anArgsNb; ++anArgIter)
+ {
+ const TCollection_AsciiString aName (theArgVec[anArgIter]);
+ if (!GetMapOfAIS().IsBound2 (aName))
+ {
+ std::cerr << "Warning: " << aName.ToCString() << " is not displayed\n";
+ continue;
+ }
+ anIO = Handle(AIS_InteractiveObject)::DownCast (GetMapOfAIS().Find2 (aName));
+ if (anIO.IsNull())
+ {
+ std::cerr << "Warning: " << aName.ToCString() << " is not an AIS object\n";
+ continue;
+ }
+ anIO->Attributes()->ShadingAspect()->Aspect()->SetShaderProgram (aProgram);
+ aCtx->Redisplay (anIO, Standard_False);
+ }
+
+ aCtx->UpdateCurrentViewer();
+ return 0;
+}
+
//=======================================================================
//function : OpenGlCommands
//purpose :
theCommands.Add("vimmediatefront",
"vimmediatefront : render immediate mode to front buffer or to back buffer",
__FILE__, VImmediateFront, aGroup);
-
theCommands.Add("vglinfo",
"vglinfo [GL_VENDOR] [GL_RENDERER] [GL_VERSION] [GL_SHADING_LANGUAGE_VERSION] [GL_EXTENSIONS]"
" : prints GL info",
__FILE__, VGlInfo, aGroup);
+ theCommands.Add("vshaderprog",
+ " 'vshaderprog [name] pathToVertexShader pathToFragmentShader'"
+ "\n\t\t: or 'vshaderprog [name] off' to disable GLSL program"
+ "\n\t\t: or 'vshaderprog [name] phong' to enable per-pixel lighting calculations"
+ "\n\t\t: * might be used to specify all displayed objects",
+ __FILE__, VShaderProg, aGroup);
}
}
//==============================================================================
-//function : SplitParameter
-//purpose : Split parameter string to parameter name an patameter value
+//function : splitParameter
+//purpose : Split parameter string to parameter name an parameter value
//==============================================================================
-Standard_Boolean SplitParameter (const TCollection_AsciiString& theString,
- TCollection_AsciiString& theName,
- TCollection_AsciiString& theValue)
+Standard_Boolean splitParameter (const TCollection_AsciiString& theString,
+ TCollection_AsciiString& theName,
+ TCollection_AsciiString& theValue)
{
Standard_Integer aParamNameEnd = theString.FirstLocationInSet("=",1, theString.Length());
if (aParamNameEnd == 0)
for (Standard_Integer i = 1; i < theArgsNb; ++i)
{
TCollection_AsciiString aName = "", aValue = "";
- if(!SplitParameter (TCollection_AsciiString(theArgVec[i]),aName,aValue) && theArgsNb == 2)
+ if(!splitParameter (TCollection_AsciiString(theArgVec[i]),aName,aValue) && theArgsNb == 2)
{
// In case of syntax: vinit ViewName
aViewName = theArgVec[1];
return 0;
}
+//===============================================================================================
+//function : VDefaults
+//purpose :
+//===============================================================================================
+static int VDefaults (Draw_Interpretor& theDi,
+ Standard_Integer theArgsNb,
+ const char** theArgVec)
+{
+ const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
+ if (aCtx.IsNull())
+ {
+ std::cerr << "No active viewer!\n";
+ return 1;
+ }
+
+ Handle(Prs3d_Drawer) aDefParams = aCtx->DefaultDrawer();
+ if (theArgsNb < 2)
+ {
+ if (aDefParams->TypeOfDeflection() == Aspect_TOD_RELATIVE)
+ {
+ theDi << "DeflType: relative\n"
+ << "DeviationCoeff: " << aDefParams->DeviationCoefficient() << "\n";
+ }
+ else
+ {
+ theDi << "DeflType: absolute\n"
+ << "AbsoluteDeflection: " << aDefParams->MaximalChordialDeviation() << "\n";
+ }
+ theDi << "AngularDeflection: " << (180.0 * aDefParams->HLRAngle() / M_PI) << "\n";
+ return 0;
+ }
+
+ for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
+ {
+ TCollection_AsciiString anArg (theArgVec[anArgIter]);
+ TCollection_AsciiString aKey, aValue;
+ if (!splitParameter (anArg, aKey, aValue)
+ || aValue.IsEmpty())
+ {
+ std::cerr << "Error, wrong syntax at: '" << anArg.ToCString() << "'!\n";
+ return 1;
+ }
+
+ aKey.UpperCase();
+ if (aKey == "ABSDEFL"
+ || aKey == "ABSOLUTEDEFLECTION"
+ || aKey == "DEFL"
+ || aKey == "DEFLECTION")
+ {
+ aDefParams->SetTypeOfDeflection (Aspect_TOD_ABSOLUTE);
+ aDefParams->SetMaximalChordialDeviation (aValue.RealValue());
+ }
+ else if (aKey == "RELDEFL"
+ || aKey == "RELATIVEDEFLECTION"
+ || aKey == "DEVCOEFF"
+ || aKey == "DEVIATIONCOEFF"
+ || aKey == "DEVIATIONCOEFFICIENT")
+ {
+ aDefParams->SetTypeOfDeflection (Aspect_TOD_RELATIVE);
+ aDefParams->SetDeviationCoefficient (aValue.RealValue());
+ }
+ else if (aKey == "ANGDEFL"
+ || aKey == "ANGULARDEFL"
+ || aKey == "ANGULARDEFLECTION")
+ {
+ // currently HLRDeviationAngle is used instead of DeviationAngle in most places
+ aDefParams->SetHLRAngle (M_PI * aValue.RealValue() / 180.0);
+ }
+ else
+ {
+ std::cerr << "Warning, unknown argument '" << anArg.ToCString() << "'\n";
+ }
+ }
+
+ return 0;
+}
+
//==============================================================================
//function : VClInfo
//purpose : Prints info about active OpenCL device
" 2 - all textures enabled.\n"
" this command sets texture details mode for the specified view.\n"
, __FILE__, VSetTextureMode, group);
+ theCommands.Add("vdefaults",
+ "vdefaults [absDefl=value] [devCoeff=value] [angDefl=value]",
+ __FILE__, VDefaults, group);
theCommands.Add("vraytrace",
"vraytrace 0|1",
__FILE__,VRaytrace,group);
set group "v3d"
pload VISUALIZATION
-vinit
+vinit View1
pload TOPTEST
if { [info exists imagedir] == 0 } {
- set imagedir .
+ set imagedir .
}
if { [info exists test_image ] == 0 } {
- set test_image photo
+ set test_image photo
}
-
-
-
-
-
catch { vfit }
if { [ catch { vdump $imagedir/${test_image}.png } catch_result ] } {
- puts $catch_result
+ puts $catch_result
}
+catch { vglinfo }
puts "TEST COMPLETED"
-
-
--- /dev/null
+puts "========"
+puts "Per-pixel lighting using GLSL program (Phong shading)"
+puts "========"
+
+# create box
+box b 1 2 3
+
+# draw box
+vinit View1
+vclear
+vsetdispmode 1
+vdisplay b
+vfit
+vrotate 0.2 0.0 0.0
+
+# take snapshot with fixed pipeline
+vdump $::imagedir/${::casename}_OFF.png
+vshaderprog b phong
+vdump $::imagedir/${::casename}_ph1.png
+
+vclear
+vdisplay b
+vshaderprog b phong
+vdump $::imagedir/${::casename}_ph2.png
+vmoveto 250 250
--- /dev/null
+puts "========"
+puts "Per-pixel lighting using GLSL program (Phong shading)"
+puts "========"
+
+# import model
+restore [locate_data_file occ/fuse.brep] f
+tclean f
+box b 2 0 0 1 0.5 0.25
+
+# draw box
+vinit View1
+vclear
+vdefaults absDefl=0.5
+vsetdispmode 1
+vdisplay f
+vfit
+vrotate -0.5 0.0 0.0
+vdisplay b
+vfit
+
+# take snapshot with fixed pipeline
+vdump $::imagedir/${::casename}_OFF.png
+
+vshaderprog f phong
+vshaderprog b phong
+vshaderprog b off
+vrotate -0.2 0.0 0.0
+vmoveto 100 100
+vdump $::imagedir/${::casename}_ph1.png
--- /dev/null
+puts "========"
+puts "Per-pixel lighting using GLSL program (Phong shading)"
+puts "========"
+
+# import model
+restore [locate_data_file occ/fuse.brep] f
+tclean f
+
+# draw box
+vinit View1
+vclear
+vdefaults absDefl=0.5
+vsetdispmode 1
+vdisplay f
+vfit
+vrotate -0.5 0.0 0.0
+vfit
+
+# take snapshot with fixed pipeline
+vdump $::imagedir/${::casename}_OFF.png
+vshaderprog f phong
+vdump $::imagedir/${::casename}_ph1.png
+
+vclear
+vdisplay f
+vshaderprog f phong
+vdump $::imagedir/${::casename}_ph2.png
+vmoveto 250 250
--- /dev/null
+puts "========"
+puts "Per-pixel lighting using GLSL program (Phong shading)"
+puts "========"
+
+# create box
+box b 1 2 3
+
+# draw box
+vinit View1
+vclear
+vsetdispmode 1
+vdisplay b
+vfit
+vrotate 0.2 0.0 0.0
+
+vshaderprog b phong
+vdump $::imagedir/${::casename}_1.png
+
+vinit View2
+vdump $::imagedir/${::casename}_2.png
+vclose View2
010 wire
011 wire_solid
012 voxel
+013 glsl