Improving Shadows on Ogre 2.1

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


xrgo
OGRE Expert User
OGRE Expert User
Posts: 1148
Joined: Sat Jul 06, 2013 10:59 pm
Location: Chile
x 168

Improving Shadows on Ogre 2.1

Post by xrgo »

Hello!! one of the things that a good modern engine needs is awesome shadows!!
so I was looking some ways to improve quality and trying to not decrease performance too much... and I came up with some interesting stuffs. This is my journey to cool shadows:

Mentioned FPS are for that camera view.
Tested with Nvidia 540m, i7, Ubuntu 14.04.
These are PSSM shadows, but it works with other shadows too (haven't tested too much)

No filtering at all:
Image
FPS: 73

=======================

Original pbs template shadows with 2x2 PCF:
Image
FPS: 72

=======================

PCF 5x5:
Image

Code: Select all

	vec3 UVCoords = psPosLN.xyz / psPosLN.w;

	float shadowFactor = 0.0;
	float bias = 0.0000000001;

	for (int y = 0 ; y < 5 ; y++) {
			for (int x = 0 ; x < 5 ; x++) {
					vec2 offsets = vec2( (x-2.5) * invShadowMapSize.x, (y-2.5) * invShadowMapSize.y );
					if ( psPosLN.z+bias <= texture( shadowMap, UVCoords.xy + offsets ).r ){
						shadowFactor+=0.04;
					}
			}
	}
	return shadowFactor;
This one is starting to look interesting, but you can still see the aliasing, good thing is from far it looks really good and soft. and its not that expensive as I though it should be for 25 lookups!
FPS: 67

=======================

PCF 5x5 with pseudo-random offset:
Image

Code: Select all

	float random(in vec3 seed)
	{
		return fract(sin(dot(seed, vec3(53.1215, 21.1352, 9.1322))) * 43758.5453);
	}

------------------------------

	vec3 UVCoords = psPosLN.xyz / psPosLN.w;

	float shadowFactor = 0.0;
	float bias = 0.0000000001;

	for (int y = 0 ; y < 5 ; y++) {
			for (int x = 0 ; x < 5 ; x++) {
					vec2 offsets = vec2( (x-2) * invShadowMapSize.x, (y-2) * invShadowMapSize.y );

					offsets = offsets + vec2(random(offsets.xyy)* invShadowMapSize.x,random(offsets.yxy)* invShadowMapSize.y);

					if ( psPosLN.z+bias <= texture( shadowMap, UVCoords.xy + offsets ).r ){
						shadowFactor+=0.04;
					}
			}
	}
	return shadowFactor;
this one looks a little better, its harder to identify the map pixels, sadly its a little expensive
FPS: 48

=======================

PCF 5x5 with pseudo-random poissonDisk:
Image

Code: Select all

	float random(in vec3 seed)
	{
		return fract(sin(dot(seed, vec3(53.1215, 21.1352, 9.1322))) * 43758.5453);
	}

------------------------------

	vec2 poissonDisk[4] = vec2[](
	  vec2( -0.94201624, -0.39906216 ),
	  vec2( 0.94558609, -0.76890725 ),
	  vec2( -0.094184101, -0.92938870 ),
	  vec2( 0.34495938, 0.29387760 )
	);

	vec3 UVCoords = psPosLN.xyz / psPosLN.w;

	float shadowFactor = 0.0;
	float bias = 0.0000000001;

	for (int y = 0 ; y < 5 ; y++) {
			for (int x = 0 ; x < 5 ; x++) {
					vec2 offsets = vec2( (x-2) * invShadowMapSize.x, (y-2) * invShadowMapSize.y );

					int index = int( 4*random( gl_FragCoord.xyz / gl_FragCoord.w ) )%4;
					offsets = offsets + poissonDisk[index]*0.001;

					if ( psPosLN.z+bias <= texture( shadowMap, UVCoords.xy + offsets ).r ){
						shadowFactor+=0.04;
					}
			}
	}
	return shadowFactor;
with this one you almost cant identify pixels, but you get a lot of noise, and it looks really bad from far, and its a little expensive too
FPS: 40

=======================

Then I read that Unity5 uses a 5x5 PCF, and it looks very good/soft, so I guess that what I was lacking is some linear interpolation.
https://unity3d.com/sites/default/files ... hics-8.jpg

I couldn't find how to enable linear filtering on the shadow texture, but here I found a way:
http://codeflow.org/entries/2013/feb/15 ... w-mapping/

this is the result with just the interpolation:
Image
FPS: 72

this is the code from that site

Code: Select all

float texture2DCompare(sampler2D depths, vec2 uv, float compare){
    float depth = texture2D(depths, uv).r;
    return step(compare, depth);
}

float texture2DShadowLerp(sampler2D depths, vec2 size, vec2 uv, float compare){
    vec2 texelSize = vec2(1.0)/size;
    vec2 f = fract(uv*size+0.5);
    vec2 centroidUV = floor(uv*size+0.5)/size;

    float lb = texture2DCompare(depths, centroidUV+texelSize*vec2(0.0, 0.0), compare);
    float lt = texture2DCompare(depths, centroidUV+texelSize*vec2(0.0, 1.0), compare);
    float rb = texture2DCompare(depths, centroidUV+texelSize*vec2(1.0, 0.0), compare);
    float rt = texture2DCompare(depths, centroidUV+texelSize*vec2(1.0, 1.0), compare);
    float a = mix(lb, lt, f.y);
    float b = mix(rb, rt, f.y);
    float c = mix(a, b, f.x);
    return c;
}

-----------------------------------------

    return texture2DShadowLerp(shadowMap, 1/invShadowMapSize, psPosLN.xy / psPosLN.w, psPosLN.z);
FPS: 72

=======================

PCF 5x5 + linear interpolation. Now I think we are talking serious!:
Image

Code: Select all

	vec3 UVCoords = psPosLN.xyz / psPosLN.w;

	float shadowFactor = 0.0;

	for (int y = 0 ; y < 5 ; y++) {
			for (int x = 0 ; x < 5 ; x++) {
					vec2 offsets = vec2( (x-2) * invShadowMapSize.x, (y-2) * invShadowMapSize.y );

					shadowFactor += texture2DShadowLerp(shadowMap, 1/invShadowMapSize, UVCoords.xy + offsets, psPosLN.z);
			}
	}
	return shadowFactor*0.04;
I think this looks really good, the problem is that its very expensive, since its 25 * 4 = 100 lookups!
FPS: 36

=======================

So I think maybe with linear interpolation, PCF 3x3 would be enough.
PCF 3x3 + linear interpolation:
Image

Code: Select all

	vec3 UVCoords = psPosLN.xyz / psPosLN.w;
	
	float shadowFactor = 0.0;
	
	for (int y = 0 ; y < 3 ; y++) {
			for (int x = 0 ; x < 3 ; x++) {
					vec2 offsets = vec2( (x-1) * invShadowMapSize.x, (y-1) * invShadowMapSize.y );
	
					shadowFactor += texture2DShadowLerp(shadowMap, 1/invShadowMapSize, UVCoords.xy + offsets, psPosLN.z);
			}
	}
	return shadowFactor*0.11111111;
and I believe Its good enough =), and I think performance is fairly ok (for a 9*4=36 lookups)
FPS: 56

=======================

Then I found this post:
http://www.ogre3d.org/forums/viewtopic.php?f=1&t=78834
That uses the same linear interpolation, and then gives a 3x3 version with less lookups.
PCF 3x3 + linear interpolation + optimization:
Image

Code: Select all

	vec2 uv = psPosLN.xy / psPosLN.w;
	
	vec2 texelSize = invShadowMapSize;
	vec2 size = 1 / invShadowMapSize;
	vec2 centroidUV = floor(uv * size + 0.5) / size;
	vec2 f = fract(uv * size + 0.5);
	
	int   X = 3;
	
	vec2 topLeft = centroidUV - texelSize * 1.5;
	
	// load all pixels needed for the computation
	// this way a pixel wont be loaded twice
	float kernel[9];
	for(int i = 0; i < X; i++){
		for(int j = 0; j < X; j++){
			kernel[i * X + j] = texture2DCompare(shadowMap, topLeft + vec2(i, j) * texelSize, psPosLN.z);
		}
	}
	
	
	float kernel_interpolated[4];
	
	kernel_interpolated[0] = kernel[0] + kernel[1] + kernel[3] + kernel[4];
	kernel_interpolated[0] /= 4.0;
	kernel_interpolated[1] = kernel[1] + kernel[2] + kernel[4] + kernel[5];
	kernel_interpolated[1] /= 4.0;
	kernel_interpolated[2] = kernel[3] + kernel[4] + kernel[6] + kernel[7];
	kernel_interpolated[2] /= 4.0;
	kernel_interpolated[3] = kernel[4] + kernel[5] + kernel[7] + kernel[8];
	kernel_interpolated[3] /= 4.0;
	
	float a = mix(kernel_interpolated[0], kernel_interpolated[1], f.y);
	float b = mix(kernel_interpolated[2], kernel_interpolated[3], f.y);
	
	float c = mix(a, b, f.x);
	return c;
The problem is that it doesn't look like the previous 3x3 version =(, looks more like a 2x2... but performance is good again!!!
FPS: 69

=======================

Conclusions:

My vote is for something like "PCF 3x3 + linear interpolation + optimization" but I am going to try to make it look like "PCF 3x3 + linear interpolation", and would be almost enough for my needs.
I believe PCF can be enabled by hardware, but its beyond my skills.
I believe that linear interpolation, or bilinear filtering can be enabled for the texture so when you do a simple PCF it would look good instantly, but I don't know how to enable it.
And the only thing that I think its a MUST is STABLE PSSM shadows, like this:
http://www.garagegames.com/community/blogs/view/21284
or this one:
http://www.ogre3d.org/forums/viewtopic.php?f=11&t=71142
but again is beyond my skills.
Hopefully some of this techniques could be on ogre 2.1 by default, maybe be able to activate some filtering like:

Code: Select all

shadow_map 0 2048 2048 PF_FLOAT32_R light 0 split 0 pcf 3 linearFiltering on
thanks for reading! :P
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5296
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: Improving Shadows on Ogre 2.1

Post by dark_sylinc »

This post is a couple hours too early. I've been working on improving the quality of the shadows this weekend and I'm hours (minutes?) away from committing.
Doesn't implement poisson / pseudo random disc samples, but uses high quality PCF filtering at a very acceptable performance.
xrgo
OGRE Expert User
OGRE Expert User
Posts: 1148
Joined: Sat Jul 06, 2013 10:59 pm
Location: Chile
x 168

Re: Improving Shadows on Ogre 2.1

Post by xrgo »

dark_sylinc wrote:This post is a couple hours too early. I've been working on improving the quality of the shadows this weekend and I'm hours (minutes?) away from committing.
Doesn't implement poisson / pseudo random disc samples, but uses high quality PCF filtering at a very acceptable performance.
Loooooooooooool thats great =D
User avatar
Crystal Hammer
Gnome
Posts: 317
Joined: Sat Jun 23, 2007 5:16 pm
x 77
Contact:

Re: Improving Shadows on Ogre 2.1

Post by Crystal Hammer »

WOW :shock: This is so amazing.
After all those years of seeing square shadows :lol:

Just a quick and probably very easy question:
How much effort (extra code?) is needed to allow end user to change shadow maps size or used shadowmaps count (i.e. allow various shadow settings presets) ?
Is it easy to do in HLMS/Ogre2.1 ?
xrgo
OGRE Expert User
OGRE Expert User
Posts: 1148
Joined: Sat Jul 06, 2013 10:59 pm
Location: Chile
x 168

Re: Improving Shadows on Ogre 2.1

Post by xrgo »

Crystal Hammer wrote:WOW :shock: This is so amazing.
After all those years of seeing square shadows :lol:

Just a quick and probably very easy question:
How much effort (extra code?) is needed to allow end user to change shadow maps size or used shadowmaps count (i.e. allow various shadow settings presets) ?
Is it easy to do in HLMS/Ogre2.1 ?
Veeeeery easy! see compositor ShadowNodes on the porting Doc
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5296
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: Improving Shadows on Ogre 2.1

Post by dark_sylinc »

It's done.

Enjoy the quality. Notice the performance degradation on each sample. It may be worth noting that HLSL optimizes much better than GLSL at least with my AMD drivers. The performance drops on HLSL are almost unnoticeable for each quality level.
I also believe the performance can be further improved.

Bonus points: The latest commit shows how to hot reload the Hlms shader templates using Ctrl+F1 (PBS) and Ctrl+F2 (Unlit).
See full commit for more details.

PCF 2x2
Image
PCF 3x3 (Default)
Image
PCF 4x4
Image

Cheers
xrgo
OGRE Expert User
OGRE Expert User
Posts: 1148
Joined: Sat Jul 06, 2013 10:59 pm
Location: Chile
x 168

Re: Improving Shadows on Ogre 2.1

Post by xrgo »

Thank you very much Matias! really good!!! better performance than in my experiments, and looks great!, the only thing missing now as I mentioned before is the "stable"
xrgo
OGRE Expert User
OGRE Expert User
Posts: 1148
Joined: Sat Jul 06, 2013 10:59 pm
Location: Chile
x 168

Re: Improving Shadows on Ogre 2.1

Post by xrgo »

edit: SOLVED: wasn't a bug at all, read 2 posts below.
Not sure if I am doing something wrong or what.... But I noticed that pssm_lambda is doing nothing, It doesn't matter what value I put in the shadowNode its always the same result.
Then I noticed that "calculateSplitPoints" method is called the first ~6 times with a value of 0.95 (even if I put another value on the shadowNode), but later on CompositorShadowNode::_update, calculateSplitPoints is being called with a value of 0. so the result that I am always seeing is the effect of a lambda = 0.

If I replace the value lambda for a numeric value in calculateSplitPoints:
Real splitPoint = lambda * nearDist * Math::Pow(farDist / nearDist, fraction) +
(1.0f - lambda) * (nearDist + fraction * (farDist - nearDist));
I obviously see the effect of, for instance, a higher lambda.

Is necessary to call calculateSplitPoints all the time (in CompositorShadowNode::_update)???, I thought that was just necessary to do it one time at the beginning (or when need to make changes)
Last edited by xrgo on Sun Mar 22, 2015 11:03 pm, edited 1 time in total.
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5296
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: Improving Shadows on Ogre 2.1

Post by dark_sylinc »

xrgo wrote:I thought that was just necessary to do it one time at the beginning (or when need to make changes)
If your compositor uses the same camera, yes.
But a workspace could use the same shadow node with different cameras or change the far/near clipping planes, or be assigned a different light with a different ShadowFarDistance setting.
Tracking all of the settings that may alter the pssm splits is more troublesome than updating on every shadow node update (usually once per frame) and isn't expensive at all.

The real question is why the lambda is 0 for you. Even with the default setting, it should always be 0.95 (called once in CompositorShadowNode::CompositorShadowNode to prevent possible uninitialized variable errors, and then the constructor sets the value to 0.95). There could be an error in your compositor setup, memory corruption, or a very rare bug you're triggering.

If there's a bug, either caused by you or by Ogre, when updating the splits every frame, similarly a bug could happen if we track whether pssm splits should be updated but we don't notice they should (problems which are much more difficult to find and solve).
xrgo
OGRE Expert User
OGRE Expert User
Posts: 1148
Joined: Sat Jul 06, 2013 10:59 pm
Location: Chile
x 168

Re: Improving Shadows on Ogre 2.1

Post by xrgo »

dark_sylinc wrote:
xrgo wrote:I thought that was just necessary to do it one time at the beginning (or when need to make changes)
If your compositor uses the same camera, yes.
But a workspace could use the same shadow node with different cameras or change the far/near clipping planes, or be assigned a different light with a different ShadowFarDistance setting.
Tracking all of the settings that may alter the pssm splits is more troublesome than updating on every shadow node update (usually once per frame) and isn't expensive at all.

The real question is why the lambda is 0 for you. Even with the default setting, it should always be 0.95 (called once in CompositorShadowNode::CompositorShadowNode to prevent possible uninitialized variable errors, and then the constructor sets the value to 0.95). There could be an error in your compositor setup, memory corruption, or a very rare bug you're triggering.

If there's a bug, either caused by you or by Ogre, when updating the splits every frame, similarly a bug could happen if we track whether pssm splits should be updated but we don't notice they should (problems which are much more difficult to find and solve).
thanks! I just wanted to make sure it was something that happens only to me.

Now I noticed what the problem is (but not how to solved it yet):
Is a bug I am having with any script, that if I remember correctly It always happened to me (with all ogre versions that I used 1.9, 2.0 and 2.1)
the bug is that I cant use float values in scripts, for instance if I put a 0.95 it turns a 0, but if I put a 1, it works as a 1. same happens for instance on an old school material if I wanted to do some anim_scroll to a texture, any value I put is rounded to the lower int, (eg: 0.5>0, 1.9>1, 5.2>5 ). It wasn't really a problem before because I always do my stuffs in c++ code, and that way float values do work

EDIT: looool, I gave 1 minute attention and I noticed that works with a comma (0,95 intead of 0.95) for me wtf!
SOLVED... but I preffer to use dots =(
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5296
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: Improving Shadows on Ogre 2.1

Post by dark_sylinc »

Uh oh. That's a problem that keeps coming back after it gets fixed.

It's a locale issue. Ogre assumes "C" locale. The setting is per-thread.
Your program must be using your system locale; since it's in Spanish, it sees "1.000,59" as "one thousand and fifty nine"; while in a computer from the US, it will see "1.000,59" as "one comma zero zero zero wrong_character fifty nine" as one thousand in US locale is "1,000.59".

You should force the locale to "C" to avoid problems when you deploy your machine to other computers and get a consistent comma separator.
xrgo
OGRE Expert User
OGRE Expert User
Posts: 1148
Joined: Sat Jul 06, 2013 10:59 pm
Location: Chile
x 168

Re: Improving Shadows on Ogre 2.1

Post by xrgo »

thanks again, that fixed it

std::setlocale(LC_ALL,"C");
xrgo
OGRE Expert User
OGRE Expert User
Posts: 1148
Joined: Sat Jul 06, 2013 10:59 pm
Location: Chile
x 168

Re: Improving Shadows on Ogre 2.1

Post by xrgo »

I noticed that setting up a value to
datablock->mShadowConstantBias
didn't work anymore

looking at the vertex shader I noticed that "shadowConstantBias" was not beeing used:

Code: Select all

@end @property( hlms_shadowcaster )
    float shadowConstantBias = uintBitsToFloat( instance.worldMaterialIdx[drawId].y );
	//Linear depth
	outVs.depth	= (gl_Position.z - pass.depthRange.x + 0.01 * pass.depthRange.y) * pass.depthRange.y;
changing it to this:

Code: Select all

@end @property( hlms_shadowcaster )
    float shadowConstantBias = uintBitsToFloat( instance.worldMaterialIdx[drawId].y );
	//Linear depth
	outVs.depth	= (gl_Position.z - pass.depthRange.x + shadowConstantBias) * pass.depthRange.y;
or maybe to this:

Code: Select all

@end @property( hlms_shadowcaster )
    float shadowConstantBias = uintBitsToFloat( instance.worldMaterialIdx[drawId].y );
	//Linear depth
	outVs.depth	= (gl_Position.z - pass.depthRange.x + 0.01 * pass.depthRange.y + shadowConstantBias) * pass.depthRange.y;
and works again!

please integrate this fix =)
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5296
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: Improving Shadows on Ogre 2.1

Post by dark_sylinc »

Ouch. That should've never happened. My bad, sorry.

Fixed.
Thanks for reporting it.
Matias
User avatar
duststorm
Minaton
Posts: 921
Joined: Sat Jul 31, 2010 6:29 pm
Location: Belgium
x 80
Contact:

Re: Improving Shadows on Ogre 2.1

Post by duststorm »

This is awesome! :)
Ogre could really use better shadow filtering, and now it happened. Thanks a lot!
Developer @ MakeHuman.org
lygyue
Greenskin
Posts: 122
Joined: Wed Nov 29, 2006 4:07 pm

Re: Improving Shadows on Ogre 2.1

Post by lygyue »

I think we can design some plugins for shadow rendering. Some popular shadow like cascade shadow method can be add to ogre source code as standard. And some other shadow method like stencil shadow can be remove from ogre support. By now, cascade shadow using all over the world, we need to improve the default ogre shadow.
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5296
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: Improving Shadows on Ogre 2.1

Post by dark_sylinc »

PSSM is a cascaded shadow map technique. At PCF 4x4 it can give really good results. Stencil shadows have already been removed from Ogre 2.1
Most modern games are starting to use SDSM to calculate the ideal split, which is just an improvement.
Our R&D is also working on novel shadow mapping algorithms to produce much superior results, but it's WIP for now.
lygyue
Greenskin
Posts: 122
Joined: Wed Nov 29, 2006 4:07 pm

Re: Improving Shadows on Ogre 2.1

Post by lygyue »

I had improved ogre shadow several years ago, the best shadow performance at that time under this link:http://www.ogre3d.org/forums/viewtopic.php?f=11&t=71142. at this link, it performance the best way at directional light. i improve this to using spot light and point light(using cube shadow map, not using multi shadowmaps), it ran well. I think ogre need to improve the default shadow performance. may be can design some plugins for some popular technology like deferred Shading, FXAA, Temporal AA, atmospheric fog and so on. Recently, all the other engine are design to be used in a more and more easy way, but ogre is hard to use all the time, it is hard to use deferred Shading, hard to use atmospheric fog……I had done many change on ogre1.72, but may be it can't be use on ogre2.0. So, is it possible to design some plugins/components to do this?
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5296
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: Improving Shadows on Ogre 2.1

Post by dark_sylinc »

Did you actually try Ogre 2.1? It is vastly different from 1.x or 2.0

Deferred Shading will be supported out of the box, but right now we're focusing on the superior Forward+ methods.
FXAA has always been dead easy to implement in all versions of Ogre.
Atmospheric Fog is something that we have on plans, but no ETA.
lygyue
Greenskin
Posts: 122
Joined: Wed Nov 29, 2006 4:07 pm

Re: Improving Shadows on Ogre 2.1

Post by lygyue »

I am sorry i did not try ogre2.1 at all. I had tried ogre2.0 half year ago, and use ogre1.x for many years. I apology.

Recently, i most use unreal and unity for my project, few times ogre. In fact, i like ogre much more than unreal and unity.I hate unreal's huge source code which too Bloated and confused. But it's good performance and easy way to use is what i need, and i think ogre can do some work on this. Good default shadow performance, good default lighting, atmospheric fog, temporal aa, fxaa(may be it is very easy to use, but people hope like call a function setUseFXAA),software occlusion culling(I had done this part job on ogre, but it need to modify source code)……

These years, i am very sad to found more and more ogre users escape, and unity and unreal become more and more popular :cry: . In my opinion, ogre need to improve default performance. The best way is to design plugins/component module.On ogre history, there are many excellent project appear, such as hydrax. But which not part of ogre, and then, not update so many years. We need excellent component all the time, such as particle system, water simulation, terrain component, oculus rift support……all these can found on ogre forum, but can not found on ogre source code project, and seldom update or almost not update for years. I think it is our fault.
kracejic
Kobold
Posts: 25
Joined: Wed Sep 10, 2014 5:18 pm
x 1

Re: Improving Shadows on Ogre 2.1

Post by kracejic »

Try Ogre2.1 then, you will get PBS, better compositor, true HDR is already implemented in samples, nice PSSM shadows, great performance and Forward3D lighting which can hadle lots of lights...

Just clone it from repo and build it and look at the samples. It is work in progress, but already it is pretty good and very promising. :)
mogumbo
Gnoblar
Posts: 14
Joined: Thu Sep 14, 2017 4:14 pm
x 1

Re: Improving Shadows on Ogre 2.1

Post by mogumbo »

I couldn't find how to enable linear filtering on the shadow texture, but here I found a way:
http://codeflow.org/entries/2013/feb/15 ... w-mapping/
This is usually called "hardware PCF", but I'm not sure if it is true PCF because it is doing interpolation instead of a multi-sample average. It looks exactly like the "just the interpolation" image in xrgo's original post but you get it with just one sample in the fragment shader. Here's a good discussion of it: https://www.opengl.org/discussion_board ... -to-get-it

I got this working in Ogre3D with OpenGL like this:

Code: Select all

// Enable shadow map comparison, so shader can use float texture(sampler2DShadow,
// vec3, [float]) instead of vec4 texture(sampler2D, vec2, [float]).
for (size_t i=0; i<sceneMgr->getShadowTextureCount(); i++) {
    const Ogre::TexturePtr tex = sceneMgr->getShadowTexture(i);
    Ogre::GLTexture* gltex = static_cast<Ogre::GLTexture*>(tex.get());
    glBindTexture(GL_TEXTURE_2D, gltex->getGLID());
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
}
The key is setting up that glTexParameteri shadow map comparison, which doesn't seem to happen anywhere in Ogre's code base right now. (I implemented this with Ogre 1.9, but I didn't see that OpenGL code anywhere in current Ogre code either. I just started looking at Ogre a couple days ago so I don't know the best place to put this in an Ogre program.) After you have enabled the shadow map comparison, just make sure to use sampler2DShadow in your GLSL shader and the texture() function that takes a sampler2DShadow and a vec3 (the z-component gets compared to your shadow map depth).

When you set things up this way, there is a driver hack that gives you interpolated shadows or "hardware PCF". I believe NVidia implemented this first, but it also works on my AMD and Intel graphics. I suppose they all decided it was worth having.

I'm currently using this enhancement with Ogre's PSSM shadows, but it's a good enhancement to couple with a lot of other shadow techniques.
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5296
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: Improving Shadows on Ogre 2.1

Post by dark_sylinc »

HW PCF filtering is used in Ogre 2.1. The relevant code is in Components/Hlms/Pbs/src/OgreHlmsPbs.cpp:

Code: Select all

samplerblock.mMinFilter     = FO_LINEAR;
samplerblock.mMagFilter     = FO_LINEAR;
samplerblock.mMipFilter     = FO_NONE;
samplerblock.mCompareFunction   = CMPF_LESS_EQUAL;
Where a samplerblock will be created (getSamplerblock -> _hlmsSamplerblockCreated) that maps these settings to GL_LINEAR and sets GL_TEXTURE_COMPARE_MODE to GL_COMPARE_REF_TO_TEXTURE and GL_TEXTURE_COMPARE_FUNC to GL_LESS.
mogumbo
Gnoblar
Posts: 14
Joined: Thu Sep 14, 2017 4:14 pm
x 1

Re: Improving Shadows on Ogre 2.1

Post by mogumbo »

Ah, I see. I was looking in the default branch instead of v2-1. Glad to see it's in there.
xrgo
OGRE Expert User
OGRE Expert User
Posts: 1148
Joined: Sat Jul 06, 2013 10:59 pm
Location: Chile
x 168

Re: Improving Shadows on Ogre 2.1

Post by xrgo »

reviving this old thread just to ask a question:
I want to add PCF 5x5 support to pbs (I'll make a PR soon).. but I was wondering why the ones already implemented in pbs are called 3x3 and 4x4 if they have 4 and 9 samples respectively, when I look online everyone mention 3x3 has 9 samples and 4x4 has 16, hence 5x5 should have 25. what am I missing?

Saludos!
Post Reply