PDA

View Full Version : D3D10 Shadow Mapping


XVincentX
02-05-2009, 03:41 AM
I'm trying to make a little shadow map example with a point light: so i had to use a cubemap via Geometry Shader.
So i made a ViewMatrix array


D3DXMatrixLookAtLH(&cNeverChange.view[0],&D3DXVECTOR3(3.0f,10.0f,-35.0f),&D3DXVECTOR3(1,0,0),&D3DXVECTOR3(0,1,0));
D3DXMatrixLookAtLH(&cNeverChange.view[1],&D3DXVECTOR3(3.0f,10.0f,-35.0f),&D3DXVECTOR3(-1,0,0),&D3DXVECTOR3(0,1,0));
D3DXMatrixLookAtLH(&cNeverChange.view[2],&D3DXVECTOR3(3.0f,10.0f,-35.0f),&D3DXVECTOR3(0,1,0),&D3DXVECTOR3(0,0,1));
D3DXMatrixLookAtLH(&cNeverChange.view[3],&D3DXVECTOR3(3.0f,10.0f,-35.0f),&D3DXVECTOR3(0,-1,0),&D3DXVECTOR3(0,0,1));
D3DXMatrixLookAtLH(&cNeverChange.view[4],&D3DXVECTOR3(3.0f,10.0f,-35.0f),&D3DXVECTOR3(0,0,1),&D3DXVECTOR3(0,1,0));
D3DXMatrixLookAtLH(&cNeverChange.view[5],&D3DXVECTOR3(3.0f,10.0f,-35.0f),&D3DXVECTOR3(0,0,-1),&D3DXVECTOR3(0,1,0));




and set it in the geometry shader using a render target view array.
Now all it's finished, but the cubemap does not really convince me.
It's normal that all the face looks at the same point?
Here is a screenshot. (I'm using DXGI_FORMAT_R32_FLOAT)

http://img4.imageshack.us/img4/1197/98524769vp9.jpg
http://img17.imageshack.us/img17/9045/42060593bo7.jpg
http://img516.imageshack.us/img516/4778/70371578ov5.jpg

and so on...

rouncer
02-05-2009, 06:44 AM
Ive only ever handled spot lights and direction lights, doing point lights is advanced, i bet using the cube texture is a complete biatch, anyway good luck.
(btw, i think they are supposed to take shots different directions. ;))

XVincentX
02-05-2009, 07:29 AM
I think the same thing...

Reedbeta
02-05-2009, 09:29 AM
The problem is the third parameter to D3DXMatrixLookAtLH is the point to look at, not the direction to look. Just add each of those values to the camera location and you'll get something closer to what it's supposed to be. (You still may need to tweak the up vectors to get all the faces rotated the right way.)

BTW, the tag for posting code is [code] rather than [source].

XVincentX
02-05-2009, 10:25 AM
Oh you're right!
But...should not i have to do A - B instead A + B in order to get direction?

Reedbeta
02-05-2009, 11:12 AM
You already have the directions, and it wants the point to look at. So you need to add the camera location to the directions.

XVincentX
02-05-2009, 01:40 PM
Ok now my texture has got 6 different faces and looks like ok.
But i'm not yet convinced about the shadow.

To help you help me, i decided to mark shadowed pixel in red, in this image.
http://img4.imageshack.us/img4/6673/img1xe5.jpg

I'm not sure about results...there is a shadow only on the lamp itself?
Here is my shader code.


PS_INPUT vs_position (VS_INPUT In)
{
PS_INPUT Out = (PS_INPUT)0;

Out.Pos = mul(mul(mul(In.Pos,WorldMatrix),ViewMatrix),ProjMa trix);
Out.WPos = mul(In.Pos,WorldMatrix);
Out.Nor = mul(In.Nor,WorldMatrix);
Out.Tex = In.Tex;

Out.Dist = distance(Out.WPos,LightInfo.xyz);
Out.LPos = Out.WPos - LightInfo.xyz;

return Out;
}

float4 ps_light (PS_INPUT In) : SV_TARGET
{
float4 BaseColor = (Lamp == true) ? float4(0.25f, 0.21f, 0.20f, 1) : Text.Sample(SamplText,In.Tex);
float3 vLight = normalize(LightInfo.xyz-In.WPos);
float NdotL = dot(In.Nor,vLight);
float Att = Attenuation(distance(LightInfo.xyz,In.WPos),0.003, 0.003,0.003);
float4 Light1 = (saturate(NdotL)) * Att;

float shadow = Cubemap.Sample(SamplText,normalize(In.LPos));

if (shadow > In.Dist)
return float4(1,0,0,1);
else
{
return BaseColor * Light1;
}
}


Thank you again.

Goz
02-05-2009, 01:59 PM
It would be much easier, btw to, simply build yourself some simple matrices directly.

As you probably know a matrix is defined in rows as

<side vector>
<up vector>
<forward vector>
<position vector>

So for the simple case of look forward you'd set up a matrix as follows

1 0 0 0
0 1 0 0
0 0 1 0
3 10 -35 1

Now to convert that to a view matrix all you need to do is take the inverse of the matrix. Basically by transforming any position by the inverse of that matrix you are moving into the view space as defined. Work through the maths. It makes good sense :)

It'll be much easier, imo, to conceptualise your matrices if defined this way.

Goz
02-05-2009, 02:19 PM
The implication is, btw, that the value returned by "shadow" is NOT greater than the interpolated distance value. I'd look at the float values you are writing into the shadow depth buffer. Have you tried debugging the shader with pix to see what happens?

XVincentX
02-05-2009, 02:27 PM
I've not understood your theory...
What's the problem? Why should i use your "solution"?

XVincentX
02-05-2009, 02:41 PM
The implication is, btw, that the value returned by "shadow" is NOT greater than the interpolated distance value. I'd look at the float values you are writing into the shadow depth buffer. Have you tried debugging the shader with pix to see what happens?

Oh, this is what i was looking for.
The shadow depth buffer it's simply filled in this way

float4 ps_depth (VGS_OUTPUT In) : SV_TARGET
{
return In.P2D.z/In.P2D.w;
}


Changin the formula in this way


float4 ps_depth (VGS_OUTPUT In) : SV_TARGET
{
return distance(In.WPos,LightInfo);
//return In.P2D.z/In.P2D.w;
}



The shadowed zone grows.
http://img3.imageshack.us/img3/951/img1wo7.jpg

Goz
02-05-2009, 03:20 PM
OK ... and if you change the line

if (shadow > In.Dist )

to

if (shadow < In.Dist)

what happens?

You are testing to see if the current pixel position "In.Dist" is further away than shadow afterall.

XVincentX
02-05-2009, 03:26 PM
I just see the complete opposite. All red except for the "shadowed" zone.

Goz
02-06-2009, 03:04 AM
Hmmm ... the distances used ought to be positive values (a negative distance is non sensical). The implication would be, therefore, that if the current pixel distance is further than the shadow buffer distance then its shadowed.

Still. Run it under pix take a grab and debug it. Pix is an amazing piece of tech for doing this sort of thing :)

XVincentX
02-06-2009, 03:37 AM
I'm sorry but my english is not so good so i'm not able to understand fully your sentences.
Please do not punish me if i will ask you every time same things.

In this afteroon i will try your suggestions with PIX, but i've not understood if, in your opinion, the shadow is wrong.

Goz
02-06-2009, 04:02 AM
It looks fine to me, but I may be missing something.

Debugging with Pix would be great for validating the data coming from.

XVincentX
02-10-2009, 03:09 PM
Hello again. Now all it's going better and now i would add a second shadow with a spotlight.
I had no problem to make spotlight work and, making the shadow, i simply used the same technique updescribed but with only 1 texture.
To make sure i made the right work, i run a PIX simulation and tried to look at Render Target result: completely white.

The big problem that also the cubemap render target (that works perfectly) at the end of all draw calls it's white. So i do not know how to verify my work (that looks like wrong, since my shadow is not drawn correctly)

Suggestions?

Goz
02-11-2009, 01:21 AM
Can you not run the shadow map pixel shader through PIX and see what the values being written to the shadow map look like? Do they look sensible?

XVincentX
02-11-2009, 07:22 AM
Yes, i checked it completely.
I see both rendertarget completely white, but it's impossibile becouse

A) The first cubemap target works infact the shadow it's displayed correctly.
B) The second (Spotlight, so a single render target) also it's filled becouse a shadow it's displayed (wrong, but it's displayed).

To help you help me, i uploaded a complete PIX simulation, you can download it ah ftp://xvincentx.netsons.org/poppi.rar
It's about 3 mega.

Have a look at EID 736 (it's the cubemap filling) of frame 1, and in each frame look at first render target binding and drawing.

Thank you again

Goz
02-11-2009, 09:30 AM
That link doesn't work.

There is one slight other issue in that I accidentally destroyed my Vista laptop so I don't know if I can do a DX10 simulation under DX9. But if you get the link working i'll give it a try :)

XVincentX
02-11-2009, 10:04 AM
Mmm it works for me...it's very strange. Are you sure?

Goz
02-11-2009, 01:23 PM
Presumably I don't have a log on to your ftp site?

Reedbeta
02-11-2009, 02:53 PM
Yeah, the ftp link for me returns a blank page.

XVincentX
02-11-2009, 03:14 PM
Try on http.

http://xvincentx.netsons.org/poppi.rar

Reedbeta
02-11-2009, 04:47 PM
BTW, I haven't been following this thread too closely, but if you are using a floating point buffer for the shadow map, and your units are smallish (like centimeters or so), then all of the distances in the shadow map could be > 1.0, and I'd guess PIX would render it as all white.

You could see if PIX lets you peek at the actual values in the buffer, or just divide the output depth by some large number in the PS.

Goz
02-12-2009, 01:38 AM
Bummer :( You can open up a D3D10 pix run under XP .. but the moment you try and click anything it returns E_NOINTERFACE ...

Sorry.

XVincentX
02-12-2009, 02:06 AM
What a problem...really do not know what to do.
I tried also to save surfaces as textures, but nothing.
I tried also to use directly depth buffer as resource (i created texture as R32_TYPELESS, depth as D32_FLOAT and texture as R32_FLOAT).
But thre are not new results.

I remember before i was able to see the cubemap render target.
Now i can't see nothing more...

Goz
02-12-2009, 04:02 AM
I remember before i was able to see the cubemap render target.
Now i can't see nothing more...

Well thats because you changed the way you write into the depth target.

You should also, potentially, look at re-writing your look up to work with the z/w system.

XVincentX
02-12-2009, 07:37 AM
Mmm...anyway, something it's drawn on the render target, becouse i'm able to get this result.
http://img440.imageshack.us/img440/8757/img1pe7.jpg

Even if completely wrong, it's something that looks like a shadow.

After i made sense of another my error: in texture projection, i was making mul with original camera matrix, not with the light's one.
I fixed it but the result was not of best.

http://img19.imageshack.us/img19/201/img2hv7.jpg

I'm on the way of complete it...


EDIT:
You was right: dividing the distance by a little number (i just decided 200.0f) now PIX shows me buffers completely.
It's a relief, finally.
But now the shadowed zone are completely...empty.
Something is not good yet.

http://img22.imageshack.us/img22/7341/img1yy6.jpg

XVincentX
02-12-2009, 08:30 AM
I will show you entire shader code, mabye it may help you.


cbuffer cMultiFrame
{
row_major float4x4 WorldMatrix;
bool Lamp;
};

cbuffer cSometime
{
row_major float4x4 ViewMatrix;
row_major float4x4 VSpotMatrix; //Spotlight matrix
float4 LightInfo; //Point light position
float4 LightInfo2; //Spotlight direction
float4 LightInfo3; //Spotlight position
float Phi;
float Theta;
};

cbuffer cNeverChange
{
row_major float4x4 ProjMatrix; //ProjMatrix for spotlight and normal rendering
row_major float4x4 VMatrix[6]; //6 matrices for cubemap point light
};

Texture2D Text;
TextureCube Cubemap;
Texture2D SpotText;
SamplerState SamplText;

float Attenuation
(
float distance,
float a,
float b,
float c
)
{
float Atten = 1.0f / ( a + b * distance + c * pow(distance,2) );
return Atten;
}

struct VS_INPUT
{
float4 Pos : POSITION;
float3 Nor : NORMAL;
float2 Tex : TEXCOORD;
};

struct PS_INPUT
{
float4 Pos : SV_POSITION;
float4 PSpot2D : P2DPOS;
float4 WPos: WORLDPOS;
float3 Nor : NORMAL;
float2 Tex : TEXCOORD;
float3 LPos : PROJPOS;
float Dist: DISTANCE;
float Dist2: DISTANCE2;
};

struct VGS_OUTPUT
{
float4 Pos : SV_POSITION;
float4 WPos: WORLDPOSITION;
uint RTIndex : SV_RenderTargetArrayIndex;
};

struct VPS_OUTPUT
{
float4 Pos : SV_POSITION;
float4 WPos: WORLDPOSITION;
};


PS_INPUT vs_position (VS_INPUT In)
{
PS_INPUT Out = (PS_INPUT)0;

Out.Pos = mul(mul(mul(In.Pos,WorldMatrix),ViewMatrix),ProjMa trix);
Out.PSpot2D = mul(mul(mul(In.Pos,WorldMatrix),VSpotMatrix),ProjM atrix);
Out.WPos = mul(In.Pos,WorldMatrix);
Out.Nor = mul(In.Nor,WorldMatrix);
Out.Tex = In.Tex;

Out.Dist = distance(Out.WPos,LightInfo.xyz);
Out.Dist2 = distance(Out.WPos,LightInfo3.xyz);
Out.LPos = Out.WPos - LightInfo.xyz;

return Out;
}

VS_INPUT vs_void (VS_INPUT In)
{
return In;
}


float4 ps_light (PS_INPUT In) : SV_TARGET
{
float4 BaseColor = (Lamp == true) ? float4(0.25f, 0.21f, 0.20f, 1) : Text.Sample(SamplText,In.Tex);
float3 vLight = normalize(LightInfo.xyz-In.WPos);
float NdotL = dot(In.Nor,vLight);
float Att = Attenuation(distance(LightInfo.xyz,In.WPos),0.003, 0.003,0.003);
float4 PointLight = (saturate(NdotL)) * Att;

float4 LightToVecDirection = normalize(LightInfo3 - In.WPos);
float4 LightToSourceDirection = normalize(LightInfo3 - LightInfo2);
float cosAlpha = dot(LightToVecDirection,LightToSourceDirection);

float Atten = 0.0f;

if( cosAlpha > Theta )
{
Atten = 1.0f;
}
else if( cosAlpha > Phi )
{
Atten = 1.0f;
}

NdotL = max( 0.0f, dot( In.Nor, LightToVecDirection ) );

float shadow = Cubemap.Sample(SamplText,normalize(In.LPos));
float4 SpotLight = (Atten * NdotL);

float2 ViewTexC = 0.5 * In.PSpot2D.xy / In.PSpot2D.w + float2( 0.5, 0.5 );
ViewTexC.y = 1.0f - ViewTexC.y;

float SpotShadow = SpotText.Sample(SamplText,ViewTexC);

if (In.Dist < shadow)
{
return float4(1,0,0,0);
}

else if (In.Dist2 < SpotShadow)
{
return float4(0,1,0,0);
}

else
{
return (PointLight + SpotLight) * BaseColor;
}

}

[maxvertexcount(24)]
void Gs_Cubemap(triangle VS_INPUT input[3], inout TriangleStream<VGS_OUTPUT> Out)
{
VGS_OUTPUT output;

for( int f = 0; f < 6; f++ )
{
output.RTIndex = f;
for( int v = 0; v < 3; v++ )
{
output.Pos = mul(mul(mul( input[v].Pos, WorldMatrix),VMatrix[f]),ProjMatrix );
output.WPos = mul(input[v].Pos,WorldMatrix);
Out.Append( output );
}

Out.RestartStrip();
}
}

float ps_depth (VGS_OUTPUT In) : SV_TARGET
{
return distance(In.WPos,LightInfo);
}

float ps_spotdepth (VPS_OUTPUT In) : SV_TARGET
{
return distance(In.WPos,LightInfo3);
}

VPS_OUTPUT vs_spot(VS_INPUT In)
{
VPS_OUTPUT p = (VPS_OUTPUT)0;

p.Pos = mul(mul(mul(In.Pos,WorldMatrix),VSpotMatrix),ProjM atrix);
p.WPos = mul(In.Pos,WorldMatrix);

return p;
}


I apologyze for the owful code.

Goz
02-12-2009, 02:30 PM
Ok I am clutching at straws here but in your vertex shader you have

Out.LPos = Out.WPos - LightInfo.xyz;

Shouldn't that be? LightInfo.xyz - Out.wPos?

XVincentX
02-12-2009, 03:15 PM
I do not think that this is the problem.
Even if your solution was OK, remains the problem on SpotLight.

Let's start to make order in the shader.

A) Have i to divide all for, as i read in some sites, FarClip of my ProjMatrix? If yes, where?

Only in depth passes or also here?

Out.Dist = distance(Out.WPos,LightInfo.xyz) / FarClip;
Out.Dist2 = distance(Out.WPos,LightInfo3.xyz) / FarClip;


B) Why the division makes the result worse? I think that in worse case it may be identical (i made a division to all factors...)

C) I know, the spotlight shadow check should be done only in the Phi and Theta range, but for now i want to see the shadow every time :D

D) Something is going wrong in shadow checking. Infact in all other tutorial and resources i found on the web, the check was done in other side.

While i make if (In.Dist < shadow)

they make the opposite. You can check this on ziggyware.
E) Wanna see also C++ source code?

Goz
02-12-2009, 11:55 PM
I do not think that this is the problem.
Even if your solution was OK, remains the problem on SpotLight.

Let's start to make order in the shader.

A) Have i to divide all for, as i read in some sites, FarClip of my ProjMatrix? If yes, where?

Only in depth passes or also here?

Out.Dist = distance(Out.WPos,LightInfo.xyz) / FarClip;
Out.Dist2 = distance(Out.WPos,LightInfo3.xyz) / FarClip;


Well if you are going to divide by FarClip then do it consistentile on all distance calculations. Afterall if x = y then x/z = y/z.

B) Why the division makes the result worse? I think that in worse case it may be identical (i made a division to all factors...)

It will make the result worse if you don't consistently divide distances by this "FarClip".

C) I know, the spotlight shadow check should be done only in the Phi and Theta range, but for now i want to see the shadow every time :D

D) Something is going wrong in shadow checking. Infact in all other tutorial and resources i found on the web, the check was done in other side.

While i make if (In.Dist < shadow)

they make the opposite. You can check this on ziggyware.

Well, as i've mentioned before in this thread, your check IS the wrong way round.

E) Wanna see also C++ source code?

I really don't see it will help, unfortunately.

I wish I had my DX10 laptop back :(

XVincentX
02-13-2009, 04:01 AM
Well if you are going to divide by FarClip then do it consistentile on all distance calculations. Afterall if x = y then x/z = y/z.


I think i did it all opportunes times. Have i miss somewhere?


Well, as i've mentioned before in this thread, your check IS the wrong way round.

IS = ? Please do not use abbreviations, i've got already a lot of difficulties to understand in right way your senteces!! :P


I wish I had my DX10 laptop back :(


Me too :D

Goz
02-13-2009, 07:01 AM
I think i did it all opportunes times. Have i miss somewhere?

I don't know .. you haven't posted up the modified code ;)


IS = ? Please do not use abbreviations, i've got already a lot of difficulties to understand in right way your senteces!! :P

Not abbreviated at all. "IS" is ... well .. is :D

XVincentX
02-13-2009, 07:17 AM
I made the division in all parts in which i used distance function.
4 times.

XVincentX
02-14-2009, 10:19 AM
Updates:

I decided to rewrite completely the pixel shader.
I wrote the correct Spotlight function, and now my aim is to get first spotlight shadow works, and after the other one.

So, this is the code:


#define FarClip 200

cbuffer cMultiFrame
{
row_major float4x4 WorldMatrix;
bool Lamp;
};

cbuffer cSometime
{
row_major float4x4 ViewMatrix;
row_major float4x4 VSpotMatrix; //Matrice spotlight
float4 LightInfo; //Luce puntiforme del lampione
float4 LightInfo2; //Direzione del fanale
float4 LightInfo3; //Posizione del fanale
float Phi;
float Theta;
};

cbuffer cNeverChange
{
row_major float4x4 ProjMatrix;
row_major float4x4 VMatrix[6];
};

Texture2D Text;
TextureCube Cubemap;
Texture2D SpotText;
SamplerState SamplText;

float Attenuation
(
float distance,
float a,
float b,
float c
)
{
float Atten = 1.0f / ( a + b * distance + c * pow(distance,2) );
return Atten;
}

struct VS_INPUT
{
float4 Pos : POSITION;
float3 Nor : NORMAL;
float2 Tex : TEXCOORD;
};

struct PS_INPUT
{
float4 Pos : SV_POSITION;
float4 PSpot2D : P2DPOS;
float4 WPos: WORLDPOS;
float3 Nor : NORMAL;
float2 Tex : TEXCOORD;
float3 LPos : PROJPOS;
float Dist: DISTANCE;
float Dist2: DISTANCE2;
};

struct VGS_OUTPUT
{
float4 Pos : SV_POSITION;
float4 WPos: WORLDPOSITION;
uint RTIndex : SV_RenderTargetArrayIndex;
};

struct VPS_OUTPUT
{
float4 Pos : SV_POSITION;
float4 WPos: WORLDPOSITION;
};


PS_INPUT vs_position (VS_INPUT In)
{
PS_INPUT Out = (PS_INPUT)0;

Out.Pos = mul(mul(mul(In.Pos,WorldMatrix),ViewMatrix),ProjMa trix);
Out.PSpot2D = mul(mul(mul(In.Pos,WorldMatrix),VSpotMatrix),ProjM atrix);
Out.WPos = mul(In.Pos,WorldMatrix);
Out.Nor = mul(In.Nor,WorldMatrix);
Out.Tex = In.Tex;

Out.Dist = distance(Out.WPos,LightInfo.xyz);
Out.Dist2 = distance(Out.WPos,LightInfo3.xyz);
Out.LPos = Out.WPos - LightInfo.xyz;

return Out;
}

VS_INPUT vs_void (VS_INPUT In)
{
return In;
}


float4 ps_light (PS_INPUT In) : SV_TARGET
{
float4 BaseColor = (Lamp == true) ? float4(0.25f, 0.21f, 0.20f, 1) : Text.Sample(SamplText,In.Tex);
float3 vLight = normalize(LightInfo.xyz-In.WPos);
float NdotL = dot(In.Nor,vLight);
float Att = Attenuation(distance(LightInfo.xyz,In.WPos),0.003, 0.003,0.003);
float4 PointLight = (saturate(NdotL)) * Att;

float4 LightToVecDirection = normalize(LightInfo3 - In.WPos);
float4 LightToSourceDirection = normalize(LightInfo3 - LightInfo2);
float cosAlpha = dot(LightToVecDirection,LightToSourceDirection);

float2 VTexC = In.PSpot2D.xy / In.PSpot2D.w * 0.5f - float2(0.5f,0.5f);
VTexC.y = 1.0f - VTexC.y;

float SpotShadow = SpotText.Sample(SamplText,VTexC);

float Atten = 0.0f;

if( cosAlpha > Theta )
{
Atten = 1.0f;
}
else if( cosAlpha > Phi )
{
Atten = 0.5f;
}

if (Atten != 0)
{
if ((In.Dist2/FarClip) <= SpotShadow)
{
return float4(1,0,0,0);
}
}

float4 SpotLight = (Atten * dot( In.Nor, LightToVecDirection ));

return (PointLight + SpotLight) * BaseColor;

}

[maxvertexcount(18)]
void Gs_Cubemap(triangle VS_INPUT input[3], inout TriangleStream<VGS_OUTPUT> Out)
{
VGS_OUTPUT output;

for( int f = 0; f < 6; f++ )
{
output.RTIndex = f;
for( int v = 0; v < 3; v++ )
{
output.Pos = mul(mul(mul( input[v].Pos, WorldMatrix),VMatrix[f]),ProjMatrix );
output.WPos = mul(input[v].Pos,WorldMatrix);
Out.Append( output );
}

Out.RestartStrip();
}
}

float ps_depth (VGS_OUTPUT In) : SV_TARGET
{
return distance(In.WPos,LightInfo) / FarClip;
}

float ps_spotdepth (VPS_OUTPUT In) : SV_TARGET
{
return distance(In.WPos,LightInfo3) / FarClip;
}

VPS_OUTPUT vs_spot(VS_INPUT In)
{
VPS_OUTPUT p = (VPS_OUTPUT)0;

p.Pos = mul(mul(mul(In.Pos,WorldMatrix),VSpotMatrix),ProjM atrix);
p.WPos = mul(In.Pos,WorldMatrix);

return p;
}


That, obiously, does not work.
But now the render target it's completely and correctly filled, as this screen shows.
http://img3.imageshack.us/img3/4621/imggj9.jpg

Goz
02-14-2009, 04:13 PM
if ((In.Dist2/FarClip) <= SpotShadow)

This line should still be

if ((In.Dist2/FarClip) >= SpotShadow)

in my mind. I can't understand why you are trying to shadow pixels CLOSER to the light. Still ... it "should" just give you an inverted shadow.

Also for consistency's sake shouldn't

return distance(In.WPos,LightInfo3) / FarClip;

be

return distance(In.WPos,LightInfo3.xyz) / FarClip;

?

Anyway ... thats just some past midnight slightly drunked thoughts ...

XVincentX
02-15-2009, 01:58 AM
if ((In.Dist2/FarClip) <= SpotShadow)

This line should still be

if ((In.Dist2/FarClip) >= SpotShadow)

in my mind. I can't understand why you are trying to shadow pixels CLOSER to the light. Still ... it "should" just give you an inverted shadow.



I'm sorry i make every time the same mistake, but usually when something does not work i start simply to play with values.
Anyway, it does not work becouse it shows me ALL in shadow, and not only some parts.


Also for consistency's sake shouldn't

return distance(In.WPos,LightInfo3) / FarClip;

be

return distance(In.WPos,LightInfo3.xyz) / FarClip;

?

Anyway ... thats just some past midnight slightly drunked thoughts ...


I will adjust this.

XVincentX
02-15-2009, 05:33 AM
I made another try in shader.
I just wrote a return In.Dist2/FarClip, and the image looks fine.
You can see it here
http://img24.imageshack.us/img24/7074/imgtk1.jpg

So now i think that textures are completely filled fine. But still i can't see any kind of shadow. What's going wrong???

XVincentX
02-15-2009, 01:09 PM
Another update.
I decided to look directly at the buffer with this new shader


#define FarClip 200

cbuffer cMultiFrame
{
row_major float4x4 WorldMatrix;
bool Lamp;
};

cbuffer cSometime
{
row_major float4x4 ViewMatrix;
row_major float4x4 VSpotMatrix; //Matrice spotlight
float4 LightInfo; //Luce puntiforme del lampione
float4 LightInfo2; //Direzione del fanale
float4 LightInfo3; //Posizione del fanale
float Phi;
float Theta;
};

cbuffer cNeverChange
{
row_major float4x4 ProjMatrix;
row_major float4x4 VMatrix[6];
};

Texture2D Text;
Texture2D SpotText;
TextureCube Cubemap;
SamplerState SamplText;

float Attenuation
(
float distance,
float a,
float b,
float c
)
{
float Atten = 1.0f / ( a + b * distance + c * pow(distance,2) );
return Atten;
}

struct VS_INPUT
{
float4 Pos : POSITION;
float3 Nor : NORMAL;
float2 Tex : TEXCOORD;
};

struct PS_INPUT
{
float4 Pos : SV_POSITION;
float4 PSpot2D : P2DPOS;
float4 WPos: WORLDPOS;
float3 Nor : NORMAL;
float2 Tex : TEXCOORD;
float3 LPos : PROJPOS;
float Dist: DISTANCE;
float Dist2: DISTANCE2;
};

struct VGS_OUTPUT
{
float4 Pos : SV_POSITION;
float4 WPos: WORLDPOSITION;
uint RTIndex : SV_RenderTargetArrayIndex;
};

struct VPS_OUTPUT
{
float4 Pos : SV_POSITION;
float4 WPos: WORLDPOSITION;
};


PS_INPUT vs_position (VS_INPUT In)
{
PS_INPUT Out = (PS_INPUT)0;

Out.Pos = mul(mul(mul(In.Pos,WorldMatrix),ViewMatrix),ProjMa trix);
Out.PSpot2D = mul(mul(mul(In.Pos,WorldMatrix),VSpotMatrix),ProjM atrix);
Out.WPos = mul(In.Pos,WorldMatrix);
Out.Nor = mul(In.Nor,WorldMatrix);
Out.Tex = In.Tex;

Out.Dist = distance(Out.WPos,LightInfo.xyz);
Out.Dist2 = distance(Out.WPos,LightInfo3.xyz);
Out.LPos = Out.WPos - LightInfo.xyz;

return Out;
}

VS_INPUT vs_void (VS_INPUT In)
{
return In;
}


float4 ps_light (PS_INPUT In) : SV_TARGET
{


float4 BaseColor = (Lamp == true) ? float4(0.25f, 0.21f, 0.20f, 1) : Text.Sample(SamplText,In.Tex);
float3 vLight = normalize(LightInfo.xyz-In.WPos);
float NdotL = dot(In.Nor,vLight);
float Att = Attenuation(distance(LightInfo.xyz,In.WPos),0.003, 0.003,0.003);
float4 PointLight = (saturate(NdotL)) * Att;

float3 LightToVecDirection = normalize(LightInfo3.xyz - In.WPos);
float3 LightToSourceDirection = normalize(LightInfo3.xyz - LightInfo2.xyz);
float cosAlpha = dot(LightToVecDirection,LightToSourceDirection);

float2 VTexC;
VTexC[0] = In.PSpot2D.x/In.PSpot2D.w/2.0f +0.5f;
VTexC[1] = -In.PSpot2D.y/In.PSpot2D.w/2.0f +0.5f;

float SpotShadow = SpotText.Sample(SamplText,VTexC);


float Atten = 0.0f;

if( cosAlpha > Theta )
{
Atten = 1.0f;
}
else if( cosAlpha > Phi )
{
Atten = 0.5f;
}

if (Atten != 0)
{
if ((In.Dist2/FarClip) >= SpotShadow)
{
return SpotShadow;
}
}

float4 SpotLight = (Atten * dot( In.Nor, LightToVecDirection ));
return (PointLight + SpotLight) * BaseColor;

}

[maxvertexcount(18)]
void Gs_Cubemap(triangle VS_INPUT input[3], inout TriangleStream<VGS_OUTPUT> Out)
{
VGS_OUTPUT output;

for( int f = 0; f < 6; f++ )
{
output.RTIndex = f;
for( int v = 0; v < 3; v++ )
{
output.Pos = mul(mul(mul( input[v].Pos, WorldMatrix),VMatrix[f]),ProjMatrix );
output.WPos = mul(input[v].Pos,WorldMatrix);
Out.Append( output );
}

Out.RestartStrip();
}
}

float ps_depth (VGS_OUTPUT In) : SV_TARGET
{
return distance(In.WPos,LightInfo.xyz) / FarClip;
}

float ps_spotdepth (VPS_OUTPUT In) : SV_TARGET
{
return distance(In.WPos,LightInfo3.xyz) / FarClip;
}

VPS_OUTPUT vs_spot(VS_INPUT In)
{
VPS_OUTPUT p = (VPS_OUTPUT)0;

p.Pos = mul(mul(mul(In.Pos,WorldMatrix),VSpotMatrix),ProjM atrix);
p.WPos = mul(In.Pos,WorldMatrix);

return p;
}


And i had this new result.
http://img7.imageshack.us/img7/2738/28018315ze0.jpg

Can this help?

Goz
02-16-2009, 01:39 AM
Well you can definitely see there is an error there. The car in the shadow map "should" line up with the car in the scene (By my understand anyway). This implies, to me, that there is a problem with your shadow lookup method.

It "looks" like you are offset by 0.5 in the y direction. But i'm checking over your code and I can't see why that would be.

XVincentX
02-16-2009, 04:07 AM
May the view matrix be wrong?

XVincentX
02-16-2009, 10:45 AM
Another update.
Today i was playing aroud application trying to have a decent camera system.
After some tries, i changed the Projection matrix, from this
D3DXMatrixPerspectiveFovLH(&cNeverChange.proj,D3DXToRadian(90.0f),1.0f,1.0f,20 0.0f);
to this other one
D3DXMatrixPerspectiveFovLH(&cNeverChange.proj,(float)D3DX_PI * 0.25f ,4/3,1.0f,200.0f);

And i had this new result.

http://img99.imageshack.us/img99/1210/imgdv2.jpg

That looks like better in terms of projection texture, but i read that to make the light rendering i have to make a projection matrix with 90 as degree and 1 as aspect ratio.
I'm using also the SAME matrix to render the normal scene.

Mabye something is going wrong here?

XVincentX
02-16-2009, 10:56 AM
Making also a quad backbuffer (so they can really share the same matrix) the situations improves.

http://img12.imageshack.us/img12/7430/imgxf9.jpg

But it stills say me that all spotlight is in shadow.

Goz
02-17-2009, 01:45 PM
Ok .. now offset the values written into the shadow buffer by some tiny amount.

ie change

return distance(In.WPos,LightInfo3);

to return distance(In.WPos,LightInfo3) + 0.00001f; and see if that improves your results.

Either that or you could also change

if ((In.Dist2/FarClip) >= SpotShadow)

to

if ((In.Dist2/FarClip) > SpotShadow)

Basically, what i'm guessing is happening, is that when you test a pixel to see if it is furhter than the shadow buffer you ALSO check to see if it is the same distance. Logically any pixel that has gone through the same set of transformations in 2 different shaders is STILL going to evaluate to the same position (It would be a nightmare if this didn't happen). That way any pixel that falls on the same position as the shadow texel will have the same depth.

XVincentX
02-17-2009, 03:49 PM
Nothing of two helped. I was able to get a decent result only adding 30.0f in distance pixel shader.
This is the best result i had.

http://img16.imageshack.us/img16/4255/senzatitolo1yv8.jpg

that looks like ok, but 30 it's too much...i think.

Goz
02-18-2009, 05:59 AM
Do you add the small epsilon value (my suggested 0.00001 might be too small) before or after the divide by far clip? (Seeing as i got that wrong).

I'm shocked that you need to push it back as far as 30 units you ought to be able to get away with far smaller. Can you write the spot shadow buffer to a file and take a look at the ACTUAL values in it?

XVincentX
02-18-2009, 08:57 AM
sure. i will lock the buffer and write it on file.

XVincentX
02-18-2009, 09:36 AM
Ok i did it.
Texture is completely aviable from here
http://xvincentx.netsons.org/depth.rar

To better understand it, this is the code i used to lock it.

ID3D10Texture2D *z,*w;
D3D10_TEXTURE2D_DESC gigi;
SSV->GetResource((ID3D10Resource**)&z);
z->GetDesc(&gigi);
gigi.CPUAccessFlags = D3D10_CPU_ACCESS_READ;
gigi.Usage = D3D10_USAGE_STAGING;
gigi.BindFlags = 0;
Device->CreateTexture2D(&gigi,NULL,&w);
Device->CopyResource(w,z);

D3D10_MAPPED_TEXTURE2D mapped;
w->Map(0,D3D10_MAP_READ,0,&mapped);

float *values = new float[gigi.Width*gigi.Height];

memcpy(values,mapped.pData,sizeof(float)*gigi.Widt h*gigi.Height);
w->Unmap(0);
w->Release();


FILE *zeta = fopen("depth.txt","w");

for (int v = 0; v < _msize(values) / sizeof(float); v++)
{
fprintf(zeta,"%f \n",values[v]);

if (v%800 == 0 && v >= 800)
fprintf(zeta,"\n");

}

fclose(zeta);



The values looks like "normal" so i do not understand the need to subract 50.
About your sum value, i tried before and also after the division.

I forgot to post it to you yesterday.
Adding 0.1 in this way

return (distance(In.WPos,LightInfo3.xyz) ) / FarClip + 0.1f;
http://img519.imageshack.us/img519/7945/imgty8.jpg
This is the result.

Adding 0.11 instead of 0.1 the ball on the car vanishes, but anyway some parts are, anyway, unrendered correctly.
http://img27.imageshack.us/img27/2362/imgxl5.jpg

Compare these two images with the one with gray shadow: near the real car there is a black spot (due to return 0 statement)...while it should be lighted (anyway, it happens if instead of 30 i add 27)

Goz
02-19-2009, 01:05 AM
Hmm A few new thoughts come to mind. You do the world position to spot light distance check in the vertex shader in the non-shadow pass and in the pixel shader in the shadow pass. Do them both in the vertex or pixel shader.

Also you didn't add the 0.0001 to the non-shadow pass did you?

It makes no sense that it would only work by adding 30 to the shadow distances because they are all between 0.0 and 1.0. By adding 30 you are pushing them to 30.0 to 31.0 and then checking them against distances in the 0 to 1 range. I really think there must be something you are doing wrong.

Goz
02-19-2009, 01:12 AM
I have also re-written your shader code slightly. I haven't compiled it so it may fail but give it a try.


#define FarClip 200

cbuffer cMultiFrame
{
row_major float4x4 WorldMatrix;
bool Lamp;
};

cbuffer cSometime
{
row_major float4x4 ViewMatrix;
row_major float4x4 VSpotMatrix; //Matrice spotlight
float4 LightInfo; //Luce puntiforme del lampione
float4 LightInfo2; //Direzione del fanale
float4 LightInfo3; //Posizione del fanale
float Phi;
float Theta;
};

cbuffer cNeverChange
{
row_major float4x4 ProjMatrix;
row_major float4x4 VMatrix[6];
};

Texture2D Text;
TextureCube Cubemap;
Texture2D SpotText;
SamplerState SamplText;

float Attenuation
(
float distance,
float a,
float b,
float c
)
{
float Atten = 1.0f / ( a + b * distance + c * pow(distance,2) );
return Atten;
}

struct VS_INPUT
{
float4 Pos : POSITION;
float3 Nor : NORMAL;
float2 Tex : TEXCOORD;
};

struct PS_INPUT
{
float4 Pos : SV_POSITION;
float4 PSpot2D : P2DPOS;
float4 WPos: WORLDPOS;
float3 Nor : NORMAL;
float2 Tex : TEXCOORD;
};

struct VGS_OUTPUT
{
float4 Pos : SV_POSITION;
float4 WPos: WORLDPOSITION;
uint RTIndex : SV_RenderTargetArrayIndex;
};

struct VPS_OUTPUT
{
float4 Pos : SV_POSITION;
float4 WPos: WORLDPOSITION;
};


PS_INPUT vs_position (VS_INPUT In)
{
PS_INPUT Out = (PS_INPUT)0;

Out.Pos = mul(mul(mul(In.Pos,WorldMatrix),ViewMatrix),ProjMa trix);
Out.PSpot2D = mul(mul(mul(In.Pos,WorldMatrix),VSpotMatrix),ProjM atrix);
Out.WPos = mul(In.Pos,WorldMatrix);
Out.Nor = mul(In.Nor,WorldMatrix);
Out.Tex = In.Tex;

return Out;
}

VS_INPUT vs_void (VS_INPUT In)
{
return In;
}


float4 ps_light (PS_INPUT In) : SV_TARGET
{
float4 BaseColor = (Lamp == true) ? float4(0.25f, 0.21f, 0.20f, 1) : Text.Sample(SamplText,In.Tex);
float3 vLight = normalize(LightInfo.xyz-In.WPos);
float NdotL = dot(In.Nor,vLight);
float Att = Attenuation(distance(LightInfo.xyz,In.WPos),0.003, 0.003,0.003);
float4 PointLight = (saturate(NdotL)) * Att;

// Get the light to vec distance inside the pixel shader to match
float4 LightToVec = LightInfo3.xyz - In.WPos;
float LightToVecDist = length( LightToVec )
float4 LightToVecDirection = lightToVec / lightToVecDist; // This normalises


float4 LightToSourceDirection = normalize(LightInfo3 - LightInfo2);
float cosAlpha = dot(LightToVecDirection,LightToSourceDirection);

float2 VTexC = In.PSpot2D.xy / In.PSpot2D.w * 0.5f - float2(0.5f,0.5f);
VTexC.y = 1.0f - VTexC.y;

float SpotShadow = SpotText.Sample(SamplText,VTexC);

float Atten = 0.0f;

if( cosAlpha > Theta )
{
Atten = 1.0f;
}
else if( cosAlpha > Phi )
{
Atten = 0.5f;
}

if (Atten != 0)
{
if ((LightToVecDist / FarClip) >= SpotShadow)
{
return float4(1,0,0,0);
}
}

float4 SpotLight = (Atten * dot( In.Nor, LightToVecDirection ));

return (PointLight + SpotLight) * BaseColor;

}

[maxvertexcount(18)]
void Gs_Cubemap(triangle VS_INPUT input[3], inout TriangleStream<VGS_OUTPUT> Out)
{
VGS_OUTPUT output;

for( int f = 0; f < 6; f++ )
{
output.RTIndex = f;
for( int v = 0; v < 3; v++ )
{
output.Pos = mul(mul(mul( input[v].Pos, WorldMatrix),VMatrix[f]),ProjMatrix );
output.WPos = mul(input[v].Pos,WorldMatrix);
Out.Append( output );
}

Out.RestartStrip();
}
}

float ps_depth (VGS_OUTPUT In) : SV_TARGET
{
return distance(In.WPos,LightInfo) / FarClip;
}

float ps_spotdepth (VPS_OUTPUT In) : SV_TARGET
{
return (distance(In.WPos,LightInfo3) / FarClip) + 0.0001;
}

VPS_OUTPUT vs_spot(VS_INPUT In)
{
VPS_OUTPUT p = (VPS_OUTPUT)0;

p.Pos = mul(mul(mul(In.Pos,WorldMatrix),VSpotMatrix),ProjM atrix);
p.WPos = mul(In.Pos,WorldMatrix);

return p;
}

XVincentX
02-19-2009, 03:22 AM
I simply corrected the compiling error...it works.
As i can see you just computed distances all in pixel shader...while i made a mistake (one in vertex, another in pixel)
Why don't you use the normalize function?

Goz
02-19-2009, 04:22 AM
So that code gives you the right shadowing?

The only reason I don't use the normalize function is that it saves computation. Normalize is the same as doing vec / length( vec ). So i need the length in the pixel shader and THEN i need to normalize the vector. Length is not a speedy calculation (sqrt( dot( vec, vec ) )) so i see no point in doing the work twice :)

But yes .. essentially the only difference is that I am calculating the distance per pixel instead of per vertex and interpolating. I'm not entirely sure why they don't both produce the same result. Its probably to do with perspective correct interpolation of the distance value that causes it to wander from exactly what you are after. I should go through the maths but I'm supposed to be working (Bloody bayesian likelihood ratios and n-Vectors all rolled into one! :wacko:)

XVincentX
02-19-2009, 05:23 AM
Thank you again. I will try the same thing for the PointLight shadow made with cubemap, even if i'm fighing against a D3D10 Internal Compiler error.

XVincentX
02-19-2009, 01:29 PM
Ok now i started to work on second shadow.
I tried to follow your example, reusing the same code, but (...) the result was not the hoped one.


#define FarClip 200

cbuffer cMultiFrame
{
row_major float4x4 WorldMatrix;
bool Lamp;
};

cbuffer cSometime
{
row_major float4x4 ViewMatrix;
row_major float4x4 VSpotMatrix; //Matrice spotlight
float4 LightInfo; //Luce puntiforme del lampione
float4 LightInfo2; //Direzione del fanale
float4 LightInfo3; //Posizione del fanale
float2 Angles;
};

cbuffer cNeverChange
{
row_major float4x4 ProjMatrix;
row_major float4x4 VMatrix[6];
};

Texture2D Text;
TextureCube Cubemap;
Texture2D SpotText;
SamplerState SamplText;

float Attenuation
(
float distance,
float a,
float b,
float c
)
{
float Atten = 1.0f / ( a + b * distance + c * pow(distance,2) );
return Atten;
}

struct VS_INPUT
{
float4 Pos : POSITION;
float3 Nor : NORMAL;
float2 Tex : TEXCOORD;
};

struct PS_INPUT
{
float4 Pos : SV_POSITION;
float4 PSpot2D : P2DPOS;
float4 WPos: WORLDPOS;
float3 Nor : NORMAL;
float2 Tex : TEXCOORD;
};

struct VGS_OUTPUT
{
float4 Pos : SV_POSITION;
float4 WPos: WORLDPOSITION;
uint RTIndex : SV_RenderTargetArrayIndex;
};

struct VPS_OUTPUT
{
float4 Pos : SV_POSITION;
float4 WPos: WORLDPOSITION;
};


PS_INPUT vs_position (VS_INPUT In)
{
PS_INPUT Out = (PS_INPUT)0;

Out.Pos = mul(mul(mul(In.Pos,WorldMatrix),ViewMatrix),ProjMa trix);
Out.PSpot2D = mul(mul(mul(In.Pos,WorldMatrix),VSpotMatrix),ProjM atrix);
Out.WPos = mul(In.Pos,WorldMatrix);
Out.Nor = mul(In.Nor,WorldMatrix);
Out.Tex = In.Tex;

return Out;
}

VS_INPUT vs_void (VS_INPUT In)
{
return In;
}


float4 ps_light (PS_INPUT In) : SV_TARGET
{
float4 BaseColor = (Lamp == true) ? float4(0.25f, 0.21f, 0.20f, 1) : Text.Sample(SamplText,In.Tex);
float3 vLight = normalize(LightInfo.xyz-In.WPos);
float NdotL = dot(In.Nor,vLight);
float Att = Attenuation(distance(LightInfo.xyz,In.WPos),0.003, 0.003,0.003);
float4 PointLight = (saturate(NdotL)) * Att;

float3 LightToVec = LightInfo3.xyz - In.WPos;
float LightToVecDist = length(LightToVec);
float3 LightToVecDirection = LightToVec / LightToVecDist;

float4 LightToSourceDirection = normalize(LightInfo3 - LightInfo2);
float cosAlpha = dot(LightToVecDirection,LightToSourceDirection);

float2 VTexC;

VTexC[0] = In.PSpot2D.x/In.PSpot2D.w * 0.5f + 0.5f;
VTexC[1] = -In.PSpot2D.y/In.PSpot2D.w * 0.5f + 0.5f;

float SpotShadow = SpotText.Sample(SamplText,VTexC);

float Atten = 0.0f;

if( cosAlpha > Angles.y )
{
Atten = 1.0f;
}
else if( cosAlpha > Angles.x )
{
Atten = 0.5f;
}

int ShadowValue = (!((LightToVecDist / FarClip) >= SpotShadow && Atten != 0));

LightToVec = In.WPos - LightInfo.xyz;
LightToVecDist = length(LightToVec);
float CubeShadow = Cubemap.Sample(SamplText,(LightToVec/LightToVecDist));
int CubeValue = (((LightToVecDist / FarClip) > CubeShadow));

float4 SpotLight = (Atten * float4(1.0f,0.8f,0.12f,0) * dot( In.Nor, LightToVecDirection ));
return (PointLight + SpotLight) * BaseColor * ShadowValue * CubeValue;

}

[maxvertexcount(18)]
void Gs_Cubemap(triangle VS_INPUT input[3], inout TriangleStream<VGS_OUTPUT> Out)
{
VGS_OUTPUT output;

for( int f = 0; f < 6; f++ )
{
output.RTIndex = f;
for( int v = 0; v < 3; v++ )
{
output.Pos = mul(mul(mul( input[v].Pos, WorldMatrix),VMatrix[f]),ProjMatrix );
output.WPos = mul(input[v].Pos,WorldMatrix);
Out.Append( output );
}

Out.RestartStrip();
}
}

float ps_depth (VGS_OUTPUT In) : SV_TARGET
{
return distance(In.WPos,LightInfo) / FarClip;
}

float ps_spotdepth (VPS_OUTPUT In) : SV_TARGET
{
return (distance(In.WPos,LightInfo3) / FarClip) + 0.0001;
}

VPS_OUTPUT vs_spot(VS_INPUT In)
{
VPS_OUTPUT p = (VPS_OUTPUT)0;

p.Pos = mul(mul(mul(In.Pos,WorldMatrix),VSpotMatrix),ProjM atrix);
p.WPos = mul(In.Pos,WorldMatrix);

return p;
}



The cubemap it's correctly filled (in particular the face 4 is perfect), but i can see a lot of points on the image as result...

Goz
02-19-2009, 01:45 PM
Is the point light at the same position as the spot light? Thats what the code suggests ...

Goz
02-19-2009, 01:48 PM
Nope . my mistake .. not reading the code closely enough. Btw you don't need to do my optimisation there you may as well just use a normalize. The only reason i didn't was to avoid using 2 square roots. That said .. the code should be pretty much identical anyway.

Any reason the cubemap depth test isn't "not" like the spot shadow?

Also what does the output look like?

XVincentX
02-19-2009, 02:00 PM
Here is the strange output
http://img238.imageshack.us/img238/1703/imgiu7.jpg

I tried also to recopy the original copy (that worked) in page 1, but nothing looks like to change.

Goz
02-20-2009, 02:27 AM
Can you set ps_depth to

return (distance(In.WPos,LightInfo) / FarClip) + 0.0001;

XVincentX
02-20-2009, 02:33 AM
Mmm, do you think that it's the same problem?
BTW no problem, i will add the small value and will let you know.

Thank you again for all your help.
Mabye i i would gave up without you!

XVincentX
02-20-2009, 06:28 AM
It looks like completely ok with the small adding (and a change in condition)

http://img7.imageshack.us/img7/9598/imgdp4.jpg

Goz
02-20-2009, 02:53 PM
It looks like completely ok with the small adding (and a change in condition)

I'd wager that with that addition of an epsilon it would work with >= too.


Thank you again for all your help.


You're welcome :) I'm glad I was of some help :) Even if it did take far too long to figure out the issues :lol:

XVincentX
02-25-2009, 01:12 PM
Hello. I'm still here with 2-3 questions.

A) I just tested that, pointing the spotlight ON the shadowed zone gave by the point light: as i expected, the shader draws still black.
So i tried to replace this code

return (PointLight + SpotLight) * BaseColor * ShadowValue * CubeValue;

with

return (PointLight + SpotLight) * BaseColor * (ShadowValue || CubeValue);

Hoping that the OR on the ints would leave lighted at least the points lighted by a light source.

B) Can you suggest me a good way to avoid black shadow and simply give less light (i already did it but i want to make it in another way, if possible)?

Thank you.

Goz
02-25-2009, 02:00 PM
A) Naturally you will get black. You are multiplying with a conditional held in an int. The value will be either 1 or 0. As you are, i'm sure, aware 0x = 0 and 1x = x.

B) You could try

(ambientColour + (PointLight * CubeValue) + (SpotLight * ShadowValue)) * SampledTextureColour;

PointLight * CubeValue means that you will light, with the point light, any section that isn't in shadow. If in shadow then it will add nothing to the ambient colour. The same goes for the SpotLight * ShadowValue. However it will allow you to have a difference between things lit by the point light but in the shadow of the spot light or lit by the spot light and in the shadow of the point, or in shadow of both or in shadow of neither. This gives you far more control.

Essentially when doing multipass rendering, ala Doom3, this is what you would be doing. You would do an ambient pass. And then do a pass for each light where you add the contribution from that light (or not if in shadow). You would then multiply the whole thing by the texture colour.

Of course once you have done that you can then add specular highlights on top of that whole lot. But that might just be complicating matters further ;)

I'd strongly recommend doing some reading on how the lighting pipeline works.

This page is a good start: http://msdn.microsoft.com/en-us/library/bb147178(VS.85).aspx

Its also worth looking into the physics of lighting itself, the RGB colour model and additive colours. Once you understand HOW light contributes to a surface you will have a much better understanding of how direct lighting works :)

A quick flick found this: http://www.rgbworld.com/color.html

XVincentX
02-26-2009, 03:07 AM
I tried your "equation" and, while the Point Shadow it's black but lighted when spotlight goes on it, the Spotlight simply "does not draw", as you can see here

http://img204.imageshack.us/img204/2640/senzatitolo1a.jpg

Mabye the point light on the lamp lights also the wall and reduces shadow?

Thanks for the links and yes, i really have to read something more about lights, i'm completely on 0 (just lambert and phong)

Goz
02-26-2009, 03:57 AM
Are you sure the spot light just isn't very bright? I can see what appears to be the spot light to the right of the car on the ground its just really not particularly bright. The fact that it casts a shadow on the wall behind the car that fades nicely into the light from the point light seems to indicate its working to me ...

Goz
02-26-2009, 04:00 AM
Also worth noting that yellow isn't the easiest of colours to see ... set the spot light to full white (ie 255, 255, 255) and see what happens then.

vrnunes
02-26-2009, 06:59 AM
These screenshots are starting to look nice. :-)

As a suggestion, sometimes when debugging thinks like this, it may help if you change objects and positions from time to time, you may find a bug just doing this and looking the new results.

Good luck!

XVincentX
02-26-2009, 07:28 AM
Thank you, but the 80% of work was made by Goz's suggestions.
There is still a lot to do.
A) Make a decent scene with good illumination
B) Make a camera system (the one i'm using is owful, if you can suggest me one "Maya Like" it would be great)
C) Use some more advanced shadow mapping alghoritm.

P.S.
I made sense of strange post hours...i'm not from USA or Canada, so when you see 5.00 AM here are 10 o clock...but do you REALLY post at that time???

vrnunes
02-26-2009, 10:21 AM
Not sure if you were talking to me about post hours, but I usually wake up in random hours (like 4:00AM), then I come to this PC and start reading forums or programming. Well, sometimes I just don't sleep. :-)

XVincentX
02-28-2009, 04:10 AM
Here is modified light color
http://img504.imageshack.us/img504/3874/imgi.jpg

The less "darkness" of shadow is due to point light contribution?

Goz
02-28-2009, 07:23 AM
The less "darkness" of shadow is due to point light contribution?

Behind the car? Cos yes if thats what you mean. If you turn on a torch and it casts a shadow if you then place a light behind the object casting the shadow then the shadow will get washed out by the new light ...

XVincentX
03-01-2009, 02:07 AM
Mmm...i can't get any kind of antialiasing in the scene, mabye becouse shadow map is big enough to avoid it?
I tried to reduce it to 100x100 or 200x200, and the antialiasing comes out. So the PSM and TSM are used to reduce antialiasing of little textures (in front of backbuffer size)?

Goz
03-01-2009, 11:10 AM
position the camera right next to the wall the shadow is cast upon and im pretty sure you'll see the aliasing.

Of course its worth noting that unless you are right up against the wall its nto actually worth, in many case, wasting time doing anti-aliasing.

If itg looks good as is then its not worth wasting time making it look a tiny percent better. Only bother when its needed and save your GPU time for where its really needed.

XVincentX
03-01-2009, 12:34 PM
I ask you help once again.
I checked on nvidia developer site, and i found A LOT of other shadow map implementation:
Parallel-Split Shadow Maps
Variance Shadow Maps
Percentage-Closer Filtering
Perspective Shadow Maps
Trapezoidal Shadow Maps

What could be the "must" to learn about it?

Goz
03-01-2009, 02:43 PM
I ask you help once again.
I checked on nvidia developer site, and i found A LOT of other shadow map implementation:
Parallel-Split Shadow Maps
Variance Shadow Maps
Percentage-Closer Filtering
Perspective Shadow Maps
Trapezoidal Shadow Maps

What could be the "must" to learn about it?

Learn any one of them inside out. Once you've learnt it you'll find it easier to get your head round the others. Each method has its advantage and its disadvantages. The learning process teaches yyou when to use one over another :) It take a while, though ... good luck!

XVincentX
03-02-2009, 06:47 AM
I hope i will be able to find you here to help me!!

XVincentX
03-02-2009, 03:52 PM
I was giving a look to Variance Shadow Mapping and the alghoritm looks like very easy.

I just wanted to try without the usual gaussian blur.
So i modified my code in pixel shader:



int ShadowValue = (step((LightToVecDist/FarClip),SpotShadow.x) && Atten != 0);

float lit = (float2)0.0f;
float E_x2 = SpotShadow.y;
float Ex_2 = SpotShadow.x * SpotShadow.x;
float variance = E_x2 - Ex_2;
float mD = SpotShadow.x - (LightToVecDist/FarClip);
float mD_2 = mD * mD;
float p = variance / (variance + mD_2);
lit = max( p, ShadowValue );


LightToVec = In.WPos - LightInfo.xyz;
LightToVecDist = length(LightToVec);
float CubeShadow = Cubemap.Sample(SamplText,(LightToVec/LightToVecDist));
int CubeValue = step((LightToVecDist / FarClip),CubeShadow);

float4 SpotLight = (Atten * dot( In.Nor, LightToVecDirection ));
return ((PointLight * CubeValue) + (SpotLight * lit) + 0.1f) * BaseColor;



And obiously modified the depth pass
return float2(depth,pow(depth,2));

But it does not work: the shadow remains perfectly the same.

BTW, a concept is not really clear to me.
Why have i to store depth^2 in the second channel and retrive it?
Can't i compute it directly in Pixel shader retriving original depth?

Anyway, reading original paper, i have to scale light intensity by lit value. But how? Dividing?

Thank you.

XVincentX
03-03-2009, 01:56 PM
As i expected, Ex_2 and E_x2 are the same: my troubles it's confirmed.
http://img125.imageshack.us/img125/6706/imgm.jpg
It's something due to limited 32bit precision?

I do not think it, becouse the code
float E_x2 = SpotShadow.y;
float Ex_2 = SpotShadow.x * SpotShadow.x;
Are the SAME thing!!!!

Goz
03-04-2009, 12:01 PM
THey aren't as much the same thing as you think. You are relying on bilinear filtering of the x term and the x^2 term as well ... this won't, necessarily, give you the same value.

http://graphicsrunner.blogspot.com/2008/07/dual-paraboloid-variance-shadow-mapping.html

You may want to look at that page. Dunno if it will help. Never implemented variance shadow mapping (TBH, I've never implemented shadow mapping before either ;)).

Don't forget that you will make your life a HELL of a lot easier using just the spot light to begin with.

XVincentX
03-10-2009, 03:37 PM
I made a lot of reseraches, but as i can see my implementation is correct...but it looks like VSM does not improve my shadows. The only way to have some improvements is to add some Gaussian Blur...someone made VSM correctly?

Goz
03-10-2009, 03:44 PM
try using a lower resolution shadow map and see what happens?

JarkkoL
03-10-2009, 03:49 PM
I implemented various versions of VSM (PSSM, spot lights, static omni shadows) in my engine if you like to have a look. But yeah, blurring the map is the essential part to make the difference.

XVincentX
03-10-2009, 04:06 PM
Mabye it's all a my mistake. Please, judge this images:
BackBuffer: 800x600
ShadowMap: 128x128

Standard Shadow Mapping
http://img9.imageshack.us/img9/1444/bn0c30btmp.jpg
Standard Shadow Mapping (ShadowMap: 1024x1024)
http://img8.imageshack.us/img8/3181/qcm58d6tmp.jpg
Variance Shadow Map (128x128)
http://img24.imageshack.us/img24/4048/qjz46cbtmp.jpg
Variance Shadow Map with Gaussian Blur (128x128)
http://img27.imageshack.us/img27/4275/xzmb4aatmp.jpg

It looks good but i see nVidia demos and other that with same technique reaches very better results!

JarkkoL
03-10-2009, 04:14 PM
Judging from the images, it looks like it's working right. 128x128 shadow map is just very low res shadow map and you might want to try also larger filter kernel size. And also better placament of the spot light where you can see the car shadow casted along the ground and not only to the wall behind.

Goz
03-10-2009, 04:19 PM
How do you do your gaussian blur?

XVincentX
03-10-2009, 04:42 PM
float4 BlurPixel(texture2D Text, float2 TexCoord, float blurSize)
{
float4 c = (float4)0;

c += Text.Sample(SamplText, float2(TexCoord.x - 4.0*blurSize, TexCoord.y - 4.0*blurSize)) * 1.0/25.0;
c += Text.Sample(SamplText, float2(TexCoord.x - 3.0*blurSize, TexCoord.y - 3.0*blurSize)) * 2.0/25.0;
c += Text.Sample(SamplText, float2(TexCoord.x - 2.0*blurSize, TexCoord.y - 2.0*blurSize)) * 3.0/25.0;
c += Text.Sample(SamplText, float2(TexCoord.x - blurSize, TexCoord.y - blurSize)) * 4.0/25.0;
c += Text.Sample(SamplText, float2(TexCoord.x, TexCoord.y)) * 5.0/25.0;
c += Text.Sample(SamplText, float2(TexCoord.x + blurSize, TexCoord.y + blurSize)) * 4.0/25.0;
c += Text.Sample(SamplText, float2(TexCoord.x + 2.0*blurSize, TexCoord.y + 2.0*blurSize)) * 3.0/25.0;
c += Text.Sample(SamplText, float2(TexCoord.x + 3.0*blurSize, TexCoord.y + 3.0*blurSize)) * 2.0/25.0;
c += Text.Sample(SamplText, float2(TexCoord.x + 4.0*blurSize, TexCoord.y + 4.0*blurSize)) * 1.0/25.0;

return c;

}


I do not know if it's correct, but i was bored about make 2 passes in order to have a quicker blur and i tried to make it all in one time.

JarkkoL
03-10-2009, 05:06 PM
Ok, well this is a very bad blur kernel you are using. You should make the separable gaussian blur (the 2 pass blur you were probably thinking initially) and also calculate the weights for the blur properly.

XVincentX
03-11-2009, 01:59 AM
I just used this post as reference
http://www.gamerendering.com/2008/10/11/gaussian-blur-filter-shader/
And i tried to adapt the 2 shader in one.

Since i read that 2 pass instead of one simply is only faster, i decided that was better to leave one (to avoid a new render target creation).
Have you got better references to make Blur?

JarkkoL
03-11-2009, 02:26 AM
Yes, I can see you tried to merge the two passes to one, but you did it wrong. Your kernel is just a weighted diagonal row of samples through the center, not actual 2D kernel you need to do it right. If you would like to do the blur in a single pass for 9 sample wide kernel, you would have to take 9*9=81 samples.

Edit: I had a closer look to the page you gave, and it seems that they use wrong weights for the Gaussian kernel (probably because they didn't bother calculating the right weights and the results looked good enough). What they have is more like a conish filter kernel, but it's just better to use the right weights because it costs you no more (other than your time that is). You can find the right function for example here (http://en.wikipedia.org/wiki/Gaussian_filter)

Goz
03-11-2009, 02:52 AM
Actually further to what Jarkko says it may be interesting once you've got a proper gaussian blur working to have a play round with different filter kernels. Its sometimes surprising what effects you can create by using strange kernels :)

Edit: Definitely don't mess about with this until you've got a proper gaussian blur going :)

XVincentX
03-13-2009, 04:46 PM
I found on web a lot of good blur implementation, but all of them are done using two passes, but i really can't do that for a lot of reason (render targets, vertex buffer).
I'm not able to found right references about single pass blur implementation, do you know where to find them??

juhnu
03-13-2009, 05:18 PM
What are those "lots of reasons"? With dx10 class hardware additional blur passes using a ping-pong style rendertarget switching (with discard flag ofc) should be doable. Don't underestimate the power of passes!

Goz
03-14-2009, 02:10 AM
I found on web a lot of good blur implementation, but all of them are done using two passes, but i really can't do that for a lot of reason (render targets, vertex buffer).
I'm not able to found right references about single pass blur implementation, do you know where to find them??

How many texture samples can you take per pass with DX10? Obviously 9 which allows you to do a single pass 3x3 kernel. Is it 16? That allows for a 4x4. However it is FAR cheaper to do 2 7 or 9 tap passes and get a 7x7 or 9x9 kernel (49 or 81 taps!). ie to do a 7x7 blur would take 49 texture samples for single pass but only 14 for dual pass.

JarkkoL
03-14-2009, 02:13 AM
Also, you should consider using multi-sampled render targets for shadow map rendering.

XVincentX
03-14-2009, 02:54 AM
The performance gain is very consistent...
So i made a new render target (completely equal to the original depth map) and used this code to make vertical blur first


float4 Blur(VSB_OUTPUT Inp) : SV_TARGET
{
float4 c = 0;
for (int i = 0; i < SAMPLE_COUNT; i++)
{
c += SpotText.Sample(SamplText, Inp.Tex + SampleOffsets[i].xy) * SampleWeights[i];
}

return c;
}



Shouldn't made c/SAMPLE_COUNT at the end?

SampleOffset and SampleWeights are filled in this way and sent to the shader

static float a[] = {1,7,21,35,35,21,7,1};
memcpy(cEachFrame.Sample_Weights,a,sizeof(a));
for (int i = 0; i < SAMPLE_COUNT; i++)
cEachFrame.Sample_Offsets[i] = D3DXVECTOR2(0,(1.0f/(float)SMX)*i);


According to an article about Digital Image Processing found on gamedev. (SMX is depth map dimension).

I think that offset are computed non very well, becose it's completely avoided the left part. So i made this other code


cEachFrame.Sample_Offsets[0] = D3DXVECTOR2(0,(-4.0f * 1/SMX));
cEachFrame.Sample_Offsets[1] = D3DXVECTOR2(0,(-3.0f * 1/SMX));
cEachFrame.Sample_Offsets[2] = D3DXVECTOR2(0,(-2.0f * 1/SMX));
cEachFrame.Sample_Offsets[3] = D3DXVECTOR2(0,0);
cEachFrame.Sample_Offsets[4] = D3DXVECTOR2(0,2.0f*1/SMX);
cEachFrame.Sample_Offsets[5] = D3DXVECTOR2(0,3.0f*1/SMX);
cEachFrame.Sample_Offsets[6] = D3DXVECTOR2(0,4.0f*1/SMX);


That should take left and right and make blur.
The final result is not one of bests: even with /SAMPLE_COUNT and without, i can't see any kind of blur on the image.

XVincentX
03-17-2009, 05:13 PM
Ok after a lot of problems with any kind of strange things (constant buffers packing bla bla bla bla) finally i've got all necessary data passed to the shader, but now:

HOW DAMN DO Gaussian Blur?
Let's start with horizontal:

A)How to compute TextureOffset
B)How to compute BlurWeights

A.1) Simply take integer values from -n-1 to n-1 where n is sample number, and compute it as a texel.
So, if SMX is texture dimension, and n = 8, it will be


cTwiceFrame.SampleOffsets[0] = D3DXVECTOR4(0,(-4.0f * 1/SMX),0,(-3.0f * 1/SMX));
cTwiceFrame.SampleOffsets[1] = D3DXVECTOR4(0,(-2.0f * 1/SMX),0,(-1.0f * 1/SMX));
cTwiceFrame.SampleOffsets[2] = D3DXVECTOR4(0,( 1.0f * 1/SMX),0,( 2.0f * 1/SMX));
cTwiceFrame.SampleOffsets[4] = D3DXVECTOR4(0,( 3.0f * 1/SMX),0,( 4.0f * 1/SMX));


Do not warry about packing in float4, it's for shader reason.
Is this OK? Have i to sample also with offset 0,0?

B) I do not know nothing about this. Here anyone has got his theory: who uses values and i do not know where did he take it, or in some parts i read to decompose the matrix in a product of row X columns, using Tartaglia's Triangle's values...so i should use


cTwiceFrame.SampleWeights[0].x = 1;
cTwiceFrame.SampleWeights[0].y = 7;
cTwiceFrame.SampleWeights[0].z = 21;
cTwiceFrame.SampleWeights[0].w = 35;
cTwiceFrame.SampleWeights[1].x = 35;
cTwiceFrame.SampleWeights[1].y = 21;
cTwiceFrame.SampleWeights[1].z = 7;
cTwiceFrame.SampleWeights[1].w = 1;


And so? What have i to do with these? Kill myself? Divite it with something??

Thank you again for help

Goz
03-18-2009, 03:59 AM
Ok after a lot of problems with any kind of strange things (constant buffers packing bla bla bla bla) finally i've got all necessary data passed to the shader, but now:

HOW DAMN DO Gaussian Blur?
Let's start with horizontal:

A)How to compute TextureOffset
B)How to compute BlurWeights

A.1) Simply take integer values from -n-1 to n-1 where n is sample number, and compute it as a texel.
So, if SMX is texture dimension, and n = 8, it will be


cTwiceFrame.SampleOffsets[0] = D3DXVECTOR4(0,(-4.0f * 1/SMX),0,(-3.0f * 1/SMX));
cTwiceFrame.SampleOffsets[1] = D3DXVECTOR4(0,(-2.0f * 1/SMX),0,(-1.0f * 1/SMX));
cTwiceFrame.SampleOffsets[2] = D3DXVECTOR4(0,( 1.0f * 1/SMX),0,( 2.0f * 1/SMX));
cTwiceFrame.SampleOffsets[4] = D3DXVECTOR4(0,( 3.0f * 1/SMX),0,( 4.0f * 1/SMX));


Unless im misunderstanding you are going to miss texture samples here.

The way I always did it was to sample each texture at (1/ textureWidth or 1 / textureHeight) steps. You can also calculate this in the shader by simply passing the texture width.

ie for a 3x3 tap you'd be doing for the horizontal pass (1 / textureWidth is stored in rcpTw, and texCoord is the interpolated texture coordinate received from the vertex shader).

float2 samplePos[3];
samplePos[0].xy = (texCoord) - float2( 1 * rcpTw, 0 );
samplePos[1].xy = (texCoord);
samplePos[2].xy = (texCoord) + float2( 1 * rcpTw, 0 );


This will sample the texture either side of the sample pixel.

You then need to sample the texture and weight it which is simply a matter of multiplying each sample by the appropriate weighting factor.

e.g


float4 finalColour;
finalColour = Texture2d( texture, samplePos[0] ) * weight[0].x;
finalColour += Texture2d( texture, samplePos[1] ) * weight[0].y;
finalColour += Texture2d( texture, samplePos[2] ) * weight[0].z;


You now have your final horizontally blurred value.

XVincentX
03-18-2009, 04:29 AM
So the sample number must be every time dispair. I will let you know.

JarkkoL
03-18-2009, 05:10 AM
For the weights, just use the Gaussian distribution function I posted link earlier in this thread. I use variance 0.75 myself, which seems to work ok. Also, normalize the weights so that they add up to 1.

XVincentX
03-18-2009, 07:48 AM
Ok i made also gaussian blur with this results:

I computed Gaussian distribution using the formula found on wikipedia.


float GaussianWidth(float Sigma, float Displace)
{
return (1/(sqrt(2*D3DX_PI) * Sigma)) * (pow(exp(1.0f),-(Displace*Displace)/(2 * Sigma * Sigma)));
}


What do you mean "normalize" weights?

With Sigma = 1 and 9 samples (from -4 to 4), and 128x128 texture

http://img25.imageshack.us/img25/3545/62791266.jpg
http://img24.imageshack.us/img24/8586/21531100.png
http://img12.imageshack.us/img12/2449/17951660.jpg

What do you think about it? Should i blur more? Changing what? Samples number? Sigma?

XVincentX
03-18-2009, 08:22 AM
I do not know why, but saving image using PIX (like last one) is different than saving images using STAMP:

http://img17.imageshack.us/img17/5681/peppe.jpg

Looks like miss anisotropic filtering (that is enabled)

Goz
03-18-2009, 09:19 AM
For future reference if you hit "alt-printscreen" it will grab the current window's contents to the clipboard. Probably the best way to do screenshots and get it representitive of what you are seeing, IMO.

Your screenshots look, to me, like anisotropic filtering is turned OFF.

Well your blur could definitely do with looking a tad better. For a 9x9 blur you should get MUCH better results than that ...

XVincentX
03-18-2009, 09:40 AM
For future reference if you hit "alt-printscreen" it will grab the current window's contents to the clipboard. Probably the best way to do screenshots and get it representitive of what you are seeing, IMO.

Your screenshots look, to me, like anisotropic filtering is turned OFF.


But it's enabled, as you can see from screenshot grabbed from Pix...i will check better this, anyway.


Well your blur could definitely do with looking a tad better. For a 9x9 blur you should get MUCH better results than that ...

I thought same thing but for now i do not have got ideas...mabye gaussian parameters?

JarkkoL
03-18-2009, 10:21 AM
What do you mean "normalize" weights?
When you sum the weights, make sure they equal to 1.

Goz
03-18-2009, 12:03 PM
could you post up the code for your 2 passes as well?

XVincentX
03-19-2009, 01:12 PM
Sure.
Gaussian coefficients are computed using this forumula

float GaussianWidth(float Sigma, float Displace)
{
return (1/(sqrt(2*D3DX_PI) * Sigma)) * (pow(exp(1.0f),-(Displace*Displace)/(2 * Sigma * Sigma)));
}


Due to packing HLSL rules, coefficient are grouped in float4, in this way


cbuffer cTwiceFrame
{
float4 SampleOffsets[SAMPLE_COUNT/2];
float4 SampleWeights[SAMPLE_COUNT/4];
};


SAMPLE_COUNT = 8 (the nineth sample is taken directly in Pixel Shader).

Data is filled in this way


cTwiceFrame.SampleWeights[0].x = GaussianWidth(1.0f,-4.0f);
cTwiceFrame.SampleWeights[0].y = GaussianWidth(1.0f,-3.0f);
cTwiceFrame.SampleWeights[0].z = GaussianWidth(1.0f,-2.0f);
cTwiceFrame.SampleWeights[0].w = GaussianWidth(1.0f,-1.0f);
cTwiceFrame.SampleWeights[1].x = GaussianWidth(1.0f, 1.0f);
cTwiceFrame.SampleWeights[1].y = GaussianWidth(1.0f, 2.0f);
cTwiceFrame.SampleWeights[1].z = GaussianWidth(1.0f, 3.0f);
cTwiceFrame.SampleWeights[1].w = GaussianWidth(1.0f, 4.0f);


While texture displacement:


cTwiceFrame.SampleOffsets[0] = D3DXVECTOR4(0,(-4.0f * 1/SMX),0,(-3.0f * 1/SMX));
cTwiceFrame.SampleOffsets[1] = D3DXVECTOR4(0,(-2.0f * 1/SMX),0,(-1.0f * 1/SMX));
cTwiceFrame.SampleOffsets[2] = D3DXVECTOR4(0,( 1.0f * 1/SMX),0,( 2.0f * 1/SMX));
cTwiceFrame.SampleOffsets[4] = D3DXVECTOR4(0,( 3.0f * 1/SMX),0,( 4.0f * 1/SMX));



And make Pixel Shader. So reuse the same target and make same pixel shader with these


cTwiceFrame.SampleOffsets[0] = D3DXVECTOR4((-4.0f * 1/SMX),0,(-3.0f * 1/SMX),0);
cTwiceFrame.SampleOffsets[1] = D3DXVECTOR4((-2.0f * 1/SMX),0,(-1.0f * 1/SMX),0);
cTwiceFrame.SampleOffsets[2] = D3DXVECTOR4(( 1.0f * 1/SMX),0,( 2.0f * 1/SMX),0);
cTwiceFrame.SampleOffsets[4] = D3DXVECTOR4(( 3.0f * 1/SMX),0,( 4.0f * 1/SMX),0);


Finally, the pixel shader:

float4 Blur(VSB_OUTPUT Inp) : SV_TARGET
{
float4 c = 0;

float4 SampleOnZero = SpotText.Sample(SamplText,Inp.Tex);

for (int i = 0; i < SAMPLE_COUNT / 4; i++)
{
int i2 = i * 2;

c += SpotText.Sample( SamplText, Inp.Tex + SampleOffsets[i2].xy ) * SampleWeights[i].x;
c += SpotText.Sample( SamplText, Inp.Tex + SampleOffsets[i2].zw ) * SampleWeights[i].y;
c += SpotText.Sample( SamplText, Inp.Tex + SampleOffsets[i2 + 1].xy ) * SampleWeights[i].z;
c += SpotText.Sample( SamplText, Inp.Tex + SampleOffsets[i2 + 1].zw ) * SampleWeights[i].w;
}

return c + (SampleOnZero*0.39); //0.39 is GaussianWidth with 1.0f,0.0f.
}

XVincentX
03-22-2009, 11:12 AM
So?

Goz
03-22-2009, 02:51 PM
Try:


float GaussianWidth(float Sigma, float Displace)
{
return (1/(sqrt(2*D3DX_PI) * Sigma)) * exp( -(Displace*Displace)/(2 * Sigma * Sigma)));
}


exp( 1.0 ) IS 1.0

What you are saying is raise 1 to the power you should be rasing e too ...

Reedbeta
03-22-2009, 03:16 PM
exp( 1.0 ) IS 1.0

Actually exp(0) = 1.0, and exp(1.0) = e. ;)

Goz
03-22-2009, 03:19 PM
Actually exp(0) = 1.0, and exp(1.0) = e. ;)

goddammit reedbeta would you stop correcting my completely retarded ramblings :lol: hehehe

Goz
03-22-2009, 03:25 PM
Still not convinced by thaty GaussianWidth function though.

You know btw that value for "-x" is the same as for "x"? ie you don't need to run it for every value.

Can you post up the values returned by GaussianWidth?

XVincentX
03-23-2009, 11:08 AM
Actually exp(0) = 1.0, and exp(1.0) = e. ;)

I just used it to avoid writing costans by my own.
Gaussian values coming soon.

XVincentX
03-23-2009, 01:02 PM
Values for you


GaussianWidth(1.0f,-4.0f); 0.00013383027
GaussianWidth(1.0f,-3.0f); 0.0044318493
GaussianWidth(1.0f,-2.0f); 0.053990975
GaussianWidth(1.0f,-1.0f); 0.24197073


Your function version return quite same values, except for last 2 numbers.

Goz
03-23-2009, 02:04 PM
Values for you


GaussianWidth(1.0f,-4.0f); 0.00013383027
GaussianWidth(1.0f,-3.0f); 0.0044318493
GaussianWidth(1.0f,-2.0f); 0.053990975
GaussianWidth(1.0f,-1.0f); 0.24197073


Your function version return quite same values, except for last 2 numbers.

It should return identical values ...

I can't see anything wrong in your code .. the only thing that strikes me as being a potential problem (and I'm grasping at straws here) is your value for "SMX" ...

JarkkoL
03-23-2009, 02:05 PM
The variance value you are using is way too small. The Gaussian weight values are way too small for more distant samples thus they barely contribute to the value. Use the value 0.75 that I originally said for x=[-1, 1].

XVincentX
03-23-2009, 02:13 PM
I just tried, but i did not find any noticeable improvement.

http://img7.imageshack.us/img7/7236/45361973.jpg
http://img7.imageshack.us/img7/3915/21009137.jpg

I was also forced to mul by 2 all spotlight becouse it was too dark

JarkkoL
03-23-2009, 02:15 PM
So what are the new values?

XVincentX
03-23-2009, 03:21 PM
Sorry i forgot to paste them
4.6268983e-008
5.8531972e-005
0.0096201422
0.20542553

JarkkoL
03-23-2009, 03:40 PM
How about trying to do what I have been saying for quite some time here? ;) Spoon feeding follows:

float weights[9];
float weight_sum=0.0f;
for(int i=0; i<9; ++i)
{
float weight=GaussianWeight(0.75f, float(i-4)/4.0f);
weight_sum+=weight;
weights[i]=weight;
}
for(unsigned i=0; i<9; ++i)
weight[i]/=weight_sum;

XVincentX
03-23-2009, 04:10 PM
I'm sorry you should understand me.
When you work so much and too many time on the same project, sometimes happens to me to have fog and clouds on my head and forget all suggestion. I will try also this other.
Thank you still for the help.

XVincentX
03-23-2009, 04:35 PM
With normalization the darkening is vanished, and i can see a better blur (even if little).

Anisotropic filtering, 128x128 variance shadow map (Gauss 0.75). The ligher is due to 2*light i used before
http://img9.imageshack.us/img9/1237/95943469.jpg
No anisotropic, 128x128 variance shadow map (Gauss 0.75).
http://img8.imageshack.us/img8/3928/93033594.jpg
Lit factor. Looks like perfect.
http://img17.imageshack.us/img17/233/96340201.jpg

Shadow Map.
http://img6.imageshack.us/img6/2969/91301862.jpg

XVincentX
03-26-2009, 02:47 PM
Thank you all for your help.