# Shadowmaps: Is this as good as it gets?

This topic is 4718 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

First some screenshots: I can set my epsilon dynamically while the program runs. Therefore, the epsilon you see this scene rendered with, is the optimal. If it is any smaller, the boxes will selfshadow on the illuminated sides. Im particularly disappointed with the distance from the top of the box to where the box begins to actually shadow itself (if you see the single boxes in the top screenshot). Secondly, Im also disappointed with the quite ugly stripes the shadows make on their own boxes (see lower screenshot). Is this really as good as it gets with shadowmaps? Or is it I who does something wrong? I will provide my shadow-shader here:
float4x4 g_world_view;
float4x4 g_projection;
texture g_texture0;
float4 g_light_ambient;
float3 g_light_directional_direction;
float4 g_light_directional_diffuse;
float3 g_camera_lookat;

float4x4 g_viewtolight_projection;

// ----------------------------------------------------------
sampler2D g_texsampler0 =
sampler_state
{
Texture = <g_texture0>;
MinFilter = Anisotropic;
MagFilter = Anisotropic;
MipFilter = Linear;
};

sampler_state
{
MinFilter = Point;
MagFilter = Point;
MipFilter = Point;
};

// ----------------------------------------------------------
struct VS_OUTPUT_TEX0
{
float4 position: POSITION;
float2 texcoord0: TEXCOORD0;
float4 position_viewspace : TEXCOORD1;
float3 normal: TEXCOORD2;
float4 position_lightspace : TEXCOORD3;
};

// ----------------------------------------------------------

// ----------------------------------------------------------
// returns the factor that the diffuse light contributes with
// ----------------------------------------------------------
float DiffuseFactor(float3 a_normal, float3 a_lightdir)
{
return max(0.0f, dot(a_normal, a_lightdir));
}

// ----------------------------------------------------------
// Desc: Process vertex for scene
// ----------------------------------------------------------
VS_OUTPUT_TEX0 VSTex0(float4 a_position: POSITION, float4 a_normal: NORMAL, float2 a_texcoord0: TEXCOORD0)
{
VS_OUTPUT_TEX0 l_output;

l_output.position_viewspace = mul(a_position, g_world_view);
l_output.position = mul(l_output.position_viewspace, g_projection);
l_output.normal = mul(a_normal, (float3x3)g_world_view);

l_output.texcoord0 = a_texcoord0;

l_output.position_lightspace = mul(l_output.position_viewspace, g_viewtolight_projection);

return l_output;
}

// ----------------------------------------------------------
// Desc: Process pixel (do per-pixel lighting) for enabled scene
// ----------------------------------------------------------
float4 PSTex0(float2 a_texcoord0: TEXCOORD0, float4 a_position_viewspace : TEXCOORD1, float3 a_normal : TEXCOORD2, float4 a_position_lightspace : TEXCOORD3) : COLOR
{
//transform from RT space to texture space.
float2 l_shadowtexC = 0.5 * a_position_lightspace.xy / a_position_lightspace.w + float2(0.5, 0.5);

float l_lightamount = 1.0f;

// l_shadowtexC.x/y will have values between 0.0 and 1.0, if they are in the texturing area
// - only then do we have to consider any kind of shadow
{

if(l_lightamount < 1.0f)
}
a_normal = normalize(a_normal);

float4 l_diffuse = g_light_directional_diffuse * DiffuseFactor(a_normal, -g_light_directional_direction.xyz);

// Light it
float4 l_finalcolor = (tex2D(g_texsampler0, a_texcoord0) * (l_diffuse + g_light_ambient)) * l_lightamount;	// base color

return l_finalcolor;
}

// ----------------------------------------------------------
// Technique: RenderScene
// Desc: Renders scene objects
// ----------------------------------------------------------
technique SimpleTexture
{
pass p0
{
}
}



##### Share on other sites

Reason:
Linear distribution of z values. In projective SM, depth values are "more thightly packed" when far away from the camera. Thus a constant epsilon will be offseting more the far objects, and less (to nearly nothing) the near objects.

Of course, it brings some problems of its own, as it's unable to cover nice frustum-shaped areas (at least not without some matrix-voodoo tweaking).

As for the blocky-thingy - that the sad thing about the SM.
The least you can do is to sample 4 times for four neighbour pixels, compare, and perform some kind of linear interpolation of the results (but not depths, but results of comparison). DX SDK Shadow Map sample has the implementation.

Also, you might want to look at this thread:
Need help to convert DX sample "Shadowmap" so it uses directional light.

Cheers.
~def

##### Share on other sites
Actually, most of those problems are because you're not using the shadow maps correctly.

Shadow maps affect the lighting equation. Thus, they must be part of the lighting calculation, just like N dot L. The lighting equation becomes something like "outLight = ambientLight + shadowMap * (diffuseLight * N dot L)". It's clear that you're not doing this in your screen shots: instead, you're using the shadow maps as a "darkening factor" after the lighting is already computed.

The reason this problem is obvious is because the ugly stripes all show up on the already dark-shaded sides of the cubes. If you did the lighting correctly, it wouldn't matter if the shadows aliased with the dark sides of the cubes or not.

##### Share on other sites
Deffer:
I already use orthogonal lights. Im not sure if its visible from the screenshots, since the area is quite small, but all the shadows are parallel.

By the way, the link you sent, was a thread started by me, hehe.

I built my shader over the DX-sample, so I will try to put back in the sampling of neighbours (I removed it in a learning phase, where I wanted to keep the code simple for comprehensibility).

hplus0603:
Wierd name you have there :)

[I deleted some comments here, as they are totally irrelevant now - they were quite confused - see Edit comment]

Edit:
I went back and tore my shader apart. It seems my only problem was in my lighting calculation.
As hplus0603 pointed out, I did not factor my lightamount into the equation, but instead added it afterwards.

Thanx alot hplus0603!!

I altered:
float4 l_diffuse = g_light_directional_diffuse * DiffuseFactor(a_normal, -g_light_directional_direction.xyz);
float4 l_finalcolor = (tex2D(g_texsampler0, a_texcoord0) * (l_diffuse + g_light_ambient)) * l_lightamount; // base color

To:
float4 l_diffuse = g_light_directional_diffuse * (DiffuseFactor(a_normal, -g_light_directional_direction.xyz) * l_lightamount + g_light_ambient);
float4 l_finalcolor = tex2D(g_texsampler0, a_texcoord0) * l_diffuse;

(I already implemented the multisampling for softer shadows, but I just wanted to show how it looks with the implementation shown in the above example).

[Edited by - Mercenarey on December 18, 2005 4:37:05 AM]

1. 1
Rutin
40
2. 2
3. 3
4. 4
5. 5

• 18
• 20
• 12
• 14
• 9
• ### Forum Statistics

• Total Topics
633363
• Total Posts
3011514
• ### Who's Online (See full list)

There are no registered users currently online

×