Skip to content
Open
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
9 changes: 7 additions & 2 deletions trinity/Tr2LightManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -339,16 +339,21 @@ void Tr2LightManager::AddLight( PerLightData& data )
}

float brightness = std::max( std::max( data.color.x, data.color.y ), data.color.z );

if( brightness <= 0 || data.radius <= 0 )
{
return;
}
if( !m_frustum.IsSphereVisible( reinterpret_cast<Vector4*>( &data.position ) ) )

bool isVolumetric = ( data.flags & FLAG_IS_VOLUMETRIC ) != 0;
const Vector4* sphere = reinterpret_cast<const Vector4*>( &data.position );

if( !isVolumetric && !m_frustum.IsSphereVisible( sphere ) )
{
return;
}
float size = isVolumetric ? m_frustum.GetPixelSizeAccrossEst( sphere ) : m_frustum.GetPixelSizeAccross( sphere );

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

There are issues with this approach:

We have a limit on volumetric and shadowcasting lights. Volumetric lights outside the frustum now compete with lights inside the frustum.

So for starters, we will have less volumetric lights on the screen, as large lights outside the frustum may very well be prioritized over small lights inside the frustum.

But in particular, (volumetric) shadowcasting lights outside the frustum may be prioritized over shadowcasting lights inside the frustum.

However, look at Tr2VolumetricsRenderer::RenderFogIntoReflectionMap
It calls RenderFog with ShadowQuality::SHADOW_DISABLED
Due to that, RenderFog sets shadowType = SHADOWS_DISABLED;
And then it sets resources.calculateFroxels->SetOption with "SHADOWS_DISABLED"

So you end up evicting valid shadow casters with ones that aren't visible, neither in main frustum nor in reflections - but they do cost performance, as their shadow maps will be rendered and put into the atlas! So you pay the cost for rasterization, and atlas space. And the atlas space will affect visual quality, as other lights may have their shadow maps scaled down to make space, when the atlas gets pretty full.

Also, this line in particular causes volumetric lights to have another size calculated than non-volumetric lights, and therefore the dimming factor will be different. And this is not only affecting lights in reflections, but in main frustum too! And dimming affects light color, so stuff lit by the light will look different, too.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

  1. How would we get away from that, if the lights are in the reflection probe then they may hit something and we won't be able to know about it. F.ex the light that is not in the frustum may be extremely large and bright, while the others may not be. I totally get your point and agree with it, just don't think there is anything we can do about it.
  2. Ok that is a problem wiht the resources, but same question, the lights that are outside the frustum may have a bigger impact on the overall scene than the ones that are in the frustum.
  3. Yeah I know, it was the only way I could think of to have no popping when the lights go in/out of frustum.

All of your points are valid btw.
I would love suggestions, as I don't have a clear solution on how to solve these things (yet, still thinking)

@ccp-intern ccp-intern Oct 5, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Regarding 2: As it stands, shadow casting lights are not affecting reflections, so if they are outside the frustum, they are not visible anywhere. So, unless that is subject to change as well:
You can see me removing the shadow casting flag based on quality settings in Tr2LightManager::AddLight. Similarly, you could remove the flag if the light is volumetric and outside the frustum. Then those (former shadow casting) lights would not affect performance anymore.

Regarding 3: If you always use GetPixelSizeAccrossEst, regardless whether a light is volumetric or not, then it's not inconsistent anymore.

Regarding 1: Not sure myself yet. Maybe it requires a different approach altogether. Currently the volumetric lights are selected in Tr2LightManager::ResolveLightData and stored in m_volumetricLights. Maybe we need to create a list for main frustum, and a list for reflection probe. Or 6 lists for the 6 sides of the reflection probe... VolumetricsRenderer currently gets the lights in Tr2VolumetricsRenderer::UpdatePerObjectData by calling Tr2LightManager::GetVolumetricLights.


float size = m_frustum.GetPixelSizeAccross( reinterpret_cast<Vector4*>( &data.position ) );
if( size > m_adjustedCutoff )
{
float dimming = std::min( ( size - m_adjustedCutoff ) / FADE_SIZE, 1.f );
Expand Down
Loading