1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-21 10:13:43 +03:00

0032039: Visualization, TKOpenGl - implement simple shadow mapping for a direct light source

Graphic3d_CLight::ToCastShadows() - added new property defining if light should cast shadows (ignored by Ray-Tracing).

OpenGl_ShaderManager::stdComputeLighting() now implements shadow mapping for directional lights.
OpenGl_ShaderManager::prepareGeomMainSrc() now handles copying of arrays.
OpenGl_Context::ShadowMapTexUnit() - added property defining an offset for shadow map texture units.
OpenGl_ShadowMap - added new class storing shadow map FBO with parameters.
OpenGl_View::prepareFrameBuffers() - added resizing of shadow map FBOs.
OpenGl_View::Redraw() - added section redrawing scene into shadow map FBOs via OpenGl_View::renderShadowMap() method.

vrenderparams - added new parameters -shadowMapResolution and -shadowMapBias.
This commit is contained in:
kgv 2021-01-04 12:17:44 +03:00 committed by bugmaster
parent 37f80e163c
commit d84e866973
33 changed files with 1025 additions and 47 deletions

View File

@ -14,6 +14,7 @@
#include <Graphic3d_CLight.hxx> #include <Graphic3d_CLight.hxx>
#include <Standard_Atomic.hxx> #include <Standard_Atomic.hxx>
#include <Standard_NotImplemented.hxx>
#include <Standard_OutOfRange.hxx> #include <Standard_OutOfRange.hxx>
IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_CLight, Standard_Transient) IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_CLight, Standard_Transient)
@ -56,7 +57,8 @@ Graphic3d_CLight::Graphic3d_CLight (Graphic3d_TypeOfLightSource theType)
myType (theType), myType (theType),
myRevision (0), myRevision (0),
myIsHeadlight(false), myIsHeadlight(false),
myIsEnabled (true) myIsEnabled (true),
myToCastShadows (false)
{ {
switch (theType) switch (theType)
{ {
@ -108,6 +110,20 @@ void Graphic3d_CLight::SetEnabled (Standard_Boolean theIsOn)
myIsEnabled = theIsOn; myIsEnabled = theIsOn;
} }
// =======================================================================
// function : SetCastShadows
// purpose :
// =======================================================================
void Graphic3d_CLight::SetCastShadows (Standard_Boolean theToCast)
{
if (myType != Graphic3d_TOLS_DIRECTIONAL)
{
throw Standard_NotImplemented ("Graphic3d_CLight::SetCastShadows() is not implemented for this light type");
}
updateRevisionIf (myToCastShadows != theToCast);
myToCastShadows = theToCast;
}
// ======================================================================= // =======================================================================
// function : SetHeadlight // function : SetHeadlight
// purpose : // purpose :

View File

@ -58,6 +58,13 @@ public:
//! instead it turns it OFF so that it just have no effect. //! instead it turns it OFF so that it just have no effect.
Standard_EXPORT void SetEnabled (Standard_Boolean theIsOn); Standard_EXPORT void SetEnabled (Standard_Boolean theIsOn);
//! Return TRUE if shadow casting is enabled; FALSE by default.
//! Has no effect in Ray-Tracing rendering mode.
Standard_Boolean ToCastShadows() const { return myToCastShadows; }
//! Enable/disable shadow casting.
Standard_EXPORT void SetCastShadows (Standard_Boolean theToCast);
//! Returns true if the light is a headlight; FALSE by default. //! Returns true if the light is a headlight; FALSE by default.
//! Headlight flag means that light position/direction are defined not in a World coordinate system, but relative to the camera orientation. //! Headlight flag means that light position/direction are defined not in a World coordinate system, but relative to the camera orientation.
Standard_Boolean IsHeadlight() const { return myIsHeadlight; } Standard_Boolean IsHeadlight() const { return myIsHeadlight; }
@ -258,6 +265,7 @@ protected:
Standard_Size myRevision; //!< modification counter Standard_Size myRevision; //!< modification counter
Standard_Boolean myIsHeadlight; //!< flag to mark head light Standard_Boolean myIsHeadlight; //!< flag to mark head light
Standard_Boolean myIsEnabled; //!< enabled state Standard_Boolean myIsEnabled; //!< enabled state
Standard_Boolean myToCastShadows;//!< casting shadows is requested
}; };

View File

@ -36,6 +36,7 @@ namespace
Graphic3d_LightSet::Graphic3d_LightSet() Graphic3d_LightSet::Graphic3d_LightSet()
: myAmbient (0.0f, 0.0f, 0.0f, 0.0f), : myAmbient (0.0f, 0.0f, 0.0f, 0.0f),
myNbEnabled (0), myNbEnabled (0),
myNbCastShadows (0),
myRevision (1), myRevision (1),
myCacheRevision (0) myCacheRevision (0)
{ {
@ -110,6 +111,7 @@ Standard_Size Graphic3d_LightSet::UpdateRevision()
} }
myCacheRevision = myRevision; myCacheRevision = myRevision;
myNbCastShadows = 0;
myAmbient.SetValues (0.0f, 0.0f, 0.0f, 0.0f); myAmbient.SetValues (0.0f, 0.0f, 0.0f, 0.0f);
memset (myLightTypesEnabled, 0, sizeof(myLightTypesEnabled)); memset (myLightTypesEnabled, 0, sizeof(myLightTypesEnabled));
NCollection_LocalArray<char, 32> aKeyLong (myLights.Extent() + 1); NCollection_LocalArray<char, 32> aKeyLong (myLights.Extent() + 1);
@ -130,7 +132,15 @@ Standard_Size Graphic3d_LightSet::UpdateRevision()
} }
else else
{ {
aKeyLong[aLightLast++] = THE_LIGHT_KEY_LETTERS[aLight->Type()]; if (aLight->ToCastShadows())
{
++myNbCastShadows;
aKeyLong[aLightLast++] = UpperCase (THE_LIGHT_KEY_LETTERS[aLight->Type()]);
}
else
{
aKeyLong[aLightLast++] = THE_LIGHT_KEY_LETTERS[aLight->Type()];
}
} }
} }
aKeyLong[aLightLast] = '\0'; aKeyLong[aLightLast] = '\0';

View File

@ -29,7 +29,9 @@ public:
IterationFilter_None = 0x0000, //!< no filter IterationFilter_None = 0x0000, //!< no filter
IterationFilter_ExcludeAmbient = 0x0002, //!< exclude ambient light sources IterationFilter_ExcludeAmbient = 0x0002, //!< exclude ambient light sources
IterationFilter_ExcludeDisabled = 0x0004, //!< exclude disabled light sources IterationFilter_ExcludeDisabled = 0x0004, //!< exclude disabled light sources
IterationFilter_ExcludeNoShadow = 0x0008, //!< exclude light sources not casting shadow
IterationFilter_ExcludeDisabledAndAmbient = IterationFilter_ExcludeAmbient | IterationFilter_ExcludeDisabled, IterationFilter_ExcludeDisabledAndAmbient = IterationFilter_ExcludeAmbient | IterationFilter_ExcludeDisabled,
IterationFilter_ActiveShadowCasters = IterationFilter_ExcludeDisabledAndAmbient | IterationFilter_ExcludeNoShadow,
}; };
//! Iterator through light sources. //! Iterator through light sources.
@ -95,6 +97,11 @@ public:
{ {
continue; continue;
} }
else if ((myFilter & IterationFilter_ExcludeNoShadow) != 0
&& !myIter.Key()->ToCastShadows())
{
continue;
}
break; break;
} }
@ -155,6 +162,10 @@ public:
//! @sa UpdateRevision() //! @sa UpdateRevision()
Standard_Integer NbEnabledLightsOfType (Graphic3d_TypeOfLightSource theType) const { return myLightTypesEnabled[theType]; } Standard_Integer NbEnabledLightsOfType (Graphic3d_TypeOfLightSource theType) const { return myLightTypesEnabled[theType]; }
//! Returns total amount of enabled lights castings shadows.
//! @sa UpdateRevision()
Standard_Integer NbCastShadows() const { return myNbCastShadows; }
//! Returns cumulative ambient color, which is computed as sum of all enabled ambient light sources. //! Returns cumulative ambient color, which is computed as sum of all enabled ambient light sources.
//! Values are NOT clamped (can be greater than 1.0f) and alpha component is fixed to 1.0f. //! Values are NOT clamped (can be greater than 1.0f) and alpha component is fixed to 1.0f.
//! @sa UpdateRevision() //! @sa UpdateRevision()
@ -181,6 +192,7 @@ protected:
Standard_Integer myLightTypes [Graphic3d_TypeOfLightSource_NB]; //!< counters per each light source type defined in the list Standard_Integer myLightTypes [Graphic3d_TypeOfLightSource_NB]; //!< counters per each light source type defined in the list
Standard_Integer myLightTypesEnabled[Graphic3d_TypeOfLightSource_NB]; //!< counters per each light source type enabled in the list Standard_Integer myLightTypesEnabled[Graphic3d_TypeOfLightSource_NB]; //!< counters per each light source type enabled in the list
Standard_Integer myNbEnabled; //!< number of enabled light sources, excluding ambient Standard_Integer myNbEnabled; //!< number of enabled light sources, excluding ambient
Standard_Integer myNbCastShadows; //!< number of enabled light sources casting shadows
Standard_Size myRevision; //!< current revision of light source set Standard_Size myRevision; //!< current revision of light source set
Standard_Size myCacheRevision; //!< revision of cached state Standard_Size myCacheRevision; //!< revision of cached state
}; };

View File

@ -106,6 +106,8 @@ public:
OitDepthFactor (0.0f), OitDepthFactor (0.0f),
NbMsaaSamples (0), NbMsaaSamples (0),
RenderResolutionScale (1.0f), RenderResolutionScale (1.0f),
ShadowMapResolution (1024),
ShadowMapBias (0.005f),
ToEnableDepthPrepass (Standard_False), ToEnableDepthPrepass (Standard_False),
ToEnableAlphaToCoverage (Standard_True), ToEnableAlphaToCoverage (Standard_True),
// ray tracing parameters // ray tracing parameters
@ -199,6 +201,8 @@ public:
Standard_Integer NbMsaaSamples; //!< number of MSAA samples (should be within 0..GL_MAX_SAMPLES, power-of-two number), 0 by default Standard_Integer NbMsaaSamples; //!< number of MSAA samples (should be within 0..GL_MAX_SAMPLES, power-of-two number), 0 by default
Standard_ShortReal RenderResolutionScale; //!< rendering resolution scale factor, 1 by default; Standard_ShortReal RenderResolutionScale; //!< rendering resolution scale factor, 1 by default;
//! incompatible with MSAA (e.g. NbMsaaSamples should be set to 0) //! incompatible with MSAA (e.g. NbMsaaSamples should be set to 0)
Standard_Integer ShadowMapResolution; //!< shadow texture map resolution, 1024 by default
Standard_ShortReal ShadowMapBias; //!< shadowmap bias, 0.005 by default;
Standard_Boolean ToEnableDepthPrepass; //!< enables/disables depth pre-pass, False by default Standard_Boolean ToEnableDepthPrepass; //!< enables/disables depth pre-pass, False by default
Standard_Boolean ToEnableAlphaToCoverage; //!< enables/disables alpha to coverage, True by default Standard_Boolean ToEnableAlphaToCoverage; //!< enables/disables alpha to coverage, True by default

View File

@ -78,6 +78,7 @@ const TCollection_AsciiString& Graphic3d_ShaderProgram::ShadersFolder()
// ======================================================================= // =======================================================================
Graphic3d_ShaderProgram::Graphic3d_ShaderProgram() Graphic3d_ShaderProgram::Graphic3d_ShaderProgram()
: myNbLightsMax (THE_MAX_LIGHTS_DEFAULT), : myNbLightsMax (THE_MAX_LIGHTS_DEFAULT),
myNbShadowMaps (0),
myNbClipPlanesMax (THE_MAX_CLIP_PLANES_DEFAULT), myNbClipPlanesMax (THE_MAX_CLIP_PLANES_DEFAULT),
myNbFragOutputs (THE_NB_FRAG_OUTPUTS), myNbFragOutputs (THE_NB_FRAG_OUTPUTS),
myTextureSetBits (Graphic3d_TextureSetBits_NONE), myTextureSetBits (Graphic3d_TextureSetBits_NONE),

View File

@ -96,6 +96,12 @@ public:
//! Specify the length of array of light sources (THE_MAX_LIGHTS). //! Specify the length of array of light sources (THE_MAX_LIGHTS).
void SetNbLightsMax (Standard_Integer theNbLights) { myNbLightsMax = theNbLights; } void SetNbLightsMax (Standard_Integer theNbLights) { myNbLightsMax = theNbLights; }
//! Return the length of array of shadow maps (THE_NB_SHADOWMAPS); 0 by default.
Standard_Integer NbShadowMaps() const { return myNbShadowMaps; }
//! Specify the length of array of shadow maps (THE_NB_SHADOWMAPS).
void SetNbShadowMaps (Standard_Integer theNbMaps) { myNbShadowMaps = theNbMaps; }
//! Return the length of array of clipping planes (THE_MAX_CLIP_PLANES), //! Return the length of array of clipping planes (THE_MAX_CLIP_PLANES),
//! to be used for initialization occClipPlaneEquations. //! to be used for initialization occClipPlaneEquations.
//! Default value is THE_MAX_CLIP_PLANES_DEFAULT. //! Default value is THE_MAX_CLIP_PLANES_DEFAULT.
@ -213,6 +219,7 @@ private:
Graphic3d_ShaderAttributeList myAttributes; //!< the list of custom vertex attributes Graphic3d_ShaderAttributeList myAttributes; //!< the list of custom vertex attributes
TCollection_AsciiString myHeader; //!< GLSL header with version code and used extensions TCollection_AsciiString myHeader; //!< GLSL header with version code and used extensions
Standard_Integer myNbLightsMax; //!< length of array of light sources (THE_MAX_LIGHTS) Standard_Integer myNbLightsMax; //!< length of array of light sources (THE_MAX_LIGHTS)
Standard_Integer myNbShadowMaps; //!< length of array of shadow maps (THE_NB_SHADOWMAPS)
Standard_Integer myNbClipPlanesMax; //!< length of array of clipping planes (THE_MAX_CLIP_PLANES) Standard_Integer myNbClipPlanesMax; //!< length of array of clipping planes (THE_MAX_CLIP_PLANES)
Standard_Integer myNbFragOutputs; //!< length of array of Fragment Shader outputs (THE_NB_FRAG_OUTPUTS) Standard_Integer myNbFragOutputs; //!< length of array of Fragment Shader outputs (THE_NB_FRAG_OUTPUTS)
Standard_Integer myTextureSetBits;//!< texture units declared within the program, @sa Graphic3d_TextureSetBits Standard_Integer myTextureSetBits;//!< texture units declared within the program, @sa Graphic3d_TextureSetBits

View File

@ -67,6 +67,10 @@ enum Graphic3d_TextureUnit
//! Note that it can be overridden to Graphic3d_TextureUnit_0 for FFP fallback on hardware without multi-texturing. //! Note that it can be overridden to Graphic3d_TextureUnit_0 for FFP fallback on hardware without multi-texturing.
Graphic3d_TextureUnit_PointSprite = Graphic3d_TextureUnit_1, Graphic3d_TextureUnit_PointSprite = Graphic3d_TextureUnit_1,
//! sampler2D occShadowMapSampler.
//! Directional light source shadowmap texture.
Graphic3d_TextureUnit_ShadowMap = -4,
//! sampler2D occEnvLUT. //! sampler2D occEnvLUT.
//! Lookup table for approximated PBR environment lighting. //! Lookup table for approximated PBR environment lighting.
//! Configured as index at the end of available texture units - 3. //! Configured as index at the end of available texture units - 3.

View File

@ -122,6 +122,8 @@ OpenGl_ShaderProgram.cxx
OpenGl_ShaderProgram.hxx OpenGl_ShaderProgram.hxx
OpenGl_ShaderStates.cxx OpenGl_ShaderStates.cxx
OpenGl_ShaderStates.hxx OpenGl_ShaderStates.hxx
OpenGl_ShadowMap.cxx
OpenGl_ShadowMap.hxx
OpenGl_StencilTest.cxx OpenGl_StencilTest.cxx
OpenGl_StencilTest.hxx OpenGl_StencilTest.hxx
OpenGl_TileSampler.hxx OpenGl_TileSampler.hxx

View File

@ -220,6 +220,7 @@ OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps)
myPBREnvLUTTexUnit (Graphic3d_TextureUnit_PbrEnvironmentLUT), myPBREnvLUTTexUnit (Graphic3d_TextureUnit_PbrEnvironmentLUT),
myPBRDiffIBLMapSHTexUnit (Graphic3d_TextureUnit_PbrIblDiffuseSH), myPBRDiffIBLMapSHTexUnit (Graphic3d_TextureUnit_PbrIblDiffuseSH),
myPBRSpecIBLMapTexUnit (Graphic3d_TextureUnit_PbrIblSpecular), myPBRSpecIBLMapTexUnit (Graphic3d_TextureUnit_PbrIblSpecular),
myShadowMapTexUnit (Graphic3d_TextureUnit_ShadowMap),
myFrameStats (new OpenGl_FrameStats()), myFrameStats (new OpenGl_FrameStats()),
myActiveMockTextures (0), myActiveMockTextures (0),
myActiveHatchType (Aspect_HS_SOLID), myActiveHatchType (Aspect_HS_SOLID),
@ -3353,6 +3354,7 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile)
myPBRDiffIBLMapSHTexUnit = static_cast<Graphic3d_TextureUnit>(myMaxTexCombined + Graphic3d_TextureUnit_PbrIblDiffuseSH); myPBRDiffIBLMapSHTexUnit = static_cast<Graphic3d_TextureUnit>(myMaxTexCombined + Graphic3d_TextureUnit_PbrIblDiffuseSH);
myPBRSpecIBLMapTexUnit = static_cast<Graphic3d_TextureUnit>(myMaxTexCombined + Graphic3d_TextureUnit_PbrIblSpecular); myPBRSpecIBLMapTexUnit = static_cast<Graphic3d_TextureUnit>(myMaxTexCombined + Graphic3d_TextureUnit_PbrIblSpecular);
} }
myShadowMapTexUnit = static_cast<Graphic3d_TextureUnit>(myMaxTexCombined + Graphic3d_TextureUnit_ShadowMap);
} }
// ======================================================================= // =======================================================================

View File

@ -630,6 +630,9 @@ public:
//! Returns texture unit where Specular IBL map is expected to be bound, or 0 if PBR is unavailable. //! Returns texture unit where Specular IBL map is expected to be bound, or 0 if PBR is unavailable.
Graphic3d_TextureUnit PBRSpecIBLMapTexUnit() const { return myPBRSpecIBLMapTexUnit; } Graphic3d_TextureUnit PBRSpecIBLMapTexUnit() const { return myPBRSpecIBLMapTexUnit; }
//! Returns texture unit where shadow map is expected to be bound, or 0 if unavailable.
Graphic3d_TextureUnit ShadowMapTexUnit() const { return myShadowMapTexUnit; }
//! Returns true if VBO is supported and permitted. //! Returns true if VBO is supported and permitted.
inline bool ToUseVbo() const inline bool ToUseVbo() const
{ {
@ -1169,6 +1172,7 @@ private: // context info
Graphic3d_TextureUnit myPBRDiffIBLMapSHTexUnit; //!< sampler2D occDiffIBLMapSHCoeffs, texture unit where diffuse (irradiance) IBL map's spherical harmonics coefficients is expected to be binded Graphic3d_TextureUnit myPBRDiffIBLMapSHTexUnit; //!< sampler2D occDiffIBLMapSHCoeffs, texture unit where diffuse (irradiance) IBL map's spherical harmonics coefficients is expected to be binded
//! (0 if PBR is not supported) //! (0 if PBR is not supported)
Graphic3d_TextureUnit myPBRSpecIBLMapTexUnit; //!< samplerCube occSpecIBLMap, texture unit where specular IBL map is expected to be binded (0 if PBR is not supported) Graphic3d_TextureUnit myPBRSpecIBLMapTexUnit; //!< samplerCube occSpecIBLMap, texture unit where specular IBL map is expected to be binded (0 if PBR is not supported)
Graphic3d_TextureUnit myShadowMapTexUnit; //!< sampler2D occShadowMapSampler
Handle(OpenGl_ShaderManager) myShaderManager; //! support object for managing shader programs Handle(OpenGl_ShaderManager) myShaderManager; //! support object for managing shader programs

View File

@ -236,13 +236,13 @@ public:
Standard_EXPORT virtual void UnbindBuffer (const Handle(OpenGl_Context)& theGlCtx); Standard_EXPORT virtual void UnbindBuffer (const Handle(OpenGl_Context)& theGlCtx);
//! Returns the color texture for the given color buffer index. //! Returns the color texture for the given color buffer index.
inline const Handle(OpenGl_Texture)& ColorTexture (const GLint theColorBufferIndex = 0) const const Handle(OpenGl_Texture)& ColorTexture (const GLint theColorBufferIndex = 0) const
{ {
return myColorTextures (theColorBufferIndex); return myColorTextures (theColorBufferIndex);
} }
//! Returns the depth-stencil texture. //! Returns the depth-stencil texture.
inline const Handle(OpenGl_Texture)& DepthStencilTexture() const const Handle(OpenGl_Texture)& DepthStencilTexture() const
{ {
return myDepthStencilTexture; return myDepthStencilTexture;
} }

View File

@ -15,6 +15,7 @@
#include <OpenGl_GlCore20.hxx> #include <OpenGl_GlCore20.hxx>
#include <OpenGl_View.hxx> #include <OpenGl_View.hxx>
#include <OpenGl_ShadowMap.hxx>
#include <OpenGl_Workspace.hxx> #include <OpenGl_Workspace.hxx>
IMPLEMENT_STANDARD_RTTIEXT(OpenGl_FrameStats, Graphic3d_FrameStats) IMPLEMENT_STANDARD_RTTIEXT(OpenGl_FrameStats, Graphic3d_FrameStats)
@ -148,6 +149,8 @@ void OpenGl_FrameStats::updateStatistics (const Handle(Graphic3d_CView)& theView
aMemFbos += estimatedDataSize (aView->myMainSceneFbosOit[1]); aMemFbos += estimatedDataSize (aView->myMainSceneFbosOit[1]);
aMemFbos += estimatedDataSize (aView->myImmediateSceneFbosOit[0]); aMemFbos += estimatedDataSize (aView->myImmediateSceneFbosOit[0]);
aMemFbos += estimatedDataSize (aView->myImmediateSceneFbosOit[1]); aMemFbos += estimatedDataSize (aView->myImmediateSceneFbosOit[1]);
// shadowmap FBOs
aMemFbos += aView->myShadowMaps->EstimatedDataSize();
// dump FBO // dump FBO
aMemFbos += estimatedDataSize (aView->myFBO); aMemFbos += estimatedDataSize (aView->myFBO);
// RayTracing FBO // RayTracing FBO

View File

@ -589,12 +589,13 @@ void OpenGl_LayerList::renderLayer (const Handle(OpenGl_Workspace)& theWorkspace
const Standard_Boolean hasLocalCS = !aLayerSettings.OriginTransformation().IsNull(); const Standard_Boolean hasLocalCS = !aLayerSettings.OriginTransformation().IsNull();
const Handle(OpenGl_ShaderManager)& aManager = aCtx->ShaderManager(); const Handle(OpenGl_ShaderManager)& aManager = aCtx->ShaderManager();
Handle(Graphic3d_LightSet) aLightsBack = aManager->LightSourceState().LightSources(); Handle(Graphic3d_LightSet) aLightsBack = aManager->LightSourceState().LightSources();
Handle(OpenGl_ShadowMapArray) aShadowMaps = aManager->LightSourceState().ShadowMaps();
const bool hasOwnLights = aCtx->ColorMask() && !aLayerSettings.Lights().IsNull() && aLayerSettings.Lights() != aLightsBack; const bool hasOwnLights = aCtx->ColorMask() && !aLayerSettings.Lights().IsNull() && aLayerSettings.Lights() != aLightsBack;
if (hasOwnLights) if (hasOwnLights)
{ {
aLayerSettings.Lights()->UpdateRevision(); aLayerSettings.Lights()->UpdateRevision();
aManager->UpdateLightSourceStateTo (aLayerSettings.Lights(), theWorkspace->View()->SpecIBLMapLevels()); aManager->UpdateLightSourceStateTo (aLayerSettings.Lights(), theWorkspace->View()->SpecIBLMapLevels(), Handle(OpenGl_ShadowMapArray)());
} }
const Handle(Graphic3d_Camera)& aWorldCamera = theWorkspace->View()->Camera(); const Handle(Graphic3d_Camera)& aWorldCamera = theWorkspace->View()->Camera();
@ -665,7 +666,7 @@ void OpenGl_LayerList::renderLayer (const Handle(OpenGl_Workspace)& theWorkspace
if (hasOwnLights) if (hasOwnLights)
{ {
aManager->UpdateLightSourceStateTo (aLightsBack, theWorkspace->View()->SpecIBLMapLevels()); aManager->UpdateLightSourceStateTo (aLightsBack, theWorkspace->View()->SpecIBLMapLevels(), aShadowMaps);
} }
if (hasLocalCS) if (hasLocalCS)
{ {
@ -703,6 +704,8 @@ void OpenGl_LayerList::Render (const Handle(OpenGl_Workspace)& theWorkspace,
aCtx->core11fwd->glGetIntegerv (GL_DEPTH_FUNC, &aPrevSettings.DepthFunc); aCtx->core11fwd->glGetIntegerv (GL_DEPTH_FUNC, &aPrevSettings.DepthFunc);
aCtx->core11fwd->glGetBooleanv (GL_DEPTH_WRITEMASK, &aPrevSettings.DepthMask); aCtx->core11fwd->glGetBooleanv (GL_DEPTH_WRITEMASK, &aPrevSettings.DepthMask);
OpenGl_GlobalLayerSettings aDefaultSettings = aPrevSettings; OpenGl_GlobalLayerSettings aDefaultSettings = aPrevSettings;
const bool isShadowMapPass = theReadDrawFbo != NULL
&& !theReadDrawFbo->HasColor();
// Two render filters are used to support transparency draw. Opaque filter accepts // Two render filters are used to support transparency draw. Opaque filter accepts
// only non-transparent OpenGl elements of a layer and counts number of skipped // only non-transparent OpenGl elements of a layer and counts number of skipped
@ -722,8 +725,10 @@ void OpenGl_LayerList::Render (const Handle(OpenGl_Workspace)& theWorkspace,
OpenGl_LayerStack::iterator aStackIter (myTransparentToProcess.Origin()); OpenGl_LayerStack::iterator aStackIter (myTransparentToProcess.Origin());
Standard_Integer aClearDepthLayerPrev = -1, aClearDepthLayer = -1; Standard_Integer aClearDepthLayerPrev = -1, aClearDepthLayer = -1;
const bool toPerformDepthPrepass = theWorkspace->View()->RenderingParams().ToEnableDepthPrepass const bool toPerformDepthPrepass = theWorkspace->View()->RenderingParams().ToEnableDepthPrepass
&& aPrevSettings.DepthMask == GL_TRUE; && aPrevSettings.DepthMask == GL_TRUE
const Handle(Graphic3d_LightSet) aLightsBack = aCtx->ShaderManager()->LightSourceState().LightSources(); && !isShadowMapPass;
const Handle(Graphic3d_LightSet) aLightsBack = aCtx->ShaderManager()->LightSourceState().LightSources();
const Handle(OpenGl_ShadowMapArray) aShadowMaps = aCtx->ShaderManager()->LightSourceState().ShadowMaps();
for (OpenGl_FilteredIndexedLayerIterator aLayerIterStart (myLayers, theToDrawImmediate, theLayersToProcess); aLayerIterStart.More();) for (OpenGl_FilteredIndexedLayerIterator aLayerIterStart (myLayers, theToDrawImmediate, theLayersToProcess); aLayerIterStart.More();)
{ {
bool hasSkippedDepthLayers = false; bool hasSkippedDepthLayers = false;
@ -732,7 +737,7 @@ void OpenGl_LayerList::Render (const Handle(OpenGl_Workspace)& theWorkspace,
if (aPassIter == 0) if (aPassIter == 0)
{ {
aCtx->SetColorMask (false); aCtx->SetColorMask (false);
aCtx->ShaderManager()->UpdateLightSourceStateTo (Handle(Graphic3d_LightSet)(), theWorkspace->View()->SpecIBLMapLevels()); aCtx->ShaderManager()->UpdateLightSourceStateTo (Handle(Graphic3d_LightSet)(), theWorkspace->View()->SpecIBLMapLevels(), Handle(OpenGl_ShadowMapArray)());
aDefaultSettings.DepthFunc = aPrevSettings.DepthFunc; aDefaultSettings.DepthFunc = aPrevSettings.DepthFunc;
aDefaultSettings.DepthMask = GL_TRUE; aDefaultSettings.DepthMask = GL_TRUE;
} }
@ -743,13 +748,21 @@ void OpenGl_LayerList::Render (const Handle(OpenGl_Workspace)& theWorkspace,
continue; continue;
} }
aCtx->SetColorMask (true); aCtx->SetColorMask (true);
aCtx->ShaderManager()->UpdateLightSourceStateTo (aLightsBack, theWorkspace->View()->SpecIBLMapLevels()); aCtx->ShaderManager()->UpdateLightSourceStateTo (aLightsBack, theWorkspace->View()->SpecIBLMapLevels(), aShadowMaps);
aDefaultSettings = aPrevSettings; aDefaultSettings = aPrevSettings;
} }
else if (aPassIter == 2) else if (aPassIter == 2)
{ {
aCtx->SetColorMask (true); if (isShadowMapPass)
aCtx->ShaderManager()->UpdateLightSourceStateTo (aLightsBack, theWorkspace->View()->SpecIBLMapLevels()); {
aCtx->SetColorMask (false);
aCtx->ShaderManager()->UpdateLightSourceStateTo (Handle(Graphic3d_LightSet)(), theWorkspace->View()->SpecIBLMapLevels(), Handle(OpenGl_ShadowMapArray)());
}
else
{
aCtx->SetColorMask (true);
aCtx->ShaderManager()->UpdateLightSourceStateTo (aLightsBack, theWorkspace->View()->SpecIBLMapLevels(), aShadowMaps);
}
if (toPerformDepthPrepass) if (toPerformDepthPrepass)
{ {
aDefaultSettings.DepthFunc = GL_EQUAL; aDefaultSettings.DepthFunc = GL_EQUAL;
@ -830,6 +843,7 @@ void OpenGl_LayerList::Render (const Handle(OpenGl_Workspace)& theWorkspace,
} }
} }
aCtx->ShaderManager()->UpdateLightSourceStateTo (aLightsBack, theWorkspace->View()->SpecIBLMapLevels(), aShadowMaps);
aCtx->core11fwd->glDepthMask (aPrevSettings.DepthMask); aCtx->core11fwd->glDepthMask (aPrevSettings.DepthMask);
aCtx->core11fwd->glDepthFunc (aPrevSettings.DepthFunc); aCtx->core11fwd->glDepthFunc (aPrevSettings.DepthFunc);

View File

@ -21,12 +21,14 @@
#include <OpenGl_Context.hxx> #include <OpenGl_Context.hxx>
#include <Graphic3d_CubeMapPacked.hxx> #include <Graphic3d_CubeMapPacked.hxx>
#include <OpenGl_ShaderManager.hxx> #include <OpenGl_ShaderManager.hxx>
#include <OpenGl_ShadowMap.hxx>
#include <OpenGl_ShaderProgram.hxx> #include <OpenGl_ShaderProgram.hxx>
#include <OpenGl_VertexBufferCompat.hxx> #include <OpenGl_VertexBufferCompat.hxx>
#include <OpenGl_PointSprite.hxx> #include <OpenGl_PointSprite.hxx>
#include <OpenGl_Workspace.hxx> #include <OpenGl_Workspace.hxx>
#include <TCollection_ExtendedString.hxx> #include <TCollection_ExtendedString.hxx>
#include "../Shaders/Shaders_DirectionalLightShadow_glsl.pxx"
#include "../Shaders/Shaders_PBRDistribution_glsl.pxx" #include "../Shaders/Shaders_PBRDistribution_glsl.pxx"
#include "../Shaders/Shaders_PBRGeometry_glsl.pxx" #include "../Shaders/Shaders_PBRGeometry_glsl.pxx"
#include "../Shaders/Shaders_PBRFresnel_glsl.pxx" #include "../Shaders/Shaders_PBRFresnel_glsl.pxx"
@ -249,7 +251,8 @@ const char THE_FUNC_directionalLight[] =
EOL"void directionalLight (in int theId," EOL"void directionalLight (in int theId,"
EOL" in vec3 theNormal," EOL" in vec3 theNormal,"
EOL" in vec3 theView," EOL" in vec3 theView,"
EOL" in bool theIsFront)" EOL" in bool theIsFront,"
EOL" in float theShadow)"
EOL"{" EOL"{"
EOL" vec3 aLight = vec3 (occWorldViewMatrix * vec4 (occLight_Position (theId), 0.0));" EOL" vec3 aLight = vec3 (occWorldViewMatrix * vec4 (occLight_Position (theId), 0.0));"
EOL EOL
@ -265,8 +268,8 @@ const char THE_FUNC_directionalLight[] =
EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());" EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
EOL" }" EOL" }"
EOL EOL
EOL" Diffuse += occLight_Diffuse (theId) * aNdotL;" EOL" Diffuse += occLight_Diffuse (theId) * aNdotL * theShadow;"
EOL" Specular += occLight_Specular (theId) * aSpecl;" EOL" Specular += occLight_Specular (theId) * aSpecl * theShadow;"
EOL"}"; EOL"}";
//! Function computes contribution of directional light source //! Function computes contribution of directional light source
@ -274,7 +277,8 @@ const char THE_FUNC_PBR_directionalLight[] =
EOL"void directionalLight (in int theId," EOL"void directionalLight (in int theId,"
EOL" in vec3 theNormal," EOL" in vec3 theNormal,"
EOL" in vec3 theView," EOL" in vec3 theView,"
EOL" in bool theIsFront)" EOL" in bool theIsFront,"
EOL" in float theShadow)"
EOL"{" EOL"{"
EOL" vec3 aLight = occLight_Position (theId);" EOL" vec3 aLight = occLight_Position (theId);"
EOL EOL
@ -282,7 +286,7 @@ const char THE_FUNC_PBR_directionalLight[] =
EOL" DirectLighting += occPBRIllumination (theView, aLight, theNormal," EOL" DirectLighting += occPBRIllumination (theView, aLight, theNormal,"
EOL" BaseColor, Metallic, Roughness, IOR," EOL" BaseColor, Metallic, Roughness, IOR,"
EOL" occLight_Specular (theId)," EOL" occLight_Specular (theId),"
EOL" occLight_Intensity(theId));" EOL" occLight_Intensity(theId)) * theShadow;"
EOL"}"; EOL"}";
//! The same as THE_FUNC_directionalLight but for the light with zero index //! The same as THE_FUNC_directionalLight but for the light with zero index
@ -290,7 +294,8 @@ const char THE_FUNC_PBR_directionalLight[] =
const char THE_FUNC_directionalLightFirst[] = const char THE_FUNC_directionalLightFirst[] =
EOL"void directionalLightFirst (in vec3 theNormal," EOL"void directionalLightFirst (in vec3 theNormal,"
EOL" in vec3 theView," EOL" in vec3 theView,"
EOL" in bool theIsFront)" EOL" in bool theIsFront,"
EOL" in float theShadow)"
EOL"{" EOL"{"
EOL" vec3 aLight = vec3 (occWorldViewMatrix * vec4 (occLight_Position (0), 0.0));" EOL" vec3 aLight = vec3 (occWorldViewMatrix * vec4 (occLight_Position (0), 0.0));"
EOL EOL
@ -306,8 +311,8 @@ const char THE_FUNC_directionalLightFirst[] =
EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());" EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
EOL" }" EOL" }"
EOL EOL
EOL" Diffuse += occLight_Diffuse(0) * aNdotL;" EOL" Diffuse += occLight_Diffuse(0) * aNdotL * theShadow;"
EOL" Specular += occLight_Specular(0) * aSpecl;" EOL" Specular += occLight_Specular(0) * aSpecl * theShadow;"
EOL"}"; EOL"}";
//! Returns the real cubemap fetching direction considering sides orientation, memory layout and vertical flip. //! Returns the real cubemap fetching direction considering sides orientation, memory layout and vertical flip.
@ -489,11 +494,14 @@ EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatr
#endif #endif
//! Generate map key for light sources configuration. //! Generate map key for light sources configuration.
static TCollection_AsciiString genLightKey (const Handle(Graphic3d_LightSet)& theLights) static TCollection_AsciiString genLightKey (const Handle(Graphic3d_LightSet)& theLights,
const bool theHasShadowMap)
{ {
if (theLights->NbEnabled() <= THE_NB_UNROLLED_LIGHTS_MAX) if (theLights->NbEnabled() <= THE_NB_UNROLLED_LIGHTS_MAX)
{ {
return TCollection_AsciiString ("l_") + theLights->KeyEnabledLong(); return theHasShadowMap
? TCollection_AsciiString ("ls_") + theLights->KeyEnabledLong()
: TCollection_AsciiString ("l_") + theLights->KeyEnabledLong();
} }
const Standard_Integer aMaxLimit = roundUpMaxLightSources (theLights->NbEnabled()); const Standard_Integer aMaxLimit = roundUpMaxLightSources (theLights->NbEnabled());
@ -661,7 +669,7 @@ void OpenGl_ShaderManager::switchLightPrograms()
return; return;
} }
const TCollection_AsciiString aKey = genLightKey (aLights); const TCollection_AsciiString aKey = genLightKey (aLights, myLightSourceState.HasShadowMaps());
if (!myMapOfLightPrograms.Find (aKey, myLightPrograms)) if (!myMapOfLightPrograms.Find (aKey, myLightPrograms))
{ {
myLightPrograms = new OpenGl_SetOfShaderPrograms(); myLightPrograms = new OpenGl_SetOfShaderPrograms();
@ -691,10 +699,12 @@ void OpenGl_ShaderManager::UpdateSRgbState()
// purpose : Updates state of OCCT light sources // purpose : Updates state of OCCT light sources
// ======================================================================= // =======================================================================
void OpenGl_ShaderManager::UpdateLightSourceStateTo (const Handle(Graphic3d_LightSet)& theLights, void OpenGl_ShaderManager::UpdateLightSourceStateTo (const Handle(Graphic3d_LightSet)& theLights,
Standard_Integer theSpecIBLMapLevels) Standard_Integer theSpecIBLMapLevels,
const Handle(OpenGl_ShadowMapArray)& theShadowMaps)
{ {
myLightSourceState.Set (theLights); myLightSourceState.Set (theLights);
myLightSourceState.SetSpecIBLMapLevels (theSpecIBLMapLevels); myLightSourceState.SetSpecIBLMapLevels (theSpecIBLMapLevels);
myLightSourceState.SetShadowMaps (theShadowMaps);
myLightSourceState.Update(); myLightSourceState.Update();
switchLightPrograms(); switchLightPrograms();
} }
@ -954,6 +964,31 @@ void OpenGl_ShaderManager::pushLightSourceState (const Handle(OpenGl_ShaderProgr
{ {
theProgram->SetUniform (myContext, aLocation, myLightSourceState.SpecIBLMapLevels()); theProgram->SetUniform (myContext, aLocation, myLightSourceState.SpecIBLMapLevels());
} }
// update shadow map variables
if (const OpenGl_ShaderUniformLocation aShadowMatLoc = theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SHADOWMAP_MATRICES))
{
if (myShadowMatArray.Size() < theProgram->NbShadowMaps())
{
myShadowMatArray.Resize (0, theProgram->NbShadowMaps() - 1, false);
}
Graphic3d_Vec2 aSizeBias;
if (myLightSourceState.HasShadowMaps())
{
aSizeBias.SetValues (1.0f / (float )myLightSourceState.ShadowMaps()->First()->Texture()->SizeX(),
myLightSourceState.ShadowMaps()->First()->ShadowMapBias());
const Standard_Integer aNbShadows = Min (theProgram->NbShadowMaps(), myLightSourceState.ShadowMaps()->Size());
for (Standard_Integer aShadowIter = 0; aShadowIter < aNbShadows; ++aShadowIter)
{
const Handle(OpenGl_ShadowMap)& aShadow = myLightSourceState.ShadowMaps()->Value (aShadowIter);
myShadowMatArray[aShadowIter] = aShadow->LightSourceMatrix();
}
}
theProgram->SetUniform (myContext, aShadowMatLoc, theProgram->NbShadowMaps(), &myShadowMatArray.First());
theProgram->SetUniform (myContext, theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SHADOWMAP_SIZE_BIAS), aSizeBias);
}
} }
// ======================================================================= // =======================================================================
@ -1491,6 +1526,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFont()
defaultGlslVersion (aProgramSrc, "font", 0); defaultGlslVersion (aProgramSrc, "font", 0);
aProgramSrc->SetDefaultSampler (false); aProgramSrc->SetDefaultSampler (false);
aProgramSrc->SetNbLightsMax (0); aProgramSrc->SetNbLightsMax (0);
aProgramSrc->SetNbShadowMaps (0);
aProgramSrc->SetNbClipPlanesMax (0); aProgramSrc->SetNbClipPlanesMax (0);
aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts)); aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts)); aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
@ -1636,6 +1672,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFboBlit (Handle(OpenGl_S
aProgramSrc->SetId (anId); aProgramSrc->SetId (anId);
aProgramSrc->SetDefaultSampler (false); aProgramSrc->SetDefaultSampler (false);
aProgramSrc->SetNbLightsMax (0); aProgramSrc->SetNbLightsMax (0);
aProgramSrc->SetNbShadowMaps (0);
aProgramSrc->SetNbClipPlanesMax (0); aProgramSrc->SetNbClipPlanesMax (0);
aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts)); aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts)); aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
@ -1728,6 +1765,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramOitCompositing (const St
aProgramSrc->SetId (theMsaa ? "occt_weight-oit-msaa" : "occt_weight-oit"); aProgramSrc->SetId (theMsaa ? "occt_weight-oit-msaa" : "occt_weight-oit");
aProgramSrc->SetDefaultSampler (false); aProgramSrc->SetDefaultSampler (false);
aProgramSrc->SetNbLightsMax (0); aProgramSrc->SetNbLightsMax (0);
aProgramSrc->SetNbShadowMaps (0);
aProgramSrc->SetNbClipPlanesMax (0); aProgramSrc->SetNbClipPlanesMax (0);
aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts)); aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts)); aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
@ -1930,8 +1968,18 @@ TCollection_AsciiString OpenGl_ShaderManager::prepareGeomMainSrc (OpenGl_ShaderO
if (aVarListIter.Value().Stages == (Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)) if (aVarListIter.Value().Stages == (Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT))
{ {
const TCollection_AsciiString aVarName = aVarListIter.Value().Name.Token (" ", 2); const TCollection_AsciiString aVarName = aVarListIter.Value().Name.Token (" ", 2);
aSrcMainGeom += TCollection_AsciiString() if (aVarName.Value (aVarName.Length()) == ']')
+ EOL" geomOut." + aVarName + " = geomIn[" + aVertIndex + "]." + aVarName + ";"; {
// copy the whole array
const TCollection_AsciiString aVarName2 = aVarName.Token ("[", 1);
aSrcMainGeom += TCollection_AsciiString()
+ EOL" geomOut." + aVarName2 + " = geomIn[" + aVertIndex + "]." + aVarName2 + ";";
}
else
{
aSrcMainGeom += TCollection_AsciiString()
+ EOL" geomOut." + aVarName + " = geomIn[" + aVertIndex + "]." + aVarName + ";";
}
} }
} }
@ -2179,6 +2227,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramUnlit (Handle(OpenGl_Sha
defaultGlslVersion (aProgramSrc, theIsOutline ? "outline" : "unlit", theBits); defaultGlslVersion (aProgramSrc, theIsOutline ? "outline" : "unlit", theBits);
aProgramSrc->SetDefaultSampler (false); aProgramSrc->SetDefaultSampler (false);
aProgramSrc->SetNbLightsMax (0); aProgramSrc->SetNbLightsMax (0);
aProgramSrc->SetNbShadowMaps (0);
aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes); aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes);
aProgramSrc->SetAlphaTest ((theBits & OpenGl_PO_AlphaTest) != 0); aProgramSrc->SetAlphaTest ((theBits & OpenGl_PO_AlphaTest) != 0);
const Standard_Integer aNbGeomInputVerts = !aSrcGeom.IsEmpty() ? 3 : 0; const Standard_Integer aNbGeomInputVerts = !aSrcGeom.IsEmpty() ? 3 : 0;
@ -2235,34 +2284,65 @@ TCollection_AsciiString OpenGl_ShaderManager::pointSpriteShadingSrc (const TColl
TCollection_AsciiString OpenGl_ShaderManager::stdComputeLighting (Standard_Integer& theNbLights, TCollection_AsciiString OpenGl_ShaderManager::stdComputeLighting (Standard_Integer& theNbLights,
Standard_Boolean theHasVertColor, Standard_Boolean theHasVertColor,
Standard_Boolean theIsPBR, Standard_Boolean theIsPBR,
Standard_Boolean theHasEmissive) Standard_Boolean theHasEmissive,
Standard_Boolean theHasShadowMap)
{ {
TCollection_AsciiString aLightsFunc, aLightsLoop; TCollection_AsciiString aLightsFunc, aLightsLoop;
theNbLights = 0; theNbLights = 0;
const Handle(Graphic3d_LightSet)& aLights = myLightSourceState.LightSources(); const Handle(Graphic3d_LightSet)& aLights = myLightSourceState.LightSources();
if (!aLights.IsNull()) if (!aLights.IsNull())
{ {
const bool hasShadowMap = theHasShadowMap && myLightSourceState.HasShadowMaps();
theNbLights = aLights->NbEnabled(); theNbLights = aLights->NbEnabled();
if (theNbLights <= THE_NB_UNROLLED_LIGHTS_MAX) if (theNbLights <= THE_NB_UNROLLED_LIGHTS_MAX)
{ {
Standard_Integer anIndex = 0; Standard_Integer anIndex = 0;
if (hasShadowMap)
{
for (Graphic3d_LightSet::Iterator aLightIter (aLights, Graphic3d_LightSet::IterationFilter_ExcludeDisabledAndAmbient);
aLightIter.More(); aLightIter.Next())
{
if (aLightIter.Value()->Type() == Graphic3d_TOLS_DIRECTIONAL
&& aLightIter.Value()->ToCastShadows())
{
aLightsLoop = aLightsLoop + EOL" directionalLight (" + anIndex + ", theNormal, theView, theIsFront,"
EOL" occDirectionalLightShadow (" + anIndex + ", theNormal));";
++anIndex;
}
}
}
for (Graphic3d_LightSet::Iterator aLightIter (aLights, Graphic3d_LightSet::IterationFilter_ExcludeDisabledAndAmbient); for (Graphic3d_LightSet::Iterator aLightIter (aLights, Graphic3d_LightSet::IterationFilter_ExcludeDisabledAndAmbient);
aLightIter.More(); aLightIter.Next(), ++anIndex) aLightIter.More(); aLightIter.Next())
{ {
switch (aLightIter.Value()->Type()) switch (aLightIter.Value()->Type())
{ {
case Graphic3d_TOLS_AMBIENT: case Graphic3d_TOLS_AMBIENT:
--anIndex; {
break; // skip ambient break; // skip ambient
}
case Graphic3d_TOLS_DIRECTIONAL: case Graphic3d_TOLS_DIRECTIONAL:
aLightsLoop = aLightsLoop + EOL" directionalLight (" + anIndex + ", theNormal, theView, theIsFront);"; {
if (hasShadowMap
&& aLightIter.Value()->ToCastShadows())
{
break;
}
aLightsLoop = aLightsLoop + EOL" directionalLight (" + anIndex + ", theNormal, theView, theIsFront, 1.0);";
++anIndex;
break; break;
}
case Graphic3d_TOLS_POSITIONAL: case Graphic3d_TOLS_POSITIONAL:
{
aLightsLoop = aLightsLoop + EOL" pointLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);"; aLightsLoop = aLightsLoop + EOL" pointLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);";
++anIndex;
break; break;
}
case Graphic3d_TOLS_SPOT: case Graphic3d_TOLS_SPOT:
{
aLightsLoop = aLightsLoop + EOL" spotLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);"; aLightsLoop = aLightsLoop + EOL" spotLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);";
++anIndex;
break; break;
}
} }
} }
} }
@ -2280,7 +2360,7 @@ TCollection_AsciiString OpenGl_ShaderManager::stdComputeLighting (Standard_Integ
aLightsLoop += aLightsLoop +=
EOL" if (aType == OccLightType_Direct)" EOL" if (aType == OccLightType_Direct)"
EOL" {" EOL" {"
EOL" directionalLight (anIndex, theNormal, theView, theIsFront);" EOL" directionalLight (anIndex, theNormal, theView, theIsFront, 1.0);"
EOL" }"; EOL" }";
} }
if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_POSITIONAL) > 0) if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_POSITIONAL) > 0)
@ -2323,14 +2403,19 @@ TCollection_AsciiString OpenGl_ShaderManager::stdComputeLighting (Standard_Integ
if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_DIRECTIONAL) == 1 if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_DIRECTIONAL) == 1
&& theNbLights == 1 && theNbLights == 1
&& !theIsPBR) && !theIsPBR
&& !hasShadowMap)
{ {
// use the version with hard-coded first index // use the version with hard-coded first index
aLightsLoop = EOL" directionalLightFirst(theNormal, theView, theIsFront);"; aLightsLoop = EOL" directionalLightFirst(theNormal, theView, theIsFront, 1.0);";
aLightsFunc += THE_FUNC_directionalLightFirst; aLightsFunc += THE_FUNC_directionalLightFirst;
} }
else if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_DIRECTIONAL) > 0) else if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_DIRECTIONAL) > 0)
{ {
if (hasShadowMap)
{
aLightsFunc += Shaders_DirectionalLightShadow_glsl;
}
aLightsFunc += theIsPBR ? THE_FUNC_PBR_directionalLight : THE_FUNC_directionalLight; aLightsFunc += theIsPBR ? THE_FUNC_PBR_directionalLight : THE_FUNC_directionalLight;
} }
if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_POSITIONAL) > 0) if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_POSITIONAL) > 0)
@ -2521,7 +2606,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_S
aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 BackColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 BackColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
Standard_Integer aNbLights = 0; Standard_Integer aNbLights = 0;
const TCollection_AsciiString aLights = stdComputeLighting (aNbLights, !aSrcVertColor.IsEmpty(), false, true); const TCollection_AsciiString aLights = stdComputeLighting (aNbLights, !aSrcVertColor.IsEmpty(), false, true, false);
aSrcVert = TCollection_AsciiString() aSrcVert = TCollection_AsciiString()
+ THE_FUNC_transformNormal_view + THE_FUNC_transformNormal_view
+ EOL + EOL
@ -2533,8 +2618,8 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_S
EOL" vec4 aPosition = occWorldViewMatrix * aPositionWorld;" EOL" vec4 aPosition = occWorldViewMatrix * aPositionWorld;"
EOL" vec3 aNormal = transformNormal (occNormal);" EOL" vec3 aNormal = transformNormal (occNormal);"
EOL" vec3 aView = vec3 (0.0, 0.0, 1.0);" EOL" vec3 aView = vec3 (0.0, 0.0, 1.0);"
EOL" FrontColor = computeLighting (normalize (aNormal), normalize (aView), aPosition, true);" EOL" FrontColor = computeLighting (aNormal, aView, aPosition, true);"
EOL" BackColor = computeLighting (normalize (aNormal), normalize (aView), aPosition, false);" EOL" BackColor = computeLighting (aNormal, aView, aPosition, false);"
+ aSrcVertExtraMain + aSrcVertExtraMain
+ THE_VERT_gl_Position + THE_VERT_gl_Position
+ EOL"}"; + EOL"}";
@ -2552,10 +2637,11 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_S
+ EOL" occSetFragColor (getFinalColor());" + EOL" occSetFragColor (getFinalColor());"
+ EOL"}"; + EOL"}";
const TCollection_AsciiString aProgId = TCollection_AsciiString ("gouraud-") + genLightKey (myLightSourceState.LightSources()) + "-"; const TCollection_AsciiString aProgId = TCollection_AsciiString ("gouraud-") + genLightKey (myLightSourceState.LightSources(), false) + "-";
defaultGlslVersion (aProgramSrc, aProgId, theBits); defaultGlslVersion (aProgramSrc, aProgId, theBits);
aProgramSrc->SetDefaultSampler (false); aProgramSrc->SetDefaultSampler (false);
aProgramSrc->SetNbLightsMax (aNbLights); aProgramSrc->SetNbLightsMax (aNbLights);
aProgramSrc->SetNbShadowMaps (0);
aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes); aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes);
aProgramSrc->SetAlphaTest ((theBits & OpenGl_PO_AlphaTest) != 0); aProgramSrc->SetAlphaTest ((theBits & OpenGl_PO_AlphaTest) != 0);
const Standard_Integer aNbGeomInputVerts = !aSrcGeom.IsEmpty() ? 3 : 0; const Standard_Integer aNbGeomInputVerts = !aSrcGeom.IsEmpty() ? 3 : 0;
@ -2760,6 +2846,19 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha
aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 PositionWorld", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 PositionWorld", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 Position", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 Position", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec3 View", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec3 View", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
if (myLightSourceState.HasShadowMaps())
{
aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("mat4 occShadowMapMatrices[THE_NB_SHADOWMAPS]", Graphic3d_TOS_VERTEX));
aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occShadowMapSamplers[THE_NB_SHADOWMAPS]", Graphic3d_TOS_FRAGMENT));
aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("vec2 occShadowMapSizeBias", Graphic3d_TOS_FRAGMENT));
aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 PosLightSpace[THE_NB_SHADOWMAPS]", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
aSrcVertExtraMain +=
EOL" for (int aShadowIter = 0; aShadowIter < THE_NB_SHADOWMAPS; ++aShadowIter)"
EOL" {"
EOL" PosLightSpace[aShadowIter] = occShadowMapMatrices[aShadowIter] * PositionWorld;"
EOL" }";
}
aSrcVert = TCollection_AsciiString() aSrcVert = TCollection_AsciiString()
+ aSrcVertExtraFunc + aSrcVertExtraFunc
@ -2786,9 +2885,13 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha
: EOL"#define getFinalColor getColor"; : EOL"#define getFinalColor getColor";
Standard_Integer aNbLights = 0; Standard_Integer aNbLights = 0;
Standard_Integer aNbShadowMaps = myLightSourceState.HasShadowMaps()
? myLightSourceState.LightSources()->NbCastShadows()
: 0;
const TCollection_AsciiString aLights = stdComputeLighting (aNbLights, !aSrcFragGetVertColor.IsEmpty(), theIsPBR, const TCollection_AsciiString aLights = stdComputeLighting (aNbLights, !aSrcFragGetVertColor.IsEmpty(), theIsPBR,
(theBits & OpenGl_PO_TextureRGB) == 0 (theBits & OpenGl_PO_TextureRGB) == 0
|| (theBits & OpenGl_PO_IsPoint) != 0); || (theBits & OpenGl_PO_IsPoint) != 0,
myLightSourceState.HasShadowMaps());
aSrcFrag += TCollection_AsciiString() aSrcFrag += TCollection_AsciiString()
+ EOL + EOL
+ aSrcFragGetVertColor + aSrcFragGetVertColor
@ -2802,10 +2905,12 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha
+ EOL" occSetFragColor (getFinalColor());" + EOL" occSetFragColor (getFinalColor());"
+ EOL"}"; + EOL"}";
const TCollection_AsciiString aProgId = TCollection_AsciiString (theIsFlatNormal ? "flat-" : "phong-") + (theIsPBR ? "pbr-" : "") + genLightKey (myLightSourceState.LightSources()) + "-"; const TCollection_AsciiString aProgId = TCollection_AsciiString (theIsFlatNormal ? "flat-" : "phong-") + (theIsPBR ? "pbr-" : "")
+ genLightKey (myLightSourceState.LightSources(), aNbShadowMaps > 0) + "-";
defaultGlslVersion (aProgramSrc, aProgId, theBits, isFlatNormal); defaultGlslVersion (aProgramSrc, aProgId, theBits, isFlatNormal);
aProgramSrc->SetDefaultSampler (false); aProgramSrc->SetDefaultSampler (false);
aProgramSrc->SetNbLightsMax (aNbLights); aProgramSrc->SetNbLightsMax (aNbLights);
aProgramSrc->SetNbShadowMaps (aNbShadowMaps);
aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes); aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes);
aProgramSrc->SetAlphaTest ((theBits & OpenGl_PO_AlphaTest) != 0); aProgramSrc->SetAlphaTest ((theBits & OpenGl_PO_AlphaTest) != 0);
@ -3002,6 +3107,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_Sh
defaultGlslVersion (aProgramSrc, aName, 0); defaultGlslVersion (aProgramSrc, aName, 0);
aProgramSrc->SetDefaultSampler (false); aProgramSrc->SetDefaultSampler (false);
aProgramSrc->SetNbLightsMax (0); aProgramSrc->SetNbLightsMax (0);
aProgramSrc->SetNbShadowMaps (0);
aProgramSrc->SetNbClipPlanesMax (0); aProgramSrc->SetNbClipPlanesMax (0);
aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts)); aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts)); aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
@ -3048,6 +3154,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramBoundBox()
defaultGlslVersion (aProgramSrc, "bndbox", 0); defaultGlslVersion (aProgramSrc, "bndbox", 0);
aProgramSrc->SetDefaultSampler (false); aProgramSrc->SetDefaultSampler (false);
aProgramSrc->SetNbLightsMax (0); aProgramSrc->SetNbLightsMax (0);
aProgramSrc->SetNbShadowMaps (0);
aProgramSrc->SetNbClipPlanesMax (0); aProgramSrc->SetNbClipPlanesMax (0);
aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts)); aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts)); aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
@ -3126,6 +3233,7 @@ Standard_Boolean OpenGl_ShaderManager::preparePBREnvBakingProgram()
defaultGlslVersion (aProgramSrc, "pbr_env_baking", 0); defaultGlslVersion (aProgramSrc, "pbr_env_baking", 0);
aProgramSrc->SetDefaultSampler (false); aProgramSrc->SetDefaultSampler (false);
aProgramSrc->SetNbLightsMax (0); aProgramSrc->SetNbLightsMax (0);
aProgramSrc->SetNbShadowMaps (0);
aProgramSrc->SetNbClipPlanesMax (0); aProgramSrc->SetNbClipPlanesMax (0);
aProgramSrc->SetPBR (true); aProgramSrc->SetPBR (true);
aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts)); aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
@ -3200,6 +3308,7 @@ const Handle(Graphic3d_ShaderProgram)& OpenGl_ShaderManager::GetBgCubeMapProgram
defaultGlslVersion (myBgCubeMapProgram, "background_cubemap", 0); defaultGlslVersion (myBgCubeMapProgram, "background_cubemap", 0);
myBgCubeMapProgram->SetDefaultSampler (false); myBgCubeMapProgram->SetDefaultSampler (false);
myBgCubeMapProgram->SetNbLightsMax (0); myBgCubeMapProgram->SetNbLightsMax (0);
myBgCubeMapProgram->SetNbShadowMaps (0);
myBgCubeMapProgram->SetNbClipPlanesMax (0); myBgCubeMapProgram->SetNbClipPlanesMax (0);
myBgCubeMapProgram->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts)); myBgCubeMapProgram->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
myBgCubeMapProgram->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts)); myBgCubeMapProgram->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));

View File

@ -287,7 +287,24 @@ public:
//! Updates state of OCCT light sources. //! Updates state of OCCT light sources.
Standard_EXPORT void UpdateLightSourceStateTo (const Handle(Graphic3d_LightSet)& theLights, Standard_EXPORT void UpdateLightSourceStateTo (const Handle(Graphic3d_LightSet)& theLights,
Standard_Integer theSpecIBLMapLevels = 0); Standard_Integer theSpecIBLMapLevels,
const Handle(OpenGl_ShadowMapArray)& theShadowMaps);
//! Updates state of OCCT light sources to dynamically enable/disable shadowmap.
//! @param theToCast [in] flag to enable/disable shadowmap
//! @return previous flag state
bool SetCastShadows (const bool theToCast)
{
if (myLightSourceState.ShadowMaps().IsNull()
|| myLightSourceState.ToCastShadows() == theToCast)
{
return myLightSourceState.ToCastShadows();
}
myLightSourceState.SetCastShadows (theToCast);
switchLightPrograms();
return !theToCast;
}
//! Invalidate state of OCCT light sources. //! Invalidate state of OCCT light sources.
Standard_EXPORT void UpdateLightSourceState(); Standard_EXPORT void UpdateLightSourceState();
@ -709,10 +726,12 @@ protected:
//! @param theHasVertColor [in] flag to use getVertColor() instead of Ambient and Diffuse components of active material //! @param theHasVertColor [in] flag to use getVertColor() instead of Ambient and Diffuse components of active material
//! @param theIsPBR [in] flag to activate PBR pipeline //! @param theIsPBR [in] flag to activate PBR pipeline
//! @param theHasEmissive [in] flag to include emissive //! @param theHasEmissive [in] flag to include emissive
//! @param theHasShadowMap [in] flag to include shadow map
Standard_EXPORT TCollection_AsciiString stdComputeLighting (Standard_Integer& theNbLights, Standard_EXPORT TCollection_AsciiString stdComputeLighting (Standard_Integer& theNbLights,
Standard_Boolean theHasVertColor, Standard_Boolean theHasVertColor,
Standard_Boolean theIsPBR, Standard_Boolean theIsPBR,
Standard_Boolean theHasEmissive = true); Standard_Boolean theHasEmissive,
Standard_Boolean theHasShadowMap);
//! Bind specified program to current context and apply state. //! Bind specified program to current context and apply state.
Standard_EXPORT Standard_Boolean bindProgramWithState (const Handle(OpenGl_ShaderProgram)& theProgram, Standard_EXPORT Standard_Boolean bindProgramWithState (const Handle(OpenGl_ShaderProgram)& theProgram,
@ -834,6 +853,7 @@ protected:
mutable NCollection_Array1<Standard_Integer> myLightTypeArray; mutable NCollection_Array1<Standard_Integer> myLightTypeArray;
mutable NCollection_Array1<OpenGl_ShaderLightParameters> myLightParamsArray; mutable NCollection_Array1<OpenGl_ShaderLightParameters> myLightParamsArray;
mutable NCollection_Array1<Graphic3d_Mat4> myShadowMatArray;
mutable NCollection_Array1<OpenGl_Vec4> myClipPlaneArray; mutable NCollection_Array1<OpenGl_Vec4> myClipPlaneArray;
mutable NCollection_Array1<OpenGl_Vec4d> myClipPlaneArrayFfp; mutable NCollection_Array1<OpenGl_Vec4d> myClipPlaneArrayFfp;
mutable NCollection_Array1<Standard_Integer> myClipChainArray; mutable NCollection_Array1<Standard_Integer> myClipChainArray;

View File

@ -64,6 +64,9 @@ Standard_CString OpenGl_ShaderProgram::PredefinedKeywords[] =
"occLightSourcesTypes", // OpenGl_OCC_LIGHT_SOURCE_TYPES "occLightSourcesTypes", // OpenGl_OCC_LIGHT_SOURCE_TYPES
"occLightSources", // OpenGl_OCC_LIGHT_SOURCE_PARAMS "occLightSources", // OpenGl_OCC_LIGHT_SOURCE_PARAMS
"occLightAmbient", // OpenGl_OCC_LIGHT_AMBIENT "occLightAmbient", // OpenGl_OCC_LIGHT_AMBIENT
"occShadowMapSizeBias", // OpenGl_OCC_LIGHT_SHADOWMAP_SIZE_BIAS
"occShadowMapSamplers", // OpenGl_OCC_LIGHT_SHADOWMAP_SAMPLERS,
"occShadowMapMatrices", // OpenGl_OCC_LIGHT_SHADOWMAP_MATRICES,
"occTextureEnable", // OpenGl_OCCT_TEXTURE_ENABLE "occTextureEnable", // OpenGl_OCCT_TEXTURE_ENABLE
"occDistinguishingMode", // OpenGl_OCCT_DISTINGUISH_MODE "occDistinguishingMode", // OpenGl_OCCT_DISTINGUISH_MODE
@ -169,6 +172,7 @@ OpenGl_ShaderProgram::OpenGl_ShaderProgram (const Handle(Graphic3d_ShaderProgram
myProxy (theProxy), myProxy (theProxy),
myShareCount(1), myShareCount(1),
myNbLightsMax (0), myNbLightsMax (0),
myNbShadowMaps (0),
myNbClipPlanesMax (0), myNbClipPlanesMax (0),
myNbFragOutputs (1), myNbFragOutputs (1),
myTextureSetBits (Graphic3d_TextureSetBits_NONE), myTextureSetBits (Graphic3d_TextureSetBits_NONE),
@ -406,10 +410,15 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)&
TCollection_AsciiString aHeaderConstants; TCollection_AsciiString aHeaderConstants;
myNbLightsMax = !myProxy.IsNull() ? myProxy->NbLightsMax() : 0; myNbLightsMax = !myProxy.IsNull() ? myProxy->NbLightsMax() : 0;
myNbShadowMaps = !myProxy.IsNull() ? myProxy->NbShadowMaps() : 0;
myNbClipPlanesMax = !myProxy.IsNull() ? myProxy->NbClipPlanesMax() : 0; myNbClipPlanesMax = !myProxy.IsNull() ? myProxy->NbClipPlanesMax() : 0;
aHeaderConstants += TCollection_AsciiString("#define THE_MAX_LIGHTS ") + myNbLightsMax + "\n"; aHeaderConstants += TCollection_AsciiString("#define THE_MAX_LIGHTS ") + myNbLightsMax + "\n";
aHeaderConstants += TCollection_AsciiString("#define THE_MAX_CLIP_PLANES ") + myNbClipPlanesMax + "\n"; aHeaderConstants += TCollection_AsciiString("#define THE_MAX_CLIP_PLANES ") + myNbClipPlanesMax + "\n";
aHeaderConstants += TCollection_AsciiString("#define THE_NB_FRAG_OUTPUTS ") + myNbFragOutputs + "\n"; aHeaderConstants += TCollection_AsciiString("#define THE_NB_FRAG_OUTPUTS ") + myNbFragOutputs + "\n";
if (myNbShadowMaps > 0)
{
aHeaderConstants += TCollection_AsciiString("#define THE_NB_SHADOWMAPS ") + myNbShadowMaps + "\n";
}
if (!myProxy.IsNull() if (!myProxy.IsNull()
&& myProxy->HasDefaultSampler()) && myProxy->HasDefaultSampler())
{ {
@ -556,6 +565,16 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)&
{ {
SetUniform (theCtx, aLocSampler, GLint(theCtx->PBREnvLUTTexUnit())); SetUniform (theCtx, aLocSampler, GLint(theCtx->PBREnvLUTTexUnit()));
} }
if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occShadowMapSamplers"))
{
std::vector<GLint> aShadowSamplers (myNbShadowMaps);
const GLint aSamplFrom = GLint(theCtx->ShadowMapTexUnit()) - myNbShadowMaps + 1;
for (Standard_Integer aSamplerIter = 0; aSamplerIter < myNbShadowMaps; ++aSamplerIter)
{
aShadowSamplers[aSamplerIter] = aSamplFrom + aSamplerIter;
}
SetUniform (theCtx, aLocSampler, myNbShadowMaps, &aShadowSamplers.front());
}
const TCollection_AsciiString aSamplerNamePrefix ("occSampler"); const TCollection_AsciiString aSamplerNamePrefix ("occSampler");
const Standard_Integer aNbUnitsMax = Max (theCtx->MaxCombinedTextureUnits(), Graphic3d_TextureUnit_NB); const Standard_Integer aNbUnitsMax = Max (theCtx->MaxCombinedTextureUnits(), Graphic3d_TextureUnit_NB);
@ -1369,6 +1388,24 @@ Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)&
return SetUniform (theCtx, theLocation, OpenGl_Mat4::Map (*theValue.mat), theTranspose); return SetUniform (theCtx, theLocation, OpenGl_Mat4::Map (*theValue.mat), theTranspose);
} }
// =======================================================================
// function : SetUniform
// purpose :
// =======================================================================
Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
GLint theLocation,
GLuint theCount,
const OpenGl_Mat4* theData)
{
if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
{
return Standard_False;
}
theCtx->core20fwd->glUniformMatrix4fv (theLocation, theCount, GL_FALSE, theData->GetData());
return Standard_True;
}
// ======================================================================= // =======================================================================
// function : SetUniform // function : SetUniform
// purpose : Specifies the value of the float uniform array // purpose : Specifies the value of the float uniform array

View File

@ -59,6 +59,9 @@ enum OpenGl_StateVariable
OpenGl_OCC_LIGHT_SOURCE_TYPES, OpenGl_OCC_LIGHT_SOURCE_TYPES,
OpenGl_OCC_LIGHT_SOURCE_PARAMS, OpenGl_OCC_LIGHT_SOURCE_PARAMS,
OpenGl_OCC_LIGHT_AMBIENT, OpenGl_OCC_LIGHT_AMBIENT,
OpenGl_OCC_LIGHT_SHADOWMAP_SIZE_BIAS,// occShadowMapSizeBias
OpenGl_OCC_LIGHT_SHADOWMAP_SAMPLERS, // occShadowMapSamplers
OpenGl_OCC_LIGHT_SHADOWMAP_MATRICES, // occShadowMapMatrices
// Material state // Material state
OpenGl_OCCT_TEXTURE_ENABLE, OpenGl_OCCT_TEXTURE_ENABLE,
@ -284,6 +287,9 @@ public:
//! to be used for initialization occLightSources (OpenGl_OCC_LIGHT_SOURCE_PARAMS). //! to be used for initialization occLightSources (OpenGl_OCC_LIGHT_SOURCE_PARAMS).
Standard_Integer NbLightsMax() const { return myNbLightsMax; } Standard_Integer NbLightsMax() const { return myNbLightsMax; }
//! Return the length of array of shadow maps (THE_NB_SHADOWMAPS); 0 by default.
Standard_Integer NbShadowMaps() const { return myNbShadowMaps; }
//! Return the length of array of clipping planes (THE_MAX_CLIP_PLANES), //! Return the length of array of clipping planes (THE_MAX_CLIP_PLANES),
//! to be used for initialization occClipPlaneEquations (OpenGl_OCC_CLIP_PLANE_EQUATIONS) and occClipPlaneChains (OpenGl_OCC_CLIP_PLANE_CHAINS). //! to be used for initialization occClipPlaneEquations (OpenGl_OCC_CLIP_PLANE_EQUATIONS) and occClipPlaneChains (OpenGl_OCC_CLIP_PLANE_CHAINS).
Standard_Integer NbClipPlanesMax() const { return myNbClipPlanesMax; } Standard_Integer NbClipPlanesMax() const { return myNbClipPlanesMax; }
@ -546,6 +552,13 @@ public:
const OpenGl_Mat4& theValue, const OpenGl_Mat4& theValue,
GLboolean theTranspose = GL_FALSE); GLboolean theTranspose = GL_FALSE);
//! Specifies the value of the array of float uniform 4x4 matrices.
//! Wrapper over glUniformMatrix4fv().
Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx,
GLint theLocation,
GLuint theCount,
const OpenGl_Mat4* theData);
//! Specifies the value of the float uniform 4x4 matrix. //! Specifies the value of the float uniform 4x4 matrix.
Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx, Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx,
const GLchar* theName, const GLchar* theName,
@ -661,6 +674,7 @@ protected:
Handle(Graphic3d_ShaderProgram) myProxy; //!< Proxy shader program (from application layer) Handle(Graphic3d_ShaderProgram) myProxy; //!< Proxy shader program (from application layer)
Standard_Integer myShareCount; //!< program users count, initialized with 1 (already shared by one user) Standard_Integer myShareCount; //!< program users count, initialized with 1 (already shared by one user)
Standard_Integer myNbLightsMax; //!< length of array of light sources (THE_MAX_LIGHTS) Standard_Integer myNbLightsMax; //!< length of array of light sources (THE_MAX_LIGHTS)
Standard_Integer myNbShadowMaps; //!< length of array of shadow maps (THE_NB_SHADOWMAPS)
Standard_Integer myNbClipPlanesMax; //!< length of array of clipping planes (THE_MAX_CLIP_PLANES) Standard_Integer myNbClipPlanesMax; //!< length of array of clipping planes (THE_MAX_CLIP_PLANES)
Standard_Integer myNbFragOutputs; //!< length of array of Fragment Shader outputs (THE_NB_FRAG_OUTPUTS) Standard_Integer myNbFragOutputs; //!< length of array of Fragment Shader outputs (THE_NB_FRAG_OUTPUTS)
Standard_Integer myTextureSetBits;//!< texture units declared within the program, @sa Graphic3d_TextureSetBits Standard_Integer myTextureSetBits;//!< texture units declared within the program, @sa Graphic3d_TextureSetBits

View File

@ -21,6 +21,8 @@
#include <OpenGl_Element.hxx> #include <OpenGl_Element.hxx>
#include <OpenGl_Vec.hxx> #include <OpenGl_Vec.hxx>
class OpenGl_ShadowMapArray;
//! Defines interface for OpenGL state. //! Defines interface for OpenGL state.
class OpenGl_StateInterface class OpenGl_StateInterface
{ {
@ -122,7 +124,7 @@ class OpenGl_LightSourceState : public OpenGl_StateInterface
public: public:
//! Creates uninitialized state of light sources. //! Creates uninitialized state of light sources.
OpenGl_LightSourceState() : mySpecIBLMapLevels (0) {} OpenGl_LightSourceState() : mySpecIBLMapLevels (0), myToCastShadows (Standard_True) {}
//! Sets new light sources. //! Sets new light sources.
void Set (const Handle(Graphic3d_LightSet)& theLightSources) { myLightSources = theLightSources; } void Set (const Handle(Graphic3d_LightSet)& theLightSources) { myLightSources = theLightSources; }
@ -137,10 +139,27 @@ public:
//! Sets number of mipmap levels used in specular IBL map. //! Sets number of mipmap levels used in specular IBL map.
void SetSpecIBLMapLevels(Standard_Integer theSpecIBLMapLevels) { mySpecIBLMapLevels = theSpecIBLMapLevels; } void SetSpecIBLMapLevels(Standard_Integer theSpecIBLMapLevels) { mySpecIBLMapLevels = theSpecIBLMapLevels; }
//! Returns TRUE if shadowmap is set.
bool HasShadowMaps() const { return myToCastShadows && !myShadowMaps.IsNull(); }
//! Returns shadowmap.
const Handle(OpenGl_ShadowMapArray)& ShadowMaps() const { return myShadowMaps; }
//! Sets shadowmap.
void SetShadowMaps (const Handle(OpenGl_ShadowMapArray)& theMap) { myShadowMaps = theMap; }
//! Returns TRUE if shadowmap should be enabled when available; TRUE by default.
bool ToCastShadows() const { return myToCastShadows; }
//! Set if shadowmap should be enabled when available.
void SetCastShadows (bool theToCast) { myToCastShadows = theToCast; }
private: private:
Handle(Graphic3d_LightSet) myLightSources; //!< List of OCCT light sources Handle(Graphic3d_LightSet) myLightSources; //!< List of OCCT light sources
Standard_Integer mySpecIBLMapLevels; //!< Number of mipmap levels used in specular IBL map (0 by default or in case of using non-PBR shading model) Standard_Integer mySpecIBLMapLevels; //!< Number of mipmap levels used in specular IBL map (0 by default or in case of using non-PBR shading model)
Handle(OpenGl_ShadowMapArray) myShadowMaps; //!< active shadowmap
Standard_Boolean myToCastShadows; //!< enable/disable shadowmap
}; };

View File

@ -0,0 +1,171 @@
// Copyright (c) 2021 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_ShadowMap.hxx>
#include <OpenGl_ArbFBO.hxx>
#include <OpenGl_FrameBuffer.hxx>
#include <OpenGl_ShaderManager.hxx>
#include <Graphic3d_Camera.hxx>
#include <Graphic3d_CView.hxx>
#include <Message.hxx>
#include <Message_Messenger.hxx>
IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShadowMap, OpenGl_NamedResource)
// =======================================================================
// function : OpenGl_ShadowMap
// purpose :
// =======================================================================
OpenGl_ShadowMap::OpenGl_ShadowMap()
: OpenGl_NamedResource ("shadow_map"),
myShadowMapFbo (new OpenGl_FrameBuffer()),
myShadowCamera (new Graphic3d_Camera()),
myShadowMapBias (0.0f)
{
//
}
// =======================================================================
// function : Release
// purpose :
// =======================================================================
void OpenGl_ShadowMap::Release (OpenGl_Context* theCtx)
{
myShadowMapFbo->Release (theCtx);
}
// =======================================================================
// function : ~OpenGl_ShadowMap
// purpose :
// =======================================================================
OpenGl_ShadowMap::~OpenGl_ShadowMap()
{
Release (NULL);
}
// =======================================================================
// function : EstimatedDataSize
// purpose :
// =======================================================================
Standard_Size OpenGl_ShadowMap::EstimatedDataSize() const
{
return myShadowMapFbo->EstimatedDataSize();
}
// =======================================================================
// function : IsValid
// purpose :
// =======================================================================
bool OpenGl_ShadowMap::IsValid() const
{
return myShadowMapFbo->IsValid();
}
// =======================================================================
// function : Texture
// purpose :
// =======================================================================
const Handle(OpenGl_Texture)& OpenGl_ShadowMap::Texture() const
{
return myShadowMapFbo->DepthStencilTexture();
}
// =======================================================================
// function : UpdateCamera
// purpose :
// =======================================================================
bool OpenGl_ShadowMap::UpdateCamera (const Graphic3d_CView& theView)
{
const Bnd_Box aMinMaxBox = theView.MinMaxValues (false); // applicative min max boundaries
const Bnd_Box aGraphicBox = theView.MinMaxValues (true); // real graphical boundaries (not accounting infinite flag).
switch (myShadowLight->Type())
{
case Graphic3d_TOLS_AMBIENT:
{
return false; // not applicable
}
case Graphic3d_TOLS_DIRECTIONAL:
{
Graphic3d_Vec4d aDir (myShadowLight->Direction().X(), myShadowLight->Direction().Y(), myShadowLight->Direction().Z(), 0.0);
if (myShadowLight->IsHeadlight())
{
Graphic3d_Mat4d anOrientInv;
theView.Camera()->OrientationMatrix().Inverted (anOrientInv);
aDir = anOrientInv * aDir;
}
myShadowCamera->SetProjectionType (Graphic3d_Camera::Projection_Orthographic);
myShadowCamera->SetDirection (gp_Dir (aDir.x(), aDir.y(), aDir.z()));
myShadowCamera->SetUp (!myShadowCamera->Direction().IsParallel (gp::DY(), Precision::Angular())
? gp::DY()
: gp::DX());
myShadowCamera->OrthogonalizeUp();
// Fitting entire scene to the light might produce a shadow map of too low resolution.
// More reliable approach would be putting a center to a current eye position and limiting maximum range,
// so that shadow range will be limited to some reasonable distance from current eye.
if (myShadowCamera->FitMinMax (aMinMaxBox, 10.0 * Precision::Confusion(), false))
{
myShadowCamera->SetScale (Max (myShadowCamera->ViewDimensions().X() * 1.1, myShadowCamera->ViewDimensions().Y() * 1.1)); // add margin
}
myShadowCamera->ZFitAll (1.0, aMinMaxBox, aGraphicBox);
myLightMatrix = myShadowCamera->ProjectionMatrixF() * myShadowCamera->OrientationMatrixF();
return true;
}
case Graphic3d_TOLS_POSITIONAL:
{
// render into cubemap shadowmap texture
return false; // not implemented
}
case Graphic3d_TOLS_SPOT:
{
//myShadowCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
//myShadowCamera->SetEye (theCastShadowLight->Position());
return false; // not implemented
}
}
return false;
}
// =======================================================================
// function : Release
// purpose :
// =======================================================================
void OpenGl_ShadowMapArray::Release (OpenGl_Context* theCtx)
{
for (Standard_Integer anIter = Lower(); anIter <= Upper(); ++anIter)
{
if (const Handle(OpenGl_ShadowMap)& aShadow = ChangeValue (anIter))
{
aShadow->Release (theCtx);
}
}
}
// =======================================================================
// function : EstimatedDataSize
// purpose :
// =======================================================================
Standard_Size OpenGl_ShadowMapArray::EstimatedDataSize() const
{
Standard_Size aSize = 0;
for (Standard_Integer anIter = Lower(); anIter <= Upper(); ++anIter)
{
if (const Handle(OpenGl_ShadowMap)& aShadow = Value (anIter))
{
aSize += aShadow->EstimatedDataSize();
}
}
return aSize;
}

View File

@ -0,0 +1,115 @@
// Copyright (c) 2021 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_ShadowMap_HeaderFile
#define _OpenGl_ShadowMap_HeaderFile
#include <Graphic3d_Mat4.hxx>
#include <NCollection_Array1.hxx>
#include <NCollection_Shared.hxx>
#include <OpenGl_NamedResource.hxx>
class Graphic3d_Camera;
class Graphic3d_CLight;
class Graphic3d_CView;
class OpenGl_FrameBuffer;
class OpenGl_Texture;
//! This class contains shadow mapping resources.
class OpenGl_ShadowMap : public OpenGl_NamedResource
{
DEFINE_STANDARD_RTTIEXT(OpenGl_ShadowMap, OpenGl_NamedResource)
public:
//! Empty constructor.
OpenGl_ShadowMap();
//! Releases all OpenGL resources.
Standard_EXPORT virtual void Release (OpenGl_Context* theCtx) Standard_OVERRIDE;
//! Returns estimated GPU memory usage for holding data without considering overheads and allocation alignment rules.
Standard_EXPORT virtual Standard_Size EstimatedDataSize() const Standard_OVERRIDE;
//! Destructor.
Standard_EXPORT virtual ~OpenGl_ShadowMap();
//! Return TRUE if defined.
Standard_EXPORT bool IsValid() const;
//! Return framebuffer.
const Handle(OpenGl_FrameBuffer)& FrameBuffer() const { return myShadowMapFbo; }
//! Return depth texture.
Standard_EXPORT const Handle(OpenGl_Texture)& Texture() const;
//! Return light source casting the shadow or NULL if undefined.
const Handle(Graphic3d_CLight)& LightSource() const { return myShadowLight; }
//! Set light source casting the shadow.
void SetLightSource (const Handle(Graphic3d_CLight)& theLight) { myShadowLight = theLight; }
//! Return rendering camera.
const Handle(Graphic3d_Camera)& Camera() const { return myShadowCamera; }
//! Return light source mapping matrix.
const Graphic3d_Mat4& LightSourceMatrix() const { return myLightMatrix; }
//! Set light source mapping matrix.
void SetLightSourceMatrix (const Graphic3d_Mat4& theMat) { myLightMatrix = theMat; }
//! Returns shadowmap bias.
Standard_ShortReal ShadowMapBias() const { return myShadowMapBias; }
//! Sets shadowmap bias.
void SetShadowMapBias (Standard_ShortReal theBias) { myShadowMapBias = theBias; }
//! Compute camera.
Standard_EXPORT bool UpdateCamera (const Graphic3d_CView& theView);
private:
Handle(OpenGl_FrameBuffer) myShadowMapFbo; //!< frame buffer for rendering shadow map
Handle(Graphic3d_CLight) myShadowLight; //!< light source to render shadow map
Handle(Graphic3d_Camera) myShadowCamera; //!< rendering camera
Graphic3d_Mat4 myLightMatrix; //!< light source matrix
Standard_ShortReal myShadowMapBias; //!< shadowmap bias
};
//! Array of shadow maps.
class OpenGl_ShadowMapArray : public Standard_Transient, public NCollection_Array1<Handle(OpenGl_ShadowMap)>
{
public:
//! Empty constructor.
OpenGl_ShadowMapArray() {}
//! Releases all OpenGL resources.
Standard_EXPORT void Release (OpenGl_Context* theCtx);
//! Return TRUE if defined.
bool IsValid() const
{
return !IsEmpty()
&& First()->IsValid();
}
//! Returns estimated GPU memory usage for holding data without considering overheads and allocation alignment rules.
Standard_EXPORT Standard_Size EstimatedDataSize() const;
public:
DEFINE_STANDARD_ALLOC
DEFINE_NCOLLECTION_ALLOC
};
#endif // _OpenGl_ShadowMap_HeaderFile

View File

@ -440,8 +440,12 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &theWorkspace) con
} }
#endif #endif
bool anOldCastShadows = false;
if (!myTrsfPers.IsNull()) if (!myTrsfPers.IsNull())
{ {
// temporarily disable shadows on non-3d objects
anOldCastShadows = aCtx->ShaderManager()->SetCastShadows (false);
aCtx->WorldViewState.Push(); aCtx->WorldViewState.Push();
OpenGl_Mat4& aWorldView = aCtx->WorldViewState.ChangeCurrent(); OpenGl_Mat4& aWorldView = aCtx->WorldViewState.ChangeCurrent();
myTrsfPers->Apply (aCtx->Camera(), myTrsfPers->Apply (aCtx->Camera(),
@ -608,6 +612,7 @@ void OpenGl_Structure::Render (const Handle(OpenGl_Workspace) &theWorkspace) con
if (!myTrsfPers.IsNull()) if (!myTrsfPers.IsNull())
{ {
aCtx->WorldViewState.Pop(); aCtx->WorldViewState.Pop();
aCtx->ShaderManager()->SetCastShadows (anOldCastShadows);
} }
// Restore named status // Restore named status

View File

@ -30,6 +30,7 @@
#include <OpenGl_GraduatedTrihedron.hxx> #include <OpenGl_GraduatedTrihedron.hxx>
#include <OpenGl_GraphicDriver.hxx> #include <OpenGl_GraphicDriver.hxx>
#include <OpenGl_ShaderManager.hxx> #include <OpenGl_ShaderManager.hxx>
#include <OpenGl_ShadowMap.hxx>
#include <OpenGl_Texture.hxx> #include <OpenGl_Texture.hxx>
#include <OpenGl_Window.hxx> #include <OpenGl_Window.hxx>
#include <OpenGl_Workspace.hxx> #include <OpenGl_Workspace.hxx>
@ -149,6 +150,7 @@ OpenGl_View::OpenGl_View (const Handle(Graphic3d_StructureManager)& theMgr,
myRaytraceFBO1[1] = new OpenGl_FrameBuffer(); myRaytraceFBO1[1] = new OpenGl_FrameBuffer();
myRaytraceFBO2[0] = new OpenGl_FrameBuffer(); myRaytraceFBO2[0] = new OpenGl_FrameBuffer();
myRaytraceFBO2[1] = new OpenGl_FrameBuffer(); myRaytraceFBO2[1] = new OpenGl_FrameBuffer();
myShadowMaps = new OpenGl_ShadowMapArray();
} }
// ======================================================================= // =======================================================================
@ -219,6 +221,7 @@ void OpenGl_View::releaseSrgbResources (const Handle(OpenGl_Context)& theCtx)
myOpenGlFBO2 ->Release (theCtx.get()); myOpenGlFBO2 ->Release (theCtx.get());
myFullScreenQuad .Release (theCtx.get()); myFullScreenQuad .Release (theCtx.get());
myFullScreenQuadFlip .Release (theCtx.get()); myFullScreenQuadFlip .Release (theCtx.get());
myShadowMaps->Release (theCtx.get());
// Technically we should also re-initialize all sRGB/RGB8 color textures. // Technically we should also re-initialize all sRGB/RGB8 color textures.
// But for now consider this sRGB disabling/enabling to be done at application start-up // But for now consider this sRGB disabling/enabling to be done at application start-up
@ -1302,6 +1305,53 @@ bool OpenGl_View::prepareFrameBuffers (Graphic3d_Camera::Projection& theProj)
myImmediateSceneFbosOit[1]->ChangeViewport (0, 0); myImmediateSceneFbosOit[1]->ChangeViewport (0, 0);
} }
// allocate shadow maps
const Handle(Graphic3d_LightSet)& aLights = myShadingModel == Graphic3d_TOSM_UNLIT ? myNoShadingLight : myLights;
if (!aLights.IsNull())
{
aLights->UpdateRevision();
}
bool toUseShadowMap = myRenderParams.IsShadowEnabled
&& myRenderParams.ShadowMapResolution > 0
&& !myLights.IsNull()
&& myLights->NbCastShadows() > 0
&& myRenderParams.Method != Graphic3d_RM_RAYTRACING;
if (toUseShadowMap)
{
if (myShadowMaps->Size() != myLights->NbCastShadows())
{
myShadowMaps->Release (aCtx.get());
myShadowMaps->Resize (0, myLights->NbCastShadows() - 1, true);
}
const GLint aSamplFrom = GLint(aCtx->ShadowMapTexUnit()) - myLights->NbCastShadows() + 1;
for (Standard_Integer aShadowIter = 0; aShadowIter < myShadowMaps->Size(); ++aShadowIter)
{
Handle(OpenGl_ShadowMap)& aShadow = myShadowMaps->ChangeValue (aShadowIter);
if (aShadow.IsNull())
{
aShadow = new OpenGl_ShadowMap();
}
aShadow->SetShadowMapBias (myRenderParams.ShadowMapBias);
aShadow->Texture()->Sampler()->Parameters()->SetTextureUnit ((Graphic3d_TextureUnit )(aSamplFrom + aShadowIter));
const Handle(OpenGl_FrameBuffer)& aShadowFbo = aShadow->FrameBuffer();
if (aShadowFbo->GetVPSizeX() != myRenderParams.ShadowMapResolution
&& toUseShadowMap)
{
OpenGl_ColorFormats aDummy;
if (!aShadowFbo->Init (aCtx, myRenderParams.ShadowMapResolution, myRenderParams.ShadowMapResolution, aDummy, myFboDepthFormat, 0))
{
toUseShadowMap = false;
}
}
}
}
if (!toUseShadowMap && myShadowMaps->IsValid())
{
myShadowMaps->Release (aCtx.get());
}
return true; return true;
} }
@ -1361,6 +1411,28 @@ void OpenGl_View::Redraw()
return; return;
} }
// draw shadow maps
if (myShadowMaps->IsValid())
{
Standard_Integer aShadowIndex = myShadowMaps->Lower();
for (Graphic3d_LightSet::Iterator aLightIter (myLights, Graphic3d_LightSet::IterationFilter_ActiveShadowCasters);
aLightIter.More(); aLightIter.Next())
{
const Handle(Graphic3d_CLight)& aLight = aLightIter.Value();
if (aLight->ToCastShadows())
{
const Handle(OpenGl_ShadowMap)& aShadowMap = myShadowMaps->ChangeValue (aShadowIndex);
aShadowMap->SetLightSource (aLight);
renderShadowMap (aShadowMap);
++aShadowIndex;
}
}
for (; aShadowIndex <= myShadowMaps->Upper(); ++aShadowIndex)
{
myShadowMaps->ChangeValue (aShadowIndex)->SetLightSource (Handle(Graphic3d_CLight)());
}
}
OpenGl_FrameBuffer* aFrameBuffer = myFBO.get(); OpenGl_FrameBuffer* aFrameBuffer = myFBO.get();
bool toSwap = aCtx->IsRender() bool toSwap = aCtx->IsRender()
&& !aCtx->caps->buffersNoSwap && !aCtx->caps->buffersNoSwap
@ -1807,7 +1879,7 @@ void OpenGl_View::redraw (const Graphic3d_Camera::Projection theProjection,
} }
// ======================================================================= // =======================================================================
// function : redrawMonoImmediate // function : redrawImmediate
// purpose : // purpose :
// ======================================================================= // =======================================================================
bool OpenGl_View::redrawImmediate (const Graphic3d_Camera::Projection theProjection, bool OpenGl_View::redrawImmediate (const Graphic3d_Camera::Projection theProjection,
@ -1882,6 +1954,60 @@ bool OpenGl_View::redrawImmediate (const Graphic3d_Camera::Projection theProject
return !toCopyBackToFront; return !toCopyBackToFront;
} }
//=======================================================================
//function : renderShadowMap
//purpose :
//=======================================================================
void OpenGl_View::renderShadowMap (const Handle(OpenGl_ShadowMap)& theShadowMap)
{
const Handle(OpenGl_Context)& aCtx = myWorkspace->GetGlContext();
if (!theShadowMap->UpdateCamera (*this))
{
return;
}
myBVHSelector.SetViewVolume (theShadowMap->Camera());
myBVHSelector.SetViewportSize (myWindow->Width(), myWindow->Height(), myRenderParams.ResolutionRatio());
myBVHSelector.CacheClipPtsProjections();
myLocalOrigin.SetCoord (0.0, 0.0, 0.0);
aCtx->SetCamera (theShadowMap->Camera());
aCtx->ProjectionState.SetCurrent (theShadowMap->Camera()->ProjectionMatrixF());
aCtx->ApplyProjectionMatrix();
aCtx->ShaderManager()->UpdateMaterialState();
aCtx->ShaderManager()->UpdateModelWorldStateTo (OpenGl_Mat4());
aCtx->ShaderManager()->SetShadingModel (Graphic3d_TOSM_UNLIT);
const Handle(OpenGl_FrameBuffer)& aShadowBuffer = theShadowMap->FrameBuffer();
aShadowBuffer->BindBuffer (aCtx);
aShadowBuffer->SetupViewport (aCtx);
aCtx->SetColorMask (false);
aCtx->SetAllowSampleAlphaToCoverage (false);
aCtx->SetSampleAlphaToCoverage (false);
myWorkspace->UseZBuffer() = true;
myWorkspace->UseDepthWrite() = true;
aCtx->core11fwd->glDepthFunc (GL_LEQUAL);
aCtx->core11fwd->glDepthMask (GL_TRUE);
aCtx->core11fwd->glEnable (GL_DEPTH_TEST);
aCtx->core11fwd->glClearDepth (1.0);
aCtx->core11fwd->glClear (GL_DEPTH_BUFFER_BIT);
renderScene (Graphic3d_Camera::Projection_Orthographic, aShadowBuffer.get(), NULL, false);
aCtx->SetColorMask (true);
myWorkspace->ResetAppliedAspect();
aCtx->BindProgram (Handle(OpenGl_ShaderProgram)());
//Image_AlienPixMap anImage; anImage.InitZero (Image_Format_Gray, aShadowBuffer->GetVPSizeX(), aShadowBuffer->GetVPSizeY());
//OpenGl_FrameBuffer::BufferDump (aCtx, aShadowBuffer, anImage, Graphic3d_BT_Depth);
//anImage.Save (TCollection_AsciiString ("shadow") + theShadowMap->Texture()->Sampler()->Parameters()->TextureUnit() + ".png");
bindDefaultFbo();
}
//======================================================================= //=======================================================================
//function : Render //function : Render
//purpose : //purpose :
@ -1929,7 +2055,7 @@ void OpenGl_View::render (Graphic3d_Camera::Projection theProjection,
|| aLightsRevision != myLightsRevision) || aLightsRevision != myLightsRevision)
{ {
myLightsRevision = aLightsRevision; myLightsRevision = aLightsRevision;
aManager->UpdateLightSourceStateTo (aLights, SpecIBLMapLevels()); aManager->UpdateLightSourceStateTo (aLights, SpecIBLMapLevels(), myShadowMaps->IsValid() ? myShadowMaps : Handle(OpenGl_ShadowMapArray)());
myLastLightSourceState = StateInfo (myCurrLightSourceState, aManager->LightSourceState().Index()); myLastLightSourceState = StateInfo (myCurrLightSourceState, aManager->LightSourceState().Index());
} }
@ -2017,8 +2143,31 @@ void OpenGl_View::render (Graphic3d_Camera::Projection theProjection,
myWorkspace->SetEnvironmentTexture (myTextureEnv); myWorkspace->SetEnvironmentTexture (myTextureEnv);
const bool hasShadowMap = aContext->ShaderManager()->LightSourceState().HasShadowMaps();
if (hasShadowMap)
{
for (Standard_Integer aShadowIter = myShadowMaps->Lower(); aShadowIter <= myShadowMaps->Upper(); ++aShadowIter)
{
const Handle(OpenGl_ShadowMap)& aShadow = myShadowMaps->Value (aShadowIter);
aShadow->Texture()->Bind (aContext);
}
}
renderScene (theProjection, theOutputFBO, theOitAccumFbo, theToDrawImmediate); renderScene (theProjection, theOutputFBO, theOitAccumFbo, theToDrawImmediate);
if (hasShadowMap)
{
for (Standard_Integer aShadowIter = myShadowMaps->Lower(); aShadowIter <= myShadowMaps->Upper(); ++aShadowIter)
{
const Handle(OpenGl_ShadowMap)& aShadow = myShadowMaps->Value (aShadowIter);
aShadow->Texture()->Unbind (aContext);
}
if (aContext->core15fwd != NULL)
{
aContext->core15fwd->glActiveTexture (GL_TEXTURE0);
}
}
myWorkspace->SetEnvironmentTexture (Handle(OpenGl_TextureSet)()); myWorkspace->SetEnvironmentTexture (Handle(OpenGl_TextureSet)());
// =============================== // ===============================

View File

@ -59,9 +59,12 @@ class Graphic3d_StructureManager;
class OpenGl_GraphicDriver; class OpenGl_GraphicDriver;
class OpenGl_PBREnvironment; class OpenGl_PBREnvironment;
class OpenGl_StateCounter; class OpenGl_StateCounter;
class OpenGl_ShadowMap;
class OpenGl_ShadowMapArray;
class OpenGl_TriangleSet; class OpenGl_TriangleSet;
class OpenGl_Workspace; class OpenGl_Workspace;
class OpenGl_View; class OpenGl_View;
DEFINE_STANDARD_HANDLE(OpenGl_View,Graphic3d_CView) DEFINE_STANDARD_HANDLE(OpenGl_View,Graphic3d_CView)
//! Implementation of OpenGl view. //! Implementation of OpenGl view.
@ -390,6 +393,10 @@ protected: //! @name low-level redrawing sub-routines
protected: //! @name Rendering of GL graphics (with prepared drawing buffer). protected: //! @name Rendering of GL graphics (with prepared drawing buffer).
//! Renders the graphical contents of the view into the preprepared shadowmap framebuffer.
//! @param theShadowMap [in] the framebuffer for rendering shadowmap.
Standard_EXPORT virtual void renderShadowMap (const Handle(OpenGl_ShadowMap)& theShadowMap);
//! Renders the graphical contents of the view into the preprepared window or framebuffer. //! Renders the graphical contents of the view into the preprepared window or framebuffer.
//! @param theProjection [in] the projection that should be used for rendering. //! @param theProjection [in] the projection that should be used for rendering.
//! @param theReadDrawFbo [in] the framebuffer for rendering graphics. //! @param theReadDrawFbo [in] the framebuffer for rendering graphics.
@ -527,6 +534,7 @@ protected: //! @name Rendering properties
Handle(OpenGl_FrameBuffer) myImmediateSceneFbos[2]; //!< Additional buffers for immediate layer in stereo mode. Handle(OpenGl_FrameBuffer) myImmediateSceneFbos[2]; //!< Additional buffers for immediate layer in stereo mode.
Handle(OpenGl_FrameBuffer) myImmediateSceneFbosOit[2]; //!< Additional buffers for transparency draw of immediate layer. Handle(OpenGl_FrameBuffer) myImmediateSceneFbosOit[2]; //!< Additional buffers for transparency draw of immediate layer.
Handle(OpenGl_FrameBuffer) myXrSceneFbo; //!< additional FBO (without MSAA) for submitting to XR Handle(OpenGl_FrameBuffer) myXrSceneFbo; //!< additional FBO (without MSAA) for submitting to XR
Handle(OpenGl_ShadowMapArray) myShadowMaps; //!< additional FBOs for shadow map rendering
OpenGl_VertexBuffer myFullScreenQuad; //!< Vertices for full-screen quad rendering. OpenGl_VertexBuffer myFullScreenQuad; //!< Vertices for full-screen quad rendering.
OpenGl_VertexBuffer myFullScreenQuadFlip; OpenGl_VertexBuffer myFullScreenQuadFlip;
Standard_Boolean myToFlipOutput; //!< Flag to draw result image upside-down Standard_Boolean myToFlipOutput; //!< Flag to draw result image upside-down

View File

@ -0,0 +1,27 @@
//! Coefficients for gathering close samples.
const vec2 occPoissonDisk16[16] = vec2[](
vec2(-0.94201624,-0.39906216), vec2( 0.94558609,-0.76890725), vec2(-0.09418410,-0.92938870), vec2( 0.34495938, 0.29387760),
vec2(-0.91588581, 0.45771432), vec2(-0.81544232,-0.87912464), vec2(-0.38277543, 0.27676845), vec2( 0.97484398, 0.75648379),
vec2( 0.44323325,-0.97511554), vec2( 0.53742981,-0.47373420), vec2(-0.26496911,-0.41893023), vec2( 0.79197514, 0.19090188),
vec2(-0.24188840, 0.99706507), vec2(-0.81409955, 0.91437590), vec2( 0.19984126, 0.78641367), vec2( 0.14383161,-0.14100790)
);
//! Function computes directional light shadow attenuation (1.0 means no shadow).
float occDirectionalLightShadow (in int theId,
in vec3 theNormal)
{
vec4 aPosLightSpace = PosLightSpace[theId];
vec3 aLightDir = vec3 (occWorldViewMatrix * vec4 (occLight_Position (theId), 0.0));
vec3 aProjCoords = (aPosLightSpace.xyz / aPosLightSpace.w) * 0.5 + vec3 (0.5);
float aCurrentDepth = aProjCoords.z;
if (abs(aProjCoords.x) > 1.0 || abs(aProjCoords.y) > 1.0 || aCurrentDepth > 1.0) { return 1.0; }
vec2 aTexelSize = vec2 (occShadowMapSizeBias.x);
float aBias = max (occShadowMapSizeBias.y * (1.0 - dot (theNormal, aLightDir)), occShadowMapSizeBias.y * 0.1);
float aShadow = 0.0;
for (int aPosIter = 0; aPosIter < 16; ++aPosIter)
{
float aClosestDepth = occTexture2D (occShadowMapSamplers[theId], aProjCoords.xy + occPoissonDisk16[aPosIter] * aTexelSize).r;
aShadow += (aCurrentDepth - aBias) > aClosestDepth ? 1.0 : 0.0;
}
return 1.0 - aShadow / 16.0;
}

View File

@ -1,5 +1,6 @@
srcinc:::Declarations.glsl srcinc:::Declarations.glsl
srcinc:::DeclarationsImpl.glsl srcinc:::DeclarationsImpl.glsl
srcinc:::DirectionalLightShadow.glsl
srcinc:::PBRCookTorrance.glsl srcinc:::PBRCookTorrance.glsl
srcinc:::PBRDistribution.glsl srcinc:::PBRDistribution.glsl
srcinc:::PBREnvBaking.fs srcinc:::PBREnvBaking.fs
@ -19,6 +20,7 @@ srcinc:::RaytraceSmooth.fs
srcinc:::TangentSpaceNormal.glsl srcinc:::TangentSpaceNormal.glsl
Shaders_Declarations_glsl.pxx Shaders_Declarations_glsl.pxx
Shaders_DeclarationsImpl_glsl.pxx Shaders_DeclarationsImpl_glsl.pxx
Shaders_DirectionalLightShadow_glsl.pxx
Shaders_Display_fs.pxx Shaders_Display_fs.pxx
Shaders_PBRCookTorrance_glsl.pxx Shaders_PBRCookTorrance_glsl.pxx
Shaders_PBRDistribution_glsl.pxx Shaders_PBRDistribution_glsl.pxx

View File

@ -0,0 +1,30 @@
// This file has been automatically generated from resource file src/Shaders/DirectionalLightShadow.glsl
static const char Shaders_DirectionalLightShadow_glsl[] =
"//! Coefficients for gathering close samples.\n"
"const vec2 occPoissonDisk16[16] = vec2[](\n"
" vec2(-0.94201624,-0.39906216), vec2( 0.94558609,-0.76890725), vec2(-0.09418410,-0.92938870), vec2( 0.34495938, 0.29387760),\n"
" vec2(-0.91588581, 0.45771432), vec2(-0.81544232,-0.87912464), vec2(-0.38277543, 0.27676845), vec2( 0.97484398, 0.75648379),\n"
" vec2( 0.44323325,-0.97511554), vec2( 0.53742981,-0.47373420), vec2(-0.26496911,-0.41893023), vec2( 0.79197514, 0.19090188),\n"
" vec2(-0.24188840, 0.99706507), vec2(-0.81409955, 0.91437590), vec2( 0.19984126, 0.78641367), vec2( 0.14383161,-0.14100790)\n"
");\n"
"\n"
"//! Function computes directional light shadow attenuation (1.0 means no shadow).\n"
"float occDirectionalLightShadow (in int theId,\n"
" in vec3 theNormal)\n"
"{\n"
" vec4 aPosLightSpace = PosLightSpace[theId];\n"
" vec3 aLightDir = vec3 (occWorldViewMatrix * vec4 (occLight_Position (theId), 0.0));\n"
" vec3 aProjCoords = (aPosLightSpace.xyz / aPosLightSpace.w) * 0.5 + vec3 (0.5);\n"
" float aCurrentDepth = aProjCoords.z;\n"
" if (abs(aProjCoords.x) > 1.0 || abs(aProjCoords.y) > 1.0 || aCurrentDepth > 1.0) { return 1.0; }\n"
" vec2 aTexelSize = vec2 (occShadowMapSizeBias.x);\n"
" float aBias = max (occShadowMapSizeBias.y * (1.0 - dot (theNormal, aLightDir)), occShadowMapSizeBias.y * 0.1);\n"
" float aShadow = 0.0;\n"
" for (int aPosIter = 0; aPosIter < 16; ++aPosIter)\n"
" {\n"
" float aClosestDepth = occTexture2D (occShadowMapSamplers[theId], aProjCoords.xy + occPoissonDisk16[aPosIter] * aTexelSize).r;\n"
" aShadow += (aCurrentDepth - aBias) > aClosestDepth ? 1.0 : 0.0;\n"
" }\n"
" return 1.0 - aShadow / 16.0;\n"
"}\n";

View File

@ -10771,6 +10771,7 @@ static int VLight (Draw_Interpretor& theDi,
theDi << " Type: Directional\n"; theDi << " Type: Directional\n";
theDi << " Intensity: " << aLight->Intensity() << "\n"; theDi << " Intensity: " << aLight->Intensity() << "\n";
theDi << " Headlight: " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n"; theDi << " Headlight: " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
theDi << " CastShadows:" << (aLight->ToCastShadows() ? "TRUE" : "FALSE") << "\n";
theDi << " Smoothness: " << aLight->Smoothness() << "\n"; theDi << " Smoothness: " << aLight->Smoothness() << "\n";
aLight->Direction (anXYZ[0], anXYZ[1], anXYZ[2]); aLight->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
theDi << " Direction: " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n"; theDi << " Direction: " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
@ -10781,6 +10782,7 @@ static int VLight (Draw_Interpretor& theDi,
theDi << " Type: Positional\n"; theDi << " Type: Positional\n";
theDi << " Intensity: " << aLight->Intensity() << "\n"; theDi << " Intensity: " << aLight->Intensity() << "\n";
theDi << " Headlight: " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n"; theDi << " Headlight: " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
theDi << " CastShadows:" << (aLight->ToCastShadows() ? "TRUE" : "FALSE") << "\n";
theDi << " Smoothness: " << aLight->Smoothness() << "\n"; theDi << " Smoothness: " << aLight->Smoothness() << "\n";
aLight->Position (anXYZ[0], anXYZ[1], anXYZ[2]); aLight->Position (anXYZ[0], anXYZ[1], anXYZ[2]);
theDi << " Position: " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n"; theDi << " Position: " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
@ -10794,6 +10796,7 @@ static int VLight (Draw_Interpretor& theDi,
theDi << " Type: Spot\n"; theDi << " Type: Spot\n";
theDi << " Intensity: " << aLight->Intensity() << "\n"; theDi << " Intensity: " << aLight->Intensity() << "\n";
theDi << " Headlight: " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n"; theDi << " Headlight: " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
theDi << " CastShadows:" << (aLight->ToCastShadows() ? "TRUE" : "FALSE") << "\n";
aLight->Position (anXYZ[0], anXYZ[1], anXYZ[2]); aLight->Position (anXYZ[0], anXYZ[1], anXYZ[2]);
theDi << " Position: " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n"; theDi << " Position: " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
aLight->Direction (anXYZ[0], anXYZ[1], anXYZ[2]); aLight->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
@ -11295,6 +11298,25 @@ static int VLight (Draw_Interpretor& theDi,
} }
aLightCurr->SetHeadlight (isHeadLight); aLightCurr->SetHeadlight (isHeadLight);
} }
else if (anArgCase.IsEqual ("-CASTSHADOW")
|| anArgCase.IsEqual ("-CASTSHADOWS")
|| anArgCase.IsEqual ("-SHADOWS"))
{
if (aLightCurr.IsNull()
|| aLightCurr->Type() == Graphic3d_TOLS_AMBIENT)
{
Message::SendFail() << "Syntax error at argument '" << anArg << "'";
return 1;
}
bool toCastShadows = true;
if (anArgIt + 1 < theArgsNb
&& Draw::ParseOnOff (theArgVec[anArgIt + 1], toCastShadows))
{
++anArgIt;
}
aLightCurr->SetCastShadows (toCastShadows);
}
else else
{ {
Message::SendFail() << "Warning: unknown argument '" << anArg << "'"; Message::SendFail() << "Warning: unknown argument '" << anArg << "'";
@ -11541,6 +11563,8 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
theDI << "rayDepth: " << aParams.RaytracingDepth << "\n"; theDI << "rayDepth: " << aParams.RaytracingDepth << "\n";
theDI << "fsaa: " << (aParams.IsAntialiasingEnabled ? "on" : "off") << "\n"; theDI << "fsaa: " << (aParams.IsAntialiasingEnabled ? "on" : "off") << "\n";
theDI << "shadows: " << (aParams.IsShadowEnabled ? "on" : "off") << "\n"; theDI << "shadows: " << (aParams.IsShadowEnabled ? "on" : "off") << "\n";
theDI << "shadowMapRes: " << aParams.ShadowMapResolution << "\n";
theDI << "shadowMapBias: " << aParams.ShadowMapBias << "\n";
theDI << "reflections: " << (aParams.IsReflectionEnabled ? "on" : "off") << "\n"; theDI << "reflections: " << (aParams.IsReflectionEnabled ? "on" : "off") << "\n";
theDI << "gleam: " << (aParams.IsTransparentShadowEnabled ? "on" : "off") << "\n"; theDI << "gleam: " << (aParams.IsTransparentShadowEnabled ? "on" : "off") << "\n";
theDI << "GI: " << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << "\n"; theDI << "GI: " << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << "\n";
@ -11912,6 +11936,37 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
} }
aParams.IsShadowEnabled = toEnable; aParams.IsShadowEnabled = toEnable;
} }
else if (aFlag == "-shadowmapresolution"
|| aFlag == "-shadowmap")
{
if (toPrint)
{
theDI << aParams.ShadowMapResolution << " ";
continue;
}
else if (++anArgIter >= theArgNb)
{
Message::SendFail() << "Syntax error at argument '" << anArg << "'";
return 1;
}
aParams.ShadowMapResolution = Draw::Atoi (theArgVec[anArgIter]);
}
else if (aFlag == "-shadowmapbias")
{
if (toPrint)
{
theDI << aParams.ShadowMapBias << " ";
continue;
}
else if (++anArgIter >= theArgNb)
{
Message::SendFail() << "Syntax error at argument '" << anArg << "'";
return 1;
}
aParams.ShadowMapBias = (float )Draw::Atof (theArgVec[anArgIter]);
}
else if (aFlag == "-refl" else if (aFlag == "-refl"
|| aFlag == "-reflections") || aFlag == "-reflections")
{ {
@ -14824,6 +14879,7 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
"\n -{dir}ection X Y Z (for directional light or for spotlight)" "\n -{dir}ection X Y Z (for directional light or for spotlight)"
"\n -color colorName" "\n -color colorName"
"\n -{head}light 0|1" "\n -{head}light 0|1"
"\n -castShadows 0|1"
"\n -{sm}oothness value" "\n -{sm}oothness value"
"\n -{int}ensity value" "\n -{int}ensity value"
"\n -{constAtten}uation value" "\n -{constAtten}uation value"
@ -14854,6 +14910,7 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
"\n\t\t: vrenderparams [-raster] [-shadingModel {unlit|facet|gouraud|phong|pbr|pbr_facet}=gouraud]" "\n\t\t: vrenderparams [-raster] [-shadingModel {unlit|facet|gouraud|phong|pbr|pbr_facet}=gouraud]"
"\n\t\t: [-msaa 0..8=0] [-rendScale scale=1] [-resolution value=72]" "\n\t\t: [-msaa 0..8=0] [-rendScale scale=1] [-resolution value=72]"
"\n\t\t: [-oit {off|0.0-1.0}=off]" "\n\t\t: [-oit {off|0.0-1.0}=off]"
"\n\t\t: [-shadows {on|off}=on] [-shadowMapResolution value=1024] [-shadowMapBias value=0.005]"
"\n\t\t: [-depthPrePass {on|off}=off] [-alphaToCoverage {on|off}=on]" "\n\t\t: [-depthPrePass {on|off}=off] [-alphaToCoverage {on|off}=on]"
"\n\t\t: [-frustumCulling {on|off|noupdate}=on] [-lineFeather width=1.0]" "\n\t\t: [-frustumCulling {on|off|noupdate}=on] [-lineFeather width=1.0]"
"\n\t\t: [-sync {default|views}] [-reset]" "\n\t\t: [-sync {default|views}] [-reset]"
@ -14867,6 +14924,9 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
"\n\t\t: -oit Enables/disables order-independent transparency (OIT) rendering;" "\n\t\t: -oit Enables/disables order-independent transparency (OIT) rendering;"
"\n\t\t: weight OIT fixes transparency artifacts at the cost of blurry result," "\n\t\t: weight OIT fixes transparency artifacts at the cost of blurry result,"
"\n\t\t: it is managed by depth weight factor (0.0 value also enables weight OIT)." "\n\t\t: it is managed by depth weight factor (0.0 value also enables weight OIT)."
"\n\t\t: -shadows Enables/disables shadows rendering."
"\n\t\t: -shadowMapResolution Shadow texture map resolution."
"\n\t\t: -shadowMapBias Shadow map bias."
"\n\t\t: -depthPrePass Enables/disables depth pre-pass." "\n\t\t: -depthPrePass Enables/disables depth pre-pass."
"\n\t\t: -frustumCulling Enables/disables objects frustum clipping or" "\n\t\t: -frustumCulling Enables/disables objects frustum clipping or"
"\n\t\t: sets state to check structures culled previously." "\n\t\t: sets state to check structures culled previously."
@ -14881,7 +14941,7 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
"\n\t\t: -perfChart Show frame timers chart limited by specified number of frames." "\n\t\t: -perfChart Show frame timers chart limited by specified number of frames."
"\n\t\t: -perfChartMax Maximum time in seconds with the chart." "\n\t\t: -perfChartMax Maximum time in seconds with the chart."
"\n\t\t: Ray-Tracing options:" "\n\t\t: Ray-Tracing options:"
"\n\t\t: vrenderparams [-rayTrace] [-rayDepth {0..10}=3] [-shadows {on|off}=on] [-reflections {on|off}=off]" "\n\t\t: vrenderparams [-rayTrace] [-rayDepth {0..10}=3] [-reflections {on|off}=off]"
"\n\t\t: [-fsaa {on|off}=off] [-gleam {on|off}=off] [-env {on|off}=off]" "\n\t\t: [-fsaa {on|off}=off] [-gleam {on|off}=off] [-env {on|off}=off]"
"\n\t\t: [-gi {on|off}=off] [-brng {on|off}=off]" "\n\t\t: [-gi {on|off}=off] [-brng {on|off}=off]"
"\n\t\t: [-iss {on|off}=off] [-tileSize {1..4096}=32] [-nbTiles {64..1024}=256]" "\n\t\t: [-iss {on|off}=off] [-tileSize {1..4096}=32] [-nbTiles {64..1024}=256]"
@ -14891,7 +14951,6 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
"\n\t\t: [-exposure value=0.0] [-whitePoint value=1.0] [-toneMapping {disabled|filmic}=disabled]" "\n\t\t: [-exposure value=0.0] [-whitePoint value=1.0] [-toneMapping {disabled|filmic}=disabled]"
"\n\t\t: -rayTrace Enables GPU ray-tracing." "\n\t\t: -rayTrace Enables GPU ray-tracing."
"\n\t\t: -rayDepth Defines maximum ray-tracing depth." "\n\t\t: -rayDepth Defines maximum ray-tracing depth."
"\n\t\t: -shadows Enables/disables shadows rendering."
"\n\t\t: -reflections Enables/disables specular reflections." "\n\t\t: -reflections Enables/disables specular reflections."
"\n\t\t: -fsaa Enables/disables adaptive anti-aliasing." "\n\t\t: -fsaa Enables/disables adaptive anti-aliasing."
"\n\t\t: -gleam Enables/disables transparency shadow effects." "\n\t\t: -gleam Enables/disables transparency shadow effects."

View File

@ -22,3 +22,4 @@
023 viewcube 023 viewcube
024 colors 024 colors
025 quadric 025 quadric
026 shadows

30
tests/v3d/shadows/buggy Normal file
View File

@ -0,0 +1,30 @@
puts "========"
puts "0032039: Visualization, TKOpenGl - implement simple shadow mapping for a direct light source"
puts "Test shadow map from single directional light source on a buggy."
puts "========"
pload MODELING VISUALIZATION XDE OCAF
if { $::tcl_platform(os) == "Darwin" } { vcaps -core }
catch {Close D}
ReadGltf D [locate_data_file bug30691_Buggy.glb]
vclear
vinit View1
vzbufftrihedron
XDisplay -dispMode 1 D
vfit
vzoom 0.75
box bb -500000 -500000 -10875 1000000 1000000 0 -preview
vdisplay -dispMode 1 bb
vaspects bb -material STONE
vlight -change 0 -head 0 -dir -1 -1 -1 -castShadows 1
vraytrace 1
vdump $::imagedir/${::casename}_raytrace.png
vraytrace 0
vrenderparams -shadingModel phong
vrenderparams -shadowMapResolution 2048
vdump $::imagedir/${::casename}_phong.png
vrenderparams -shadingModel pbr
vdump $::imagedir/${::casename}_pbr.png

30
tests/v3d/shadows/dir1 Normal file
View File

@ -0,0 +1,30 @@
puts "========"
puts "0032039: Visualization, TKOpenGl - implement simple shadow mapping for a direct light source"
puts "Test shadow map from a single directional light source on a box geometry."
puts "========"
pload MODELING VISUALIZATION
if { $::tcl_platform(os) == "Darwin" } { vcaps -core }
box b 1 2 3
box bb -5 -5 0 10 10 0 -preview
vgldebug 1
vcaps -core
vcaps -vsync 0
vclear
vinit View1
vrenderparams -shadingModel PHONG
vdisplay -dispMode 1 b bb
vaspects bb -material STONE
vfit
vlight -change 0 -castShadows 1 -direction 1 1 -1 -head 0
vraytrace 1
vdump $::imagedir/${::casename}_raytrace.png
vraytrace 0
vrenderparams -shadingModel phong
vrenderparams -shadowMapBias 0.01
vdump $::imagedir/${::casename}_phong.png
vrenderparams -shadingModel pbr
vdump $::imagedir/${::casename}_pbr.png

34
tests/v3d/shadows/dir2 Normal file
View File

@ -0,0 +1,34 @@
puts "========"
puts "0032039: Visualization, TKOpenGl - implement simple shadow mapping for a direct light source"
puts "Test shadow map from two directional light sources on a box geometry."
puts "========"
pload MODELING VISUALIZATION
if { $::tcl_platform(os) == "Darwin" } { vcaps -core }
box b 1 2 3
box bb -5 -5 0 10 10 0 -preview
vgldebug 1
vcaps -core
vcaps -vsync 0
vclear
vinit View1
vrenderparams -shadingModel PHONG
vdisplay -dispMode 1 b bb
vaspects bb -material STONE
vfit
vlight -clear
vlight -add AMBIENT
vlight -add DIRECTIONAL -direction 0.2 0.2 -1 -head 0 -castShadows 1 -color RED
vlight -add DIRECTIONAL -direction -0.2 -0.2 -1 -head 0 -castShadows 1 -color GREEN
vraytrace 1
vdump $::imagedir/${::casename}_raytrace.png
vraytrace 0
vrenderparams -shadingModel phong
vrenderparams -shadowMapBias 0.01
vdump $::imagedir/${::casename}_phong.png
vrenderparams -shadingModel pbr
vdump $::imagedir/${::casename}_pbr.png

31
tests/v3d/shadows/dirhead Normal file
View File

@ -0,0 +1,31 @@
puts "========"
puts "0032039: Visualization, TKOpenGl - implement simple shadow mapping for a direct light source"
puts "Test shadow map from a single directional light source with headlight flag."
puts "========"
pload MODELING VISUALIZATION
if { $::tcl_platform(os) == "Darwin" } { vcaps -core }
box b 1 2 3
box bb -5 -5 0 10 10 0 -preview
vgldebug 1
vcaps -core
vcaps -vsync 0
vclear
vinit View1
vcamera -persp
vrenderparams -shadingModel PHONG
vdisplay -dispMode 1 b bb
vaspects bb -material STONE
vfit
vlight -change 0 -castShadows 1 -direction -0.2 0.2 -1 -head 1
vraytrace 1
vdump $::imagedir/${::casename}_raytrace.png
vraytrace 0
vrenderparams -shadingModel phong
vrenderparams -shadowMapBias 0.01
vdump $::imagedir/${::casename}_phong.png
vrenderparams -shadingModel pbr
vdump $::imagedir/${::casename}_pbr.png