1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-29 14:00:49 +03:00

0032172: Visualization, TKOpenGl - implement simple shadow mapping for a spot light source

added test: opengl/data/shadows/spotlight
This commit is contained in:
mzernova
2022-08-24 15:04:10 +03:00
parent acac44d571
commit 06aa200142
14 changed files with 143 additions and 54 deletions

View File

@@ -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");
}

View File

@@ -18,7 +18,7 @@
#include <Graphic3d_TextureSetBits.hxx>
#include <Message.hxx>
#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;
}
}

View File

@@ -268,7 +268,7 @@ public:
{
if (myLightSourceState.ShadowMaps().IsNull()
|| myLightSourceState.ToCastShadows() == theToCast)
{
{
return myLightSourceState.ToCastShadows();
}

View File

@@ -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;

View File

@@ -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();

View File

@@ -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

View File

@@ -9,10 +9,10 @@ const vec2 occPoissonDisk16[16] = vec2[](
);
#endif
//! Function computes directional light shadow attenuation (1.0 means no shadow).
float occDirectionalLightShadow (in sampler2D theShadow,
in int theId,
in vec3 theNormal)
//! 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);

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -1,6 +1,6 @@
// This file has been automatically generated from resource file src/Shaders/DirectionalLightShadow.glsl
// This file has been automatically generated from resource file src/Shaders/LightShadow.glsl
static const char Shaders_DirectionalLightShadow_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"
@@ -12,10 +12,10 @@ static const char Shaders_DirectionalLightShadow_glsl[] =
");\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"
"//! 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"

View File

@@ -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";

View File

@@ -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";

View File

@@ -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.