From 37f80e163c6651a5905c91f7e8c84e7dbdeac303 Mon Sep 17 00:00:00 2001 From: kgv Date: Fri, 8 Jan 2021 00:48:29 +0300 Subject: [PATCH] 0032042: Visualization, TKOpenGl - pre-multiply headlight flag into light source position OpenGl_ShaderManager::pushLightSourceState() now pre-multiplies headlight transformation. Built-in shading GLSL programs have been updated to remove special handling if headlight flag; also removed redundant pre-normalization of light source direction (already normalized implicitly by Graphic3d_CLight interface). Graphic3d_CLight::SetHeadlight() now raises exception in case of ambient light type. OpenGl_ShaderManager::SetLastView() - removed unused property. --- src/Graphic3d/Graphic3d_CLight.cxx | 4 + src/Graphic3d/Graphic3d_CLight.hxx | 3 + src/OpenGl/OpenGl_ShaderManager.cxx | 137 +++++++++---------- src/OpenGl/OpenGl_ShaderManager.hxx | 21 +-- src/OpenGl/OpenGl_View.cxx | 10 -- src/Shaders/Declarations.glsl | 6 +- src/Shaders/Shaders_Declarations_glsl.pxx | 6 +- src/ViewerTest/ViewerTest_ViewerCommands.cxx | 1 + 8 files changed, 81 insertions(+), 107 deletions(-) diff --git a/src/Graphic3d/Graphic3d_CLight.cxx b/src/Graphic3d/Graphic3d_CLight.cxx index f46c67587c..b46de002b6 100644 --- a/src/Graphic3d/Graphic3d_CLight.cxx +++ b/src/Graphic3d/Graphic3d_CLight.cxx @@ -114,6 +114,10 @@ void Graphic3d_CLight::SetEnabled (Standard_Boolean theIsOn) // ======================================================================= void Graphic3d_CLight::SetHeadlight (Standard_Boolean theValue) { + if (myType == Graphic3d_TOLS_AMBIENT) + { + throw Standard_ProgramError ("Graphic3d_CLight::SetHeadlight() is not applicable to ambient light"); + } updateRevisionIf (myIsHeadlight != theValue); myIsHeadlight = theValue; } diff --git a/src/Graphic3d/Graphic3d_CLight.hxx b/src/Graphic3d/Graphic3d_CLight.hxx index a52f0dad2c..b2218ff877 100644 --- a/src/Graphic3d/Graphic3d_CLight.hxx +++ b/src/Graphic3d/Graphic3d_CLight.hxx @@ -202,6 +202,9 @@ public: //! Returns direction of directional/spot light and range for positional/spot light in alpha channel. const Graphic3d_Vec4& PackedDirectionRange() const { return myDirection; } + //! Returns direction of directional/spot light. + Graphic3d_Vec3 PackedDirection() const { return myDirection.xyz(); } + //! @return modification counter Standard_Size Revision() const { return myRevision; } diff --git a/src/OpenGl/OpenGl_ShaderManager.cxx b/src/OpenGl/OpenGl_ShaderManager.cxx index 274b298fbd..857b5c692e 100644 --- a/src/OpenGl/OpenGl_ShaderManager.cxx +++ b/src/OpenGl/OpenGl_ShaderManager.cxx @@ -110,12 +110,7 @@ const char THE_FUNC_pointLight[] = EOL" in vec3 thePoint," EOL" in bool theIsFront)" EOL"{" - EOL" vec3 aLight = occLight_Position (theId);" - EOL" if (!occLight_IsHeadlight (theId))" - EOL" {" - EOL" aLight = vec3 (occWorldViewMatrix * vec4 (aLight, 1.0));" - EOL" }" - EOL" aLight -= thePoint;" + EOL" vec3 aLight = vec3 (occWorldViewMatrix * vec4 (occLight_Position (theId), 1.0)) - thePoint;" EOL EOL" float aDist = length (aLight);" EOL" float aRange = occLight_Range (theId);" @@ -147,12 +142,7 @@ const char THE_FUNC_PBR_pointLight[] = EOL" in vec3 thePoint," EOL" in bool theIsFront)" EOL"{" - EOL" vec3 aLight = occLight_Position (theId);" - EOL" if (occLight_IsHeadlight (theId))" - EOL" {" - EOL" aLight = vec3 (occWorldViewMatrixInverse * vec4 (aLight, 1.0));" - EOL" }" - EOL" aLight -= thePoint;" + EOL" vec3 aLight = occLight_Position (theId) - thePoint;" EOL EOL" float aDist = length (aLight);" EOL" float aRange = occLight_Range (theId);" @@ -175,14 +165,7 @@ const char THE_FUNC_spotLight[] = EOL" in vec3 thePoint," EOL" in bool theIsFront)" EOL"{" - EOL" vec3 aLight = occLight_Position (theId);" - EOL" vec3 aSpotDir = occLight_SpotDirection (theId);" - EOL" if (!occLight_IsHeadlight (theId))" - EOL" {" - EOL" aLight = vec3 (occWorldViewMatrix * vec4 (aLight, 1.0));" - EOL" aSpotDir = vec3 (occWorldViewMatrix * vec4 (aSpotDir, 0.0));" - EOL" }" - EOL" aLight -= thePoint;" + EOL" vec3 aLight = vec3 (occWorldViewMatrix * vec4 (occLight_Position (theId), 1.0)) - thePoint;" EOL EOL" float aDist = length (aLight);" EOL" float aRange = occLight_Range (theId);" @@ -190,6 +173,7 @@ const char THE_FUNC_spotLight[] = EOL" if (anAtten <= 0.0) return;" EOL" aLight /= aDist;" EOL + EOL" vec3 aSpotDir = vec3 (occWorldViewMatrix * vec4 (occLight_SpotDirection (theId), 0.0));" EOL" aSpotDir = normalize (aSpotDir);" // light cone EOL" float aCosA = dot (aSpotDir, -aLight);" @@ -228,14 +212,7 @@ const char THE_FUNC_spotLight[] = EOL" in vec3 thePoint," EOL" in bool theIsFront)" EOL"{" - EOL" vec3 aLight = occLight_Position (theId);" - EOL" vec3 aSpotDir = occLight_SpotDirection (theId);" - EOL" if (occLight_IsHeadlight (theId))" - EOL" {" - EOL" aLight = vec3 (occWorldViewMatrixInverse * vec4 (aLight, 1.0));" - EOL" aSpotDir = vec3 (occWorldViewMatrixInverse * vec4 (aSpotDir, 0.0));" - EOL" }" - EOL" aLight -= thePoint;" + EOL" vec3 aLight = occLight_Position (theId) - thePoint;" EOL EOL" float aDist = length (aLight);" EOL" float aRange = occLight_Range (theId);" @@ -243,7 +220,7 @@ const char THE_FUNC_spotLight[] = EOL" if (anAtten <= 0.0) return;" EOL" aLight /= aDist;" EOL - EOL" aSpotDir = normalize (aSpotDir);" + EOL" vec3 aSpotDir = occLight_SpotDirection (theId);" // light cone EOL" float aCosA = dot (aSpotDir, -aLight);" EOL" float aRelativeAngle = 2.0 * acos(aCosA) / occLight_SpotCutOff(theId);" @@ -274,11 +251,7 @@ const char THE_FUNC_directionalLight[] = EOL" in vec3 theView," EOL" in bool theIsFront)" EOL"{" - EOL" vec3 aLight = normalize (occLight_Position (theId));" - EOL" if (!occLight_IsHeadlight (theId))" - EOL" {" - EOL" aLight = vec3 (occWorldViewMatrix * vec4 (aLight, 0.0));" - EOL" }" + EOL" vec3 aLight = vec3 (occWorldViewMatrix * vec4 (occLight_Position (theId), 0.0));" EOL EOL" vec3 aHalf = normalize (aLight + theView);" EOL @@ -303,11 +276,7 @@ const char THE_FUNC_PBR_directionalLight[] = EOL" in vec3 theView," EOL" in bool theIsFront)" EOL"{" - EOL" vec3 aLight = normalize (occLight_Position (theId));" - EOL" if (occLight_IsHeadlight (theId))" - EOL" {" - EOL" aLight = vec3 (occWorldViewMatrixInverse * vec4 (aLight, 0.0));" - EOL" }" + EOL" vec3 aLight = occLight_Position (theId);" EOL EOL" theNormal = theIsFront ? theNormal : -theNormal;" EOL" DirectLighting += occPBRIllumination (theView, aLight, theNormal," @@ -323,11 +292,7 @@ const char THE_FUNC_directionalLightFirst[] = EOL" in vec3 theView," EOL" in bool theIsFront)" EOL"{" - EOL" vec3 aLight = normalize (occLight_Position(0));" - EOL" if (!occLight_IsHeadlight (0))" - EOL" {" - EOL" aLight = vec3 (occWorldViewMatrix * vec4 (aLight, 0.0));" - EOL" }" + EOL" vec3 aLight = vec3 (occWorldViewMatrix * vec4 (occLight_Position (0), 0.0));" EOL EOL" vec3 aHalf = normalize (aLight + theView);" EOL @@ -546,8 +511,7 @@ OpenGl_ShaderManager::OpenGl_ShaderManager (OpenGl_Context* theContext) myUnlitPrograms (new OpenGl_SetOfPrograms()), myContext (theContext), mySRgbState (theContext->ToRenderSRGB()), - myHasLocalOrigin (Standard_False), - myLastView (NULL) + myHasLocalOrigin (Standard_False) { // } @@ -910,33 +874,60 @@ void OpenGl_ShaderManager::pushLightSourceState (const Handle(OpenGl_ShaderProgr aLightType = aLight.Type(); aLightParams.Color = aLight.PackedColor(); aLightParams.Color.a() = aLight.Intensity(); // used by PBR and ignored by old shading model - if (aLight.Type() == Graphic3d_TOLS_DIRECTIONAL) - { - aLightParams.Position = -aLight.PackedDirectionRange(); - } - else if (!aLight.IsHeadlight()) - { - aLightParams.Position.x() = static_cast(aLight.Position().X() - myLocalOrigin.X()); - aLightParams.Position.y() = static_cast(aLight.Position().Y() - myLocalOrigin.Y()); - aLightParams.Position.z() = static_cast(aLight.Position().Z() - myLocalOrigin.Z()); - } - else - { - aLightParams.Position.x() = static_cast(aLight.Position().X()); - aLightParams.Position.y() = static_cast(aLight.Position().Y()); - aLightParams.Position.z() = static_cast(aLight.Position().Z()); - } - aLightParams.Position.w() = aLight.IsHeadlight() ? 1.0f : 0.0f; - - if (aLight.Type() == Graphic3d_TOLS_SPOT) - { - aLightParams.Direction = aLight.PackedDirectionRange(); - } - if (aLight.Type() == Graphic3d_TOLS_POSITIONAL) - { - aLightParams.Direction.w() = aLight.Range(); - } aLightParams.Parameters = aLight.PackedParams(); + switch (aLight.Type()) + { + case Graphic3d_TOLS_AMBIENT: + { + break; + } + case Graphic3d_TOLS_DIRECTIONAL: + { + if (aLight.IsHeadlight()) + { + const Graphic3d_Mat4& anOrientInv = myWorldViewState.WorldViewMatrixInverse(); + aLightParams.Position = anOrientInv * Graphic3d_Vec4 (-aLight.PackedDirection(), 0.0f); + } + else + { + aLightParams.Position = Graphic3d_Vec4 (-aLight.PackedDirection(), 0.0f); + } + break; + } + case Graphic3d_TOLS_SPOT: + { + if (aLight.IsHeadlight()) + { + const Graphic3d_Mat4& anOrientInv = myWorldViewState.WorldViewMatrixInverse(); + aLightParams.Direction = anOrientInv * Graphic3d_Vec4 (aLight.PackedDirection(), 0.0f); + } + else + { + aLightParams.Direction = Graphic3d_Vec4 (aLight.PackedDirection(), 0.0f); + } + } + Standard_FALLTHROUGH + case Graphic3d_TOLS_POSITIONAL: + { + if (aLight.IsHeadlight()) + { + aLightParams.Position.x() = static_cast(aLight.Position().X()); + aLightParams.Position.y() = static_cast(aLight.Position().Y()); + aLightParams.Position.z() = static_cast(aLight.Position().Z()); + const Graphic3d_Mat4& anOrientInv = myWorldViewState.WorldViewMatrixInverse(); + aLightParams.Position = anOrientInv * Graphic3d_Vec4 (aLightParams.Position.xyz(), 1.0f); + } + else + { + aLightParams.Position.x() = static_cast(aLight.Position().X() - myLocalOrigin.X()); + aLightParams.Position.y() = static_cast(aLight.Position().Y() - myLocalOrigin.Y()); + aLightParams.Position.z() = static_cast(aLight.Position().Z() - myLocalOrigin.Z()); + aLightParams.Position.w() = 0.0f; + } + aLightParams.Direction.w() = aLight.Range(); + break; + } + } ++aLightsNb; } @@ -1426,10 +1417,10 @@ void OpenGl_ShaderManager::PushState (const Handle(OpenGl_ShaderProgram)& thePro { const Handle(OpenGl_ShaderProgram)& aProgram = !theProgram.IsNull() ? theProgram : myFfpProgram; PushClippingState (aProgram); + PushLightSourceState (aProgram); // should be before PushWorldViewState() PushWorldViewState (aProgram); PushModelWorldState (aProgram); PushProjectionState (aProgram); - PushLightSourceState (aProgram); PushMaterialState (aProgram); PushOitState (aProgram); diff --git a/src/OpenGl/OpenGl_ShaderManager.hxx b/src/OpenGl/OpenGl_ShaderManager.hxx index 755be61a70..f6280fde0a 100644 --- a/src/OpenGl/OpenGl_ShaderManager.hxx +++ b/src/OpenGl/OpenGl_ShaderManager.hxx @@ -293,9 +293,11 @@ public: Standard_EXPORT void UpdateLightSourceState(); //! Pushes current state of OCCT light sources to specified program (only on state change). + //! Note that light sources definition depends also on WorldViewState. void PushLightSourceState (const Handle(OpenGl_ShaderProgram)& theProgram) const { - if (myLightSourceState.Index() != theProgram->ActiveState (OpenGl_LIGHT_SOURCES_STATE)) + if (myLightSourceState.Index() != theProgram->ActiveState (OpenGl_LIGHT_SOURCES_STATE) + || myWorldViewState.Index() != theProgram->ActiveState (OpenGl_WORLD_VIEW_STATE)) { pushLightSourceState (theProgram); } @@ -540,19 +542,6 @@ public: //! Sets shading model. Standard_EXPORT void SetShadingModel (const Graphic3d_TypeOfShadingModel theModel); - //! Sets last view manger used with. - //! Helps to handle matrix states in multi-view configurations. - void SetLastView (const OpenGl_View* theLastView) - { - myLastView = theLastView; - } - - //! Returns true when provided view is the same as cached one. - bool IsSameView (const OpenGl_View* theView) const - { - return myLastView == theView; - } - protected: //! Define clipping planes program bits. @@ -849,10 +838,6 @@ protected: mutable NCollection_Array1 myClipPlaneArrayFfp; mutable NCollection_Array1 myClipChainArray; -private: - - const OpenGl_View* myLastView; //!< Pointer to the last view shader manager used with - }; DEFINE_STANDARD_HANDLE(OpenGl_ShaderManager, Standard_Transient) diff --git a/src/OpenGl/OpenGl_View.cxx b/src/OpenGl/OpenGl_View.cxx index 5f8e602b51..449d58fdeb 100644 --- a/src/OpenGl/OpenGl_View.cxx +++ b/src/OpenGl/OpenGl_View.cxx @@ -129,7 +129,6 @@ OpenGl_View::OpenGl_View (const Handle(Graphic3d_StructureManager)& theMgr, myWorkspace = new OpenGl_Workspace (this, NULL); Handle(Graphic3d_CLight) aLight = new Graphic3d_CLight (Graphic3d_TOLS_AMBIENT); - aLight->SetHeadlight (false); aLight->SetColor (Quantity_NOC_WHITE); myLights = new Graphic3d_LightSet(); myNoShadingLight = new Graphic3d_LightSet(); @@ -2063,15 +2062,6 @@ void OpenGl_View::render (Graphic3d_Camera::Projection theProjection, { aContext->ShaderManager()->PushState (Handle(OpenGl_ShaderProgram)()); } - - // ============================================================== - // Step 6: Keep shader manager informed about last View - // ============================================================== - - if (!aManager.IsNull()) - { - aManager->SetLastView (this); - } } // ======================================================================= diff --git a/src/Shaders/Declarations.glsl b/src/Shaders/Declarations.glsl index 081fa70e7f..644fe7b2a9 100644 --- a/src/Shaders/Declarations.glsl +++ b/src/Shaders/Declarations.glsl @@ -147,10 +147,10 @@ uniform THE_PREC_ENUM int occLightSourcesCount; //!< Total number of light sour //! Intensity of light source (>= 0), float. #define occLight_Intensity(theId) occLightSources[theId * 4 + 0].a -//! Is light a headlight, bool? -#define occLight_IsHeadlight(theId) (occLightSources[theId * 4 + 1].w > 0.5) +//! Is light a headlight, bool? DEPRECATED method. +#define occLight_IsHeadlight(theId) false -//! Position of specified light source, vec3. +//! Position of specified light source or direction of directional light source, vec3. #define occLight_Position(theId) occLightSources[theId * 4 + 1].xyz //! Direction of specified spot light source, vec3. diff --git a/src/Shaders/Shaders_Declarations_glsl.pxx b/src/Shaders/Shaders_Declarations_glsl.pxx index cffec84091..b64b83d045 100644 --- a/src/Shaders/Shaders_Declarations_glsl.pxx +++ b/src/Shaders/Shaders_Declarations_glsl.pxx @@ -150,10 +150,10 @@ static const char Shaders_Declarations_glsl[] = "//! Intensity of light source (>= 0), float.\n" "#define occLight_Intensity(theId) occLightSources[theId * 4 + 0].a\n" "\n" - "//! Is light a headlight, bool?\n" - "#define occLight_IsHeadlight(theId) (occLightSources[theId * 4 + 1].w > 0.5)\n" + "//! Is light a headlight, bool? DEPRECATED method.\n" + "#define occLight_IsHeadlight(theId) false\n" "\n" - "//! Position of specified light source, vec3.\n" + "//! Position of specified light source or direction of directional light source, vec3.\n" "#define occLight_Position(theId) occLightSources[theId * 4 + 1].xyz\n" "\n" "//! Direction of specified spot light source, vec3.\n" diff --git a/src/ViewerTest/ViewerTest_ViewerCommands.cxx b/src/ViewerTest/ViewerTest_ViewerCommands.cxx index a8b8a84d05..fd09f89439 100644 --- a/src/ViewerTest/ViewerTest_ViewerCommands.cxx +++ b/src/ViewerTest/ViewerTest_ViewerCommands.cxx @@ -11562,6 +11562,7 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI, case Graphic3d_TOSM_PBR: theDI << "pbr"; break; case Graphic3d_TOSM_PBR_FACET: theDI << "pbr_facet"; break; } + theDI << "\n"; { theDI << "perfCounters:"; if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_FrameRate) != 0)