[OpenGL] Cascaded shadow mapping - Render shadows to world?

Started by
26 comments, last by Silverlan 9 years, 6 months ago

Did you set GL_TEXTURE_COMPARE_MODE too ? eg

glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE)

Thank you, that seems to be going in the right direction, but introduced a bunch of other issues:

[video]http:

[/video]

Offsetting the 'w'-component doesn't help a lot either.

Advertisement

I'm wondering, you're computing the shadow coord in the vertex shader : what happens if a triangle has vertex in two different cascade ?

It may explain the artifact you're experiencing

I'm wondering, you're computing the shadow coord in the vertex shader : what happens if a triangle has vertex in two different cascade ?

It may explain the artifact you're experiencing

I've swapped it to the fragment shader, but the result hasn't changed:


[...]
in vec4 vertPos;
float GetShadowCoefficient()
{
	int index = numCascades -1;
	mat4 vp;
	for(int i=0;i<numCascades;i++)
	{
		if(gl_FragCoord.z < csmFard[i])
		{
			vp = csmVP[i];
			index = i;
			break;
		}
	}
	vec4 shadowCoord = vp *(M *vertPos);

	shadowCoord.w = shadowCoord.z;
	shadowCoord.z = float(index);
	shadowCoord.x = shadowCoord.x *0.5f +0.5f;
	shadowCoord.y = shadowCoord.y *0.5f +0.5f;
	float z = shadow2DArray(csmTextureArray,shadowCoord).x;
	return z;
}
[...]

Update:

It looks like the issue with the shadows being cut off occurred because the area I used for the orthographic matrix was too small.

I've implemented a culling-algorithm to get the tightest area around all shadow casters and that fixed it:

[video]http:

[/video]

There's still two problems left however. If any shadow is around the edges of a cascade, it will stretch massively (As shown in the video), and the self-shadowing looks extremely off. I'm assuming the latter is just some texture parameters I'm missing?

Textures “stretch” when they reach borders. Use clamp-to-border sampling to avoid it and use a border color of 1. Or make sure the objects can’t render to the end of the shadow maps.


L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

I had already tried the clamp-to-border parameters, but I didn't know you could change the border color like that, that fixed it.

By the way, I actually used your tutorial for the culling.

It was very easy to follow, very well explained and works like a charm! Thank you!

The last major issue is the self-shadowing:

47c52eb467.jpg

The light is pointing straight down, so the shadow should start right below the branches (e.g. at the encircled area), but it seems to start a fair bit further down and there are some 'holes' in the shadow, which don't exist on the cascade maps.

// Edit

I tried messing around with glPolygonOffset when rendering to the shadow cascade maps, but that didn't help. (I tried fairly large positive and negative ranges)

From the images of the shadow maps, it appears you have clamped the near and far planes to encompass exactly the range from the top of the highest branch to the bottom of the trunk (the tree takes the full depth range).

If you will notice, the shadow itself seems to cover exactly half of that range over the tree.

This is likely because depth values in OpenGL cover the range from -1 to 1 rather than from 0 to 1 like in Direct3D.

Since your image of the shadow map isn’t clipping off negative values, it means either you are only using the 0-to-1 range inside the shadow map or that you have accounted for this upon displaying of the shadow map.

How are you writing depth values?

If you are manually calculating depth values to write into the shadow map, stretch them over the [-1,1] range.

Otherwise you have a problem with the bias matrix, which should have its Z scale halved and the Z offset increased by an additional 0.5f.

Since the the values closer to 1 are being used progressively more correctly starting at half the range of the shadow, I would assume the problem is in how the depth values are being written. Writing to only the [0,1] range would have such a result, whereas improperly biasing would have the opposite result (shadows would start more correct near the top of the tree and then at the mid-way point everything would become black, non-shadowed, or stretch-shadowed (depending on how you handle Z >= 1.0f in the shader).

L. Spiro

I restore Nintendo 64 video-game OST’s into HD! https://www.youtube.com/channel/UCCtX_wedtZ5BoyQBXEhnVZw/playlists?view=1&sort=lad&flow=grid

From the images of the shadow maps, it appears you have clamped the near and far planes to encompass exactly the range from the top of the highest branch to the bottom of the trunk (the tree takes the full depth range).

That's correct.

If you will notice, the shadow itself seems to cover exactly half of that range over the tree.

After taking a closer look at the shadow on the tree, this seems very likely.

Since your image of the shadow map isn’t clipping off negative values, it means either you are only using the 0-to-1 range inside the shadow map or that you have accounted for this upon displaying of the shadow map.

How are you writing depth values?

If you are manually calculating depth values to write into the shadow map, stretch them over the [-1,1] range.

The fragment shader for the shadow maps does nothing but write the depth value unmodified:


gl_FragDepth = gl_FragCoord.z;

I assume by stretching it you mean:


gl_FragDepth = (gl_FragCoord.z *2.0) -1.0;

However that leaves me with:

9dd8a6c6b2.jpg

Otherwise you have a problem with the bias matrix, which should have its Z scale halved and the Z offset increased by an additional 0.5f.

That's what I'm doing, pretty sure my bias matrix is correct:

static const glm::mat4 bias(
    0.5f,0.0f,0.0f,0.0f,
    0.0f,0.5f,0.0f,0.0f,
    0.0f,0.0f,0.5f,0.0f,
    0.5f,0.5f,0.5f,1.0f
);

This topic is closed to new replies.

Advertisement