Jump to content
  • Advertisement
Sign in to follow this  
papulko

Transforming a split frustum from NDC to world space

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

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, I'm trying to implement cascaded shadow maps in my Direct3D project and I've been struggling with this issue for a few days now. What I'm trying to do is calculate the current view frustum splits in world space by manually constructing frustum splits in NDC space and transforming them with the current inverse viewprojection matrix. I've managed to create the frustums in NDC space, using these values for the first frustum;


/// NDC Frustum points (xyzw)
LTN:-1.000000  1.000000  0.100000  1.000000
RTN: 1.000000  1.000000  0.100000  1.000000
LBN:-1.000000 -1.000000  0.100000  1.000000
RBN: 1.000000 -1.000000  0.100000  1.000000
LTF:-1.000000  1.000000  0.215443  1.000000
RTF: 1.000000  1.000000  0.215443  1.000000
LBF:-1.000000 -1.000000  0.215443  1.000000
RBF: 1.000000 -1.000000  0.215443  1.000000

LTN means LeftTopNear, LBF means LeftBottomFar and so on. The data for the second and third frustum are similar, but with the different z-values for the far planes (0.464159 for the second frustum and 1.0 for the last one)

 

Here's the code that is supposed to transform and normalize the frustum points:

/// m_viewProjection verified to be correct
XMMATRIX invViewProjection = XMMatrixInverse(nullptr, m_viewProjection);

/// GFX_SHADOW_CASCADE_COUNT is set to 3
for (unsigned short i = 0; i < Config::GFX_SHADOW_CASCADE_COUNT; i++)
{
  for (int j = 0; j < 8; j++)
  {
    m_frustumsWorld[i].point[j] = XMVector4Transform(m_frustumsNDC[i].point[j], invViewProjection);
    m_frustumsWorld[i].point[j] /= m_frustumsWorld[i].point[j].m128_f32[3];			
  }
}

The problem seems to occur when I do the transform. The last frustum (with NDC z-far distance of 1.0) seems to get transformed right with a world z-value corresponding to 100% of the max view distance, but the other two doesn't. Their transformed values puts them extremly close to the camera, not ~21% and ~46% of the max view distance which is what I'm looking for. I've spent days trying to figure out whats wrong appreciate any help I can get!

 

Share this post


Link to post
Share on other sites
Advertisement

Here the code to compute the 8 corners of the camera frustum in world-space :

void CCameraComponent::ComputeFrustumCornerPoints( CVector3* Points ) const
{
  // Get property values.
  const float NearClipPlane = GetNearClipPlane();
  const float FarClipPlane = GetFarClipPlane();

  // Compute the projection inverse scale factor.
  const float ScaleXInv = 1.0f / m_ProjectionMatrix( 0, 0 );
  const float ScaleYInv = 1.0f / m_ProjectionMatrix( 1, 1 );

  // Compute corners in view space.
  CVector3 CornersVS[ 8 ];
  const float NearX = ScaleXInv * NearClipPlane;
  const float NearY = ScaleYInv * NearClipPlane;
  CornersVS[ 0 ] = CVector3( -NearX, +NearY, NearClipPlane );
  CornersVS[ 1 ] = CVector3( +NearX, +NearY, NearClipPlane );
  CornersVS[ 2 ] = CVector3( +NearX, -NearY, NearClipPlane );
  CornersVS[ 3 ] = CVector3( -NearX, -NearY, NearClipPlane );
  const float FarX = ScaleXInv * FarClipPlane;
  const float FarY = ScaleYInv * FarClipPlane;
  CornersVS[ 4 ] = CVector3( -FarX, +FarY, FarClipPlane );
  CornersVS[ 5 ] = CVector3( +FarX, +FarY, FarClipPlane );
  CornersVS[ 6 ] = CVector3( +FarX, -FarY, FarClipPlane );
  CornersVS[ 7 ] = CVector3( -FarX, -FarY, FarClipPlane );

  // Compute the inverse of the view matrix.
  const CMatrix4 InverseViewMatrix = m_ViewMatrix.Inversed();

  // Compute the world space corners.
  for( UInt32 i = 0; i < 8; ++i )
    Points[ i ] = InverseViewMatrix.TransformPoint( CornersVS[ i ] );
}
Edited by Alundra

Share this post


Link to post
Share on other sites

Thanks so much Alundra, your solution with constructing the corners in view space works much better. Still curious as to why the original solution didn't work though!

Share this post


Link to post
Share on other sites

Thanks so much Alundra, your solution with constructing the corners in view space works much better. Still curious as to why the original solution didn't work though!

The reason why is would be this (To quote Eric Lengyel)
Z is nonlinear because perspective-correct rasterization requires linear interpolation of 1/z -- linear interpolation of z itself does not produce the correct results.

http://www.gamedev.net/topic/539378-why-non-linear-depth-buffer/#entry4483438

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!