From: mzernova Date: Wed, 24 Aug 2022 12:04:10 +0000 (+0300) Subject: 0032172: Visualization, TKOpenGl - implement simple shadow mapping for a spot light... X-Git-Tag: V7_7_0_beta~24 X-Git-Url: http://git.dev.opencascade.org/gitweb/?a=commitdiff_plain;h=06aa200142ee691919dd364162992f47b1ae4b01;p=occt.git 0032172: Visualization, TKOpenGl - implement simple shadow mapping for a spot light source added test: opengl/data/shadows/spotlight --- diff --git a/src/Graphic3d/Graphic3d_CLight.cxx b/src/Graphic3d/Graphic3d_CLight.cxx index 4aa8a4bdfb..8283af632d 100644 --- a/src/Graphic3d/Graphic3d_CLight.cxx +++ b/src/Graphic3d/Graphic3d_CLight.cxx @@ -149,7 +149,8 @@ void Graphic3d_CLight::SetEnabled (Standard_Boolean theIsOn) // ======================================================================= void Graphic3d_CLight::SetCastShadows (Standard_Boolean theToCast) { - if (myType != Graphic3d_TypeOfLightSource_Directional) + if (myType != Graphic3d_TypeOfLightSource_Directional + && myType != Graphic3d_TypeOfLightSource_Spot) { throw Standard_NotImplemented ("Graphic3d_CLight::SetCastShadows() is not implemented for this light type"); } diff --git a/src/Graphic3d/Graphic3d_ShaderManager.cxx b/src/Graphic3d/Graphic3d_ShaderManager.cxx index 6c6edc6eef..8650a554df 100644 --- a/src/Graphic3d/Graphic3d_ShaderManager.cxx +++ b/src/Graphic3d/Graphic3d_ShaderManager.cxx @@ -18,7 +18,7 @@ #include #include -#include "../Shaders/Shaders_DirectionalLightShadow_glsl.pxx" +#include "../Shaders/Shaders_LightShadow_glsl.pxx" #include "../Shaders/Shaders_PBRDistribution_glsl.pxx" #include "../Shaders/Shaders_PBRDirectionalLight_glsl.pxx" #include "../Shaders/Shaders_PBRGeometry_glsl.pxx" @@ -1165,20 +1165,6 @@ TCollection_AsciiString Graphic3d_ShaderManager::stdComputeLighting (Standard_In if (theNbLights <= THE_NB_UNROLLED_LIGHTS_MAX) { Standard_Integer anIndex = 0; - if (theNbShadowMaps > 0) - { - for (Graphic3d_LightSet::Iterator aLightIter (theLights, Graphic3d_LightSet::IterationFilter_ExcludeDisabledAndAmbient); - aLightIter.More(); aLightIter.Next()) - { - if (aLightIter.Value()->Type() == Graphic3d_TypeOfLightSource_Directional - && aLightIter.Value()->ToCastShadows()) - { - aLightsLoop = aLightsLoop + EOL" occDirectionalLight (" + anIndex + ", theNormal, theView, theIsFront," - EOL" occDirectionalLightShadow (occShadowMapSamplers[" + anIndex + "], " + anIndex + ", theNormal));"; - ++anIndex; - } - } - } for (Graphic3d_LightSet::Iterator aLightIter (theLights, Graphic3d_LightSet::IterationFilter_ExcludeDisabledAndAmbient); aLightIter.More(); aLightIter.Next()) { @@ -1193,9 +1179,14 @@ TCollection_AsciiString Graphic3d_ShaderManager::stdComputeLighting (Standard_In if (theNbShadowMaps > 0 && aLightIter.Value()->ToCastShadows()) { - break; + aLightsLoop = aLightsLoop + + EOL" occDirectionalLight (" + anIndex + ", theNormal, theView, theIsFront," + EOL" occLightShadow (occShadowMapSamplers[" + anIndex + "], " + anIndex + ", theNormal));"; + } + else + { + aLightsLoop = aLightsLoop + EOL" occDirectionalLight (" + anIndex + ", theNormal, theView, theIsFront, 1.0);"; } - aLightsLoop = aLightsLoop + EOL" occDirectionalLight (" + anIndex + ", theNormal, theView, theIsFront, 1.0);"; ++anIndex; break; } @@ -1207,7 +1198,17 @@ TCollection_AsciiString Graphic3d_ShaderManager::stdComputeLighting (Standard_In } case Graphic3d_TypeOfLightSource_Spot: { - aLightsLoop = aLightsLoop + EOL" occSpotLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);"; + if (theNbShadowMaps > 0 + && aLightIter.Value()->ToCastShadows()) + { + aLightsLoop = aLightsLoop + + EOL" occSpotLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront," + EOL" occLightShadow (occShadowMapSamplers[" + anIndex + "], " + anIndex + ", theNormal));"; + } + else + { + aLightsLoop = aLightsLoop + EOL" occSpotLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront, 1.0);"; + } ++anIndex; break; } @@ -1254,7 +1255,7 @@ TCollection_AsciiString Graphic3d_ShaderManager::stdComputeLighting (Standard_In aLightsLoop += EOL" if (aType == OccLightType_Spot)" EOL" {" - EOL" occSpotLight (anIndex, theNormal, theView, aPoint, theIsFront);" + EOL" occSpotLight (anIndex, theNormal, theView, aPoint, theIsFront, 1.0);" EOL" }"; } aLightsLoop += EOL" }"; @@ -1269,6 +1270,7 @@ TCollection_AsciiString Graphic3d_ShaderManager::stdComputeLighting (Standard_In aLightsFunc += Shaders_PBRIllumination_glsl; } + bool isShadowShaderAdded = false; if (theLights->NbEnabledLightsOfType (Graphic3d_TypeOfLightSource_Directional) == 1 && theNbLights == 1 && !theIsPBR @@ -1280,9 +1282,10 @@ TCollection_AsciiString Graphic3d_ShaderManager::stdComputeLighting (Standard_In } else if (theLights->NbEnabledLightsOfType (Graphic3d_TypeOfLightSource_Directional) > 0) { - if (theNbShadowMaps > 0) + if (theNbShadowMaps > 0 && !isShadowShaderAdded) { - aLightsFunc += Shaders_DirectionalLightShadow_glsl; + aLightsFunc += Shaders_LightShadow_glsl; + isShadowShaderAdded = true; } aLightsFunc += theIsPBR ? Shaders_PBRDirectionalLight_glsl : Shaders_PhongDirectionalLight_glsl; } @@ -1292,6 +1295,10 @@ TCollection_AsciiString Graphic3d_ShaderManager::stdComputeLighting (Standard_In } if (theLights->NbEnabledLightsOfType (Graphic3d_TypeOfLightSource_Spot) > 0) { + if (theNbShadowMaps > 0 && !isShadowShaderAdded) + { + aLightsFunc += Shaders_LightShadow_glsl; + } aLightsFunc += theIsPBR ? Shaders_PBRSpotLight_glsl : Shaders_PhongSpotLight_glsl; } } diff --git a/src/OpenGl/OpenGl_ShaderManager.hxx b/src/OpenGl/OpenGl_ShaderManager.hxx index 00cbbb1e5f..f8dc9da70b 100644 --- a/src/OpenGl/OpenGl_ShaderManager.hxx +++ b/src/OpenGl/OpenGl_ShaderManager.hxx @@ -268,7 +268,7 @@ public: { if (myLightSourceState.ShadowMaps().IsNull() || myLightSourceState.ToCastShadows() == theToCast) - { + { return myLightSourceState.ToCastShadows(); } diff --git a/src/OpenGl/OpenGl_ShadowMap.cxx b/src/OpenGl/OpenGl_ShadowMap.cxx index 2ca10fd601..14854d9128 100644 --- a/src/OpenGl/OpenGl_ShadowMap.cxx +++ b/src/OpenGl/OpenGl_ShadowMap.cxx @@ -138,9 +138,41 @@ bool OpenGl_ShadowMap::UpdateCamera (const Graphic3d_CView& theView, } case Graphic3d_TypeOfLightSource_Spot: { - //myShadowCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective); - //myShadowCamera->SetEye (theCastShadowLight->Position()); - return false; // not implemented + if (theOrigin != NULL) + { + Graphic3d_Mat4d aTrans; + aTrans.Translate (Graphic3d_Vec3d (theOrigin->X(), theOrigin->Y(), theOrigin->Z())); + Graphic3d_Mat4d anOrientMat = myShadowCamera->OrientationMatrix() * aTrans; + myLightMatrix = myShadowCamera->ProjectionMatrixF() * Graphic3d_Mat4 (anOrientMat); + return true; + } + + Graphic3d_Vec4d aDir (myShadowLight->Direction().X(), myShadowLight->Direction().Y(), myShadowLight->Direction().Z(), 0.0); + if (myShadowLight->IsHeadlight()) + { + Graphic3d_Mat4d anOrientInv; + theView.Camera()->OrientationMatrix().Inverted (anOrientInv); + aDir = anOrientInv * aDir; + } + + myShadowCamera->SetZeroToOneDepth (theView.Camera()->IsZeroToOneDepth()); + myShadowCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective); + + const gp_Pnt& aLightPos = myShadowLight->Position(); + Standard_Real aDistance (aMinMaxBox.Distance (Bnd_Box (aLightPos, aLightPos)) + + aMinMaxBox.CornerMin().Distance (aMinMaxBox.CornerMax())); + myShadowCamera->SetDistance (aDistance); + myShadowCamera->MoveEyeTo (aLightPos); + myShadowCamera->SetDirectionFromEye (myShadowLight->Direction()); + myShadowCamera->SetUp (!myShadowCamera->Direction().IsParallel (gp::DY(), Precision::Angular()) + ? gp::DY() + : gp::DX()); + myShadowCamera->OrthogonalizeUp(); + myShadowCamera->SetZRange (1.0, aDistance); + + myLightMatrix = myShadowCamera->ProjectionMatrixF() * myShadowCamera->OrientationMatrixF(); + + return true; } } return false; diff --git a/src/OpenGl/OpenGl_View.cxx b/src/OpenGl/OpenGl_View.cxx index 9eb16aeae7..7907795567 100644 --- a/src/OpenGl/OpenGl_View.cxx +++ b/src/OpenGl/OpenGl_View.cxx @@ -2334,9 +2334,12 @@ void OpenGl_View::renderShadowMap (const Handle(OpenGl_ShadowMap)& theShadowMap) aCtx->core11fwd->glClearDepth (1.0); aCtx->core11fwd->glClear (GL_DEPTH_BUFFER_BIT); + Graphic3d_Camera::Projection aProjection = theShadowMap->LightSource()->Type() == Graphic3d_TypeOfLightSource_Directional + ? Graphic3d_Camera::Projection_Orthographic + : Graphic3d_Camera::Projection_Perspective; myWorkspace->SetRenderFilter (myWorkspace->RenderFilter() | OpenGl_RenderFilter_SkipTrsfPersistence); - renderScene (Graphic3d_Camera::Projection_Orthographic, aShadowBuffer.get(), NULL, false); - myWorkspace->SetRenderFilter (myWorkspace->RenderFilter() & ~(Standard_Integer )OpenGl_RenderFilter_SkipTrsfPersistence); + renderScene (aProjection, aShadowBuffer.get(), NULL, false); + myWorkspace->SetRenderFilter (myWorkspace->RenderFilter() & ~(Standard_Integer)OpenGl_RenderFilter_SkipTrsfPersistence); aCtx->SetColorMask (true); myWorkspace->ResetAppliedAspect(); diff --git a/src/Shaders/DirectionalLightShadow.glsl b/src/Shaders/DirectionalLightShadow.glsl deleted file mode 100644 index d0447fd570..0000000000 --- a/src/Shaders/DirectionalLightShadow.glsl +++ /dev/null @@ -1,48 +0,0 @@ -#if (__VERSION__ >= 120) -//! Coefficients for gathering close samples for antialiasing. -//! Use only with decent OpenGL (array constants cannot be initialized with GLSL 1.1 / GLSL ES 1.1) -const vec2 occPoissonDisk16[16] = vec2[]( - vec2(-0.94201624,-0.39906216), vec2( 0.94558609,-0.76890725), vec2(-0.09418410,-0.92938870), vec2( 0.34495938, 0.29387760), - vec2(-0.91588581, 0.45771432), vec2(-0.81544232,-0.87912464), vec2(-0.38277543, 0.27676845), vec2( 0.97484398, 0.75648379), - vec2( 0.44323325,-0.97511554), vec2( 0.53742981,-0.47373420), vec2(-0.26496911,-0.41893023), vec2( 0.79197514, 0.19090188), - vec2(-0.24188840, 0.99706507), vec2(-0.81409955, 0.91437590), vec2( 0.19984126, 0.78641367), vec2( 0.14383161,-0.14100790) -); -#endif - -//! Function computes directional light shadow attenuation (1.0 means no shadow). -float occDirectionalLightShadow (in sampler2D theShadow, - in int theId, - in vec3 theNormal) -{ - vec4 aPosLightSpace = PosLightSpace[occLight_Index(theId)]; - vec3 aLightDir = occLight_Position (theId); - vec3 aProjCoords = (aPosLightSpace.xyz / aPosLightSpace.w); -#ifdef THE_ZERO_TO_ONE_DEPTH - aProjCoords.xy = aProjCoords.xy * 0.5 + vec2 (0.5); -#else - aProjCoords = aProjCoords * 0.5 + vec3 (0.5); -#endif - float aCurrentDepth = aProjCoords.z; - if (aProjCoords.x < 0.0 || aProjCoords.x > 1.0 - || aProjCoords.y < 0.0 || aProjCoords.y > 1.0 - || aCurrentDepth > 1.0) - { - return 1.0; - } - - vec2 aTexelSize = vec2 (occShadowMapSizeBias.x); - float aBias = max (occShadowMapSizeBias.y * (1.0 - dot (theNormal, aLightDir)), occShadowMapSizeBias.y * 0.1); -#if (__VERSION__ >= 120) - float aShadow = 0.0; - for (int aPosIter = 0; aPosIter < 16; ++aPosIter) - { - float aClosestDepth = occTexture2D (theShadow, aProjCoords.xy + occPoissonDisk16[aPosIter] * aTexelSize).r; - aShadow += (aCurrentDepth - aBias) > aClosestDepth ? 1.0 : 0.0; - } - return 1.0 - aShadow / 16.0; -#else - float aClosestDepth = occTexture2D (theShadow, aProjCoords.xy).r; - float aShadow = (aCurrentDepth - aBias) > aClosestDepth ? 1.0 : 0.0; - return 1.0 - aShadow; -#endif -} diff --git a/src/Shaders/FILES b/src/Shaders/FILES index 2a1d29017d..f509a23877 100644 --- a/src/Shaders/FILES +++ b/src/Shaders/FILES @@ -1,6 +1,6 @@ srcinc:::Declarations.glsl srcinc:::DeclarationsImpl.glsl -srcinc:::DirectionalLightShadow.glsl +srcinc:::LightShadow.glsl srcinc:::PBRCookTorrance.glsl srcinc:::PBRDirectionalLight.glsl srcinc:::PBRDistribution.glsl @@ -27,7 +27,7 @@ srcinc:::TangentSpaceNormal.glsl srcinc:::SkydomBackground.fs Shaders_Declarations_glsl.pxx Shaders_DeclarationsImpl_glsl.pxx -Shaders_DirectionalLightShadow_glsl.pxx +Shaders_LightShadow_glsl.pxx Shaders_Display_fs.pxx Shaders_PBRCookTorrance_glsl.pxx Shaders_PBRDirectionalLight_glsl.pxx diff --git a/src/Shaders/LightShadow.glsl b/src/Shaders/LightShadow.glsl new file mode 100644 index 0000000000..82dafeafb2 --- /dev/null +++ b/src/Shaders/LightShadow.glsl @@ -0,0 +1,48 @@ +#if (__VERSION__ >= 120) +//! Coefficients for gathering close samples for antialiasing. +//! Use only with decent OpenGL (array constants cannot be initialized with GLSL 1.1 / GLSL ES 1.1) +const vec2 occPoissonDisk16[16] = vec2[]( + vec2(-0.94201624,-0.39906216), vec2( 0.94558609,-0.76890725), vec2(-0.09418410,-0.92938870), vec2( 0.34495938, 0.29387760), + vec2(-0.91588581, 0.45771432), vec2(-0.81544232,-0.87912464), vec2(-0.38277543, 0.27676845), vec2( 0.97484398, 0.75648379), + vec2( 0.44323325,-0.97511554), vec2( 0.53742981,-0.47373420), vec2(-0.26496911,-0.41893023), vec2( 0.79197514, 0.19090188), + vec2(-0.24188840, 0.99706507), vec2(-0.81409955, 0.91437590), vec2( 0.19984126, 0.78641367), vec2( 0.14383161,-0.14100790) +); +#endif + +//! Function computes directional and spot light shadow attenuation (1.0 means no shadow). +float occLightShadow (in sampler2D theShadow, + in int theId, + in vec3 theNormal) +{ + vec4 aPosLightSpace = PosLightSpace[occLight_Index(theId)]; + vec3 aLightDir = occLight_Position (theId); + vec3 aProjCoords = (aPosLightSpace.xyz / aPosLightSpace.w); +#ifdef THE_ZERO_TO_ONE_DEPTH + aProjCoords.xy = aProjCoords.xy * 0.5 + vec2 (0.5); +#else + aProjCoords = aProjCoords * 0.5 + vec3 (0.5); +#endif + float aCurrentDepth = aProjCoords.z; + if (aProjCoords.x < 0.0 || aProjCoords.x > 1.0 + || aProjCoords.y < 0.0 || aProjCoords.y > 1.0 + || aCurrentDepth > 1.0) + { + return 1.0; + } + + vec2 aTexelSize = vec2 (occShadowMapSizeBias.x); + float aBias = max (occShadowMapSizeBias.y * (1.0 - dot (theNormal, aLightDir)), occShadowMapSizeBias.y * 0.1); +#if (__VERSION__ >= 120) + float aShadow = 0.0; + for (int aPosIter = 0; aPosIter < 16; ++aPosIter) + { + float aClosestDepth = occTexture2D (theShadow, aProjCoords.xy + occPoissonDisk16[aPosIter] * aTexelSize).r; + aShadow += (aCurrentDepth - aBias) > aClosestDepth ? 1.0 : 0.0; + } + return 1.0 - aShadow / 16.0; +#else + float aClosestDepth = occTexture2D (theShadow, aProjCoords.xy).r; + float aShadow = (aCurrentDepth - aBias) > aClosestDepth ? 1.0 : 0.0; + return 1.0 - aShadow; +#endif +} diff --git a/src/Shaders/PBRSpotLight.glsl b/src/Shaders/PBRSpotLight.glsl index 4692f7be02..b1ad34281c 100644 --- a/src/Shaders/PBRSpotLight.glsl +++ b/src/Shaders/PBRSpotLight.glsl @@ -9,7 +9,8 @@ void occSpotLight (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; @@ -40,5 +41,5 @@ void occSpotLight (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/PhongSpotLight.glsl b/src/Shaders/PhongSpotLight.glsl index aab56c1bf8..611ceb5543 100644 --- a/src/Shaders/PhongSpotLight.glsl +++ b/src/Shaders/PhongSpotLight.glsl @@ -5,11 +5,13 @@ //! @param theView view direction //! @param thePoint 3D position (world space) //! @param theIsFront front/back face flag +//! @param theShadow the value from shadow map void occSpotLight (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; @@ -45,6 +47,6 @@ void occSpotLight (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_DirectionalLightShadow_glsl.pxx b/src/Shaders/Shaders_DirectionalLightShadow_glsl.pxx deleted file mode 100644 index d84223d3a2..0000000000 --- a/src/Shaders/Shaders_DirectionalLightShadow_glsl.pxx +++ /dev/null @@ -1,51 +0,0 @@ -// This file has been automatically generated from resource file src/Shaders/DirectionalLightShadow.glsl - -static const char Shaders_DirectionalLightShadow_glsl[] = - "#if (__VERSION__ >= 120)\n" - "//! Coefficients for gathering close samples for antialiasing.\n" - "//! Use only with decent OpenGL (array constants cannot be initialized with GLSL 1.1 / GLSL ES 1.1)\n" - "const vec2 occPoissonDisk16[16] = vec2[](\n" - " vec2(-0.94201624,-0.39906216), vec2( 0.94558609,-0.76890725), vec2(-0.09418410,-0.92938870), vec2( 0.34495938, 0.29387760),\n" - " vec2(-0.91588581, 0.45771432), vec2(-0.81544232,-0.87912464), vec2(-0.38277543, 0.27676845), vec2( 0.97484398, 0.75648379),\n" - " vec2( 0.44323325,-0.97511554), vec2( 0.53742981,-0.47373420), vec2(-0.26496911,-0.41893023), vec2( 0.79197514, 0.19090188),\n" - " vec2(-0.24188840, 0.99706507), vec2(-0.81409955, 0.91437590), vec2( 0.19984126, 0.78641367), vec2( 0.14383161,-0.14100790)\n" - ");\n" - "#endif\n" - "\n" - "//! Function computes directional light shadow attenuation (1.0 means no shadow).\n" - "float occDirectionalLightShadow (in sampler2D theShadow,\n" - " in int theId,\n" - " in vec3 theNormal)\n" - "{\n" - " vec4 aPosLightSpace = PosLightSpace[occLight_Index(theId)];\n" - " vec3 aLightDir = occLight_Position (theId);\n" - " vec3 aProjCoords = (aPosLightSpace.xyz / aPosLightSpace.w);\n" - "#ifdef THE_ZERO_TO_ONE_DEPTH\n" - " aProjCoords.xy = aProjCoords.xy * 0.5 + vec2 (0.5);\n" - "#else\n" - " aProjCoords = aProjCoords * 0.5 + vec3 (0.5);\n" - "#endif\n" - " float aCurrentDepth = aProjCoords.z;\n" - " if (aProjCoords.x < 0.0 || aProjCoords.x > 1.0\n" - " || aProjCoords.y < 0.0 || aProjCoords.y > 1.0\n" - " || aCurrentDepth > 1.0)\n" - " {\n" - " return 1.0;\n" - " }\n" - "\n" - " vec2 aTexelSize = vec2 (occShadowMapSizeBias.x);\n" - " float aBias = max (occShadowMapSizeBias.y * (1.0 - dot (theNormal, aLightDir)), occShadowMapSizeBias.y * 0.1);\n" - "#if (__VERSION__ >= 120)\n" - " float aShadow = 0.0;\n" - " for (int aPosIter = 0; aPosIter < 16; ++aPosIter)\n" - " {\n" - " float aClosestDepth = occTexture2D (theShadow, aProjCoords.xy + occPoissonDisk16[aPosIter] * aTexelSize).r;\n" - " aShadow += (aCurrentDepth - aBias) > aClosestDepth ? 1.0 : 0.0;\n" - " }\n" - " return 1.0 - aShadow / 16.0;\n" - "#else\n" - " float aClosestDepth = occTexture2D (theShadow, aProjCoords.xy).r;\n" - " float aShadow = (aCurrentDepth - aBias) > aClosestDepth ? 1.0 : 0.0;\n" - " return 1.0 - aShadow;\n" - "#endif\n" - "}\n"; diff --git a/src/Shaders/Shaders_LightShadow_glsl.pxx b/src/Shaders/Shaders_LightShadow_glsl.pxx new file mode 100644 index 0000000000..c35efe671c --- /dev/null +++ b/src/Shaders/Shaders_LightShadow_glsl.pxx @@ -0,0 +1,51 @@ +// This file has been automatically generated from resource file src/Shaders/LightShadow.glsl + +static const char Shaders_LightShadow_glsl[] = + "#if (__VERSION__ >= 120)\n" + "//! Coefficients for gathering close samples for antialiasing.\n" + "//! Use only with decent OpenGL (array constants cannot be initialized with GLSL 1.1 / GLSL ES 1.1)\n" + "const vec2 occPoissonDisk16[16] = vec2[](\n" + " vec2(-0.94201624,-0.39906216), vec2( 0.94558609,-0.76890725), vec2(-0.09418410,-0.92938870), vec2( 0.34495938, 0.29387760),\n" + " vec2(-0.91588581, 0.45771432), vec2(-0.81544232,-0.87912464), vec2(-0.38277543, 0.27676845), vec2( 0.97484398, 0.75648379),\n" + " vec2( 0.44323325,-0.97511554), vec2( 0.53742981,-0.47373420), vec2(-0.26496911,-0.41893023), vec2( 0.79197514, 0.19090188),\n" + " vec2(-0.24188840, 0.99706507), vec2(-0.81409955, 0.91437590), vec2( 0.19984126, 0.78641367), vec2( 0.14383161,-0.14100790)\n" + ");\n" + "#endif\n" + "\n" + "//! Function computes directional and spot light shadow attenuation (1.0 means no shadow).\n" + "float occLightShadow (in sampler2D theShadow,\n" + " in int theId,\n" + " in vec3 theNormal)\n" + "{\n" + " vec4 aPosLightSpace = PosLightSpace[occLight_Index(theId)];\n" + " vec3 aLightDir = occLight_Position (theId);\n" + " vec3 aProjCoords = (aPosLightSpace.xyz / aPosLightSpace.w);\n" + "#ifdef THE_ZERO_TO_ONE_DEPTH\n" + " aProjCoords.xy = aProjCoords.xy * 0.5 + vec2 (0.5);\n" + "#else\n" + " aProjCoords = aProjCoords * 0.5 + vec3 (0.5);\n" + "#endif\n" + " float aCurrentDepth = aProjCoords.z;\n" + " if (aProjCoords.x < 0.0 || aProjCoords.x > 1.0\n" + " || aProjCoords.y < 0.0 || aProjCoords.y > 1.0\n" + " || aCurrentDepth > 1.0)\n" + " {\n" + " return 1.0;\n" + " }\n" + "\n" + " vec2 aTexelSize = vec2 (occShadowMapSizeBias.x);\n" + " float aBias = max (occShadowMapSizeBias.y * (1.0 - dot (theNormal, aLightDir)), occShadowMapSizeBias.y * 0.1);\n" + "#if (__VERSION__ >= 120)\n" + " float aShadow = 0.0;\n" + " for (int aPosIter = 0; aPosIter < 16; ++aPosIter)\n" + " {\n" + " float aClosestDepth = occTexture2D (theShadow, aProjCoords.xy + occPoissonDisk16[aPosIter] * aTexelSize).r;\n" + " aShadow += (aCurrentDepth - aBias) > aClosestDepth ? 1.0 : 0.0;\n" + " }\n" + " return 1.0 - aShadow / 16.0;\n" + "#else\n" + " float aClosestDepth = occTexture2D (theShadow, aProjCoords.xy).r;\n" + " float aShadow = (aCurrentDepth - aBias) > aClosestDepth ? 1.0 : 0.0;\n" + " return 1.0 - aShadow;\n" + "#endif\n" + "}\n"; diff --git a/src/Shaders/Shaders_PBRSpotLight_glsl.pxx b/src/Shaders/Shaders_PBRSpotLight_glsl.pxx index 92734288a1..00734d888b 100644 --- a/src/Shaders/Shaders_PBRSpotLight_glsl.pxx +++ b/src/Shaders/Shaders_PBRSpotLight_glsl.pxx @@ -12,7 +12,8 @@ static const char Shaders_PBRSpotLight_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" @@ -43,5 +44,5 @@ static const char Shaders_PBRSpotLight_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_PhongSpotLight_glsl.pxx b/src/Shaders/Shaders_PhongSpotLight_glsl.pxx index 0725975a90..e6c649337c 100644 --- a/src/Shaders/Shaders_PhongSpotLight_glsl.pxx +++ b/src/Shaders/Shaders_PhongSpotLight_glsl.pxx @@ -8,11 +8,13 @@ static const char Shaders_PhongSpotLight_glsl[] = "//! @param theView view direction\n" "//! @param thePoint 3D position (world space)\n" "//! @param theIsFront front/back face flag\n" + "//! @param theShadow the value from shadow map\n" "void occSpotLight (in int theId,\n" " 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" @@ -48,6 +50,6 @@ static const char Shaders_PhongSpotLight_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/src/ViewerTest/ViewerTest_ViewerCommands.cxx b/src/ViewerTest/ViewerTest_ViewerCommands.cxx index b295489e47..c26d53e340 100644 --- a/src/ViewerTest/ViewerTest_ViewerCommands.cxx +++ b/src/ViewerTest/ViewerTest_ViewerCommands.cxx @@ -9858,13 +9858,13 @@ static int VLight (Draw_Interpretor& theDi, << (aLight->IsEnabled() ? "ON" : "OFF") << "\n"; switch (aLight->Type()) { - case V3d_AMBIENT: + case Graphic3d_TypeOfLightSource_Ambient: { theDi << " Type: Ambient\n" << " Intensity: " << aLight->Intensity() << "\n"; break; } - case V3d_DIRECTIONAL: + case Graphic3d_TypeOfLightSource_Directional: { theDi << " Type: Directional\n" << " Intensity: " << aLight->Intensity() << "\n" @@ -9874,7 +9874,7 @@ static int VLight (Draw_Interpretor& theDi, << " Direction: " << aLight->PackedDirection().x() << " " << aLight->PackedDirection().y() << " " << aLight->PackedDirection().z() << "\n"; break; } - case V3d_POSITIONAL: + case Graphic3d_TypeOfLightSource_Positional: { theDi << " Type: Positional\n" << " Intensity: " << aLight->Intensity() << "\n" @@ -9886,7 +9886,7 @@ static int VLight (Draw_Interpretor& theDi, << " Range: " << aLight->Range() << "\n"; break; } - case V3d_SPOT: + case Graphic3d_TypeOfLightSource_Spot: { theDi << " Type: Spot\n" << " Intensity: " << aLight->Intensity() << "\n" @@ -14592,6 +14592,7 @@ Spot light parameters: -spotAngle sets spotlight angle; -spotExp sets spotlight exponenta; -headlight sets headlight flag; + -castShadows enables/disables shadow casting; -constAtten (obsolete) sets constant attenuation factor; -linearAtten (obsolete) sets linear attenuation factor. diff --git a/tests/opengl/data/shadows/spotlight b/tests/opengl/data/shadows/spotlight new file mode 100644 index 0000000000..7bed4793ed --- /dev/null +++ b/tests/opengl/data/shadows/spotlight @@ -0,0 +1,39 @@ +puts "========" +puts "0032172: Visualization, TKOpenGl - implement simple shadow mapping for a spot light source" +puts "Test shadow map from a spot light source on a box geometry." +puts "========" + +pload MODELING VISUALIZATION +if { $::tcl_platform(os) == "Darwin" } { vcaps -core } +box b 1 2 3 +box bb -5 -5 0 10 10 0 -preview +vclear +vinit View1 +vrenderparams -shadingModel phong +vdisplay -dispMode 1 b bb +vaspects b -material STONE -color blue +vaspects bb -material STONE -color red +vfit +vlight -clear +vlight lamp1 -add spot -castShadows 1 -direction 1 1 -1 -position -10 -10 10 +vlight lamp2 -add spot -castShadows 1 -direction -1 -1 -1 -position 10 10 10 -intensity 1000 +vdump $::imagedir/${::casename}_two_spots.png + +vlight -remove lamp1 + +vline lin1 10 10 10 -5 -5 -0.5 +vline lin2 10 10 10 -3.5 -5 -0.5 +vline lin3 10 10 10 -5 -2 -0.5 + +if { ![string match "OpenGL ES 2.0*" [vglinfo VERSION]] && ![string match "OpenGL ES 3.0*" [vglinfo VERSION]] } { + vraytrace 1 + vdump $::imagedir/${::casename}_raytrace.png +} + +vraytrace 0 +vrenderparams -shadingModel phong +vrenderparams -shadowMapBias 0.001 +vdump $::imagedir/${::casename}_phong.png + +vrenderparams -shadingModel pbr +vdump $::imagedir/${::casename}_pbr.png