Skip to content

Commit

Permalink
Expose shadow texture size for directional lighting in SDF (#1034)
Browse files Browse the repository at this point in the history
Signed-off-by: Athena Z <[email protected]>
Co-authored-by: Ian Chen <[email protected]>
  • Loading branch information
athenaz2 and iche033 authored Aug 16, 2024
1 parent 2acca4d commit 8edd14f
Show file tree
Hide file tree
Showing 7 changed files with 209 additions and 12 deletions.
18 changes: 18 additions & 0 deletions include/gz/rendering/Light.hh
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,24 @@ namespace gz
namespace rendering
{
inline namespace GZ_RENDERING_VERSION_NAMESPACE {

/// \enum LightType
/// \brief Enum for Light types.
enum class GZ_RENDERING_VISIBLE LightType
{
/// \brief No light type specified
EMPTY = 0,

/// \brief Point light
POINT = 1,

/// \brief Directional light
DIRECTIONAL = 2,

/// \brief Spot light
SPOT = 3
};

//
/// \class Light Light.hh gz/rendering/Light.hh
/// \brief Represents a light source in the scene graph
Expand Down
12 changes: 12 additions & 0 deletions include/gz/rendering/Scene.hh
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "gz/rendering/RenderTypes.hh"
#include "gz/rendering/Storage.hh"
#include "gz/rendering/Export.hh"
#include "gz/rendering/Light.hh"

namespace gz
{
Expand Down Expand Up @@ -1270,6 +1271,17 @@ namespace gz
/// \return true to sky is enabled, false otherwise
public: virtual bool SkyEnabled() const = 0;

/// \brief Set the shadow texture size for the given light type.
/// \param _lightType Light type that creates the shadow
/// \param _textureSize Shadow texture size
public: virtual bool SetShadowTextureSize(LightType _lightType,
unsigned int _textureSize) = 0;

/// \brief Get the shadow texture size for the given light type.
/// \param _lightType Light type that creates the shadow
public: virtual unsigned int ShadowTextureSize(LightType _lightType)
const = 0;

/// \brief Sets the given GI as the current new active GI solution
/// \param[in] _gi GI solution that should be active. Nullptr to disable
public: virtual void SetActiveGlobalIllumination(
Expand Down
8 changes: 8 additions & 0 deletions include/gz/rendering/base/BaseScene.hh
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,14 @@ namespace gz
// Documentation inherited.
public: virtual bool SkyEnabled() const override;

// Documentation inherited.
public: virtual bool SetShadowTextureSize(LightType _lightType,
unsigned int _textureSize) override;

// Documentation inherited.
public: virtual unsigned int ShadowTextureSize(LightType _lightType) const
override;

// Documentation inherited.
public: virtual void SetActiveGlobalIllumination(
GlobalIlluminationBasePtr _gi) override;
Expand Down
8 changes: 8 additions & 0 deletions ogre2/include/gz/rendering/ogre2/Ogre2Scene.hh
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,14 @@ namespace gz
// Documentation inherited
public: virtual bool SkyEnabled() const override;

// Documentation inherited
public: bool SetShadowTextureSize(LightType _lightType,
unsigned int _textureSize);

// Documentation inherited
public: unsigned int ShadowTextureSize(LightType _lightType) const
override;

// Documentation inherited
public: virtual void SetActiveGlobalIllumination(
GlobalIlluminationBasePtr _gi) override;
Expand Down
112 changes: 100 additions & 12 deletions ogre2/src/Ogre2Scene.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@
*
*/

#ifdef __APPLE__
#define GL_SILENCE_DEPRECATION
#include <OpenGL/gl.h>
#include <OpenGL/glext.h>
#else
#ifndef _WIN32
#include <GL/gl.h>
#endif
#endif

#include <gz/common/Console.hh>

#include "gz/rendering/base/SceneExt.hh"
Expand Down Expand Up @@ -90,6 +100,15 @@ class gz::rendering::Ogre2ScenePrivate
/// \brief Flag to indicate if sky is enabled or not
public: bool skyEnabled = false;

/// \brief Max shadow texture size
public: unsigned int maxTexSize = 16384u;

/// \brief Shadow texture size for directional light
public: unsigned int dirTexSize = 2048u;

/// \brief Shadow texture size for spot and point lights
public: unsigned int spotPointTexSize = 2048u;

/// \brief Flag to alert the user its usage of PreRender/PostRender
/// is incorrect
public: bool frameUpdateStarted = false;
Expand Down Expand Up @@ -651,46 +670,57 @@ void Ogre2Scene::UpdateShadowNode()

// directional lights
unsigned int atlasId = 0u;
unsigned int texSize = 2048u;
unsigned int halfTexSize = static_cast<unsigned int>(texSize * 0.5);
unsigned int dirTexSize = this->dataPtr->dirTexSize;
unsigned int halfTexSize = static_cast<unsigned int>(dirTexSize * 0.5);
for (unsigned int i = 0; i < dirLightCount; ++i)
{
shadowParam.technique = Ogre::SHADOWMAP_PSSM;
shadowParam.atlasId = atlasId;
shadowParam.numPssmSplits = 3u;
shadowParam.resolution[0].x = texSize;
shadowParam.resolution[0].y = texSize;
shadowParam.resolution[0].x = dirTexSize;
shadowParam.resolution[0].y = dirTexSize;
shadowParam.resolution[1].x = halfTexSize;
shadowParam.resolution[1].y = halfTexSize;
shadowParam.resolution[2].x = halfTexSize;
shadowParam.resolution[2].y = halfTexSize;
shadowParam.atlasStart[0].x = 0u;
shadowParam.atlasStart[0].y = 0u;
shadowParam.atlasStart[1].x = 0u;
shadowParam.atlasStart[1].y = texSize;
shadowParam.atlasStart[1].y = dirTexSize;
shadowParam.atlasStart[2].x = halfTexSize;
shadowParam.atlasStart[2].y = texSize;
shadowParam.atlasStart[2].y = dirTexSize;
shadowParam.supportedLightTypes = 0u;
shadowParam.addLightType(Ogre::Light::LT_DIRECTIONAL);
shadowParams.push_back(shadowParam);
atlasId++;
}

if (engine->GraphicsAPI() == GraphicsAPI::OPENGL)
{
GLint glMaxTexSize;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &glMaxTexSize);

// todo: there are issues when setting dirTexSize to a val larger
// than 16K
this->dataPtr->maxTexSize = std::min(this->dataPtr->maxTexSize,
static_cast<unsigned int>(glMaxTexSize));
}

// others
unsigned int maxTexSize = 8192u;
unsigned int spotPointTexSize = this->dataPtr->spotPointTexSize;
unsigned int rowIdx = 0;
unsigned int colIdx = 0;
unsigned int rowSize = maxTexSize / texSize;
unsigned int rowSize = this->dataPtr->maxTexSize / spotPointTexSize;
unsigned int colSize = rowSize;

for (unsigned int i = 0; i < spotPointLightCount; ++i)
{
shadowParam.technique = Ogre::SHADOWMAP_FOCUSED;
shadowParam.atlasId = atlasId;
shadowParam.resolution[0].x = texSize;
shadowParam.resolution[0].y = texSize;
shadowParam.atlasStart[0].x = colIdx * texSize;
shadowParam.atlasStart[0].y = rowIdx * texSize;
shadowParam.resolution[0].x = spotPointTexSize;
shadowParam.resolution[0].y = spotPointTexSize;
shadowParam.atlasStart[0].x = colIdx * spotPointTexSize;
shadowParam.atlasStart[0].y = rowIdx * spotPointTexSize;

shadowParam.supportedLightTypes = 0u;
shadowParam.addLightType(Ogre::Light::LT_DIRECTIONAL);
Expand Down Expand Up @@ -1554,6 +1584,64 @@ bool Ogre2Scene::SkyEnabled() const
return this->dataPtr->skyEnabled;
}

//////////////////////////////////////////////////
bool Ogre2Scene::SetShadowTextureSize(LightType _lightType,
unsigned int _textureSize)
{
// If _lightType is not supported, block with gzerr message
if (_lightType != LightType::DIRECTIONAL)
{
gzerr << "Light type [" << static_cast<int>(_lightType)
<< "] is not supported." << std::endl;
return false;
}

// If _textureSize exceeds max possible tex size, then use default
if (_textureSize > this->dataPtr->maxTexSize)
{
gzerr << "<texture_size> of '" << _textureSize
<< "' exceeds maximum possible texture size of "
<< this->dataPtr->maxTexSize
<< ", using default texture size" << std::endl;
return false;
}

// if _textureSize is an invalid texture size, then use default
if (_textureSize < 512u || !math::isPowerOfTwo(_textureSize))
{
gzerr << "<texture_size> of '" << _textureSize
<< "' is not a valid texture size,"
<< " using default texture size" << std::endl;
return false;
}

// Set shadow texture size as _textureSize if value is valid
if (_lightType == LightType::DIRECTIONAL)
{
this->dataPtr->dirTexSize = _textureSize;
}
return true;
}

//////////////////////////////////////////////////
unsigned int Ogre2Scene::ShadowTextureSize(LightType _lightType) const
{
// todo: return based on light type, currently only dir light is supported
switch (_lightType)
{
case LightType::DIRECTIONAL:
return this->dataPtr->dirTexSize;
case LightType::SPOT:
case LightType::POINT:
return this->dataPtr->spotPointTexSize;
default:
case LightType::EMPTY:
gzerr << "Invalid light type [" << static_cast<int>(_lightType) << "]"
<< std::endl;
return 0u;
}
}

//////////////////////////////////////////////////
void Ogre2Scene::SetActiveGlobalIllumination(GlobalIlluminationBasePtr _gi)
{
Expand Down
23 changes: 23 additions & 0 deletions src/base/BaseScene.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1475,6 +1475,29 @@ bool BaseScene::SkyEnabled() const
return false;
}

//////////////////////////////////////////////////
bool BaseScene::SetShadowTextureSize(LightType _lightType,
unsigned int _textureSize)
{
if (static_cast<int>(_lightType) || _textureSize)
{
gzerr << "Setting shadow texture size not supported by: "
<< this->Engine()->Name() << std::endl;
}
return false;
}

//////////////////////////////////////////////////
unsigned int BaseScene::ShadowTextureSize(LightType _lightType) const
{
if (static_cast<int>(_lightType))
{
gzerr << "Shadow texture size not supported by: "
<< this->Engine()->Name() << std::endl;
}
return 0;
}

//////////////////////////////////////////////////
void BaseScene::SetActiveGlobalIllumination(GlobalIlluminationBasePtr _gi)
{
Expand Down
40 changes: 40 additions & 0 deletions test/common_test/Scene_TEST.cc
Original file line number Diff line number Diff line change
Expand Up @@ -751,3 +751,43 @@ TEST_F(SceneTest, Sky)
// Clean up
engine->DestroyScene(scene);
}

/////////////////////////////////////////////////
TEST_F(SceneTest, ShadowTextureSize)
{
CHECK_SUPPORTED_ENGINE("ogre2");

auto scene = engine->CreateScene("scene");
ASSERT_NE(nullptr, scene);

// Default shadow texture size for directional light is 2048u
EXPECT_EQ(scene->ShadowTextureSize(LightType::DIRECTIONAL), 2048u);

// Currently only support setting shadow texture size for
// directional light
// If set shadow texture size for other light types, it is ignored
auto spotLight = scene->CreateSpotLight("spot_light");
auto pointLight = scene->CreatePointLight("point_light");

EXPECT_FALSE(scene->SetShadowTextureSize(LightType::POINT, 4096u));
EXPECT_EQ(scene->ShadowTextureSize(LightType::POINT), 2048u);

EXPECT_FALSE(scene->SetShadowTextureSize(LightType::SPOT, 4096u));
EXPECT_EQ(scene->ShadowTextureSize(LightType::SPOT), 2048u);

EXPECT_FALSE(scene->SetShadowTextureSize(LightType::EMPTY, 4096u));
EXPECT_EQ(scene->ShadowTextureSize(LightType::EMPTY), 0u);

// If set shadow texture size to a valid value, change it
EXPECT_TRUE(scene->SetShadowTextureSize(LightType::DIRECTIONAL, 8192u));
EXPECT_EQ(scene->ShadowTextureSize(LightType::DIRECTIONAL), 8192u);

// If set shadow texture size to an invalid value, use default
EXPECT_FALSE(scene->SetShadowTextureSize(LightType::DIRECTIONAL, 1000u));
EXPECT_EQ(scene->ShadowTextureSize(LightType::DIRECTIONAL), 8192u);

// If set shadow texture size to a value larger than maxTexSize,
// use default
EXPECT_FALSE(scene->SetShadowTextureSize(LightType::DIRECTIONAL, 32768u));
EXPECT_EQ(scene->ShadowTextureSize(LightType::DIRECTIONAL), 8192u);
}

0 comments on commit 8edd14f

Please sign in to comment.