Blend between splits and fade in last one

Discussion area about developing with Ogre-Next (2.1, 2.2 and beyond)


Post Reply
User avatar
TaaTT4
OGRE Contributor
OGRE Contributor
Posts: 267
Joined: Wed Apr 23, 2014 3:49 pm
Location: Bologna, Italy
x 75
Contact:

Blend between splits and fade in last one

Post by TaaTT4 »

Ciao,

I'm far from being a shaders guru, so I ask for your help.
Is it possible to fade in the last PSSM split based on shadow distance from the camera?

Image
What i want to avoid is the shadows pop out effect when the last split becomes visible.

I've seen some other games (Assetto Corsa for example) doing something similar.


[edit] Title changed to reflect content of my own reply post
Last edited by TaaTT4 on Fri May 27, 2016 12:24 pm, edited 1 time in total.

Senior programmer at 505 Games; former senior engine programmer at Sandbox Games
Worked on: Racecraft EsportRacecraft Coin-Op, Victory: The Age of Racing

User avatar
TaaTT4
OGRE Contributor
OGRE Contributor
Posts: 267
Joined: Wed Apr 23, 2014 3:49 pm
Location: Bologna, Italy
x 75
Contact:

Re: Blend splits and fade out last one

Post by TaaTT4 »

I've solved things by myself.
A little step toward being a shaders guru 8)

Replace this block in PixelShader_ps

Code: Select all

@property( hlms_pssm_splits )
    float fShadow = 1.0;
    if( inPs.depth <= passBuf.pssmSplitPoints@value(CurrentShadowMap) )
        fShadow = getShadow( texShadowMap[@value(CurrentShadowMap)], inPs.posL0, passBuf.shadowRcv[@counter(CurrentShadowMap)].invShadowMapSize );
@foreach( hlms_pssm_splits, n, 1 )	else if( inPs.depth <= passBuf.pssmSplitPoints@value(CurrentShadowMap) )
        fShadow = getShadow( texShadowMap[@value(CurrentShadowMap)], inPs.posL@n, passBuf.shadowRcv[@counter(CurrentShadowMap)].invShadowMapSize );
@end @end @property( !hlms_pssm_splits && hlms_num_shadow_maps && hlms_lights_directional )
    float fShadow = getShadow( texShadowMap[@value(CurrentShadowMap)], inPs.posL0, passBuf.shadowRcv[@counter(CurrentShadowMap)].invShadowMapSize );
@end
with this one

Code: Select all

@property( hlms_pssm_splits )
@psub( pssm_split_n, hlms_pssm_splits, 1 )
@pset( pssm_split_blend_m, 0 )
@padd( pssm_split_blend_m_plus_1, pssm_split_blend_m, 1 )
	float pssm_split_blend_point0 = lerp( 0.0, passBuf.pssmSplitPoints@value(pssm_split_blend_m), 0.9 );
@foreach( pssm_split_n, n, 1 )	float pssm_split_blend_point@n = lerp( passBuf.pssmSplitPoints@value(pssm_split_blend_m), passBuf.pssmSplitPoints@value(pssm_split_blend_m_plus_1), 0.9 );
	@add( pssm_split_blend_m, 1 )
	@add( pssm_split_blend_m_plus_1, 1 )
@end
    float fShadow = 1.0;
	float fShadowNextSplit = 1.0;
    if( inPs.depth <= passBuf.pssmSplitPoints@value(CurrentShadowMap) )
	{
        fShadow = getShadow( texShadowMap[@value(CurrentShadowMap)], inPs.posL0, passBuf.shadowRcv[@counter(CurrentShadowMap)].invShadowMapSize );
		if( inPs.depth > pssm_split_blend_point0 )
		{
			fShadowNextSplit = getShadow( texShadowMap[@value(CurrentShadowMap)], inPs.posL@value(CurrentShadowMap), passBuf.shadowRcv[@value(CurrentShadowMap)].invShadowMapSize );
			fShadow = lerp( fShadow, fShadowNextSplit, (inPs.depth - pssm_split_blend_point0) / (passBuf.pssmSplitPoints0 - pssm_split_blend_point0) );
		}
	}
@foreach( pssm_split_n, n, 1 )	else if( inPs.depth <= passBuf.pssmSplitPoints@value(CurrentShadowMap) )
	{
        fShadow = getShadow( texShadowMap[@value(CurrentShadowMap)], inPs.posL@n, passBuf.shadowRcv[@counter(CurrentShadowMap)].invShadowMapSize );
		if( inPs.depth > pssm_split_blend_point@n )
		{
			fShadowNextSplit = getShadow( texShadowMap[@value(CurrentShadowMap)], inPs.posL@value(CurrentShadowMap), passBuf.shadowRcv[@value(CurrentShadowMap)].invShadowMapSize );
			fShadow = lerp( fShadow, fShadowNextSplit, (inPs.depth - pssm_split_blend_point@n) / (passBuf.pssmSplitPoints@n - pssm_split_blend_point@n) );
		}
	}
@end
@psub( pssm_split_m, pssm_split_n, 1 )
	else if( inPs.depth <= passBuf.pssmSplitPoints@value(pssm_split_n) )
	{
		fShadow = getShadow( texShadowMap[@value(CurrentShadowMap)], inPs.posL@value(CurrentShadowMap), passBuf.shadowRcv[@counter(CurrentShadowMap)].invShadowMapSize );
		float pssmSplitPointFade = lerp( passBuf.pssmSplitPoints@value(pssm_split_m), passBuf.pssmSplitPoints@value(pssm_split_n), 0.5 );
		if( inPs.depth > pssmSplitPointFade )
		{
			fShadow = lerp( fShadow, 1.0, (inPs.depth - pssmSplitPointFade) / (passBuf.pssmSplitPoints@value(pssm_split_n) - pssmSplitPointFade) );
		}
	}
@end @property( !hlms_pssm_splits && hlms_num_shadow_maps && hlms_lights_directional )
    float fShadow = getShadow( texShadowMap[@value(CurrentShadowMap)], inPs.posL0, passBuf.shadowRcv[@counter(CurrentShadowMap)].invShadowMapSize );
@end
and enjoy your last splits fading in.

As a bonus track, you'll receive also blending between the various splits.
Check the "Blend between Cascades" section at this link to more info about what I'm talking about.


[edit]
Fixed an issue when spotlights are used (CurrentShadowMap value not updated)
Fade in starts at the half of the last split (instead of beginning)
Last edited by TaaTT4 on Mon Jun 13, 2016 9:49 am, edited 1 time in total.

Senior programmer at 505 Games; former senior engine programmer at Sandbox Games
Worked on: Racecraft EsportRacecraft Coin-Op, Victory: The Age of Racing

User avatar
GlowingPotato
Goblin
Posts: 211
Joined: Wed May 08, 2013 2:58 pm
x 10

Re: Blend between splits and fade in last one

Post by GlowingPotato »

That's so cool!

You should submit a pull request. Kudos!
al2950
OGRE Expert User
OGRE Expert User
Posts: 1227
Joined: Thu Dec 11, 2008 7:56 pm
Location: Bristol, UK
x 157

Re: Blend between splits and fade in last one

Post by al2950 »

GlowingPotato wrote:That's so cool!

You should submit a pull request. Kudos!
+1 :D
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5299
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1280
Contact:

Re: Blend between splits and fade in last one

Post by dark_sylinc »

Fading between all splits? how's the performance impact? Noticeable? acceptable? ok? unnoticeable?
User avatar
TaaTT4
OGRE Contributor
OGRE Contributor
Posts: 267
Joined: Wed Apr 23, 2014 3:49 pm
Location: Bologna, Italy
x 75
Contact:

Re: Blend between splits and fade in last one

Post by TaaTT4 »

Do you mean blending?
The fade-in effect happens just in the last split and is pretty much "free" as it just consist in a lerp.

Anyway, I didn't see any appreciable performance impact.
Since the blending addition mostly depends on shadows far clip, splits count and how much of the n-1 first splits must be blended with the next one, with different parameters the performance impact could become significant.

To test those additions we have used:
- 4 splits of 8K, 4K, 4K and 4K (from the nearest to the farthest)
- 200m as shadows far clip
- 10% of evey split blended with the next one

Senior programmer at 505 Games; former senior engine programmer at Sandbox Games
Worked on: Racecraft EsportRacecraft Coin-Op, Victory: The Age of Racing

User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5299
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1280
Contact:

Re: Blend between splits and fade in last one

Post by dark_sylinc »

TaaTT4 wrote:Do you mean blending?
Yes, sorry. I meant blending.
TaaTT4 wrote:Anyway, I didn't see any appreciable performance impact.
Very interesting :)
xrgo
OGRE Expert User
OGRE Expert User
Posts: 1148
Joined: Sat Jul 06, 2013 10:59 pm
Location: Chile
x 168

Re: Blend between splits and fade in last one

Post by xrgo »

This is great! I just put it in my shaders and its working great!
I only made the last split to fadeout just the last 10%, no everything, and changed lerp to mix for glsl:

Code: Select all

					@property( hlms_pssm_splits )
						@psub( pssm_split_n, hlms_pssm_splits, 1 )
						@pset( pssm_split_blend_m, 0 )
						@padd( pssm_split_blend_m_plus_1, pssm_split_blend_m, 1 )
						float pssm_split_blend_point0 = mix( 0.0, pass.pssmSplitPoints@value(pssm_split_blend_m), 0.9 );
						@foreach( hlms_pssm_splits, n, 1 )   
							float pssm_split_blend_point@n = mix( pass.pssmSplitPoints@value(pssm_split_blend_m), pass.pssmSplitPoints@value(pssm_split_blend_m_plus_1), 0.9 );
							@add( pssm_split_blend_m, 1 )
							@add( pssm_split_blend_m_plus_1, 1 )
						@end
							float fShadow = 1.0;
							float fShadowNextSplit = 1.0;
							if( inPs.depth <= pass.pssmSplitPoints@value(CurrentShadowMap) )
							{
								fShadow = getShadow( texShadowMap[@value(CurrentShadowMap)], inPs.posL0, pass.shadowRcv[@counter(CurrentShadowMap)].invShadowMapSize );
								if( inPs.depth > pssm_split_blend_point0 )
								{
									fShadowNextSplit = getShadow( texShadowMap[@value(CurrentShadowMap)], inPs.posL@value(CurrentShadowMap), pass.shadowRcv[@value(CurrentShadowMap)].invShadowMapSize );
									fShadow = mix( fShadow, fShadowNextSplit, (inPs.depth - pssm_split_blend_point0) / (pass.pssmSplitPoints0 - pssm_split_blend_point0) );
								}
							}
						@foreach( pssm_split_n, n, 1 )
							else if( inPs.depth <= pass.pssmSplitPoints@value(CurrentShadowMap) )
							{
								fShadow = getShadow( texShadowMap[@value(CurrentShadowMap)], inPs.posL@n, pass.shadowRcv[@counter(CurrentShadowMap)].invShadowMapSize );
								if( inPs.depth > pssm_split_blend_point@n )
								{
									fShadowNextSplit = getShadow( texShadowMap[@value(CurrentShadowMap)], inPs.posL@value(CurrentShadowMap), pass.shadowRcv[@value(CurrentShadowMap)].invShadowMapSize );
									fShadow = mix( fShadow, fShadowNextSplit, (inPs.depth - pssm_split_blend_point@n) / (pass.pssmSplitPoints@n - pssm_split_blend_point@n) );
								}
							}
						@end
						@psub( pssm_split_m, pssm_split_n, 1 )
					    else if( inPs.depth <= pass.pssmSplitPoints@value(pssm_split_n) )
					    {
							fShadow = getShadow( texShadowMap[@value(pssm_split_n)], inPs.posL@value(pssm_split_n), pass.shadowRcv[@value(pssm_split_n)].invShadowMapSize );
					    	if( inPs.depth > pssm_split_blend_point@value(pssm_split_n) )
							{
								fShadow = mix( fShadow, 1.0, (inPs.depth - pssm_split_blend_point@value(pssm_split_n)) / (pass.pssmSplitPoints@value(pssm_split_n) - pssm_split_blend_point@value(pssm_split_n)) );
					    	}
					    }
					@end
Thank you soooo much!!

have to test performance yet
User avatar
TaaTT4
OGRE Contributor
OGRE Contributor
Posts: 267
Joined: Wed Apr 23, 2014 3:49 pm
Location: Bologna, Italy
x 75
Contact:

Re: Blend between splits and fade in last one

Post by TaaTT4 »

I've edited the original source code fixing a bug when spotlights are used too and starting the fade in at the half of the last splits (thanks @xrgo).

Senior programmer at 505 Games; former senior engine programmer at Sandbox Games
Worked on: Racecraft EsportRacecraft Coin-Op, Victory: The Age of Racing

User avatar
TaaTT4
OGRE Contributor
OGRE Contributor
Posts: 267
Joined: Wed Apr 23, 2014 3:49 pm
Location: Bologna, Italy
x 75
Contact:

Re: Blend between splits and fade in last one

Post by TaaTT4 »

Better late than never, I've finally find some time to make a PR of this: https://bitbucket.org/sinbad/ogre/pull- ... prove-pssm

Enjoy!

Senior programmer at 505 Games; former senior engine programmer at Sandbox Games
Worked on: Racecraft EsportRacecraft Coin-Op, Victory: The Age of Racing

User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5299
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1280
Contact:

Re: Blend between splits and fade in last one

Post by dark_sylinc »

It's been approved. Thank you for this wonderful contribution!

Now shadows look prettier! :)

PS: Worked out of the box on Metal.
zxz
Gremlin
Posts: 184
Joined: Sat Apr 16, 2016 9:25 pm
x 19

Re: Blend between splits and fade in last one

Post by zxz »

This sounds really nice. I'm looking forward to trying it out. Do you have any before/after shots?
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5299
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1280
Contact:

Re: Blend between splits and fade in last one

Post by dark_sylinc »

Screenshots can work, but it's much better to appreciate in motion. Particularly the last split as they now smoothly fade in/out as you move in/away, instead of being stopped by an invisible wall that cuts shadows.
Post Reply