Ogre Soft Shadows Demo

A place to show off your latest screenshots and for people to comment on them. Only start a new thread here if you have some nice images to show off!
User avatar
Nargil
Greenskin
Posts: 124
Joined: Thu Feb 15, 2007 8:47 pm

Re: Ogre Soft Shadows Demo

Post by Nargil »

I'm having some problems integrating it.

The light is a point light somewhere above the house.
For some reasons the shadows move with the camera, and are projected wrong.
On the video you can see it (and the shadow map too)

Youtube video: http://www.youtube.com/watch?v=Cr39dVuSgMQ (the codec sux - sorry, but you can see the problem)

base.program

Code: Select all

vertex_program PerPixel_Lim3_Vert cg
{
	source normalSpecDiffuse.cg

	default_params
	{		
		param_named_auto lightPosition[0] light_position_object_space 0
		param_named_auto lightPosition[1] light_position_object_space 1
		param_named_auto lightPosition[2] light_position_object_space 2
		//param_named_auto lightPosition[3] light_position_object_space 3
		//param_named_auto lightPosition[4] light_position_object_space 4
		//param_named_auto lightPosition[5] light_position_object_space 5
		param_named_auto eyePosition camera_position_object_space
		param_named_auto worldviewproj worldviewproj_matrix
		
		param_named_auto lpoz light_position 0
		param_named_auto wMat world_matrix
        //param_named_auto wvpMat worldviewproj_matrix
        param_named_auto tvpMat texture_viewproj_matrix 0
	} 

	entry_point PerPixel_Lim3_Vert
	profiles vs_1_1 arbvp1
}

fragment_program PerPixel_Lim3_Frag cg
{
	source normalSpecDiffuse.cg 

	default_params
	{
		param_named_auto lightDiffuse[0] light_diffuse_colour 0
		param_named_auto lightDiffuse[1] light_diffuse_colour 1
		param_named_auto lightDiffuse[2] light_diffuse_colour 2
//		param_named_auto lightDiffuse[3] light_diffuse_colour 3
//		param_named_auto lightDiffuse[4] light_diffuse_colour 4
//		param_named_auto lightDiffuse[5] light_diffuse_colour 5

		param_named_auto lightSpecular[0] light_specular_colour 0
		param_named_auto lightSpecular[1] light_specular_colour 1
		param_named_auto lightSpecular[2] light_specular_colour 2 
//		param_named_auto lightSpecular[3] light_specular_colour 3
//		param_named_auto lightSpecular[4] light_specular_colour 4
//		param_named_auto lightSpecular[5] light_specular_colour 5 
		
		param_named_auto lightAtt[0] light_attenuation 0
		param_named_auto lightAtt[1] light_attenuation 1
		param_named_auto lightAtt[2] light_attenuation 2
//		param_named_auto lightAtt[3] light_attenuation 3
//		param_named_auto lightAtt[4] light_attenuation 4
//		param_named_auto lightAtt[5] light_attenuation 5

		param_named_auto ambient ambient_light_colour 
		
		param_named exponent0 float 12
	} 

	entry_point PerPixel_Lim3_Frag
	profiles ps_2_x fp30
} 
base.material

Code: Select all

material DiffuseNormalSpecSSAO
{
	technique
	{
		pass
		{
			vertex_program_ref PerPixel_Lim3_Vert
			{
	 		}  

			fragment_program_ref PerPixel_Lim3_Frag
			{
			}


			texture_unit diffuse_tex
			{
				tex_coord_set 0
			}
			
			texture_unit normal_tex
			{
				colour_op replace
				tex_coord_set 0
			}

			texture_unit specular_tex
			{
				tex_coord_set 0
			}
			
			texture_unit shadow_tex
            {
                content_type shadow
                filtering anisotropic
                max_anisotropy 16
                tex_address_mode border
                tex_border_colour 1 1 1
            }
		}
	}
	

	
	technique geom
	{
	    scheme geom

	    pass
	    {
	        vertex_program_ref geom_vs
	        {
	        }

	        fragment_program_ref geom_ps
	        {
	        }
	    }
	}
}
normalSpecDiffuse.cg

Code: Select all

float3 expand(float3 v)
{
	return (v - 0.5) * 2;
}

float4 btex2D(sampler2D map, float2 uv, float radius, float steps)
{
    half stepSize = 2.0 * radius / steps;
    uv.xy -= radius.xx;

    float4 total = float4(0, 0, 0, 0);
    for (int x = 0; x < steps; ++x)
        for (int y = 0; y < steps; ++y)
            total +=
                tex2D(map, float2(uv.xy + float2(x * stepSize, y * stepSize)));

    return total / (steps * steps);
}

float computeShadow(
    sampler2D shadowMap, float4 shadowMapPos, float ourDepth)
{
    float2 suv = shadowMapPos.xy / shadowMapPos.w;

    float2 moments = btex2D(shadowMap, suv, 0.01, 4).rg;
    float litFactor = (ourDepth <= moments.x ? 1 : 0);

    // standard variance shadow mapping code
    float E_x2 = moments.y;
    float Ex_2 = moments.x * moments.x;
    float vsmEpsilon = 0.0001;
    float variance = min(max(E_x2 - Ex_2, 0.0) + vsmEpsilon, 1.0);
    float m_d = moments.x - ourDepth;
    float p = variance / (variance + m_d * m_d);

    return smoothstep(0.2, 1, max(litFactor, p));
}

struct VOut
{
			float4 oPosition	: POSITION;
			float2 oUv			: TEXCOORD0;
			float3 oEyeDir     	: TEXCOORD1;
			
			float4 oLightDir0  	: TEXCOORD2;
			float4 oLightDir1  	: TEXCOORD3;
			float4 oLightDir2	: TEXCOORD4;
			//float4 oLightDir3	: TEXCOORD5;
			//float4 oLightDir4  	: TEXCOORD6;
			//float4 oLightDir5	: TEXCOORD7;
			float4 lpoz			: TEXCOORD5;
			float4 wp			: TEXCOORD6;
			float4 lp 			: TEXCOORD7;	
};


VOut PerPixel_Lim3_Vert(
			float4 position	: POSITION,
			float3 normal		: NORMAL,
			float2 uv		: TEXCOORD0,
			float3 tangent     	: TEXCOORD1, 

	 		uniform float4 lightPosition[6],
			uniform float4 lpoz,
			
			uniform float3 eyePosition,
			uniform float4x4 worldviewproj,
			uniform float4x4 wMat,
			uniform float4x4 tvpMat
		) 
{
	VOut OUT;

	OUT.oPosition = mul(worldviewproj , position);
	OUT.oUv = uv; 
	
	OUT.wp = mul(wMat, position);
	OUT.lp = mul(tvpMat, OUT.wp);
	
	OUT.lpoz = lpoz;
	
	float3 eyeDir = eyePosition - position.xyz;
	float3 binormal = cross(tangent, normal);
	float3x3 rotation = float3x3(tangent, binormal, normal);
	eyeDir = normalize(mul(rotation, eyeDir));
 
	OUT.oEyeDir = eyeDir;
 
 	float3 temp_lightDir = normalize(lightPosition[0].xyz -  (position.xyz * lightPosition[0].w));
	OUT.oLightDir0 = float4(normalize(mul(rotation, temp_lightDir)),distance(position.xyz, lightPosition[0].xyz)*lightPosition[0].w);

	temp_lightDir = normalize(lightPosition[1].xyz -  (position.xyz * lightPosition[1].w));
	OUT.oLightDir1 = float4(normalize(mul(rotation, temp_lightDir)),distance(position.xyz, lightPosition[1].xyz)*lightPosition[1].w);
	
	temp_lightDir = normalize(lightPosition[2].xyz -  (position.xyz * lightPosition[2].w));
	OUT.oLightDir2 = float4(normalize(mul(rotation, temp_lightDir)),distance(position.xyz, lightPosition[2].xyz)*lightPosition[2].w);
	
	//temp_lightDir = normalize(lightPosition[3].xyz -  (position.xyz * lightPosition[3].w));
	//OUT.oLightDir3 = float4(normalize(mul(rotation, temp_lightDir)),distance(position.xyz, lightPosition[3].xyz)*lightPosition[3].w);

	//temp_lightDir = normalize(lightPosition[4].xyz -  (position.xyz * lightPosition[4].w));
	//OUT.oLightDir4 = float4(normalize(mul(rotation, temp_lightDir)),distance(position.xyz, lightPosition[4].xyz)*lightPosition[4].w);

	//temp_lightDir = normalize(lightPosition[5].xyz -  (position.xyz * lightPosition[5].w));
	//OUT.oLightDir5 = float4(normalize(mul(rotation, temp_lightDir)),distance(position.xyz, lightPosition[5].xyz)*lightPosition[5].w);
	
	return OUT;
}
 

void PerPixel_Lim3_Frag(
			float2 Uv		: TEXCOORD0,
			float3 eyeDir     : TEXCOORD1,
			
			float4 LightDir0  : TEXCOORD2,
			float4 LightDir1  : TEXCOORD3,
			float4 LightDir2	: TEXCOORD4,
			//float4 LightDir3  : TEXCOORD5,
			//float4 LightDir4  : TEXCOORD6,
			float4 lpoz	: TEXCOORD5,
			float4 wp : TEXCOORD6,
			float4 lp	: TEXCOORD7,
			
			uniform float4 lightDiffuse[3],
			uniform float4 lightSpecular[3],			
			uniform float4 lightAtt[3],
			
			uniform float exponent0,

			uniform float4 ambient, 

		   	out float4 oColor : COLOR,
			
			uniform sampler2D   diffuseCol : register(s0),
			uniform sampler2D   normalMap : register(s1),
			uniform sampler2D   specularCol : register(s2),
			uniform sampler2D   ShadowMap : register(s3)
		   )
{ 
	float4 diffusetex = tex2D(diffuseCol, Uv);
	float3 bumpVec = expand(tex2D(normalMap, Uv ).xyz);
	float3 specVec = tex2D(specularCol, Uv ).xyz;
	float3 N = normalize(bumpVec);
	
	float3 HalfAngle[3];
	float NdotL[3];
	float NdotH[3];
	float4 Lit[3];
	float attFactor[3];
	
	float4 ldir[5];
	ldir[0] = LightDir0;
	ldir[1] = LightDir1;
	ldir[2] = LightDir2;
	//ldir[3] = LightDir3;
	//ldir[4] = LightDir4;
	//ldir[5] = LightDir5;
	
	half lightDist = length(lpoz.xyz - wp.xyz) / 100;
	
	float4 diffFact = 0;
	float4 specFact = 0;
	
	for(int i=0; i<3; ++i)
	{
		HalfAngle[i] = normalize(eyeDir + ldir[i].xyz);
		NdotL[i] = dot(ldir[i].xyz, N);
		NdotH[i] = dot(HalfAngle[i], N);
		Lit[i] = lit(NdotL[i],NdotH[i],exponent0); 
		attFactor[i] = saturate(1 / ldir[i].w / lightAtt[i].z) * saturate(1 / pow(ldir[i].w,2) / lightAtt[i].w);
		
		diffFact += lightDiffuse[i] * Lit[i].y * attFactor[i];
		specFact += lightSpecular[i] * Lit[i].z * attFactor[i]; 
	}
	
	 float3 shadow = computeShadow(
        // pass in the shadow map
        ShadowMap,
        // the calculated shadow position in the shadow map
        lp,
        // distance to light, done just as in the caster shader
       lightDist).xxx; // 3 components

	
	oColor = (diffusetex * (ambient + diffFact) + specFact) * shadow.x;	 // I know this produces a very dark shadow - it's just for debugging

}
PS. Yes I know i do lighting for 3 lights, and shadowing just for 1. I want to get this working first, then I'll modify it.
Hardcore libertarian, hardcore programmer.
Dell M6300: T9300, 4GB, Quadro FX1600M, 17" 1920x1200p non-glare, OCZ Vertex 120 + external Seagate 120GB 7200.3
Use the power of 2 - literally. Non 2^n texture sizes may crash your graphic driver
User avatar
nullsquared
Old One
Posts: 3245
Joined: Tue Apr 24, 2007 8:23 pm
Location: NY, NY, USA
x 11

Re: Ogre Soft Shadows Demo

Post by nullsquared »

Use a spotlight. Point lights are very complex to shadow map, they require either a cube map or a texture atlas. This is because a point light has 6 directions (up/down/left/right/forward/backward), but a spotlight has 1.
MattStevens
Goblin
Posts: 239
Joined: Mon Apr 07, 2008 10:27 pm
x 4

Re: Ogre Soft Shadows Demo

Post by MattStevens »

I have a strange issue with your shader. For testing purpose I changed the shadow map to use TEXUNIT2 instead of TEXUNIT1 (Thats the only change) and the resolution seems to get smaller because of that.

See the result, the second image's shadow is more blurry. I'll try to get more convincing pictures, but I'm sure that there is a problem related to this.

Good:
Image
Bad:
Image

- Matt
MattStevens
Goblin
Posts: 239
Joined: Mon Apr 07, 2008 10:27 pm
x 4

Re: Ogre Soft Shadows Demo

Post by MattStevens »

Here's another exemple with the same mesh & shaders, but implemented in my application. The difference is more visible.
You see the edge of the shadow has a blurry 1 pixel width all around.
Once again the only difference is that the shadow texture is passed in TEXUNIT2 instead of TEXUNIT1

EDIT: Okay, I finally found the problem. It is the parameter

Code: Select all

param_named_auto invSMSize inverse_texture_size
that had to be set accordingly to the index of the shadow texture. I still have to find why my result seems more pixelized, but that's another issue[/b]

Bad:
Image
Good:
Image

- Matt
wizardofoz
Gnoblar
Posts: 13
Joined: Tue Jan 27, 2009 10:21 pm

Re: Ogre Soft Shadows Demo

Post by wizardofoz »

Hi, first of all thanks for this beautiful example of soft shadows with Ogre.

I have only a problem:

While your example binary works perfectly when I try to implement it in my engine (it uses Ogre 1.6.2) my shadows have horrible hard edges.
I've tried using both PF_FLOAT32_RGB and PF_FLOAT15_RGB with Direct3D 9.0. In my laptop I've an ATI X1300, could be this the problem?
If I run my test program on Window Vista, NVIDIA 8800GTX shadows are softer.

I thought that ATI X1300 doesn't support something but your example binary (compiled with Ogre 1.4.9) works without problem....

Any help?

Thanks very much!
wizardofoz
Gnoblar
Posts: 13
Joined: Tue Jan 27, 2009 10:21 pm

Re: Ogre Soft Shadows Demo

Post by wizardofoz »

After some testing I discovered that ATI X1300 doesn't support texture filtering with float textures.
To have soft shadows I have to turn shadow textures to PF_A8R8G8B8.. so I've to found a different way to implement this code for older cards...

An idea:

1) Create a depth texture of the camera (PF_FLOAT32_RGB)
2) Use PF_A8R8G8B8 for shadow textures and in the shadow caster shader directly calculate the shadows by depth comparison (instead of writing the depth texture of the light).
3) Applying the shadow texture to object as always

Downside: rendering the depth buffer texture of the camera (but the depth is often used by shaders in general so no big problem).

Upside: Only one PF_FLOAT32_RGB for depth and more PF_A8R8G8B8 instead of having many PF_FLOAT32_RGB for every light.
(?)Another advantage could be the possibility of directly blurring the shadow texture using PCF (percentage close filtering(?)

I'm not an expert, so do you think this is a stupid idea or I could give it a try and trying to implement it?

Thanks again
Shimayama
Halfling
Posts: 74
Joined: Sat Apr 25, 2009 2:20 pm
Location: Norway
x 1

Re: Ogre Soft Shadows Demo

Post by Shimayama »

Thanks for this neat algorithm.

We would like to integrate it into our project, but having problems doing it in a generic way. Since we're using oFusion as exporter, we're stuck to oFusion's materials without the shadow code. Does anyone have any good idea of how to intergrate the softshadows with already defined shaders in an as generic way as possible? I want to modify existing shading code as little as possible, for example bump map fragment program.

Would it for example be possible to specify two separate passes? So that we first run our lighting code in one pass, and then multiply it by the shadow map code which is run in a second pass? Of course in the shadow pass we would have to return just the shadow map's value without lighting calculations. And finally apply the diffuse texture as a decal in one last pass? Maybe each material that would be a shadow receiver could then inherit this property of having a shadow pass from an abstract shadow-receiving material?
edelord
Gnoblar
Posts: 16
Joined: Wed May 27, 2009 7:39 am
Location: France

Re: Ogre Soft Shadows Demo

Post by edelord »

Hi,
This ogre Soft Shadows is a good works. Thanks for your sharing.
However, I have a problem and I need your help.
With Robot I have aliasing with the shadow. Look at the picture:
Robotaliasing.jpg

How can I resolve it please? I haven't got find a good solution.

Moreover, my shadow needs to change the color with an event.
I used for example a red (or another it's depend the event) like this:
mSceneMgr->setShadowColour(Ogre::CoulourValue(1, 0, 0, 1));
I used SHADOWTYPE_TEXTURE_MODULATIVE_INTEGRATED techniques. I'm beginner with Cg progem and I don't know How to do this.

Thanks for your help
You do not have the required permissions to view the files attached to this post.
mapleleaf
Gnoblar
Posts: 8
Joined: Fri Aug 21, 2009 3:27 am

Soft Shadows Problem..

Post by mapleleaf »

Hi, all

i'm question..

Image

You've seen pictures like this into the light is leaking.
(Using soft shadows light leaks.)

I would like to solve this problem.

Help Me ~~~~~~~

(i'm from korean, English is difficult.... Please understand... T.T;;)
Last edited by mapleleaf on Sun Apr 18, 2010 7:10 am, edited 1 time in total.
Hello.
User avatar
mkultra333
Gold Sponsor
Gold Sponsor
Posts: 1894
Joined: Sun Mar 08, 2009 5:25 am
x 116

Re: Ogre Soft Shadows Demo

Post by mkultra333 »

Shadow maps often "leak" a little bit at their bases, like for instance where a chair-leg touches the ground. Provided you make the chair leg thick enough you won't notice. The same can happen at wall edges if your wall is too thin.

There's an Epsilon value and some other tweaks in the shader you can experiment with to cut down with this kind of leakage, the tradeoff being that you can introduce other kinds of noise and error.

So if this is the cause of your light leakage, it could be that your walls are too thin, or you need to tweak some of the shader parameters.
"In theory there is no difference between practice and theory. In practice, there is." - Psychology Textbook.
nero81af
Gnoblar
Posts: 21
Joined: Wed Mar 12, 2014 10:07 am
x 2

Re: Ogre Soft Shadows Demo

Post by nero81af »

I'm sorry to bump this post but does anyone know where I can get this demo?