OpenGl_ShaderObject.cxx
OpenGl_ShaderProgram.hxx
OpenGl_ShaderProgram.cxx
+OpenGl_SetOfShaderPrograms.hxx
OpenGl_ShaderManager.hxx
OpenGl_ShaderManager.cxx
OpenGl_ShaderStates.hxx
--- /dev/null
+// Created on: 2014-10-08
+// Created by: Kirill Gavrilov
+// Copyright (c) 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.
+
+#ifndef _OpenGl_SetOfShaderPrograms_HeaderFile
+#define _OpenGl_SetOfShaderPrograms_HeaderFile
+
+#include <NCollection_DataMap.hxx>
+#include <OpenGl_ShaderProgram.hxx>
+
+//! Standard GLSL program combination bits.
+enum OpenGl_ProgramOptions
+{
+ OpenGl_PO_ClipPlanes = 0x01, //!< handle clipping planes
+ OpenGl_PO_Point = 0x02, //!< point marker
+ OpenGl_PO_VertColor = 0x04, //!< per-vertex color
+ OpenGl_PO_TextureRGB = 0x08, //!< handle RGB texturing
+ OpenGl_PO_TextureA = 0x10, //!< handle Alpha texturing
+ OpenGl_PO_NB = 0x20 //!< overall number of combinations
+};
+
+//! Alias to programs array of predefined length
+class OpenGl_SetOfShaderPrograms : public Standard_Transient
+{
+
+public:
+
+ //! Empty constructor
+ OpenGl_SetOfShaderPrograms() {}
+
+ //! Access program by index
+ Handle(OpenGl_ShaderProgram)& ChangeValue (const Standard_Integer theIndex) { return myPrograms[theIndex]; }
+
+protected:
+
+ Handle(OpenGl_ShaderProgram) myPrograms[OpenGl_PO_NB]; //!< programs array
+
+public:
+
+ DEFINE_STANDARD_RTTI (OpenGl_SetOfShaderPrograms)
+
+};
+
+DEFINE_STANDARD_HANDLE(OpenGl_SetOfShaderPrograms, Standard_Transient)
+
+typedef NCollection_DataMap<TCollection_AsciiString, Handle(OpenGl_SetOfShaderPrograms)> OpenGl_MapOfShaderPrograms;
+
+#endif // _OpenGl_SetOfShaderPrograms_HeaderFile
#include <OpenGl_ShaderProgram.hxx>
#include <OpenGl_Workspace.hxx>
+IMPLEMENT_STANDARD_HANDLE (OpenGl_SetOfShaderPrograms, Standard_Transient)
+IMPLEMENT_STANDARD_RTTIEXT(OpenGl_SetOfShaderPrograms, Standard_Transient)
+
IMPLEMENT_STANDARD_HANDLE (OpenGl_ShaderManager, Standard_Transient)
IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderManager, Standard_Transient)
EOL"vec3 Diffuse;" //!< Diffuse contribution of light sources
EOL"vec3 Specular;"; //!< Specular contribution of light sources
-//! Computes illumination from light sources
-const char THE_FUNC_computeLighting[] =
- EOL"vec4 computeLighting (in vec3 theNormal,"
- EOL" in vec3 theView,"
- EOL" in vec4 thePoint,"
- EOL" in bool theIsFront)"
- EOL"{"
- // clear the light intensity accumulators
- EOL" Ambient = occLightAmbient.rgb;"
- EOL" Diffuse = vec3 (0.0);"
- EOL" Specular = vec3 (0.0);"
- EOL" vec3 aPoint = thePoint.xyz / thePoint.w;"
- EOL" for (int anIndex = 0; anIndex < occLightSourcesCount; ++anIndex)"
- EOL" {"
- EOL" int aType = occLight_Type (anIndex);"
- EOL" if (aType == OccLightType_Direct)"
- EOL" {"
- EOL" directionalLight (anIndex, theNormal, theView, theIsFront);"
- EOL" }"
- EOL" else if (aType == OccLightType_Point)"
- EOL" {"
- EOL" pointLight (anIndex, theNormal, theView, aPoint, theIsFront);"
- EOL" }"
- EOL" else if (aType == OccLightType_Spot)"
- EOL" {"
- EOL" spotLight (anIndex, theNormal, theView, aPoint, theIsFront);"
- EOL" }"
- EOL" }"
- EOL
- EOL" vec4 aMaterialAmbient = theIsFront ? occFrontMaterial_Ambient() : occBackMaterial_Ambient();"
- EOL" vec4 aMaterialDiffuse = theIsFront ? occFrontMaterial_Diffuse() : occBackMaterial_Diffuse();"
- EOL" vec4 aMaterialSpecular = theIsFront ? occFrontMaterial_Specular() : occBackMaterial_Specular();"
- EOL" vec4 aMaterialEmission = theIsFront ? occFrontMaterial_Emission() : occBackMaterial_Emission();"
- EOL" return vec4 (Ambient, 1.0) * aMaterialAmbient"
- EOL" + vec4 (Diffuse, 1.0) * aMaterialDiffuse"
- EOL" + vec4 (Specular, 1.0) * aMaterialSpecular"
- EOL" + aMaterialEmission;"
- EOL"}";
-
//! Function computes contribution of isotropic point light source
const char THE_FUNC_pointLight[] =
EOL"void pointLight (in int theId,"
myContext (theContext),
myLastView (NULL)
{
- myLightPrograms = myGouraudPrograms;
+ //
}
// =======================================================================
return myProgramList.IsEmpty();
}
+// =======================================================================
+// function : switchLightPrograms
+// purpose :
+// =======================================================================
+void OpenGl_ShaderManager::switchLightPrograms()
+{
+ TCollection_AsciiString aKey (myShadingModel == Visual3d_TOM_FRAGMENT ? "p_" : "g_");
+ const OpenGl_ListOfLight* aLights = myLightSourceState.LightSources();
+ if (aLights != NULL)
+ {
+ for (OpenGl_ListOfLight::Iterator aLightIter (*aLights); aLightIter.More(); aLightIter.Next())
+ {
+ switch (aLightIter.Value().Type)
+ {
+ case Visual3d_TOLS_AMBIENT:
+ break; // skip ambient
+ case Visual3d_TOLS_DIRECTIONAL:
+ aKey += "d";
+ break;
+ case Visual3d_TOLS_POSITIONAL:
+ aKey += "p";
+ break;
+ case Visual3d_TOLS_SPOT:
+ aKey += "s";
+ break;
+ }
+ }
+ }
+
+ if (!myMapOfLightPrograms.Find (aKey, myLightPrograms))
+ {
+ myLightPrograms = new OpenGl_SetOfShaderPrograms();
+ myMapOfLightPrograms.Bind (aKey, myLightPrograms);
+ }
+}
+
// =======================================================================
// function : UpdateLightSourceStateTo
// purpose : Updates state of OCCT light sources
{
myLightSourceState.Set (theLights);
myLightSourceState.Update();
+ switchLightPrograms();
+}
+
+// =======================================================================
+// function : SetShadingModel
+// purpose :
+// =======================================================================
+void OpenGl_ShaderManager::SetShadingModel (const Visual3d_TypeOfModel theModel)
+{
+ myShadingModel = theModel;
+ switchLightPrograms();
}
// =======================================================================
return Standard_True;
}
+// =======================================================================
+// function : stdComputeLighting
+// purpose :
+// =======================================================================
+TCollection_AsciiString OpenGl_ShaderManager::stdComputeLighting()
+{
+ bool aLightsMap[Visual3d_TOLS_SPOT + 1] = { false, false, false, false };
+ TCollection_AsciiString aLightsFunc, aLightsLoop;
+ const OpenGl_ListOfLight* aLights = myLightSourceState.LightSources();
+ if (aLights != NULL)
+ {
+ Standard_Integer anIndex = 0;
+ for (OpenGl_ListOfLight::Iterator aLightIter (*aLights); aLightIter.More(); aLightIter.Next(), ++anIndex)
+ {
+ switch (aLightIter.Value().Type)
+ {
+ case Visual3d_TOLS_AMBIENT:
+ --anIndex;
+ break; // skip ambient
+ case Visual3d_TOLS_DIRECTIONAL:
+ aLightsLoop = aLightsLoop + EOL" directionalLight (" + anIndex + ", theNormal, theView, theIsFront);";
+ break;
+ case Visual3d_TOLS_POSITIONAL:
+ aLightsLoop = aLightsLoop + EOL" pointLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);";
+ break;
+ case Visual3d_TOLS_SPOT:
+ aLightsLoop = aLightsLoop + EOL" spotLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);";
+ break;
+ }
+
+ bool& aTypeBit = aLightsMap[aLightIter.Value().Type];
+ if (aTypeBit)
+ {
+ continue;
+ }
+
+ aTypeBit = true;
+ switch (aLightIter.Value().Type)
+ {
+ case Visual3d_TOLS_AMBIENT: break;
+ case Visual3d_TOLS_DIRECTIONAL: aLightsFunc += THE_FUNC_directionalLight; break;
+ case Visual3d_TOLS_POSITIONAL: aLightsFunc += THE_FUNC_pointLight; break;
+ case Visual3d_TOLS_SPOT: aLightsFunc += THE_FUNC_spotLight; break;
+ }
+ }
+ }
+
+ return TCollection_AsciiString()
+ + THE_FUNC_lightDef
+ + aLightsFunc
+ + EOL
+ EOL"vec4 computeLighting (in vec3 theNormal,"
+ EOL" in vec3 theView,"
+ EOL" in vec4 thePoint,"
+ EOL" in bool theIsFront)"
+ EOL"{"
+ EOL" Ambient = occLightAmbient.rgb;"
+ EOL" Diffuse = vec3 (0.0);"
+ EOL" Specular = vec3 (0.0);"
+ EOL" vec3 aPoint = thePoint.xyz / thePoint.w;"
+ + aLightsLoop
+ + EOL" vec4 aMaterialAmbient = theIsFront ? occFrontMaterial_Ambient() : occBackMaterial_Ambient();"
+ EOL" vec4 aMaterialDiffuse = theIsFront ? occFrontMaterial_Diffuse() : occBackMaterial_Diffuse();"
+ EOL" vec4 aMaterialSpecular = theIsFront ? occFrontMaterial_Specular() : occBackMaterial_Specular();"
+ EOL" vec4 aMaterialEmission = theIsFront ? occFrontMaterial_Emission() : occBackMaterial_Emission();"
+ EOL" return vec4 (Ambient, 1.0) * aMaterialAmbient"
+ EOL" + vec4 (Diffuse, 1.0) * aMaterialDiffuse"
+ EOL" + vec4 (Specular, 1.0) * aMaterialSpecular"
+ EOL" + aMaterialEmission;"
+ EOL"}";
+}
+
// =======================================================================
// function : prepareStdProgramGouraud
// purpose :
aSrcFragExtraMain += THE_FRAG_CLIP_PLANES;
}
+ const TCollection_AsciiString aLights = stdComputeLighting();
aSrcVert = TCollection_AsciiString()
+ THE_FUNC_transformNormal
+ EOL
- + THE_FUNC_lightDef
- + THE_FUNC_pointLight
- + THE_FUNC_spotLight
- + THE_FUNC_directionalLight
- + EOL
- + THE_FUNC_computeLighting
+ + aLights
+ EOL
EOL"varying vec4 FrontColor;"
EOL"varying vec4 BackColor;"
+ EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
EOL"}";
+ const TCollection_AsciiString aLights = stdComputeLighting();
aSrcFrag = TCollection_AsciiString()
+ EOL"varying vec4 PositionWorld;"
EOL"varying vec4 Position;"
EOL"varying vec3 Normal;"
EOL"varying vec3 View;"
+ EOL
- + THE_FUNC_lightDef
- + THE_FUNC_pointLight
- + THE_FUNC_spotLight
- + THE_FUNC_directionalLight
- + EOL
- + THE_FUNC_computeLighting
+ + aLights
+ EOL
EOL"void main()"
EOL"{"
#include <NCollection_Sequence.hxx>
#include <Handle_OpenGl_ShaderManager.hxx>
-#include <OpenGl_ShaderProgram.hxx>
+#include <OpenGl_SetOfShaderPrograms.hxx>
#include <OpenGl_ShaderStates.hxx>
#include <OpenGl_AspectFace.hxx>
#include <OpenGl_AspectLine.hxx>
//! Map to declare per-program states of OCCT materials.
typedef NCollection_DataMap<Handle(OpenGl_ShaderProgram), OpenGl_MaterialState> OpenGl_MaterialStates;
-//! Standard GLSL program combination bits.
-enum OpenGl_ProgramOptions
-{
- OpenGl_PO_ClipPlanes = 0x01, //!< handle clipping planes
- OpenGl_PO_Point = 0x02, //!< point marker
- OpenGl_PO_VertColor = 0x04, //!< per-vertex color
- OpenGl_PO_TextureRGB = 0x08, //!< handle RGB texturing
- OpenGl_PO_TextureA = 0x10, //!< handle Alpha texturing
- OpenGl_PO_NB = 0x20 //!< overall number of combinations
-};
-
//! This class is responsible for managing shader programs.
class OpenGl_ShaderManager : public Standard_Transient
{
}
//! Sets shading model.
- void SetShadingModel(const Visual3d_TypeOfModel theModel)
- {
- myLightPrograms = theModel == Visual3d_TOM_FRAGMENT
- ? myLightPrograms = myPhongPrograms
- : myLightPrograms = myGouraudPrograms;
- myShadingModel = theModel;
- }
+ Standard_EXPORT void SetShadingModel(const Visual3d_TypeOfModel theModel);
//! Sets last view manger used with.
//! Helps to handle matrix states in multi-view configurations.
{
if (theToLightOn)
{
- Handle(OpenGl_ShaderProgram)& aProgram = myLightPrograms[theBits];
+ Handle(OpenGl_ShaderProgram)& aProgram = myLightPrograms->ChangeValue (theBits);
if (aProgram.IsNull())
{
prepareStdProgramLight (aProgram, theBits);
return aProgram;
}
- Handle(OpenGl_ShaderProgram)& aProgram = myFlatPrograms[theBits];
+ Handle(OpenGl_ShaderProgram)& aProgram = myFlatPrograms.ChangeValue (theBits);
if (aProgram.IsNull())
{
prepareStdProgramFlat (aProgram, theBits);
Standard_EXPORT Standard_Boolean prepareStdProgramPhong (Handle(OpenGl_ShaderProgram)& theProgram,
const Standard_Integer theBits);
+ //! Define computeLighting GLSL function depending on current lights configuration
+ Standard_EXPORT TCollection_AsciiString stdComputeLighting();
+
//! Bind specified program to current context and apply state.
Standard_EXPORT Standard_Boolean bindProgramWithState (const Handle(OpenGl_ShaderProgram)& theProgram,
const OpenGl_Element* theAspect);
+ //! Set pointer myLightPrograms to active lighting programs set from myMapOfLightPrograms
+ Standard_EXPORT void switchLightPrograms();
+
protected:
- Visual3d_TypeOfModel myShadingModel; //!< lighting shading model
- OpenGl_ShaderProgramList myProgramList; //!< The list of shader programs
- Handle(OpenGl_ShaderProgram)* myLightPrograms; //!< pointer to active lighting programs matrix, depending on shading model and lights configuration
- Handle(OpenGl_ShaderProgram) myGouraudPrograms[OpenGl_PO_NB]; //!< matrix with per-vertex lighting programs
- Handle(OpenGl_ShaderProgram) myPhongPrograms [OpenGl_PO_NB]; //!< matrix with per-fragment lighting programs
- Handle(OpenGl_ShaderProgram) myFlatPrograms [OpenGl_PO_NB]; //!< programs matrix without lighting
- Handle(OpenGl_ShaderProgram) myFontProgram; //!< standard program for textured text
+ Visual3d_TypeOfModel myShadingModel; //!< lighting shading model
+ OpenGl_ShaderProgramList myProgramList; //!< The list of shader programs
+ Handle(OpenGl_SetOfShaderPrograms) myLightPrograms; //!< pointer to active lighting programs matrix
+ OpenGl_SetOfShaderPrograms myFlatPrograms; //!< programs matrix without lighting
+ Handle(OpenGl_ShaderProgram) myFontProgram; //!< standard program for textured text
+ OpenGl_MapOfShaderPrograms myMapOfLightPrograms; //!< map of lighting programs depending on shading model and lights configuration
- OpenGl_Context* myContext; //!< OpenGL context
+ OpenGl_Context* myContext; //!< OpenGL context
protected:
- OpenGl_MaterialStates myMaterialStates; //!< Per-program state of OCCT material
- OpenGl_ProjectionState myProjectionState; //!< State of OCCT projection transformation
- OpenGl_ModelWorldState myModelWorldState; //!< State of OCCT model-world transformation
- OpenGl_WorldViewState myWorldViewState; //!< State of OCCT world-view transformation
- OpenGl_LightSourceState myClippingState; //!< State of OCCT clipping planes
- OpenGl_LightSourceState myLightSourceState; //!< State of OCCT light sources
+ OpenGl_MaterialStates myMaterialStates; //!< Per-program state of OCCT material
+ OpenGl_ProjectionState myProjectionState; //!< State of OCCT projection transformation
+ OpenGl_ModelWorldState myModelWorldState; //!< State of OCCT model-world transformation
+ OpenGl_WorldViewState myWorldViewState; //!< State of OCCT world-view transformation
+ OpenGl_LightSourceState myClippingState; //!< State of OCCT clipping planes
+ OpenGl_LightSourceState myLightSourceState; //!< State of OCCT light sources
private:
- const OpenGl_View* myLastView; //!< Pointer to the last view shader manager used with
+ const OpenGl_View* myLastView; //!< Pointer to the last view shader manager used with
public:
// Set OCCT state uniform variables
const Handle(OpenGl_ShaderManager) aManager = aContext->ShaderManager();
const Standard_Boolean isSameView = aManager->IsSameView (this); // force camera state update when needed
- if (!aManager->IsEmpty())
+ if (StateInfo (myCurrLightSourceState, aManager->LightSourceState().Index()) != myLastLightSourceState)
{
- if (StateInfo (myCurrLightSourceState, aManager->LightSourceState().Index()) != myLastLightSourceState)
- {
- aManager->UpdateLightSourceStateTo (&myLights);
- myLastLightSourceState = StateInfo (myCurrLightSourceState, aManager->LightSourceState().Index());
- }
+ aManager->UpdateLightSourceStateTo (&myLights);
+ myLastLightSourceState = StateInfo (myCurrLightSourceState, aManager->LightSourceState().Index());
+ }
- if (myProjectionState != myCamera->ProjectionState()
- || !isSameView)
- {
- myProjectionState = myCamera->ProjectionState();
- aManager->UpdateProjectionStateTo ((const Tmatrix3*)myCamera->ProjectionMatrixF().GetData());
- }
+ if (myProjectionState != myCamera->ProjectionState()
+ || !isSameView)
+ {
+ myProjectionState = myCamera->ProjectionState();
+ aManager->UpdateProjectionStateTo ((const Tmatrix3*)myCamera->ProjectionMatrixF().GetData());
+ }
- if (myModelViewState != myCamera->ModelViewState()
- || !isSameView)
- {
- myModelViewState = myCamera->ModelViewState();
- aManager->UpdateWorldViewStateTo ((const Tmatrix3*)myCamera->OrientationMatrixF().GetData());
- }
+ if (myModelViewState != myCamera->ModelViewState()
+ || !isSameView)
+ {
+ myModelViewState = myCamera->ModelViewState();
+ aManager->UpdateWorldViewStateTo ((const Tmatrix3*)myCamera->OrientationMatrixF().GetData());
+ }
- 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 } };
+ 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 } };
- aContext->ShaderManager()->UpdateModelWorldStateTo (&aModelWorldState);
- }
+ aContext->ShaderManager()->UpdateModelWorldStateTo (&aModelWorldState);
}
if (isProjectionMatUpdateNeeded