From 48f8f1e6ea9662512c1c049e1d8a14c64b90527a Mon Sep 17 00:00:00 2001 From: drochalo Date: Mon, 5 Feb 2024 15:11:09 +0000 Subject: [PATCH] 0032173: Visualization, TKOpenGl - implement simple shadow mapping for a point light source Modified shadowmap calculations to include multipass for point lights. Added shader funtions to calculate point light shadows. Added getter for default znear and zfar values in Graphic3d_Camera. Added direction and up vector calulations on Graphic3d_CubeMap. Added logical exception for opengles2.0 lack of support on some key features of cube shadow maps. Added test case. --- src/Graphic3d/Graphic3d_CLight.cxx | 3 +- src/Graphic3d/Graphic3d_Camera.cxx | 18 +++ src/Graphic3d/Graphic3d_Camera.hxx | 6 + src/Graphic3d/Graphic3d_CubeMap.cxx | 86 +++++++++++++ src/Graphic3d/Graphic3d_CubeMap.hxx | 7 ++ src/Graphic3d/Graphic3d_LightSet.cxx | 29 +++++ src/Graphic3d/Graphic3d_LightSet.hxx | 3 + src/Graphic3d/Graphic3d_ShaderManager.cxx | 72 ++++++++--- src/Graphic3d/Graphic3d_ShaderManager.hxx | 12 +- src/Graphic3d/Graphic3d_ShaderProgram.cxx | 1 + src/Graphic3d/Graphic3d_ShaderProgram.hxx | 39 +++--- src/Graphic3d/Graphic3d_TextureUnit.hxx | 4 + src/OpenGl/OpenGl_Context.cxx | 3 + src/OpenGl/OpenGl_Context.hxx | 4 + src/OpenGl/OpenGl_FrameBuffer.cxx | 101 +++++++++++++-- src/OpenGl/OpenGl_FrameBuffer.hxx | 11 +- src/OpenGl/OpenGl_ShaderManager.cxx | 23 ++-- src/OpenGl/OpenGl_ShaderProgram.cxx | 90 ++++++++------ src/OpenGl/OpenGl_ShaderProgram.hxx | 37 +++--- src/OpenGl/OpenGl_ShadowMap.cxx | 17 ++- src/OpenGl/OpenGl_ShadowMap.hxx | 4 +- src/OpenGl/OpenGl_Texture.cxx | 46 ++++++- src/OpenGl/OpenGl_View.cxx | 116 ++++++++++++++---- src/OpenGl/OpenGl_View.hxx | 4 +- src/Shaders/Declarations.glsl | 4 + src/Shaders/FILES | 2 + src/Shaders/LightPointShadow.glsl | 24 ++++ src/Shaders/PBRPointLight.glsl | 5 +- src/Shaders/PhongPointLight.glsl | 7 +- src/Shaders/Shaders_Declarations_glsl.pxx | 4 + src/Shaders/Shaders_LightPointShadow_glsl.pxx | 27 ++++ src/Shaders/Shaders_PBRPointLight_glsl.pxx | 5 +- src/Shaders/Shaders_PhongPointLight_glsl.pxx | 7 +- tests/opengl/data/shadows/pointlight | 58 +++++++++ 34 files changed, 726 insertions(+), 153 deletions(-) create mode 100644 src/Shaders/LightPointShadow.glsl create mode 100644 src/Shaders/Shaders_LightPointShadow_glsl.pxx create mode 100644 tests/opengl/data/shadows/pointlight diff --git a/src/Graphic3d/Graphic3d_CLight.cxx b/src/Graphic3d/Graphic3d_CLight.cxx index 8283af632d..ead85cb621 100644 --- a/src/Graphic3d/Graphic3d_CLight.cxx +++ b/src/Graphic3d/Graphic3d_CLight.cxx @@ -150,7 +150,8 @@ void Graphic3d_CLight::SetEnabled (Standard_Boolean theIsOn) void Graphic3d_CLight::SetCastShadows (Standard_Boolean theToCast) { if (myType != Graphic3d_TypeOfLightSource_Directional - && myType != Graphic3d_TypeOfLightSource_Spot) + && myType != Graphic3d_TypeOfLightSource_Spot + && myType != Graphic3d_TypeOfLightSource_Positional) { throw Standard_NotImplemented ("Graphic3d_CLight::SetCastShadows() is not implemented for this light type"); } diff --git a/src/Graphic3d/Graphic3d_Camera.cxx b/src/Graphic3d/Graphic3d_Camera.cxx index ee7204fe8e..8ff6dd4704 100644 --- a/src/Graphic3d/Graphic3d_Camera.cxx +++ b/src/Graphic3d/Graphic3d_Camera.cxx @@ -200,6 +200,24 @@ void Graphic3d_Camera::Copy (const Handle(Graphic3d_Camera)& theOther) CopyOrientationData (theOther); } +// ======================================================================= +// function : GetDefaultZNear +// purpose : +// ======================================================================= +Standard_Real Graphic3d_Camera::GetDefaultZNear() +{ + return DEFAULT_ZNEAR; +} + +// ======================================================================= +// function : GetDefaultZFar +// purpose : +// ======================================================================= +Standard_Real Graphic3d_Camera::GetDefaultZFar() +{ + return DEFAULT_ZFAR; +} + // ======================================================================= // function : SetIdentityOrientation // purpose : diff --git a/src/Graphic3d/Graphic3d_Camera.hxx b/src/Graphic3d/Graphic3d_Camera.hxx index aeebc7cbf6..a44fe69d77 100644 --- a/src/Graphic3d/Graphic3d_Camera.hxx +++ b/src/Graphic3d/Graphic3d_Camera.hxx @@ -202,6 +202,12 @@ public: //! @name Public camera properties public: + //! return default valut for znear. + Standard_EXPORT Standard_Real GetDefaultZNear(); + + //! return default valut for zfar. + Standard_EXPORT Standard_Real GetDefaultZFar(); + //! Get camera look direction. //! @return camera look direction. const gp_Dir& Direction() const { return myDirection; } diff --git a/src/Graphic3d/Graphic3d_CubeMap.cxx b/src/Graphic3d/Graphic3d_CubeMap.cxx index 4d2abb1b84..4f8b40d929 100644 --- a/src/Graphic3d/Graphic3d_CubeMap.cxx +++ b/src/Graphic3d/Graphic3d_CubeMap.cxx @@ -52,3 +52,89 @@ Graphic3d_CubeMap::~Graphic3d_CubeMap() { // } + +// ======================================================================= +// function : GetCubeDirection +// purpose : +// ======================================================================= +gp_Dir Graphic3d_CubeMap::GetCubeDirection (Graphic3d_CubeMapSide theFace) +{ + gp_Dir aResult; + switch (theFace) + { + case (Graphic3d_CMS_POS_X): + { + aResult = gp_Dir(1.0, 0.0, 0.0); + } + break; + case (Graphic3d_CMS_NEG_X): + { + aResult = gp_Dir(-1.0, 0.0, 0.0); + } + break; + case (Graphic3d_CMS_POS_Y): + { + aResult = gp_Dir(0.0, 1.0, 0.0); + } + break; + case (Graphic3d_CMS_NEG_Y): + { + aResult = gp_Dir(0.0, -1.0, 0.0); + } + break; + case (Graphic3d_CMS_POS_Z): + { + aResult = gp_Dir(0.0, 0.0, 1.0); + } + break; + case (Graphic3d_CMS_NEG_Z): + { + aResult = gp_Dir(0.0, 0.0, -1.0); + } + break; + } + return aResult; +} + +// ======================================================================= +// function : GetCubeUp +// purpose : +// ======================================================================= +gp_Dir Graphic3d_CubeMap::GetCubeUp (Graphic3d_CubeMapSide theFace) +{ + gp_Dir aResult; + switch (theFace) + { + case (Graphic3d_CMS_POS_X): + { + aResult = -gp_Dir(0.0, -1.0, 0.0); + } + break; + case (Graphic3d_CMS_NEG_X): + { + aResult = -gp_Dir(0.0, -1.0, 0.0); + } + break; + case (Graphic3d_CMS_POS_Y): + { + aResult = gp_Dir(0.0, 0.0, 1.0); + } + break; + case (Graphic3d_CMS_NEG_Y): + { + aResult = gp_Dir(0.0, 0.0, -1.0); + } + break; + case (Graphic3d_CMS_POS_Z): + { + aResult = gp_Dir(0.0, -1.0, 0.0); + } + break; + case (Graphic3d_CMS_NEG_Z): + { + aResult = gp_Dir(0.0, -1.0, 0.0); + } + break; + } + return aResult; +} diff --git a/src/Graphic3d/Graphic3d_CubeMap.hxx b/src/Graphic3d/Graphic3d_CubeMap.hxx index 0566c97c84..d2f1b83b67 100644 --- a/src/Graphic3d/Graphic3d_CubeMap.hxx +++ b/src/Graphic3d/Graphic3d_CubeMap.hxx @@ -15,6 +15,7 @@ #ifndef _Graphic3d_CubeMap_HeaderFile #define _Graphic3d_CubeMap_HeaderFile +#include #include #include @@ -90,6 +91,12 @@ public: //! Empty destructor. Standard_EXPORT virtual ~Graphic3d_CubeMap(); + //! Returns direction vector for cubemap's @theFace + Standard_EXPORT gp_Dir static GetCubeDirection (Graphic3d_CubeMapSide theFace); + + //! Returns up vector for cubemap's @theFace + Standard_EXPORT gp_Dir static GetCubeUp (Graphic3d_CubeMapSide theFace); + protected: Graphic3d_CubeMapSide myCurrentSide; //!< Iterator state diff --git a/src/Graphic3d/Graphic3d_LightSet.cxx b/src/Graphic3d/Graphic3d_LightSet.cxx index 103f31cabb..a4571f4f4c 100644 --- a/src/Graphic3d/Graphic3d_LightSet.cxx +++ b/src/Graphic3d/Graphic3d_LightSet.cxx @@ -86,6 +86,35 @@ Standard_Boolean Graphic3d_LightSet::Remove (const Handle(Graphic3d_CLight)& the return Standard_True; } +// ======================================================================= +// function : CalculateNbShadows +// purpose : +// ======================================================================= +void Graphic3d_LightSet::CalculateNbShadows (Standard_Integer& theNb2DShadows, Standard_Integer& theNbPointShadows) +{ + theNb2DShadows = 0; + theNbPointShadows = 0; + for (NCollection_IndexedDataMap::Iterator aLightIter(myLights); aLightIter.More(); aLightIter.Next()) + { + const Handle(Graphic3d_CLight)& aLight = aLightIter.Key(); + //if (!aLight->IsEnabled()) + //{ + // continue; + //} + if (aLight->ToCastShadows()) + { + if (aLight->Type() == Graphic3d_TypeOfLightSource_Positional) + { + ++theNbPointShadows; + } + else + { + ++theNb2DShadows; + } + } + } +} + // ======================================================================= // function : UpdateRevision // purpose : diff --git a/src/Graphic3d/Graphic3d_LightSet.hxx b/src/Graphic3d/Graphic3d_LightSet.hxx index 584cb4c3fd..5c020bc802 100644 --- a/src/Graphic3d/Graphic3d_LightSet.hxx +++ b/src/Graphic3d/Graphic3d_LightSet.hxx @@ -143,6 +143,9 @@ public: //! Returns total amount of lights of specified type. Standard_Integer NbLightsOfType (Graphic3d_TypeOfLightSource theType) const { return myLightTypes[theType]; } + //! Calculates total amount of enabled lights castings shadows (point lights and others). + Standard_EXPORT void CalculateNbShadows (Standard_Integer& theNb2DShadows, Standard_Integer& theNbPointShadows); + //! @name cached state of lights set updated by UpdateRevision() public: diff --git a/src/Graphic3d/Graphic3d_ShaderManager.cxx b/src/Graphic3d/Graphic3d_ShaderManager.cxx index 8650a554df..284d6a1f54 100644 --- a/src/Graphic3d/Graphic3d_ShaderManager.cxx +++ b/src/Graphic3d/Graphic3d_ShaderManager.cxx @@ -19,6 +19,7 @@ #include #include "../Shaders/Shaders_LightShadow_glsl.pxx" +#include "../Shaders/Shaders_LightPointShadow_glsl.pxx" #include "../Shaders/Shaders_PBRDistribution_glsl.pxx" #include "../Shaders/Shaders_PBRDirectionalLight_glsl.pxx" #include "../Shaders/Shaders_PBRGeometry_glsl.pxx" @@ -516,6 +517,7 @@ Handle(Graphic3d_ShaderProgram) Graphic3d_ShaderManager::getStdProgramFont() con aProgramSrc->SetDefaultSampler (false); aProgramSrc->SetNbLightsMax (0); aProgramSrc->SetNbShadowMaps (0); + aProgramSrc->SetNbShadowCubeMaps (0); aProgramSrc->SetNbClipPlanesMax (0); aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts)); aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts)); @@ -645,6 +647,7 @@ Handle(Graphic3d_ShaderProgram) Graphic3d_ShaderManager::getStdProgramFboBlit (S aProgramSrc->SetDefaultSampler (false); aProgramSrc->SetNbLightsMax (0); aProgramSrc->SetNbShadowMaps (0); + aProgramSrc->SetNbShadowCubeMaps (0); aProgramSrc->SetNbClipPlanesMax (0); aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts)); aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts)); @@ -700,6 +703,7 @@ Handle(Graphic3d_ShaderProgram) Graphic3d_ShaderManager::getStdProgramOitComposi aProgramSrc->SetDefaultSampler (false); aProgramSrc->SetNbLightsMax (0); aProgramSrc->SetNbShadowMaps (0); + aProgramSrc->SetNbShadowCubeMaps (0); aProgramSrc->SetNbClipPlanesMax (0); aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts)); aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts)); @@ -1137,6 +1141,7 @@ Handle(Graphic3d_ShaderProgram) Graphic3d_ShaderManager::getStdProgramUnlit (Sta aProgramSrc->SetDefaultSampler (false); aProgramSrc->SetNbLightsMax (0); aProgramSrc->SetNbShadowMaps (0); + aProgramSrc->SetNbShadowCubeMaps (0); aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes); aProgramSrc->SetAlphaTest ((theBits & Graphic3d_ShaderFlags_AlphaTest) != 0); const Standard_Integer aNbGeomInputVerts = !aSrcGeom.IsEmpty() ? 3 : 0; @@ -1152,10 +1157,11 @@ Handle(Graphic3d_ShaderProgram) Graphic3d_ShaderManager::getStdProgramUnlit (Sta // ======================================================================= TCollection_AsciiString Graphic3d_ShaderManager::stdComputeLighting (Standard_Integer& theNbLights, const Handle(Graphic3d_LightSet)& theLights, - Standard_Boolean theHasVertColor, - Standard_Boolean theIsPBR, - Standard_Boolean theHasTexColor, - Standard_Integer theNbShadowMaps) const + Standard_Boolean theHasVertColor, + Standard_Boolean theIsPBR, + Standard_Boolean theHasTexColor, + Standard_Integer theNbShadowMaps, + Standard_Integer theNbShadowCubeMaps) const { TCollection_AsciiString aLightsFunc, aLightsLoop; theNbLights = 0; @@ -1165,6 +1171,8 @@ TCollection_AsciiString Graphic3d_ShaderManager::stdComputeLighting (Standard_In if (theNbLights <= THE_NB_UNROLLED_LIGHTS_MAX) { Standard_Integer anIndex = 0; + Standard_Integer a2DSamplerIndex = 0; + Standard_Integer aCubeSamplerIndex = 0; for (Graphic3d_LightSet::Iterator aLightIter (theLights, Graphic3d_LightSet::IterationFilter_ExcludeDisabledAndAmbient); aLightIter.More(); aLightIter.Next()) { @@ -1181,7 +1189,7 @@ TCollection_AsciiString Graphic3d_ShaderManager::stdComputeLighting (Standard_In { aLightsLoop = aLightsLoop + EOL" occDirectionalLight (" + anIndex + ", theNormal, theView, theIsFront," - EOL" occLightShadow (occShadowMapSamplers[" + anIndex + "], " + anIndex + ", theNormal));"; + EOL" occLightShadow (occShadowMapSamplers[" + a2DSamplerIndex++ + "], " + anIndex + ", theNormal));"; } else { @@ -1192,7 +1200,18 @@ TCollection_AsciiString Graphic3d_ShaderManager::stdComputeLighting (Standard_In } case Graphic3d_TypeOfLightSource_Positional: { - aLightsLoop = aLightsLoop + EOL" occPointLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);"; + if (theNbShadowCubeMaps > 0 + && aLightIter.Value()->ToCastShadows()) + { + aLightsLoop = aLightsLoop + + EOL" occPointLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront," + EOL" occLightPointShadow (occShadowCubeMapSamplers[" + aCubeSamplerIndex++ + "]," + EOL" " + anIndex + ", aPoint, theNormal)); "; + } + else + { + aLightsLoop = aLightsLoop + EOL" occPointLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront, 1.0);"; + } ++anIndex; break; } @@ -1203,7 +1222,7 @@ TCollection_AsciiString Graphic3d_ShaderManager::stdComputeLighting (Standard_In { aLightsLoop = aLightsLoop + EOL" occSpotLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront," - EOL" occLightShadow (occShadowMapSamplers[" + anIndex + "], " + anIndex + ", theNormal));"; + EOL" occLightShadow (occShadowMapSamplers[" + a2DSamplerIndex++ + "], " + anIndex + ", theNormal));"; } else { @@ -1242,7 +1261,7 @@ TCollection_AsciiString Graphic3d_ShaderManager::stdComputeLighting (Standard_In aLightsLoop += EOL" if (aType == OccLightType_Point)" EOL" {" - EOL" occPointLight (anIndex, theNormal, theView, aPoint, theIsFront);" + EOL" occPointLight (anIndex, theNormal, theView, aPoint, theIsFront, 1.0);" EOL" }"; } if (theLights->NbEnabledLightsOfType (Graphic3d_TypeOfLightSource_Spot) > 0) @@ -1271,6 +1290,7 @@ TCollection_AsciiString Graphic3d_ShaderManager::stdComputeLighting (Standard_In } bool isShadowShaderAdded = false; + bool isShadowCubeShaderAdded = false; if (theLights->NbEnabledLightsOfType (Graphic3d_TypeOfLightSource_Directional) == 1 && theNbLights == 1 && !theIsPBR @@ -1291,6 +1311,11 @@ TCollection_AsciiString Graphic3d_ShaderManager::stdComputeLighting (Standard_In } if (theLights->NbEnabledLightsOfType (Graphic3d_TypeOfLightSource_Positional) > 0) { + if (theNbShadowCubeMaps > 0 && !isShadowCubeShaderAdded) + { + aLightsFunc += Shaders_LightPointShadow_glsl; + isShadowCubeShaderAdded = true; + } aLightsFunc += theIsPBR ? Shaders_PBRPointLight_glsl : Shaders_PhongPointLight_glsl; } if (theLights->NbEnabledLightsOfType (Graphic3d_TypeOfLightSource_Spot) > 0) @@ -1475,7 +1500,7 @@ Handle(Graphic3d_ShaderProgram) Graphic3d_ShaderManager::getStdProgramGouraud (c aStageInOuts.Append (Graphic3d_ShaderObject::ShaderVariable ("vec4 BackColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); Standard_Integer aNbLights = 0; - const TCollection_AsciiString aLights = stdComputeLighting (aNbLights, theLights, !aSrcVertColor.IsEmpty(), false, toUseTexColor, 0); + const TCollection_AsciiString aLights = stdComputeLighting (aNbLights, theLights, !aSrcVertColor.IsEmpty(), false, toUseTexColor, 0, 0); aSrcVert = TCollection_AsciiString() + THE_FUNC_transformNormal_world + EOL @@ -1520,6 +1545,7 @@ Handle(Graphic3d_ShaderProgram) Graphic3d_ShaderManager::getStdProgramGouraud (c aProgramSrc->SetDefaultSampler (false); aProgramSrc->SetNbLightsMax (aNbLights); aProgramSrc->SetNbShadowMaps (0); + aProgramSrc->SetNbShadowCubeMaps (0); aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes); aProgramSrc->SetAlphaTest ((theBits & Graphic3d_ShaderFlags_AlphaTest) != 0); const Standard_Integer aNbGeomInputVerts = !aSrcGeom.IsEmpty() ? 3 : 0; @@ -1537,7 +1563,8 @@ Handle(Graphic3d_ShaderProgram) Graphic3d_ShaderManager::getStdProgramPhong (con const Standard_Integer theBits, const Standard_Boolean theIsFlatNormal, const Standard_Boolean theIsPBR, - const Standard_Integer theNbShadowMaps) const + const Standard_Integer theNbShadowMaps, + const Standard_Integer theNbShadowCubeMaps) const { TCollection_AsciiString aPhongCompLight = TCollection_AsciiString() + "computeLighting (normalize (Normal), normalize (View), PositionWorld, gl_FrontFacing)"; @@ -1690,12 +1717,18 @@ Handle(Graphic3d_ShaderProgram) Graphic3d_ShaderManager::getStdProgramPhong (con aStageInOuts.Append (Graphic3d_ShaderObject::ShaderVariable ("vec4 PositionWorld", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); aStageInOuts.Append (Graphic3d_ShaderObject::ShaderVariable ("vec3 View", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); - if (theNbShadowMaps > 0) + if (theNbShadowMaps + theNbShadowCubeMaps > 0) { - aUniforms.Append (Graphic3d_ShaderObject::ShaderVariable ("mat4 occShadowMapMatrices[THE_NB_SHADOWMAPS]", Graphic3d_TOS_VERTEX)); - aUniforms.Append (Graphic3d_ShaderObject::ShaderVariable ("sampler2D occShadowMapSamplers[THE_NB_SHADOWMAPS]", Graphic3d_TOS_FRAGMENT)); - aUniforms.Append (Graphic3d_ShaderObject::ShaderVariable ("vec2 occShadowMapSizeBias", Graphic3d_TOS_FRAGMENT)); - + aUniforms.Append (Graphic3d_ShaderObject::ShaderVariable ("mat4 occShadowMapMatrices[THE_NB_SHADOWMAPS]", Graphic3d_TOS_VERTEX)); + aUniforms.Append (Graphic3d_ShaderObject::ShaderVariable ("vec2 occShadowMapSizeBias", Graphic3d_TOS_FRAGMENT)); + if (theNbShadowMaps > 0) + { + aUniforms.Append (Graphic3d_ShaderObject::ShaderVariable ("sampler2D occShadowMapSamplers[THE_NB_SHADOWMAPS2D]", Graphic3d_TOS_FRAGMENT)); + } + if (theNbShadowCubeMaps > 0) + { + aUniforms.Append (Graphic3d_ShaderObject::ShaderVariable ("samplerCube occShadowCubeMapSamplers[THE_NB_SHADOWMAPSCUBE]", Graphic3d_TOS_FRAGMENT)); + } aStageInOuts.Append (Graphic3d_ShaderObject::ShaderVariable ("vec4 PosLightSpace[THE_NB_SHADOWMAPS]", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT)); aSrcVertExtraMain += EOL" for (int aShadowIter = 0; aShadowIter < THE_NB_SHADOWMAPS; ++aShadowIter)" @@ -1729,7 +1762,7 @@ Handle(Graphic3d_ShaderProgram) Graphic3d_ShaderManager::getStdProgramPhong (con Standard_Integer aNbLights = 0; const TCollection_AsciiString aLights = stdComputeLighting (aNbLights, theLights, !aSrcFragGetVertColor.IsEmpty(), - theIsPBR, toUseTexColor, theNbShadowMaps); + theIsPBR, toUseTexColor, theNbShadowMaps, theNbShadowCubeMaps); aSrcFrag += TCollection_AsciiString() + EOL + aSrcFragGetVertColor @@ -1745,11 +1778,12 @@ Handle(Graphic3d_ShaderProgram) Graphic3d_ShaderManager::getStdProgramPhong (con + EOL"}"; const TCollection_AsciiString aProgId = TCollection_AsciiString (theIsFlatNormal ? "flat-" : "phong-") + (theIsPBR ? "pbr-" : "") - + genLightKey (theLights, theNbShadowMaps > 0) + "-"; + + genLightKey (theLights, (theNbShadowMaps + theNbShadowCubeMaps) > 0) + "-"; defaultGlslVersion (aProgramSrc, aProgId, theBits, isFlatNormal); aProgramSrc->SetDefaultSampler (false); aProgramSrc->SetNbLightsMax (aNbLights); aProgramSrc->SetNbShadowMaps (theNbShadowMaps); + aProgramSrc->SetNbShadowCubeMaps (theNbShadowCubeMaps); aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes); aProgramSrc->SetAlphaTest ((theBits & Graphic3d_ShaderFlags_AlphaTest) != 0); @@ -1944,6 +1978,7 @@ Handle(Graphic3d_ShaderProgram) Graphic3d_ShaderManager::getStdProgramStereo (Gr aProgramSrc->SetDefaultSampler (false); aProgramSrc->SetNbLightsMax (0); aProgramSrc->SetNbShadowMaps (0); + aProgramSrc->SetNbShadowCubeMaps (0); aProgramSrc->SetNbClipPlanesMax (0); aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts)); aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts)); @@ -1980,6 +2015,7 @@ Handle(Graphic3d_ShaderProgram) Graphic3d_ShaderManager::getStdProgramBoundBox() aProgramSrc->SetDefaultSampler (false); aProgramSrc->SetNbLightsMax (0); aProgramSrc->SetNbShadowMaps (0); + aProgramSrc->SetNbShadowCubeMaps (0); aProgramSrc->SetNbClipPlanesMax (0); aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts)); aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts)); @@ -2041,6 +2077,7 @@ Handle(Graphic3d_ShaderProgram) Graphic3d_ShaderManager::getPBREnvBakingProgram aProgramSrc->SetDefaultSampler (false); aProgramSrc->SetNbLightsMax (0); aProgramSrc->SetNbShadowMaps (0); + aProgramSrc->SetNbShadowCubeMaps (0); aProgramSrc->SetNbClipPlanesMax (0); aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts)); aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts)); @@ -2107,6 +2144,7 @@ Handle(Graphic3d_ShaderProgram) Graphic3d_ShaderManager::getBgCubeMapProgram() c aProgSrc->SetDefaultSampler (false); aProgSrc->SetNbLightsMax (0); aProgSrc->SetNbShadowMaps (0); + aProgSrc->SetNbShadowCubeMaps (0); aProgSrc->SetNbClipPlanesMax (0); aProgSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts)); aProgSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts)); diff --git a/src/Graphic3d/Graphic3d_ShaderManager.hxx b/src/Graphic3d/Graphic3d_ShaderManager.hxx index 023b574260..176dbfaff2 100644 --- a/src/Graphic3d/Graphic3d_ShaderManager.hxx +++ b/src/Graphic3d/Graphic3d_ShaderManager.hxx @@ -134,7 +134,8 @@ protected: const Standard_Integer theBits, const Standard_Boolean theIsFlatNormal, const Standard_Boolean theIsPBR, - const Standard_Integer theNbShadowMaps) const; + const Standard_Integer theNbShadowMaps, + const Standard_Integer theNbShadowCubeMaps) const; //! Prepare standard GLSL program for bounding box. Standard_EXPORT Handle(Graphic3d_ShaderProgram) getStdProgramBoundBox() const; @@ -207,10 +208,11 @@ protected: //! @param theNbShadowMaps [in] flag to include shadow map Standard_EXPORT TCollection_AsciiString stdComputeLighting (Standard_Integer& theNbLights, const Handle(Graphic3d_LightSet)& theLights, - Standard_Boolean theHasVertColor, - Standard_Boolean theIsPBR, - Standard_Boolean theHasTexColor, - Standard_Integer theNbShadowMaps) const; + Standard_Boolean theHasVertColor, + Standard_Boolean theIsPBR, + Standard_Boolean theHasTexColor, + Standard_Integer theNbShadowMaps, + Standard_Integer theNbShadowCubeMaps) const; protected: diff --git a/src/Graphic3d/Graphic3d_ShaderProgram.cxx b/src/Graphic3d/Graphic3d_ShaderProgram.cxx index c4575849f4..e71ae76e0e 100755 --- a/src/Graphic3d/Graphic3d_ShaderProgram.cxx +++ b/src/Graphic3d/Graphic3d_ShaderProgram.cxx @@ -80,6 +80,7 @@ const TCollection_AsciiString& Graphic3d_ShaderProgram::ShadersFolder() Graphic3d_ShaderProgram::Graphic3d_ShaderProgram() : myNbLightsMax (THE_MAX_LIGHTS_DEFAULT), myNbShadowMaps (0), + myNbShadowCubeMaps (0), myNbClipPlanesMax (THE_MAX_CLIP_PLANES_DEFAULT), myNbFragOutputs (THE_NB_FRAG_OUTPUTS), myTextureSetBits (Graphic3d_TextureSetBits_NONE), diff --git a/src/Graphic3d/Graphic3d_ShaderProgram.hxx b/src/Graphic3d/Graphic3d_ShaderProgram.hxx index 5432d1eb8c..2f2681f168 100755 --- a/src/Graphic3d/Graphic3d_ShaderProgram.hxx +++ b/src/Graphic3d/Graphic3d_ShaderProgram.hxx @@ -96,12 +96,18 @@ public: //! Specify the length of array of light sources (THE_MAX_LIGHTS). void SetNbLightsMax (Standard_Integer theNbLights) { myNbLightsMax = theNbLights; } - //! Return the length of array of shadow maps (THE_NB_SHADOWMAPS); 0 by default. + //! Return the length of array of 2D shadow maps (THE_NB_SHADOWMAP2D); 0 by default. Standard_Integer NbShadowMaps() const { return myNbShadowMaps; } - //! Specify the length of array of shadow maps (THE_NB_SHADOWMAPS). + //! Specify the length of array of 2D shadow maps (THE_NB_SHADOWMAP2D). void SetNbShadowMaps (Standard_Integer theNbMaps) { myNbShadowMaps = theNbMaps; } + //! Return the length of array of shadow cube maps (THE_NB_SHADOWMAPCUBE); 0 by default. + Standard_Integer NbShadowCubeMaps() const { return myNbShadowCubeMaps; } + + //! Specify the length of array of shadow cube maps (THE_NB_SHADOWMAPCUBE). + void SetNbShadowCubeMaps (Standard_Integer theNbMaps) { myNbShadowCubeMaps = theNbMaps; } + //! Return the length of array of clipping planes (THE_MAX_CLIP_PLANES), //! to be used for initialization occClipPlaneEquations. //! Default value is THE_MAX_CLIP_PLANES_DEFAULT. @@ -214,20 +220,21 @@ public: private: - TCollection_AsciiString myID; //!< the unique identifier of program object - Graphic3d_ShaderObjectList myShaderObjects; //!< the list of attached shader objects - Graphic3d_ShaderVariableList myVariables; //!< the list of custom uniform variables - Graphic3d_ShaderAttributeList myAttributes; //!< the list of custom vertex attributes - 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 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 myNbFragOutputs; //!< length of array of Fragment Shader outputs (THE_NB_FRAG_OUTPUTS) - Standard_Integer myTextureSetBits;//!< texture units declared within the program, @sa Graphic3d_TextureSetBits - Graphic3d_RenderTransparentMethod myOitOutput; //!< flag indicating that Fragment Shader includes OIT outputs - Standard_Boolean myHasDefSampler; //!< flag indicating that program defines default texture sampler occSampler0 - Standard_Boolean myHasAlphaTest; //!< flag indicating that Fragment Shader performs alpha test - Standard_Boolean myIsPBR; //!< flag indicating that program defines functions and variables used in PBR pipeline + TCollection_AsciiString myID; //!< the unique identifier of program object + Graphic3d_ShaderObjectList myShaderObjects; //!< the list of attached shader objects + Graphic3d_ShaderVariableList myVariables; //!< the list of custom uniform variables + Graphic3d_ShaderAttributeList myAttributes; //!< the list of custom vertex attributes + 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 myNbShadowMaps; //!< length of array of shadow maps (THE_NB_SHADOWMAP2D) + Standard_Integer myNbShadowCubeMaps; //!< length of array of shadow maps (THE_NB_SHADOWMAPCUBE) + 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 myTextureSetBits; //!< texture units declared within the program, @sa Graphic3d_TextureSetBits + Graphic3d_RenderTransparentMethod myOitOutput; //!< flag indicating that Fragment Shader includes OIT outputs + Standard_Boolean myHasDefSampler; //!< flag indicating that program defines default texture sampler occSampler0 + Standard_Boolean myHasAlphaTest; //!< flag indicating that Fragment Shader performs alpha test + Standard_Boolean myIsPBR; //!< flag indicating that program defines functions and variables used in PBR pipeline }; diff --git a/src/Graphic3d/Graphic3d_TextureUnit.hxx b/src/Graphic3d/Graphic3d_TextureUnit.hxx index 6916c4ada8..3ea04fa235 100644 --- a/src/Graphic3d/Graphic3d_TextureUnit.hxx +++ b/src/Graphic3d/Graphic3d_TextureUnit.hxx @@ -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. Graphic3d_TextureUnit_PointSprite = Graphic3d_TextureUnit_1, + //! samplerCube occShadowCubeMapSampler. + //! Point light source shadowmap texture. + Graphic3d_TextureUnit_ShadowCubeMap = -7, + //! sampler2D occDepthPeelingDepth. //! 1st texture unit for Depth Peeling lookups. Graphic3d_TextureUnit_DepthPeelingDepth = -6, diff --git a/src/OpenGl/OpenGl_Context.cxx b/src/OpenGl/OpenGl_Context.cxx index 9380b93672..460e6341a5 100644 --- a/src/OpenGl/OpenGl_Context.cxx +++ b/src/OpenGl/OpenGl_Context.cxx @@ -227,6 +227,7 @@ OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps) myPBRDiffIBLMapSHTexUnit (Graphic3d_TextureUnit_PbrIblDiffuseSH), myPBRSpecIBLMapTexUnit (Graphic3d_TextureUnit_PbrIblSpecular), myShadowMapTexUnit (Graphic3d_TextureUnit_ShadowMap), + myShadowCubeMapTexUnit (Graphic3d_TextureUnit_ShadowCubeMap), myDepthPeelingDepthTexUnit (Graphic3d_TextureUnit_DepthPeelingDepth), myDepthPeelingFrontColorTexUnit (Graphic3d_TextureUnit_DepthPeelingFrontColor), myFrameStats (new OpenGl_FrameStats()), @@ -1653,6 +1654,7 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile) } } + myShadowCubeMapTexUnit = static_cast(myMaxTexCombined + Graphic3d_TextureUnit_ShadowCubeMap); // -7 myDepthPeelingDepthTexUnit = static_cast(myMaxTexCombined + Graphic3d_TextureUnit_DepthPeelingDepth); // -6 myDepthPeelingFrontColorTexUnit = static_cast(myMaxTexCombined + Graphic3d_TextureUnit_DepthPeelingFrontColor); // -5 myShadowMapTexUnit = static_cast(myMaxTexCombined + Graphic3d_TextureUnit_ShadowMap); // -4 @@ -1661,6 +1663,7 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile) myPBRSpecIBLMapTexUnit = static_cast(myMaxTexCombined + Graphic3d_TextureUnit_PbrIblSpecular); // -1 if (!myHasPBR) { + myShadowCubeMapTexUnit = static_cast(myShadowCubeMapTexUnit + 3); myDepthPeelingDepthTexUnit = static_cast(myDepthPeelingDepthTexUnit + 3); myDepthPeelingFrontColorTexUnit = static_cast(myDepthPeelingFrontColorTexUnit + 3); myShadowMapTexUnit = static_cast(myShadowMapTexUnit + 3); diff --git a/src/OpenGl/OpenGl_Context.hxx b/src/OpenGl/OpenGl_Context.hxx index f86c4cc461..83008cfa48 100644 --- a/src/OpenGl/OpenGl_Context.hxx +++ b/src/OpenGl/OpenGl_Context.hxx @@ -605,6 +605,9 @@ public: //! Returns texture unit where shadow map is expected to be bound, or 0 if unavailable. Graphic3d_TextureUnit ShadowMapTexUnit() const { return myShadowMapTexUnit; } + //! Returns texture unit where shadow map is expected to be bound, or 0 if unavailable. + Graphic3d_TextureUnit ShadowCubeMapTexUnit() const { return myShadowCubeMapTexUnit; } + //! Returns texture unit for occDepthPeelingDepth within enabled Depth Peeling. Graphic3d_TextureUnit DepthPeelingDepthTexUnit() const { return myDepthPeelingDepthTexUnit; } @@ -1137,6 +1140,7 @@ private: // context info //! (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 + Graphic3d_TextureUnit myShadowCubeMapTexUnit; //!< samplerCube occShadowCubeMapSampler Graphic3d_TextureUnit myDepthPeelingDepthTexUnit; //!< sampler2D occDepthPeelingDepth, texture unit for Depth Peeling lookups Graphic3d_TextureUnit myDepthPeelingFrontColorTexUnit; //!< sampler2D occDepthPeelingFrontColor, texture unit for Depth Peeling lookups diff --git a/src/OpenGl/OpenGl_FrameBuffer.cxx b/src/OpenGl/OpenGl_FrameBuffer.cxx index ca4ac757e2..e370a81576 100644 --- a/src/OpenGl/OpenGl_FrameBuffer.cxx +++ b/src/OpenGl/OpenGl_FrameBuffer.cxx @@ -330,7 +330,8 @@ Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlCo const Graphic3d_Vec2i& theSize, const OpenGl_ColorFormats& theColorFormats, const Standard_Integer theDepthFormat, - const Standard_Integer theNbSamples) + const Standard_Integer theNbSamples, + const Standard_Boolean theIsCubeMap) { myColorFormats = theColorFormats; @@ -423,9 +424,10 @@ Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlCo // extensions (GL_OES_packed_depth_stencil, GL_OES_depth_texture) + GL version might be used to determine supported formats // instead of just trying to create such texture + Graphic3d_TypeOfTexture aTypeOfTexture = theIsCubeMap ? Graphic3d_TypeOfTexture_CUBEMAP : Graphic3d_TypeOfTexture_2D; const OpenGl_TextureFormat aDepthFormat = OpenGl_TextureFormat::FindSizedFormat (theGlContext, myDepthFormat); if (aDepthFormat.IsValid() - && !myDepthStencilTexture->Init (theGlContext, aDepthFormat, Graphic3d_Vec2i (aSizeX, aSizeY), Graphic3d_TypeOfTexture_2D)) + && !myDepthStencilTexture->Init (theGlContext, aDepthFormat, Graphic3d_Vec2i (aSizeX, aSizeY), aTypeOfTexture)) { theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, "Warning! Depth textures are not supported by hardware!"); @@ -470,15 +472,42 @@ Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlCo { if (hasDepthStencilAttach (theGlContext)) { - theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, - myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0); + if (theIsCubeMap) + { + for (Standard_Integer aCubeFace = 0; aCubeFace < 6; ++aCubeFace) + { + theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, + GLenum(GL_TEXTURE_CUBE_MAP_POSITIVE_X + aCubeFace), + myDepthStencilTexture->TextureId(), 0); + } + } + else + { + theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, + myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0); + } } else { - theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, - myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0); - theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, - myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0); + if (theIsCubeMap) + { + for (Standard_Integer aCubeFace = 0; aCubeFace < 6; ++aCubeFace) + { + theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GLenum(GL_TEXTURE_CUBE_MAP_POSITIVE_X + aCubeFace), + myDepthStencilTexture->TextureId(), 0); + theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, + GLenum(GL_TEXTURE_CUBE_MAP_POSITIVE_X + aCubeFace), + myDepthStencilTexture->TextureId(), 0); + } + } + else + { + theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0); + theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, + myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0); + } } } else if (myGlDepthRBufferId != NO_RENDERBUFFER) @@ -499,8 +528,17 @@ Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlCo } } } + const GLenum aRendImgErr = theGlContext->core11fwd->glGetError(); + if (aRendImgErr != GL_NO_ERROR) + { + theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, + TCollection_AsciiString("Error: in setup of glFramebufferTexture2D: ") + OpenGl_Context::FormatGlError(aRendImgErr) + "."); + Release (theGlContext.get()); + return Standard_False; + } if (theGlContext->arbFBO->glCheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { + std::cout << "\n\nIncomplete framebuffer: " << theGlContext->arbFBO->glCheckFramebufferStatus (GL_FRAMEBUFFER) << "\n\n"; Release (theGlContext.operator->()); return Standard_False; } @@ -907,6 +945,18 @@ void OpenGl_FrameBuffer::BindReadBuffer (const Handle(OpenGl_Context)& theGlCtx) theGlCtx->arbFBO->glBindFramebuffer (GL_READ_FRAMEBUFFER, myGlFBufferId); } +// ======================================================================= +// function : BindBufferCube +// purpose : +// ======================================================================= +void OpenGl_FrameBuffer::BindBufferCube (const Handle(OpenGl_Context)& theGlCtx, const Standard_Integer theFace) +{ + theGlCtx->arbFBO->glBindFramebuffer (GL_DRAW_FRAMEBUFFER, myGlFBufferId); + theGlCtx->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, + GLenum(GL_TEXTURE_CUBE_MAP_POSITIVE_X + theFace), + myDepthStencilTexture->TextureId(), 0); +} + // ======================================================================= // function : UnbindBuffer // purpose : @@ -957,7 +1007,8 @@ inline void convertRowFromRgba (T* theRgbRow, Standard_Boolean OpenGl_FrameBuffer::BufferDump (const Handle(OpenGl_Context)& theGlCtx, const Handle(OpenGl_FrameBuffer)& theFbo, Image_PixMap& theImage, - Graphic3d_BufferType theBufferType) + Graphic3d_BufferType theBufferType, + const Standard_Integer theCubeFace) { if (theGlCtx.IsNull() || theImage.IsEmpty()) @@ -1119,6 +1170,38 @@ Standard_Boolean OpenGl_FrameBuffer::BufferDump (const Handle(OpenGl_Context)& t return Standard_False; } + if (theCubeFace >= 0) + { + theGlCtx->core11fwd->glBindTexture (GL_TEXTURE_CUBE_MAP, theFbo->DepthStencilTexture()->TextureId()); + theFbo->BindBufferCube (theGlCtx, theCubeFace); + const GLint anAligment = Min(GLint(theImage.MaxRowAligmentBytes()), 8); // limit to 8 bytes for OpenGL + theGlCtx->core11fwd->glPixelStorei (GL_PACK_ALIGNMENT, anAligment); + if (theGlCtx->hasPackRowLength) + { + theGlCtx->core11fwd->glPixelStorei (GL_PACK_ROW_LENGTH, 0); + } + theGlCtx->core11fwd->glGetTexImage (GLenum(GL_TEXTURE_CUBE_MAP_POSITIVE_X + theCubeFace), + 0, aFormat, aType, theImage.ChangeData()); + const bool hasErrors = theGlCtx->ResetErrors (true); + if (hasErrors) + { + std::cout << "\nError saving cubemap face texture to image.\n"; + return Standard_False; + } + + theGlCtx->core11fwd->glPixelStorei (GL_PACK_ALIGNMENT, 1); + + if (!theFbo.IsNull() && theFbo->IsValid()) + { + theFbo->UnbindBuffer(theGlCtx); + } + else if (theGlCtx->GraphicsLibrary() != Aspect_GraphicsLibrary_OpenGLES) + { + theGlCtx->core11fwd->glReadBuffer(aReadBufferPrev); + } + return Standard_True; + } + // bind FBO if used if (!theFbo.IsNull() && theFbo->IsValid()) { diff --git a/src/OpenGl/OpenGl_FrameBuffer.hxx b/src/OpenGl/OpenGl_FrameBuffer.hxx index d3955eca00..0ce139f259 100644 --- a/src/OpenGl/OpenGl_FrameBuffer.hxx +++ b/src/OpenGl/OpenGl_FrameBuffer.hxx @@ -48,11 +48,13 @@ public: //! @param theFbo FBO to dump (or window buffer, if NULL) //! @param theImage target image //! @param theBufferType buffer type (attachment) to dump + //! @param theCubeFace id of the cubemap face (only used for fbo's rendering to cubemaps) //! @return TRUE on success Standard_EXPORT static Standard_Boolean BufferDump (const Handle(OpenGl_Context)& theGlCtx, const Handle(OpenGl_FrameBuffer)& theFbo, Image_PixMap& theImage, - Graphic3d_BufferType theBufferType); + Graphic3d_BufferType theBufferType, + const Standard_Integer theCubeFace = -1); public: @@ -142,12 +144,14 @@ public: //! @param theColorFormats list of color texture sized format (0 means no color attachment), e.g. GL_RGBA8 //! @param theDepthFormat depth-stencil texture sized format (0 means no depth attachment), e.g. GL_DEPTH24_STENCIL8 //! @param theNbSamples MSAA number of samples (0 means normal texture) + //! @param theIsCubeMap flag to setup texture target to cubemap (FALSE by default) //! @return true on success Standard_EXPORT Standard_Boolean Init (const Handle(OpenGl_Context)& theGlCtx, const Graphic3d_Vec2i& theSize, const OpenGl_ColorFormats& theColorFormats, const Standard_Integer theDepthFormat, - const Standard_Integer theNbSamples = 0); + const Standard_Integer theNbSamples = 0, + const Standard_Boolean theIsCubeMap = Standard_False); //! (Re-)initialize FBO with specified dimensions. Standard_EXPORT Standard_Boolean InitLazy (const Handle(OpenGl_Context)& theGlCtx, @@ -225,6 +229,9 @@ public: //! Bind frame buffer for reading GL_READ_FRAMEBUFFER Standard_EXPORT virtual void BindReadBuffer (const Handle(OpenGl_Context)& theGlCtx); + //! Bind frame buffer for reading cubemap with the target @theFace. + Standard_EXPORT virtual void BindBufferCube (const Handle(OpenGl_Context)& theGlCtx, const Standard_Integer theFace); + //! Unbind frame buffer. Standard_EXPORT virtual void UnbindBuffer (const Handle(OpenGl_Context)& theGlCtx); diff --git a/src/OpenGl/OpenGl_ShaderManager.cxx b/src/OpenGl/OpenGl_ShaderManager.cxx index eff6bf9f39..0dd894ff1d 100644 --- a/src/OpenGl/OpenGl_ShaderManager.cxx +++ b/src/OpenGl/OpenGl_ShaderManager.cxx @@ -554,9 +554,10 @@ void OpenGl_ShaderManager::pushLightSourceState (const Handle(OpenGl_ShaderProgr // update shadow map variables if (const OpenGl_ShaderUniformLocation aShadowMatLoc = theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SHADOWMAP_MATRICES)) { - if (myShadowMatArray.Size() < theProgram->NbShadowMaps()) + Standard_Integer aNbShadowMaps = theProgram->NbShadowMaps() + theProgram->NbShadowCubeMaps(); + if (myShadowMatArray.Size() < aNbShadowMaps) { - myShadowMatArray.Resize (0, theProgram->NbShadowMaps() - 1, false); + myShadowMatArray.Resize (0, aNbShadowMaps - 1, false); } Graphic3d_Vec2 aSizeBias; @@ -564,7 +565,7 @@ void OpenGl_ShaderManager::pushLightSourceState (const Handle(OpenGl_ShaderProgr { aSizeBias.SetValues (1.0f / (float )myLightSourceState.ShadowMaps()->First()->Texture()->SizeX(), myLightSourceState.ShadowMaps()->First()->ShadowMapBias()); - const Standard_Integer aNbShadows = Min (theProgram->NbShadowMaps(), myLightSourceState.ShadowMaps()->Size()); + const Standard_Integer aNbShadows = Min (aNbShadowMaps, myLightSourceState.ShadowMaps()->Size()); for (Standard_Integer aShadowIter = 0; aShadowIter < aNbShadows; ++aShadowIter) { const Handle(OpenGl_ShadowMap)& aShadow = myLightSourceState.ShadowMaps()->Value (aShadowIter); @@ -572,7 +573,7 @@ void OpenGl_ShaderManager::pushLightSourceState (const Handle(OpenGl_ShaderProgr } } - theProgram->SetUniform (myContext, aShadowMatLoc, theProgram->NbShadowMaps(), &myShadowMatArray.First()); + theProgram->SetUniform (myContext, aShadowMatLoc, aNbShadowMaps, &myShadowMatArray.First()); theProgram->SetUniform (myContext, theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SHADOWMAP_SIZE_BIAS), aSizeBias); } } @@ -1229,10 +1230,16 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha const Standard_Boolean theIsFlatNormal, const Standard_Boolean theIsPBR) { - Standard_Integer aNbShadowMaps = myLightSourceState.HasShadowMaps() - ? myLightSourceState.LightSources()->NbCastShadows() - : 0; - Handle(Graphic3d_ShaderProgram) aProgramSrc = getStdProgramPhong (myLightSourceState.LightSources(), theBits, theIsFlatNormal, theIsPBR, aNbShadowMaps); + Standard_Integer aNbShadowMaps, aNbShadowCubeMaps; + myLightSourceState.LightSources()->CalculateNbShadows (aNbShadowMaps, aNbShadowCubeMaps); + // point light shadows are not currently supported on opengles 2.0. + if (myContext->GraphicsLibrary() == Aspect_GraphicsLibrary_OpenGLES + && myContext->VersionMajor() <= 2) + { + aNbShadowCubeMaps = 0; + } + Handle(Graphic3d_ShaderProgram) aProgramSrc = getStdProgramPhong (myLightSourceState.LightSources(), theBits, theIsFlatNormal, + theIsPBR, aNbShadowMaps, aNbShadowCubeMaps); TCollection_AsciiString aKey; if (!Create (aProgramSrc, aKey, theProgram)) { diff --git a/src/OpenGl/OpenGl_ShaderProgram.cxx b/src/OpenGl/OpenGl_ShaderProgram.cxx index a5504af8af..211aa13e48 100755 --- a/src/OpenGl/OpenGl_ShaderProgram.cxx +++ b/src/OpenGl/OpenGl_ShaderProgram.cxx @@ -50,43 +50,44 @@ Standard_CString OpenGl_ShaderProgram::PredefinedKeywords[] = "occWorldViewMatrixInverseTranspose", // OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE_TRANSPOSE "occProjectionMatrixInverseTranspose", // OpenGl_OCC_PROJECTION_MATRIX_INVERSE_TRANSPOSE - "occClipPlaneEquations", // OpenGl_OCC_CLIP_PLANE_EQUATIONS - "occClipPlaneChains", // OpenGl_OCC_CLIP_PLANE_CHAINS - "occClipPlaneCount", // OpenGl_OCC_CLIP_PLANE_COUNT + "occClipPlaneEquations", // OpenGl_OCC_CLIP_PLANE_EQUATIONS + "occClipPlaneChains", // OpenGl_OCC_CLIP_PLANE_CHAINS + "occClipPlaneCount", // OpenGl_OCC_CLIP_PLANE_COUNT - "occLightSourcesCount", // OpenGl_OCC_LIGHT_SOURCE_COUNT - "occLightSourcesTypes", // OpenGl_OCC_LIGHT_SOURCE_TYPES - "occLightSources", // OpenGl_OCC_LIGHT_SOURCE_PARAMS - "occLightAmbient", // OpenGl_OCC_LIGHT_AMBIENT - "occShadowMapSizeBias", // OpenGl_OCC_LIGHT_SHADOWMAP_SIZE_BIAS - "occShadowMapSamplers", // OpenGl_OCC_LIGHT_SHADOWMAP_SAMPLERS, - "occShadowMapMatrices", // OpenGl_OCC_LIGHT_SHADOWMAP_MATRICES, + "occLightSourcesCount", // OpenGl_OCC_LIGHT_SOURCE_COUNT + "occLightSourcesTypes", // OpenGl_OCC_LIGHT_SOURCE_TYPES + "occLightSources", // OpenGl_OCC_LIGHT_SOURCE_PARAMS + "occLightAmbient", // OpenGl_OCC_LIGHT_AMBIENT + "occShadowMapSizeBias", // OpenGl_OCC_LIGHT_SHADOWMAP_SIZE_BIAS + "occShadowMapSamplers", // OpenGl_OCC_LIGHT_SHADOWMAP_SAMPLERS, + "occShadowCubeMapSamplers", // OpenGl_OCC_LIGHT_SHADOWCUBEMAP_SAMPLERS, + "occShadowMapMatrices", // OpenGl_OCC_LIGHT_SHADOWMAP_MATRICES, - "occTextureEnable", // OpenGl_OCCT_TEXTURE_ENABLE - "occDistinguishingMode", // OpenGl_OCCT_DISTINGUISH_MODE - "occPbrMaterial", // OpenGl_OCCT_PBR_MATERIAL - "occCommonMaterial", // OpenGl_OCCT_COMMON_MATERIAL - "occAlphaCutoff", // OpenGl_OCCT_ALPHA_CUTOFF - "occColor", // OpenGl_OCCT_COLOR + "occTextureEnable", // OpenGl_OCCT_TEXTURE_ENABLE + "occDistinguishingMode", // OpenGl_OCCT_DISTINGUISH_MODE + "occPbrMaterial", // OpenGl_OCCT_PBR_MATERIAL + "occCommonMaterial", // OpenGl_OCCT_COMMON_MATERIAL + "occAlphaCutoff", // OpenGl_OCCT_ALPHA_CUTOFF + "occColor", // OpenGl_OCCT_COLOR - "occOitOutput", // OpenGl_OCCT_OIT_OUTPUT - "occOitDepthFactor", // OpenGl_OCCT_OIT_DEPTH_FACTOR + "occOitOutput", // OpenGl_OCCT_OIT_OUTPUT + "occOitDepthFactor", // OpenGl_OCCT_OIT_DEPTH_FACTOR - "occTexTrsf2d", // OpenGl_OCCT_TEXTURE_TRSF2D - "occPointSize", // OpenGl_OCCT_POINT_SIZE + "occTexTrsf2d", // OpenGl_OCCT_TEXTURE_TRSF2D + "occPointSize", // OpenGl_OCCT_POINT_SIZE - "occViewport", // OpenGl_OCCT_VIEWPORT - "occLineWidth", // OpenGl_OCCT_LINE_WIDTH - "occLineFeather", // OpenGl_OCCT_LINE_FEATHER - "occStipplePattern", // OpenGl_OCCT_LINE_STIPPLE_PATTERN - "occStippleFactor", // OpenGl_OCCT_LINE_STIPPLE_FACTOR - "occWireframeColor", // OpenGl_OCCT_WIREFRAME_COLOR - "occIsQuadMode", // OpenGl_OCCT_QUAD_MODE_STATE + "occViewport", // OpenGl_OCCT_VIEWPORT + "occLineWidth", // OpenGl_OCCT_LINE_WIDTH + "occLineFeather", // OpenGl_OCCT_LINE_FEATHER + "occStipplePattern", // OpenGl_OCCT_LINE_STIPPLE_PATTERN + "occStippleFactor", // OpenGl_OCCT_LINE_STIPPLE_FACTOR + "occWireframeColor", // OpenGl_OCCT_WIREFRAME_COLOR + "occIsQuadMode", // OpenGl_OCCT_QUAD_MODE_STATE - "occOrthoScale", // OpenGl_OCCT_ORTHO_SCALE - "occSilhouetteThickness", // OpenGl_OCCT_SILHOUETTE_THICKNESS + "occOrthoScale", // OpenGl_OCCT_ORTHO_SCALE + "occSilhouetteThickness", // OpenGl_OCCT_SILHOUETTE_THICKNESS - "occNbSpecIBLLevels" // OpenGl_OCCT_NB_SPEC_IBL_LEVELS + "occNbSpecIBLLevels" // OpenGl_OCCT_NB_SPEC_IBL_LEVELS }; namespace @@ -165,6 +166,7 @@ OpenGl_ShaderProgram::OpenGl_ShaderProgram (const Handle(Graphic3d_ShaderProgram myShareCount(1), myNbLightsMax (0), myNbShadowMaps (0), + myNbShadowCubeMaps (0), myNbClipPlanesMax (0), myNbFragOutputs (1), myTextureSetBits (Graphic3d_TextureSetBits_NONE), @@ -419,15 +421,24 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)& } TCollection_AsciiString aHeaderConstants; - myNbLightsMax = !myProxy.IsNull() ? myProxy->NbLightsMax() : 0; - myNbShadowMaps = !myProxy.IsNull() ? myProxy->NbShadowMaps() : 0; - myNbClipPlanesMax = !myProxy.IsNull() ? myProxy->NbClipPlanesMax() : 0; + myNbLightsMax = !myProxy.IsNull() ? myProxy->NbLightsMax() : 0; + myNbShadowMaps = !myProxy.IsNull() ? myProxy->NbShadowMaps() : 0; + myNbShadowCubeMaps = !myProxy.IsNull() ? myProxy->NbShadowCubeMaps() : 0; + myNbClipPlanesMax = !myProxy.IsNull() ? myProxy->NbClipPlanesMax() : 0; aHeaderConstants += TCollection_AsciiString("#define THE_MAX_LIGHTS ") + myNbLightsMax + "\n"; aHeaderConstants += TCollection_AsciiString("#define THE_MAX_CLIP_PLANES ") + myNbClipPlanesMax + "\n"; aHeaderConstants += TCollection_AsciiString("#define THE_NB_FRAG_OUTPUTS ") + myNbFragOutputs + "\n"; + if (myNbShadowMaps + myNbShadowCubeMaps > 0) + { + aHeaderConstants += TCollection_AsciiString("#define THE_NB_SHADOWMAPS ") + (myNbShadowMaps + myNbShadowCubeMaps) + "\n"; + } if (myNbShadowMaps > 0) { - aHeaderConstants += TCollection_AsciiString("#define THE_NB_SHADOWMAPS ") + myNbShadowMaps + "\n"; + aHeaderConstants += TCollection_AsciiString("#define THE_NB_SHADOWMAPS2D ") + myNbShadowMaps + "\n"; + } + if (myNbShadowCubeMaps > 0) + { + aHeaderConstants += TCollection_AsciiString("#define THE_NB_SHADOWMAPSCUBE ") + myNbShadowCubeMaps + "\n"; } if (theCtx->caps->useZeroToOneDepth && theCtx->arbClipControl) @@ -590,7 +601,16 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)& } SetUniform (theCtx, aLocSampler, myNbShadowMaps, &aShadowSamplers.front()); } - + if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occShadowCubeMapSamplers")) + { + std::vector aShadowSamplers (myNbShadowCubeMaps); + const GLint aSamplFrom = GLint(theCtx->ShadowCubeMapTexUnit()) - myNbShadowCubeMaps + 1; + for (Standard_Integer aSamplerIter = 0; aSamplerIter < myNbShadowCubeMaps; ++aSamplerIter) + { + aShadowSamplers[aSamplerIter] = aSamplFrom + aSamplerIter; + } + SetUniform (theCtx, aLocSampler, myNbShadowCubeMaps, &aShadowSamplers.front()); + } if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occDepthPeelingDepth")) { SetUniform (theCtx, aLocSampler, GLint(theCtx->DepthPeelingDepthTexUnit())); diff --git a/src/OpenGl/OpenGl_ShaderProgram.hxx b/src/OpenGl/OpenGl_ShaderProgram.hxx index 92d74e54ef..73d588b462 100755 --- a/src/OpenGl/OpenGl_ShaderProgram.hxx +++ b/src/OpenGl/OpenGl_ShaderProgram.hxx @@ -57,9 +57,10 @@ enum OpenGl_StateVariable OpenGl_OCC_LIGHT_SOURCE_TYPES, OpenGl_OCC_LIGHT_SOURCE_PARAMS, OpenGl_OCC_LIGHT_AMBIENT, - OpenGl_OCC_LIGHT_SHADOWMAP_SIZE_BIAS,// occShadowMapSizeBias - OpenGl_OCC_LIGHT_SHADOWMAP_SAMPLERS, // occShadowMapSamplers - OpenGl_OCC_LIGHT_SHADOWMAP_MATRICES, // occShadowMapMatrices + OpenGl_OCC_LIGHT_SHADOWMAP_SIZE_BIAS, // occShadowMapSizeBias + OpenGl_OCC_LIGHT_SHADOWMAP_SAMPLERS, // occShadowMapSamplers + OpenGl_OCC_LIGHT_SHADOWCUBEMAP_SAMPLERS, // occShadowCubeMapSamplers + OpenGl_OCC_LIGHT_SHADOWMAP_MATRICES, // occShadowMapMatrices // Material state OpenGl_OCCT_TEXTURE_ENABLE, @@ -283,9 +284,12 @@ public: //! to be used for initialization occLightSources (OpenGl_OCC_LIGHT_SOURCE_PARAMS). Standard_Integer NbLightsMax() const { return myNbLightsMax; } - //! Return the length of array of shadow maps (THE_NB_SHADOWMAPS); 0 by default. + //! Return the length of array of 2D shadow maps (THE_NB_SHADOWMAP2D); 0 by default. Standard_Integer NbShadowMaps() const { return myNbShadowMaps; } + //! Return the length of array of shadow cube maps (THE_NB_SHADOWMAPCUBE); 0 by default. + Standard_Integer NbShadowCubeMaps() const { return myNbShadowCubeMaps; } + //! 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). Standard_Integer NbClipPlanesMax() const { return myNbClipPlanesMax; } @@ -643,18 +647,19 @@ protected: protected: - GLuint myProgramID; //!< Handle of OpenGL shader program - OpenGl_ShaderList myShaderObjects; //!< List of attached shader objects - Handle(Graphic3d_ShaderProgram) myProxy; //!< Proxy shader program (from application layer) - Standard_Integer myShareCount; //!< program users count, initialized with 1 (already shared by one user) - 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 myNbFragOutputs; //!< length of array of Fragment Shader outputs (THE_NB_FRAG_OUTPUTS) - Standard_Integer myTextureSetBits;//!< texture units declared within the program, @sa Graphic3d_TextureSetBits - Graphic3d_RenderTransparentMethod myOitOutput; //!< flag indicating that Fragment Shader includes OIT outputs - Standard_Boolean myHasAlphaTest; //!< flag indicating that Fragment Shader should perform alpha-test - Standard_Boolean myHasTessShader; //!< flag indicating that program defines tessellation stage + GLuint myProgramID; //!< Handle of OpenGL shader program + OpenGl_ShaderList myShaderObjects; //!< List of attached shader objects + Handle(Graphic3d_ShaderProgram) myProxy; //!< Proxy shader program (from application layer) + Standard_Integer myShareCount; //!< program users count, initialized with 1 (already shared by one user) + Standard_Integer myNbLightsMax; //!< length of array of light sources (THE_MAX_LIGHTS) + Standard_Integer myNbShadowMaps; //!< length of array of shadow maps (THE_NB_SHADOWMAP2D) + Standard_Integer myNbShadowCubeMaps; //!< length of array of shadow maps (THE_NB_SHADOWMAPCUBE) + 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 myTextureSetBits; //!< texture units declared within the program, @sa Graphic3d_TextureSetBits + Graphic3d_RenderTransparentMethod myOitOutput; //!< flag indicating that Fragment Shader includes OIT outputs + Standard_Boolean myHasAlphaTest; //!< flag indicating that Fragment Shader should perform alpha-test + Standard_Boolean myHasTessShader; //!< flag indicating that program defines tessellation stage protected: diff --git a/src/OpenGl/OpenGl_ShadowMap.cxx b/src/OpenGl/OpenGl_ShadowMap.cxx index 14854d9128..296d205be8 100644 --- a/src/OpenGl/OpenGl_ShadowMap.cxx +++ b/src/OpenGl/OpenGl_ShadowMap.cxx @@ -83,7 +83,8 @@ const Handle(OpenGl_Texture)& OpenGl_ShadowMap::Texture() const // purpose : // ======================================================================= bool OpenGl_ShadowMap::UpdateCamera (const Graphic3d_CView& theView, - const gp_XYZ* theOrigin) + const gp_XYZ* theOrigin, + const Standard_Integer theFace) { const Bnd_Box aMinMaxBox = theOrigin == NULL ? theView.MinMaxValues (false) : Bnd_Box(); // applicative min max boundaries const Bnd_Box aGraphicBox = aMinMaxBox; @@ -134,7 +135,19 @@ bool OpenGl_ShadowMap::UpdateCamera (const Graphic3d_CView& theView, case Graphic3d_TypeOfLightSource_Positional: { // render into cubemap shadowmap texture - return false; // not implemented + myShadowCamera->SetZeroToOneDepth (theView.Camera()->IsZeroToOneDepth()); + myShadowCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective); + myShadowCamera->SetFOVy (90.0); + const gp_Pnt& aLightPos = myShadowLight->Position(); + myShadowCamera->MoveEyeTo (aLightPos); + // calculate direction and up vector for the given cubemap face + myShadowCamera->SetDirectionFromEye (Graphic3d_CubeMap::GetCubeDirection ((Graphic3d_CubeMapSide)theFace)); + myShadowCamera->SetUp (Graphic3d_CubeMap::GetCubeUp ((Graphic3d_CubeMapSide)theFace)); + // setup znear and zfar (default value) + myShadowCamera->SetZRange (1.0, myShadowCamera->GetDefaultZFar()); + myLightMatrix = myShadowCamera->ProjectionMatrixF() * myShadowCamera->OrientationMatrixF(); + + return true; } case Graphic3d_TypeOfLightSource_Spot: { diff --git a/src/OpenGl/OpenGl_ShadowMap.hxx b/src/OpenGl/OpenGl_ShadowMap.hxx index 309fbce1e1..5f04392aad 100644 --- a/src/OpenGl/OpenGl_ShadowMap.hxx +++ b/src/OpenGl/OpenGl_ShadowMap.hxx @@ -76,8 +76,10 @@ public: //! Compute camera. //! @param theView [in] active view //! @param theOrigin [in] when not-NULL - displace shadow map camera to specified Z-Layer origin + //! @param theFace [in] if light is point light calculate for given cubemap face index Standard_EXPORT bool UpdateCamera (const Graphic3d_CView& theView, - const gp_XYZ* theOrigin = NULL); + const gp_XYZ* theOrigin = NULL, + const Standard_Integer theFace = -1); private: diff --git a/src/OpenGl/OpenGl_Texture.cxx b/src/OpenGl/OpenGl_Texture.cxx index 4d90a8e96b..1e00967edc 100644 --- a/src/OpenGl/OpenGl_Texture.cxx +++ b/src/OpenGl/OpenGl_Texture.cxx @@ -443,7 +443,6 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx, return false; } } - theCtx->core11fwd->glTexImage2D (GL_TEXTURE_2D, 0, anIntFormat, theSizeXYZ.x(), theSizeXYZ.y(), 0, theFormat.PixelFormat(), theFormat.DataType(), aDataPtr); @@ -520,9 +519,48 @@ bool OpenGl_Texture::Init (const Handle(OpenGl_Context)& theCtx, } case Graphic3d_TypeOfTexture_CUBEMAP: { - Unbind (theCtx); - Release (theCtx.get()); - return false; + Bind (theCtx); + applyDefaultSamplerParams (theCtx); + if (theCtx->GraphicsLibrary() == Aspect_GraphicsLibrary_OpenGL) + { + // use proxy to check texture could be created or not + theCtx->core11fwd->glTexImage2D (GL_PROXY_TEXTURE_2D, 0, anIntFormat, + theSizeXYZ.x(), theSizeXYZ.y(), 0, + theFormat.PixelFormat(), theFormat.DataType(), NULL); + theCtx->core11fwd->glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &aTestWidth); + theCtx->core11fwd->glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &aTestHeight); + theCtx->core11fwd->glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &mySizedFormat); + if (aTestWidth == 0 || aTestHeight == 0) + { + // no memory or broken input parameters + Unbind(theCtx); + Release(theCtx.get()); + return false; + } + } + for (Standard_Integer aCubeIndex = 0; aCubeIndex < 6; ++aCubeIndex) + { + theCtx->core11fwd->glTexImage2D (GLenum(GL_TEXTURE_CUBE_MAP_POSITIVE_X + aCubeIndex), 0, anIntFormat, + theSizeXYZ.x(), theSizeXYZ.y(), 0, + theFormat.PixelFormat(), theFormat.DataType(), aDataPtr); + GLenum anErr = theCtx->core11fwd->glGetError(); + if (anErr != GL_NO_ERROR) + { + theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, + TCollection_AsciiString ("Error: Cubemap texture ") + theSizeXYZ.x() + "x" + theSizeXYZ.y() + + " IF: " + OpenGl_TextureFormat::FormatFormat (anIntFormat) + + " PF: " + OpenGl_TextureFormat::FormatFormat (theFormat.PixelFormat()) + + " DT: " + OpenGl_TextureFormat::FormatDataType (theFormat.DataType()) + + " can not be created with error " + OpenGl_Context::FormatGlError (anErr) + + " [" + myResourceId + "]"); + Unbind (theCtx); + Release (theCtx.get()); + return false; + } + } + + mySize.SetValues (theSizeXYZ.xy(), 1); + break; } } diff --git a/src/OpenGl/OpenGl_View.cxx b/src/OpenGl/OpenGl_View.cxx index 7907795567..22ee42fad0 100644 --- a/src/OpenGl/OpenGl_View.cxx +++ b/src/OpenGl/OpenGl_View.cxx @@ -1583,31 +1583,73 @@ bool OpenGl_View::prepareFrameBuffers (Graphic3d_Camera::Projection& theProj) && myRenderParams.Method != Graphic3d_RM_RAYTRACING; if (toUseShadowMap) { + Standard_Integer aNbShadows = 0; + Standard_Integer aNbPointShadows = 0; + Standard_Boolean aToReviewLights = Standard_False; + for (Graphic3d_LightSet::Iterator aLightIter(myLights); aLightIter.More(); aLightIter.Next()) + { + Handle(Graphic3d_CLight) aLight = aLightIter.Value(); + if (aLight->Type() == Graphic3d_TypeOfLightSource_Positional) + { + // point lights shadows are not currently supported on opengles 2.0 + if (aCtx->GraphicsLibrary() == Aspect_GraphicsLibrary_OpenGLES + && aCtx->VersionMajor() <= 2) + { + aLight->SetCastShadows (Standard_False); + aToReviewLights = Standard_True; + } + else if (aLight->ToCastShadows()) + { + ++aNbPointShadows; + } + } + else + { + if (aLight->ToCastShadows()) + { + ++aNbShadows; + } + } + } + if (aToReviewLights) + { + myLights->UpdateRevision(); + } 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) + const GLint aSampleFrom = GLint(aCtx->ShadowMapTexUnit()) - myLights->NbCastShadows() + aNbPointShadows + 1; + const GLint aSampleCubeFrom = GLint(aCtx->ShadowCubeMapTexUnit()) - aNbPointShadows + 1; + Standard_Integer aLightIndex = 0; + Standard_Integer a2DShadowIndex = 0; + Standard_Integer aCubeShadowIndex = 0; + for (Graphic3d_LightSet::Iterator aLightIter(myLights); aLightIter.More(); aLightIter.Next()) { - Handle(OpenGl_ShadowMap)& aShadow = myShadowMaps->ChangeValue (aShadowIter); - if (aShadow.IsNull()) + Handle(Graphic3d_CLight) aLight = aLightIter.Value(); + if (aLight->ToCastShadows()) { - 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, Graphic3d_Vec2i (myRenderParams.ShadowMapResolution), aDummy, myFboDepthFormat, 0)) + Handle(OpenGl_ShadowMap)& aShadow = myShadowMaps->ChangeValue (aLightIndex++); + if (aShadow.IsNull()) { - toUseShadowMap = false; + aShadow = new OpenGl_ShadowMap(); + } + aShadow->SetShadowMapBias (myRenderParams.ShadowMapBias); + Standard_Integer aTexUnit = aLight->Type() == Graphic3d_TypeOfLightSource_Positional + ? aSampleCubeFrom + aCubeShadowIndex++ + : aSampleFrom + a2DShadowIndex++; + aShadow->Texture()->Sampler()->Parameters()->SetTextureUnit ((Graphic3d_TextureUnit)(aTexUnit)); + const Handle(OpenGl_FrameBuffer)& aShadowFbo = aShadow->FrameBuffer(); + if (aShadowFbo->GetVPSizeX() != myRenderParams.ShadowMapResolution + && toUseShadowMap) + { + OpenGl_ColorFormats aDummy; + if (!aShadowFbo->Init (aCtx, Graphic3d_Vec2i(myRenderParams.ShadowMapResolution), aDummy, myFboDepthFormat, 0, + aLight->Type() == Graphic3d_TypeOfLightSource_Positional)) + { + toUseShadowMap = false; + } } } } @@ -1688,7 +1730,22 @@ void OpenGl_View::Redraw() { const Handle(OpenGl_ShadowMap)& aShadowMap = myShadowMaps->ChangeValue (aShadowIndex); aShadowMap->SetLightSource (aLight); - renderShadowMap (aShadowMap); + if (aLight->Type() == Graphic3d_TypeOfLightSource_Positional) + { + // point light shadows are not currently supported on opengles 2.0. + if (aCtx->GraphicsLibrary() != Aspect_GraphicsLibrary_OpenGLES + || aCtx->VersionMajor() >= 3) + { + for (Standard_Integer aCubeFace = 0; aCubeFace < 6; ++aCubeFace) + { + renderShadowMap (aShadowMap, aCubeFace); + } + } + } + else + { + renderShadowMap (aShadowMap, -1); + } ++aShadowIndex; } } @@ -2297,10 +2354,11 @@ bool OpenGl_View::blitSubviews (const Graphic3d_Camera::Projection , //function : renderShadowMap //purpose : //======================================================================= -void OpenGl_View::renderShadowMap (const Handle(OpenGl_ShadowMap)& theShadowMap) +void OpenGl_View::renderShadowMap (const Handle(OpenGl_ShadowMap)& theShadowMap, + const Standard_Integer theFace) { const Handle(OpenGl_Context)& aCtx = myWorkspace->GetGlContext(); - if (!theShadowMap->UpdateCamera (*this)) + if (!theShadowMap->UpdateCamera (*this, NULL, theFace)) { return; } @@ -2319,7 +2377,14 @@ void OpenGl_View::renderShadowMap (const Handle(OpenGl_ShadowMap)& theShadowMap) aCtx->ShaderManager()->SetShadingModel (Graphic3d_TypeOfShadingModel_Unlit); const Handle(OpenGl_FrameBuffer)& aShadowBuffer = theShadowMap->FrameBuffer(); - aShadowBuffer->BindBuffer (aCtx); + if (theFace < 0) + { + aShadowBuffer->BindBuffer (aCtx); + } + else + { + aShadowBuffer->BindBufferCube (aCtx, theFace); + } aShadowBuffer->SetupViewport (aCtx); aCtx->SetColorMask (false); @@ -2329,9 +2394,9 @@ void OpenGl_View::renderShadowMap (const Handle(OpenGl_ShadowMap)& theShadowMap) 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->glDepthMask (GL_TRUE); aCtx->core11fwd->glClear (GL_DEPTH_BUFFER_BIT); Graphic3d_Camera::Projection aProjection = theShadowMap->LightSource()->Type() == Graphic3d_TypeOfLightSource_Directional @@ -2345,10 +2410,9 @@ void OpenGl_View::renderShadowMap (const Handle(OpenGl_ShadowMap)& theShadowMap) 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"); - + //Image_AlienPixMap anImage; anImage.InitZero (Image_Format_GrayF, 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(); } diff --git a/src/OpenGl/OpenGl_View.hxx b/src/OpenGl/OpenGl_View.hxx index 17768a06d1..878e7d276c 100644 --- a/src/OpenGl/OpenGl_View.hxx +++ b/src/OpenGl/OpenGl_View.hxx @@ -354,7 +354,9 @@ 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); + //! @param theFace [in] value for cubemap face. + Standard_EXPORT virtual void renderShadowMap (const Handle(OpenGl_ShadowMap)& theShadowMap, + const Standard_Integer theFace); //! Renders the graphical contents of the view into the preprepared window or framebuffer. //! @param theProjection [in] the projection that should be used for rendering. diff --git a/src/Shaders/Declarations.glsl b/src/Shaders/Declarations.glsl index ea4bc6ca15..ae38e0a848 100644 --- a/src/Shaders/Declarations.glsl +++ b/src/Shaders/Declarations.glsl @@ -113,6 +113,10 @@ #define INV_PI 0.318309886 #define INV_PI_2 0.159154943 +// Point light depth range values +#define POINTLIGHT_ZNEAR 1.0 +#define POINTLIGHT_ZFAR 3000.0 + // Matrix state uniform mat4 occWorldViewMatrix; //!< World-view matrix uniform mat4 occProjectionMatrix; //!< Projection matrix diff --git a/src/Shaders/FILES b/src/Shaders/FILES index f509a23877..ba9211bf5d 100644 --- a/src/Shaders/FILES +++ b/src/Shaders/FILES @@ -1,6 +1,7 @@ srcinc:::Declarations.glsl srcinc:::DeclarationsImpl.glsl srcinc:::LightShadow.glsl +srcinc:::LightPointShadow.glsl srcinc:::PBRCookTorrance.glsl srcinc:::PBRDirectionalLight.glsl srcinc:::PBRDistribution.glsl @@ -28,6 +29,7 @@ srcinc:::SkydomBackground.fs Shaders_Declarations_glsl.pxx Shaders_DeclarationsImpl_glsl.pxx Shaders_LightShadow_glsl.pxx +Shaders_LightPointShadow_glsl.pxx Shaders_Display_fs.pxx Shaders_PBRCookTorrance_glsl.pxx Shaders_PBRDirectionalLight_glsl.pxx diff --git a/src/Shaders/LightPointShadow.glsl b/src/Shaders/LightPointShadow.glsl new file mode 100644 index 0000000000..463287c40e --- /dev/null +++ b/src/Shaders/LightPointShadow.glsl @@ -0,0 +1,24 @@ +//! Function computes point light shadow attenuation (1.0 means no shadow). +float occLightPointShadow (in samplerCube theShadow, + //in vec2 theDepthRange, + in int theId, + in vec3 thePoint, + in vec3 theNormal) +{ + vec4 aPosLightSpace = PosLightSpace[occLight_Index(theId)]; + vec3 aLightDir = thePoint - occLight_Position (theId); + // convert light-to-fragment vector to a depth value. + vec3 anAbsVec = abs (aLightDir); + float aLocalZcomp = max (anAbsVec.x, max (anAbsVec.y, anAbsVec.z)); + // set znear and zfar + float aNear = POINTLIGHT_ZNEAR; + float aFar = POINTLIGHT_ZFAR; + float aNormZComp = (aFar + aNear) / (aFar - aNear) - (2.0 * aFar * aNear) / (aFar - aNear) / aLocalZcomp; + float aDist = (aNormZComp + 1.0) * 0.5; + // calculate bias and test depth. + aLightDir = normalize (aLightDir); + float aBias = min (occShadowMapSizeBias.y * (1.0 - dot (theNormal, aLightDir)), occShadowMapSizeBias.y * 0.1); + float aClosestDepth = occTextureCube (theShadow, aLightDir).r; + float aShadow = (aDist - aBias) > aClosestDepth ? 1.0 : 0.0; + return 1.0 - aShadow; +} diff --git a/src/Shaders/PBRPointLight.glsl b/src/Shaders/PBRPointLight.glsl index d6c0fca936..2d71dc1963 100644 --- a/src/Shaders/PBRPointLight.glsl +++ b/src/Shaders/PBRPointLight.glsl @@ -9,7 +9,8 @@ void occPointLight (in int theId, in vec3 theNormal, in vec3 theView, in vec3 thePoint, - in bool theIsFront) + in bool theIsFront, + in float theShadow) { vec3 aLight = occLight_Position (theId) - thePoint; @@ -23,5 +24,5 @@ void occPointLight (in int theId, DirectLighting += occPBRIllumination (theView, aLight, theNormal, BaseColor, Metallic, Roughness, IOR, occLight_Specular (theId), - occLight_Intensity(theId) * anAtten); + occLight_Intensity(theId) * anAtten) * theShadow; } diff --git a/src/Shaders/PhongPointLight.glsl b/src/Shaders/PhongPointLight.glsl index 1b49bfe7dd..67ae629ad7 100644 --- a/src/Shaders/PhongPointLight.glsl +++ b/src/Shaders/PhongPointLight.glsl @@ -9,7 +9,8 @@ void occPointLight (in int theId, in vec3 theNormal, in vec3 theView, in vec3 thePoint, - in bool theIsFront) + in bool theIsFront, + in float theShadow) { vec3 aLight = occLight_Position (theId) - thePoint; @@ -31,6 +32,6 @@ void occPointLight (in int theId, aSpecl = pow (aNdotH, occMaterial_Shininess (theIsFront)); } - Diffuse += occLight_Diffuse (theId) * aNdotL * anAtten; - Specular += occLight_Specular(theId) * aSpecl * anAtten; + Diffuse += occLight_Diffuse (theId) * aNdotL * anAtten * theShadow; + Specular += occLight_Specular(theId) * aSpecl * anAtten * theShadow; } diff --git a/src/Shaders/Shaders_Declarations_glsl.pxx b/src/Shaders/Shaders_Declarations_glsl.pxx index 0485a491c6..e1083c6308 100644 --- a/src/Shaders/Shaders_Declarations_glsl.pxx +++ b/src/Shaders/Shaders_Declarations_glsl.pxx @@ -116,6 +116,10 @@ static const char Shaders_Declarations_glsl[] = "#define INV_PI 0.318309886\n" "#define INV_PI_2 0.159154943\n" "\n" + "// Point light depth range values\n" + "#define POINTLIGHT_ZNEAR 1.0\n" + "#define POINTLIGHT_ZFAR 3000.0\n" + "\n" "// Matrix state\n" "uniform mat4 occWorldViewMatrix; //!< World-view matrix\n" "uniform mat4 occProjectionMatrix; //!< Projection matrix\n" diff --git a/src/Shaders/Shaders_LightPointShadow_glsl.pxx b/src/Shaders/Shaders_LightPointShadow_glsl.pxx new file mode 100644 index 0000000000..1389d6ba32 --- /dev/null +++ b/src/Shaders/Shaders_LightPointShadow_glsl.pxx @@ -0,0 +1,27 @@ +// This file has been automatically generated from resource file src/Shaders/LightShadow.glsl + +static const char Shaders_LightPointShadow_glsl[] = + "//! Function computes point light shadow attenuation (1.0 means no shadow).\n" + "float occLightPointShadow (in samplerCube theShadow,\n" + " //in vec2 theDepthRange,\n" + " in int theId,\n" + " in vec3 thePoint,\n" + " in vec3 theNormal)\n" + "{\n" + " vec4 aPosLightSpace = PosLightSpace[occLight_Index(theId)];\n" + " vec3 aLightDir = thePoint - occLight_Position (theId);\n" + " // convert light-to-fragment vector to a depth value.\n" + " vec3 anAbsVec = abs (aLightDir);\n" + " float aLocalZcomp = max (anAbsVec.x, max (anAbsVec.y, anAbsVec.z));\n" + " // set znear and zfar\n" + " float aNear = POINTLIGHT_ZNEAR;\n" + " float aFar = POINTLIGHT_ZFAR;\n" + " float aNormZComp = (aFar + aNear) / (aFar-aNear) - (2.0 * aFar * aNear) / (aFar - aNear) / aLocalZcomp;\n" + " float aDist = (aNormZComp + 1.0) * 0.5;\n" + " // calculate bias and test depth.\n" + " aLightDir = normalize (aLightDir);\n" + " float aBias = min (occShadowMapSizeBias.y * (1.0 - dot (theNormal, aLightDir)), occShadowMapSizeBias.y * 0.1);\n" + " float aClosestDepth = occTextureCube (theShadow, aLightDir).r;\n" + " float aShadow = (aDist - aBias) > aClosestDepth ? 1.0 : 0.0;\n" + " return 1.0 - aShadow;\n" + "}\n"; diff --git a/src/Shaders/Shaders_PBRPointLight_glsl.pxx b/src/Shaders/Shaders_PBRPointLight_glsl.pxx index d08f5908e8..909fc3dba2 100644 --- a/src/Shaders/Shaders_PBRPointLight_glsl.pxx +++ b/src/Shaders/Shaders_PBRPointLight_glsl.pxx @@ -12,7 +12,8 @@ static const char Shaders_PBRPointLight_glsl[] = " in vec3 theNormal,\n" " in vec3 theView,\n" " in vec3 thePoint,\n" - " in bool theIsFront)\n" + " in bool theIsFront,\n" + " in float theShadow)\n" "{\n" " vec3 aLight = occLight_Position (theId) - thePoint;\n" "\n" @@ -26,5 +27,5 @@ static const char Shaders_PBRPointLight_glsl[] = " DirectLighting += occPBRIllumination (theView, aLight, theNormal,\n" " BaseColor, Metallic, Roughness, IOR,\n" " occLight_Specular (theId),\n" - " occLight_Intensity(theId) * anAtten);\n" + " occLight_Intensity(theId) * anAtten) * theShadow;\n" "}\n"; diff --git a/src/Shaders/Shaders_PhongPointLight_glsl.pxx b/src/Shaders/Shaders_PhongPointLight_glsl.pxx index 9b48db353d..87b784e693 100644 --- a/src/Shaders/Shaders_PhongPointLight_glsl.pxx +++ b/src/Shaders/Shaders_PhongPointLight_glsl.pxx @@ -12,7 +12,8 @@ static const char Shaders_PhongPointLight_glsl[] = " in vec3 theNormal,\n" " in vec3 theView,\n" " in vec3 thePoint,\n" - " in bool theIsFront)\n" + " in bool theIsFront,\n" + " in float theShadow)\n" "{\n" " vec3 aLight = occLight_Position (theId) - thePoint;\n" "\n" @@ -34,6 +35,6 @@ static const char Shaders_PhongPointLight_glsl[] = " aSpecl = pow (aNdotH, occMaterial_Shininess (theIsFront));\n" " }\n" "\n" - " Diffuse += occLight_Diffuse (theId) * aNdotL * anAtten;\n" - " Specular += occLight_Specular(theId) * aSpecl * anAtten;\n" + " Diffuse += occLight_Diffuse (theId) * aNdotL * anAtten * theShadow;\n" + " Specular += occLight_Specular(theId) * aSpecl * anAtten * theShadow;\n" "}\n"; diff --git a/tests/opengl/data/shadows/pointlight b/tests/opengl/data/shadows/pointlight new file mode 100644 index 0000000000..0c5ae9fcd4 --- /dev/null +++ b/tests/opengl/data/shadows/pointlight @@ -0,0 +1,58 @@ +puts "========" +puts "0032173: Visualization, TKOpenGl - implement simple shadow mapping for a point light source" +puts "Test shadow map from a point light source on multiple boxes." +puts "========" + +pload MODELING VISUALIZATION +if { $::tcl_platform(os) == "Darwin" } { vcaps -core } +vclear +vinit View1 +vrenderparams -shadingModel phong +# add geometry +box b1 20 0 0 10 10 10 +box b2 -20 0 0 10 10 10 +box b3 -50 -20 -25 100 5 50 +box b4 0 10 0 5 5 5 +box b5 0 0 5 3 3 3 +box b6 0 0 -5 7 7 7 +box b7 0 -5 -10 3 3 3 +vdisplay -dispmode 1 b1 b2 b3 b4 b5 b6 b7 +vfit +# add colors +vsetcolor b1 RED3 +vsetcolor b2 GREEN3 +vsetcolor b3 BLUE3 +vsetcolor b4 ORANGE3 +vsetcolor b5 YELLOW3 +vsetcolor b6 SALMON3 +vsetcolor b7 PURPLE3 +# add light +vlight -clear +vlight pntlight1 -type POSITIONAL -pos 0 100 0 -intensity 1000 -castShadows 1 + +#dump single light phong +vviewparams -scale 8.0 -proj 0.0 1.0 0.0 -up 0.0 0.0 1.0 -at 0.0 0.0 0.0 +vdump $imagedir/${casename}_single_pointlight_phong1.png +vviewparams -scale 8.0 -proj 0.5 1.0 0.0 -up 0.0 0.0 1.0 -at 0.0 0.0 0.0 +vdump $imagedir/${casename}_single_pointlight_phong2.png +#dump single light pbr +vrenderparams -shadingModel pbr +vviewparams -scale 10.0 -proj 0.0 1.0 0.0 -up 0.0 0.0 1.0 -at 0.0 0.0 0.0 +vdump $imagedir/${casename}_single_pointlight_pbr1.png +vviewparams -scale 10.0 -proj 0.2 1.0 0.0 -up 0.0 0.0 1.0 -at 0.0 0.0 0.0 +vdump $imagedir/${casename}_single_pointlight_pbr2.png + +#add second light +vlight pntlight2 -type POSITIONAL -pos 40 100 0 -intensity 1000 -castShadows 1 +#dump double light phong +vrenderparams -shadingModel phong +vviewparams -scale 8.0 -proj 0.0 1.0 0.0 -up 0.0 0.0 1.0 -at 0.0 0.0 0.0 +vdump $imagedir/${casename}_double_pointlight_phong1.png +vviewparams -scale 8.0 -proj 0.5 1.0 0.0 -up 0.0 0.0 1.0 -at 0.0 0.0 0.0 +vdump $imagedir/${casename}_double_pointlight_phong2.png +#dump double light pbr +vrenderparams -shadingModel pbr +vviewparams -scale 10.0 -proj 0.0 1.0 0.0 -up 0.0 0.0 1.0 -at 0.0 0.0 0.0 +vdump $imagedir/${casename}_double_pointlight_pbr1.png +vviewparams -scale 10.0 -proj -0.2 1.0 0.0 -up 0.0 0.0 1.0 -at 0.0 0.0 0.0 +vdump $imagedir/${casename}_double_pointlight_pbr2.png