#include <OpenGl_Context.hxx>
#include <OpenGl_ShaderManager.hxx>
#include <OpenGl_ShaderProgram.hxx>
+#include <OpenGl_Workspace.hxx>
IMPLEMENT_STANDARD_HANDLE (OpenGl_ShaderManager, Standard_Transient)
IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderManager, Standard_Transient)
theShareKey = theProxy->GetId();
if (myContext->GetResource<Handle(OpenGl_ShaderProgram)> (theShareKey, theProgram))
{
- theProgram->Share();
+ if (theProgram->Share())
+ {
+ myProgramList.Append (theProgram);
+ }
return;
}
else
{
theProgram.Nullify();
- myContext->ReleaseResource (anID);
+ myContext->ReleaseResource (anID, Standard_True);
}
}
return myWorldViewState;
}
+//! Packed properties of light source
+class OpenGl_ShaderLightParameters
+{
+public:
+
+ OpenGl_Vec4 Color;
+ OpenGl_Vec4 Position;
+ OpenGl_Vec4 Direction;
+ OpenGl_Vec4 Parameters;
+
+ //! Returns packed (serialized) representation of light source properties
+ const OpenGl_Vec4* Packed() const { return reinterpret_cast<const OpenGl_Vec4*> (this); }
+ static Standard_Integer NbOfVec4() { return 4; }
+
+};
+
+//! Packed light source type information
+class OpenGl_ShaderLightType
+{
+public:
+
+ Standard_Integer Type;
+ Standard_Integer IsHeadlight;
+
+ //! Returns packed (serialized) representation of light source type
+ const OpenGl_Vec2i* Packed() const { return reinterpret_cast<const OpenGl_Vec2i*> (this); }
+ static Standard_Integer NbOfVec2i() { return 1; }
+
+};
+
// =======================================================================
// function : PushLightSourceState
// purpose : Pushes state of OCCT light sources to the program
// =======================================================================
void OpenGl_ShaderManager::PushLightSourceState (const Handle(OpenGl_ShaderProgram)& theProgram) const
{
- if (myLightSourceState.Index() == theProgram->ActiveState (OpenGl_LIGHT_SOURCES_STATE))
+ if (myLightSourceState.Index() == theProgram->ActiveState (OpenGl_LIGHT_SOURCES_STATE)
+ || !theProgram->IsValid())
{
return;
}
-
- theProgram->SetUniform (myContext, theProgram->GetStateLocation (
- OpenGl_OCC_LIGHT_SOURCE_COUNT), myLightSourceState.LightSources()->Size());
- OpenGl_ListOfLight::Iterator anIter (*myLightSourceState.LightSources());
- for (unsigned int anIndex = 0; anIter.More(); anIter.Next())
+ OpenGl_ShaderLightType* aLightTypeArray = new OpenGl_ShaderLightType[OpenGLMaxLights];
+ for (Standard_Integer aLightIt = 0; aLightIt < OpenGLMaxLights; ++aLightIt)
{
- if (anIndex >= OpenGLMaxLights)
- {
- break;
- }
-
- const OpenGl_Light& aLight = anIter.Value();
- if (aLight.type == TLightAmbient)
- {
- OpenGl_Vec3 anAmbient (aLight.col.rgb[0],
- aLight.col.rgb[1],
- aLight.col.rgb[2]);
-
- theProgram->SetUniform (myContext,
- theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_AMBIENT + anIndex), anAmbient);
-
- anIter.Next();
- if (!anIter.More())
- {
- theProgram->SetUniform (myContext,
- theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_TYPE + anIndex), int (aLight.type));
- break;
- }
- }
-
- OpenGl_Vec3 aDiffuse (aLight.col.rgb[0],
- aLight.col.rgb[1],
- aLight.col.rgb[2]);
-
- OpenGl_Vec3 aPosition (aLight.type == TLightDirectional ? -aLight.dir[0] : aLight.pos[0],
- aLight.type == TLightDirectional ? -aLight.dir[1] : aLight.pos[1],
- aLight.type == TLightDirectional ? -aLight.dir[2] : aLight.pos[2]);
-
- theProgram->SetUniform (myContext,
- theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_TYPE + anIndex), int (aLight.type));
-
- theProgram->SetUniform (myContext,
- theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_HEAD + anIndex), aLight.HeadLight);
-
- theProgram->SetUniform (myContext,
- theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_DIFFUSE + anIndex), aDiffuse);
+ aLightTypeArray[aLightIt].Type = -1;
+ }
+ const Standard_Integer aLightsDefNb = Min (myLightSourceState.LightSources()->Size(), OpenGLMaxLights);
+ if (aLightsDefNb < 1)
+ {
theProgram->SetUniform (myContext,
- theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_SPECULAR + anIndex), aDiffuse);
-
+ theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT),
+ 0);
theProgram->SetUniform (myContext,
- theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_POSITION + anIndex), aPosition);
-
+ theProgram->GetStateLocation (OpenGl_OCC_LIGHT_AMBIENT),
+ OpenGl_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
theProgram->SetUniform (myContext,
- theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_CONST_ATTENUATION + anIndex), aLight.atten[0]);
+ theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
+ OpenGLMaxLights * OpenGl_ShaderLightType::NbOfVec2i(),
+ aLightTypeArray[0].Packed());
+ theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index());
+ return;
+ }
- theProgram->SetUniform (myContext,
- theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_LINEAR_ATTENUATION + anIndex), aLight.atten[1]);
+ OpenGl_ShaderLightParameters* aLightParamsArray = new OpenGl_ShaderLightParameters[aLightsDefNb];
- if (aLight.type == TLightSpot)
+ OpenGl_Vec4 anAmbient (0.0f, 0.0f, 0.0f, 0.0f);
+ Standard_Integer aLightsNb = 0;
+ for (OpenGl_ListOfLight::Iterator anIter (*myLightSourceState.LightSources()); anIter.More(); anIter.Next())
+ {
+ const OpenGl_Light& aLight = anIter.Value();
+ if (aLight.Type == Visual3d_TOLS_AMBIENT)
{
- OpenGl_Vec3 aDirection (aLight.dir[0],
- aLight.dir[1],
- aLight.dir[2]);
-
- theProgram->SetUniform (myContext,
- theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_SPOT_CUTOFF + anIndex), aLight.angle);
+ anAmbient += aLight.Color;
+ continue;
+ }
+ else if (aLightsNb >= OpenGLMaxLights)
+ {
+ continue;
+ }
- theProgram->SetUniform (myContext,
- theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_SPOT_EXPONENT + anIndex), aLight.shine);
+ OpenGl_ShaderLightType& aLightType = aLightTypeArray[aLightsNb];
+ aLightType.Type = aLight.Type;
+ aLightType.IsHeadlight = aLight.IsHeadlight;
- theProgram->SetUniform (myContext,
- theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_SPOT_DIRECTION + anIndex), aDirection);
+ OpenGl_ShaderLightParameters& aLightParams = aLightParamsArray[aLightsNb];
+ aLightParams.Color = aLight.Color;
+ aLightParams.Position = aLight.Type == Visual3d_TOLS_DIRECTIONAL
+ ? -aLight.Direction
+ : aLight.Position;
+ if (aLight.Type == Visual3d_TOLS_SPOT)
+ {
+ aLightParams.Direction = aLight.Direction;
}
+ aLightParams.Parameters = aLight.Params;
+ ++aLightsNb;
+ }
- ++anIndex;
+ theProgram->SetUniform (myContext,
+ theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT),
+ aLightsNb);
+ theProgram->SetUniform (myContext,
+ theProgram->GetStateLocation (OpenGl_OCC_LIGHT_AMBIENT),
+ anAmbient);
+ theProgram->SetUniform (myContext,
+ theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
+ OpenGLMaxLights * OpenGl_ShaderLightType::NbOfVec2i(),
+ aLightTypeArray[0].Packed());
+ if (aLightsNb > 0)
+ {
+ theProgram->SetUniform (myContext,
+ theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_PARAMS),
+ aLightsNb * OpenGl_ShaderLightParameters::NbOfVec4(),
+ aLightParamsArray[0].Packed());
}
+ delete[] aLightParamsArray;
+ delete[] aLightTypeArray;
theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index());
}
return;
}
- Graphic3d_SetOfHClipPlane::Iterator anIter (myContext->Clipping().Planes());
- for (GLuint anIndex = 0; anIter.More(); anIter.Next())
+ theProgram->UpdateState (OpenGl_CLIP_PLANES_STATE, myClippingState.Index());
+ const GLint aLocEquations = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_EQUATIONS);
+ const GLint aLocSpaces = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_SPACES);
+ if (aLocEquations == OpenGl_ShaderProgram::INVALID_LOCATION
+ && aLocSpaces == OpenGl_ShaderProgram::INVALID_LOCATION)
+ {
+ return;
+ }
+
+ GLuint aPlanesNb = 0;
+ for (Graphic3d_SequenceOfHClipPlane::Iterator anIter (myContext->Clipping().Planes());
+ anIter.More(); anIter.Next())
{
const Handle(Graphic3d_ClipPlane)& aPlane = anIter.Value();
if (!myContext->Clipping().IsEnabled (aPlane))
continue;
}
- GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_0_EQUATION + anIndex);
- if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
+ ++aPlanesNb;
+ }
+ if (aPlanesNb < 1)
+ {
+ return;
+ }
+
+ OpenGl_Vec4* anEquations = new OpenGl_Vec4[aPlanesNb];
+ GLint* aSpaces = new GLint [aPlanesNb];
+ GLuint aPlaneId = 0;
+ for (Graphic3d_SequenceOfHClipPlane::Iterator anIter (myContext->Clipping().Planes());
+ anIter.More(); anIter.Next())
+ {
+ const Handle(Graphic3d_ClipPlane)& aPlane = anIter.Value();
+ if (!myContext->Clipping().IsEnabled (aPlane))
{
- const Graphic3d_ClipPlane::Equation& anEquation = aPlane->GetEquation();
- theProgram->SetUniform (myContext, aLocation, OpenGl_Vec4 ((float) anEquation.x(),
- (float) anEquation.y(),
- (float) anEquation.z(),
- (float) anEquation.w()));
+ continue;
}
- theProgram->SetUniform (myContext,
- theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_0_SPACE + anIndex),
- myContext->Clipping().GetEquationSpace (aPlane));
- ++anIndex;
+ const Graphic3d_ClipPlane::Equation& anEquation = aPlane->GetEquation();
+ anEquations[aPlaneId] = OpenGl_Vec4 ((float) anEquation.x(),
+ (float) anEquation.y(),
+ (float) anEquation.z(),
+ (float) anEquation.w());
+ aSpaces[aPlaneId] = myContext->Clipping().GetEquationSpace (aPlane);
+ ++aPlaneId;
}
+ theProgram->SetUniform (myContext, aLocEquations, aPlanesNb, anEquations[0].GetData());
+ theProgram->SetUniform (myContext, aLocSpaces, aPlanesNb, aSpaces);
- theProgram->UpdateState (OpenGl_CLIP_PLANES_STATE, myClippingState.Index());
+ delete[] anEquations;
+ delete[] aSpaces;
}
// =======================================================================
theProgram->SetUniform (theCtx,
theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE),
theAspect->DoTextureMap());
-
theProgram->SetUniform (theCtx,
theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER),
0 /* GL_TEXTURE0 */);
-
theProgram->SetUniform (theCtx,
theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE),
theAspect->DistinguishingMode());
- for (int anIndex = 0; anIndex < 2; ++anIndex)
+ OpenGl_Material aParams;
+ for (Standard_Integer anIndex = 0; anIndex < 2; ++anIndex)
{
- const OPENGL_SURF_PROP& aProperties = (anIndex == 0) ? theAspect->IntFront() : theAspect->IntBack();
- GLint aLocation = theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_AMBIENT + anIndex);
- if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
- {
- OpenGl_Vec4 anAmbient (aProperties.ambcol.rgb[0] * aProperties.amb,
- aProperties.ambcol.rgb[1] * aProperties.amb,
- aProperties.ambcol.rgb[2] * aProperties.amb,
- aProperties.ambcol.rgb[3] * aProperties.amb);
- theProgram->SetUniform (theCtx, aLocation, anAmbient);
- }
-
- aLocation = theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_DIFFUSE + anIndex);
- if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
+ const GLint aLoc = theProgram->GetStateLocation (anIndex == 0
+ ? OpenGl_OCCT_FRONT_MATERIAL
+ : OpenGl_OCCT_BACK_MATERIAL);
+ if (aLoc == OpenGl_ShaderProgram::INVALID_LOCATION)
{
- OpenGl_Vec4 aDiffuse (aProperties.difcol.rgb[0] * aProperties.diff,
- aProperties.difcol.rgb[1] * aProperties.diff,
- aProperties.difcol.rgb[2] * aProperties.diff,
- aProperties.difcol.rgb[3] * aProperties.diff);
- theProgram->SetUniform (theCtx, aLocation, aDiffuse);
- }
-
- aLocation = theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_SPECULAR + anIndex);
- if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
- {
- OpenGl_Vec4 aSpecular (aProperties.speccol.rgb[0] * aProperties.spec,
- aProperties.speccol.rgb[1] * aProperties.spec,
- aProperties.speccol.rgb[2] * aProperties.spec,
- aProperties.speccol.rgb[3] * aProperties.spec);
- theProgram->SetUniform (theCtx, aLocation, aSpecular);
- }
-
- aLocation = theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_EMISSION + anIndex);
- if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
- {
- OpenGl_Vec4 anEmission (aProperties.emscol.rgb[0] * aProperties.emsv,
- aProperties.emscol.rgb[1] * aProperties.emsv,
- aProperties.emscol.rgb[2] * aProperties.emsv,
- aProperties.emscol.rgb[3] * aProperties.emsv);
- theProgram->SetUniform (theCtx, aLocation, anEmission);
+ continue;
}
-
- theProgram->SetUniform (theCtx,
- theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_SHININESS + anIndex),
- aProperties.shine);
- theProgram->SetUniform (theCtx,
- theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_TRANSPARENCY + anIndex),
- aProperties.trans);
+ aParams.Init (anIndex == 0 ? theAspect->IntFront() : theAspect->IntBack());
+ theProgram->SetUniform (theCtx, aLoc, OpenGl_Material::NbOfVec4(),
+ aParams.Packed());
}
}
theAspect->Color().rgb[1],
theAspect->Color().rgb[2],
theAspect->Color().rgb[3]);
- theProgram->SetUniform (theCtx,
- theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_AMBIENT),
- THE_COLOR_BLACK_VEC4);
- theProgram->SetUniform (theCtx,
- theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_DIFFUSE),
- aDiffuse);
- theProgram->SetUniform (theCtx,
- theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_SPECULAR),
- THE_COLOR_BLACK_VEC4);
- theProgram->SetUniform (theCtx,
- theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_EMISSION),
- THE_COLOR_BLACK_VEC4);
- theProgram->SetUniform (theCtx,
- theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_TRANSPARENCY),
- 0.0f);
+ OpenGl_Vec4 aParams[5];
+ aParams[0] = THE_COLOR_BLACK_VEC4;
+ aParams[1] = THE_COLOR_BLACK_VEC4;
+ aParams[2] = aDiffuse;
+ aParams[3] = THE_COLOR_BLACK_VEC4;
+ aParams[4].x() = 0.0f; // shininess
+ aParams[4].y() = 0.0f; // transparency
+ theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL),
+ 5, aParams);
}
// =======================================================================
theAspect->SubtitleColor().rgb[3]);
}
- theProgram->SetUniform (theCtx,
- theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_AMBIENT),
- THE_COLOR_BLACK_VEC4);
- theProgram->SetUniform (theCtx,
- theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_DIFFUSE),
- aDiffuse);
- theProgram->SetUniform (theCtx,
- theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_SPECULAR),
- THE_COLOR_BLACK_VEC4);
- theProgram->SetUniform (theCtx,
- theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_EMISSION),
- THE_COLOR_BLACK_VEC4);
- theProgram->SetUniform (theCtx,
- theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_TRANSPARENCY),
- 0.0f);
+ OpenGl_Vec4 aParams[5];
+ aParams[0] = THE_COLOR_BLACK_VEC4;
+ aParams[1] = THE_COLOR_BLACK_VEC4;
+ aParams[2] = aDiffuse;
+ aParams[3] = THE_COLOR_BLACK_VEC4;
+ aParams[4].x() = 0.0f; // shininess
+ aParams[4].y() = 0.0f; // transparency
+ theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL),
+ 5, aParams);
}
// =======================================================================
theAspect->Color().rgb[1],
theAspect->Color().rgb[2],
theAspect->Color().rgb[3]);
-
- theProgram->SetUniform (theCtx,
- theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_AMBIENT),
- THE_COLOR_BLACK_VEC4);
- theProgram->SetUniform (theCtx,
- theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_DIFFUSE),
- aDiffuse);
- theProgram->SetUniform (theCtx,
- theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_SPECULAR),
- THE_COLOR_BLACK_VEC4);
- theProgram->SetUniform (theCtx,
- theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_EMISSION),
- THE_COLOR_BLACK_VEC4);
- theProgram->SetUniform (theCtx,
- theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_TRANSPARENCY),
- 0.0f);
+ OpenGl_Vec4 aParams[5];
+ aParams[0] = THE_COLOR_BLACK_VEC4;
+ aParams[1] = THE_COLOR_BLACK_VEC4;
+ aParams[2] = aDiffuse;
+ aParams[3] = THE_COLOR_BLACK_VEC4;
+ aParams[4].x() = 0.0f; // shininess
+ aParams[4].y() = 0.0f; // transparency
+ theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL),
+ 5, aParams);
}
}; // nameless namespace
PushModelWorldState (theProgram);
PushProjectionState (theProgram);
PushLightSourceState (theProgram);
-}
\ No newline at end of file
+}