Shadowmap not getting projected correctly

Started by
12 comments, last by TheChubu 8 years, 3 months ago

Hi, so this is the issue:

.

Scene picture

.

[attachment=29883:scene.png]

.

Shadowmap picture

.

[attachment=29884:shadowmap.png]

.

As you can see in the scene pic, the shadowmap isn't getting projected correctly. The directional light is straight down on the Y axis. The sphere shadow should appear right next to the rightmost cube, and the cube shadows should appear below them.

.

Shadowmap size is 1024x1024, screen size is 1280x720. I'm thinking it has something to do with that but I'm not terribly sure how to rescale the tex coords.

.

Its a deferred setup, view space position gets computed from the depth buffer.

.

This is my entire directional light fragment shader:

.


// Input parameters.
in vec2 passTexCoord;

// Output parameters.
layout ( location = RT_0 ) out vec3 outLightAcc;

// G Buffer texture samplers.
SAMPLING(gbAlbedo, SMP_RT, 2D, 0);
SAMPLING(gbNormal, SMP_RT, 2D, 1);
SAMPLING(gbMisc, SMP_RT, 2D, 2);
SAMPLING(gbDepth, SMP_RT, 2D, 3);
SAMPLING(gbShadowmap, SMP_RT, 2D, 4);

USING(UBO, DIRLIGHT);
USING(UBO, VIEWRAY);
USING(UBO, FRUSTUM);

void main ( void )
{
	// Fetch shininess value.
	float shininess = texture(gbMisc, passTexCoord).x;
	// Fetch albedo texel.
	vec4 txAlbedo = texture(gbAlbedo, passTexCoord).xyzw;
	// Fetch specular intensity.
	float specIntensity = txAlbedo.w;
	// Fetch g buffer normal and decode it.
	vec3 normal = decodeNormal(texture(gbNormal, passTexCoord).xy);
        // Fetch depth and compute view space position.
	vec3 viewPos = computeViewPos(frustum, viewRays, passTexCoord, texture(gbDepth, passTexCoord).x);

	// Compute position in light space.
	vec4 tmpLightSpacePos = dirLight.invViewShadowProj * vec4(viewPos, 1.0);
	vec3 lightSpacePos = tmpLightSpacePos.xyz / tmpLightSpacePos.w;
	vec2 shadowmapCoords = lightSpacePos.xy * 0.5 + 0.5;
	float lightSpaceDepth = lightSpacePos.z * 0.5 + 0.5;

	float shadowDepth = texture2D(gbShadowmap, shadowmapCoords).x;
	float inShadow =  max(0.2, float(lightSpaceDepth < shadowDepth));
	// View space light direction.
	vec3 lightDir = normalize(dirLight.viewDir.xyz);
	// Light color
	vec3 lightColor = dirLight.color.xyz;

	// Cos angle incidence of light.
	float cosAngle = dot( normal, lightDir );
	// Influence factor to lerp for hemispheric ambient.
	float influence = dot( normal, vec3(0, 1.0, 0) ) * 0.5 + 0.5;
	// Diffuse light term.
	vec3 diffuse = max(0.0, cosAngle ) * lightColor;
	// Specular term.
	vec3 specular = computeSpecular(viewPos, lightDir, normal, specIntensity, shininess) * lightColor;
	// Hemisperic ambient term.
	vec3 ambient = mix( dirLight.groundColor.xyz, dirLight.skyColor.xyz, influence ) * lightColor;

	outLightAcc = (txAlbedo.xyz * diffuse + specular) * inShadow + ambient;
}

.

The code for computing the "invViewShadowProj" matrix is the following:

.


// Computing the shadowmap generation matrix:

private final void computeShadowViewProj ( final DirectionalLight dl )
{
	final Mat4f tmp = dl.shadowViewProj;
	final Vec3f dir = new Vec3f( dl.worldDirection ).negate();
	// Fixed bounding box for now.
	float size = 50;
	// Left, right, bottom, top, znear, zfar.
	tmp.setOrtho( -size, size, -size, size, -size, size);
	// Target, "up" vector. Up cant be (0,1,0) because target would be parallel.
	tmp.lookAlong( dir, new Vec3f( 0, 0, 1 ) );
}

// Compute view space position to light space position matrix

private final void computeInvViewShadowProj ( final DirectionalLight dl )
{
	final Mat4f view = cameras.getUnsafe( cameraEntities.getUnsafe( 0 ) ).viewTransform;
	final Mat4f invView = view.invert( new Mat4f() );
	// shadowViewProj is left, invView is right, invViewShadowProj is destination matrix.
	dl.shadowViewProj.mul( invView, dl.invViewShadowProj );
}

.

Any help is appreciated :)

"I AM ZE EMPRAH OPENGL 3.3 THE CORE, I DEMAND FROM THEE ZE SHADERZ AND MATRIXEZ"

My journals: dustArtemis ECS framework and Making a Terrain Generator

Advertisement

I'd also like any suggestion on the lighting/shader/etc you want to make, no idea if anything of that is applied correctly :D

"I AM ZE EMPRAH OPENGL 3.3 THE CORE, I DEMAND FROM THEE ZE SHADERZ AND MATRIXEZ"

My journals: dustArtemis ECS framework and Making a Terrain Generator

Hard to tell what I'm looking at. Can you just put the single sphere and single cube on the ground so we have a reference.

NBA2K, Madden, Maneater, Killing Floor, Sims http://www.pawlowskipinball.com/pinballeternal

I'll do it when I'm at my computer again biggrin.png

But for now, if it helps:

[attachment=29887:scene-marked.png]

There are a bunch of cubes, and a sphere. Floor is a rectangle. Shadows should be directly below the objects (marked in red) since the light direction is straight down. As I marked, shadows are too far away for some reason (marked in blue).

I *think* i'm just sampling the shadowmap at the wrong places, so the shadows get moved around. But I have no idea how "correct" sampling would look. Myabe the framebuffer size vs shadowmap size have something to do with it?

"I AM ZE EMPRAH OPENGL 3.3 THE CORE, I DEMAND FROM THEE ZE SHADERZ AND MATRIXEZ"

My journals: dustArtemis ECS framework and Making a Terrain Generator

What's with the 'new Mat4f' when inverting your view matrix?

Is the 'invView * shadowViewProj' order correct? Which matrix conventions do you use?

Along with that, I see in the code that the shadow TC is being biased from from [-1,1] to [0,1]. This is something that's usually messed up so maybe something's wrong there. I also see this being applied to Z which seems wrong to me.

What's with the 'new Mat4f' when inverting your view matrix?

Java mostly tongue.png Method call is Mat4f.invert(Mat4f destination). Left matrix gets inverted and stored into destination matrix.

Is the 'invView * shadowViewProj' order correct? Which matrix conventions do you use?

I'm not sure. It doesn't helps that the variable names are reversed biggrin.png

Order is "projection * cameraView * model * position".

shadowViewProj is "orthoProjection * lightView * position".

So I guess the order for transforming view space position to light view space position is:

"orthoProjection * lightView * invCameraView * position"

Which as far as I understand, is what I am doing:

.


// shadowViewProj is left, invView is right, invViewShadowProj is destination matrix.
dl.shadowViewProj.mul( invView, dl.invViewShadowProj );

.

Also, I tried creating a window the same size as the shadowmap (1024x1024), now the shadows appear in correct position O_o Look:

.

[attachment=29896:scene-1024-shadowmap.png]

.

Any considerations I should have sampling the shadowmap? (Rescaling the texcoords or something? Maybe the matrix should do it and mine is wrong?)

"I AM ZE EMPRAH OPENGL 3.3 THE CORE, I DEMAND FROM THEE ZE SHADERZ AND MATRIXEZ"

My journals: dustArtemis ECS framework and Making a Terrain Generator

Viewport ?


Viewport ?
Yes! Viewport! Saw this thread 15min ago https://www.opengl.org/discussion_boards/showthread.php/189389-Shadow-Mapping-not-working-for-textures-not-size-of-screen

He/she is *almost* doing exactly what I was doing ('cept for world space lighting computation).

I still can't get rid of the artifacts: Shadows "tremble" when I move the camera, look fine when I stop moving the camera. Progress anyway :D

"I AM ZE EMPRAH OPENGL 3.3 THE CORE, I DEMAND FROM THEE ZE SHADERZ AND MATRIXEZ"

My journals: dustArtemis ECS framework and Making a Terrain Generator

That is a whole other topic. Shadow map aliasing/ flickering/ filtering.

NBA2K, Madden, Maneater, Killing Floor, Sims http://www.pawlowskipinball.com/pinballeternal

This topic is closed to new replies.

Advertisement