Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose shadow texture size for directional lighting in SDF #1034

Merged
merged 15 commits into from
Aug 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

was there an issue with what you had before, LT_EMPTY?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing LightType to enum class ensures any usage of it is like rendering::LightType::DIRECTIONAL (or other light type values) as opposed to rendering::LT_DIRECTIONAL, so no need for LT_ in the naming anymore.


/// \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;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move this block to the top of the function so that we just return early if it's not a supported light type. Also add an else block with gzwarn msg if user specifies spot or point lights.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3b1bc7a. I also have a check for it in MinimalScene too

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