Jump to content

  • Log In with Google      Sign In   
  • Create Account

Awesome job so far everyone! Please give us your feedback on how our article efforts are going. We still need more finished articles for our May contest theme: Remake the Classics

#Actualcsisy

Posted 29 June 2012 - 01:48 PM

Thanks for the reply!

I put your code between the viewProj and the finalMat compute:

   proj = Matrix::OrthographicOffCenter(-1, 1, -1, 1, min.z, max.z);
   viewProj = view * proj * cropMat;
   Vector3 shadowOrigin = Vector3::Transform(Vector3::Zero, viewProj);
   shadowOrigin *= shadowHalfSize;
   Vector2 roundedOrigin = Vector2(Helpers::MathHelper::Round(shadowOrigin.x), Helpers::MathHelper::Round(shadowOrigin.y));
   Vector2 rounding = roundedOrigin - Vector2(shadowOrigin.x, shadowOrigin.y);
   rounding /= ((float)shadowSize * 0.5f);
   Matrix roundMatrix = Matrix::Translate(rounding.x, rounding.y, 0.0f);
   viewProj *= roundMatrix;
   finalMat = viewProj * textureMat;

I think it works, because the static meshes' shadow is not flickering (I think Posted Image), but the character (the player) moves together with the camera, and its shadow is still flickering.

This can be solved by the bounding sphere instead of light AABB?

EDIT:
I read your post, and I understand that we need a fix size for the projection (this kills the flickering when rotating the camera) and a little round to texels (which kills the flickering when the camera moves). So I rewrite my code based on your code and the idea:
   ComputeFrustumCorners();

   // spheres for each split

   Vector3 sphereCenter;
   for (int i = 0; i < NUM_CORNERS; i++)
   {
    sphereCenter += frustumCorners[i];
   }
   sphereCenter /= NUM_CORNERS;

   float sphereRadius = Vector3::Distance(sphereCenter, frustumCorners[0]);

   float nearClip = 1.0f;
   float backupDist = 10.0f + sphereRadius + nearClip;

   Vector3 camPos = sphereCenter - light->direction * backupDist;
   view = Matrix::LookAt(camPos, sphereCenter, Vector3::Up);

   float bounds = sphereRadius * 2.0f;
   float farClip = backupDist + sphereRadius;
   proj = Matrix::Orthographic(bounds, bounds, nearClip, farClip);
   viewProj = view * proj;

   // round to texel

   origin = Vector3::Transform(Vector3::Zero, viewProj);
   origin *= shadowHalfSize;

   originRounded.x = Helpers::MathHelper::Round(origin.x);
   originRounded.y = Helpers::MathHelper::Round(origin.y);

   rounding.x = originRounded.x - origin.x;
   rounding.y = originRounded.y - origin.y;
   rounding /= shadowHalfSize;

   roundingMatrix = Matrix::Translate(rounding.x, rounding.y, 0.0f);
   viewProj *= roundingMatrix;

   // compute final components

   finalMat = viewProj * textureMat;
   viewFrustum->Update(viewProj);

Is this code correct? If it is, there are some problem: my character (which moves with the camera) still flickering and the "backupDist" is really game and eyeposition relevant, so I can't hardcode it.

Or am I doing something wrong?

#1csisy

Posted 29 June 2012 - 01:01 PM

Thanks for the reply!

I put your code between the viewProj and the finalMat compute:

   proj = Matrix::OrthographicOffCenter(-1, 1, -1, 1, min.z, max.z);
   viewProj = view * proj * cropMat;
   Vector3 shadowOrigin = Vector3::Transform(Vector3::Zero, viewProj);
   shadowOrigin *= shadowHalfSize;
   Vector2 roundedOrigin = Vector2(Helpers::MathHelper::Round(shadowOrigin.x), Helpers::MathHelper::Round(shadowOrigin.y));
   Vector2 rounding = roundedOrigin - Vector2(shadowOrigin.x, shadowOrigin.y);
   rounding /= ((float)shadowSize * 0.5f);
   Matrix roundMatrix = Matrix::Translate(rounding.x, rounding.y, 0.0f);
   viewProj *= roundMatrix;
   finalMat = viewProj * textureMat;

I think it works, because the static meshes' shadow is not flickering (I think :D), but the character (the player) moves together with the camera, and its shadow is still flickering.

This can be solved by the bounding sphere instead of light AABB?

PARTNERS