graphics - How to create a minimal shadow map that covers the view frustum - Stack Overflow

I intend to implement a shadow map that fits the view frustum as follows.My method is as follows:Compu

I intend to implement a shadow map that fits the view frustum as follows.

My method is as follows:

Compute the coordinates of the view frustum in camera space.

Transform them into world space.

Compute a temporary light matrix using the center of the view frustum and the light's direction to transform into light space.

In light space, determine the maximum and minimum values of the eight points to define the light's position and the size of the shadow map.

Use the light's position to compute the view matrix.

However, after implementation, the shadow map changes depending on the camera's rotation. I assume this is due to an issue with the position and direction of the light source. Could there be any problems with my code?

SimpleMath::Matrix invViewMatrix
(SimpleMath::Matrix::CreateLookAt(camera.GetTransform().GetPosition(), 
    camera.GetTransform().GetPosition() + camera.GetTransform().GetForward(),
    SimpleMath::Vector3::Up).Invert());

float farZ = 800.0f;
float nearHeight = cameraParam.nearZ * tanf(cameraParam.fov * 0.5f);

float farHeight = farZ * tanf(cameraParam.fov * 0.5f);

float nearWidth = nearHeight * cameraParam.aspect;
float farWidth = farHeight * cameraParam.aspect;


//view frustum position in Camera Space
mFrustums[0] = SimpleMath::Vector4(-nearWidth, nearHeight, cameraParam.nearZ, 1.0f);
mFrustums[1] = SimpleMath::Vector4(nearWidth, nearHeight, cameraParam.nearZ, 1.0f);
mFrustums[2] = SimpleMath::Vector4(-nearWidth, -nearHeight, cameraParam.nearZ, 1.0f);
mFrustums[3] = SimpleMath::Vector4(nearWidth, -nearHeight, cameraParam.nearZ, 1.0f);

mFrustums[4] = SimpleMath::Vector4(-farWidth, farHeight, farZ, 1.0f);
mFrustums[5] = SimpleMath::Vector4(farWidth, farHeight, farZ, 1.0f);
mFrustums[6] = SimpleMath::Vector4(-farWidth, -farHeight, farZ, 1.0f);
mFrustums[7] = SimpleMath::Vector4(farWidth, -farHeight, farZ, 1.0f);

//translation to World Space
for (SimpleMath::Vector4& point : mFrustums) {
    
    point = SimpleMath::Vector4::Transform(point, invViewMatrix);

}


SimpleMath::Vector4 averageFrustum = 
    (mFrustums[0] + mFrustums[1] + mFrustums[2] + mFrustums[3] + mFrustums[4] + mFrustums[5] + mFrustums[6] + mFrustums[7]) / 8.0f;

//Light Space Matrix
SimpleMath::Matrix view = SimpleMath::Matrix::CreateLookAt(
    SimpleMath::Vector3(averageFrustum.x, averageFrustum.y, averageFrustum.z) + 50.0f * SimpleMath::Vector3(1.0f,1.0f,1.0f),
    SimpleMath::Vector3(averageFrustum.x, averageFrustum.y, averageFrustum.z),
    SimpleMath::Vector3(0.0f, 1.0f, 0.0f)
);

//translation to Light Space
for (SimpleMath::Vector4& point : mFrustums) {
    
    point = SimpleMath::Vector4::Transform(point, view);

}

SimpleMath::Vector4 minPoint = mFrustums[0];
SimpleMath::Vector4 maxPoint = mFrustums[0];

//calculation LightPos to render Shadow map
for (const SimpleMath::Vector4& point : mFrustums)
{
    minPoint.x = (std::min)(minPoint.x, point.x);
    minPoint.y = (std::min)(minPoint.y, point.y);
    minPoint.z = (std::min)(minPoint.z, point.z);

    maxPoint.x = (std::max)(maxPoint.x, point.x);
    maxPoint.y = (std::max)(maxPoint.y, point.y);
    maxPoint.z = (std::max)(maxPoint.z, point.z);
}

SimpleMath::Vector4 lightPos((maxPoint.x + minPoint.x) / 2.0f, (maxPoint.y + minPoint.y) / 2.0f, maxPoint.z, 1.0f);
lightPos = SimpleMath::Vector4::Transform(lightPos, view.Invert());

mShadowMapWidth = (std::max)(maxPoint.x - minPoint.x, maxPoint.y - minPoint.y);

mLightInfo.Position = SimpleMath::Vector3(lightPos.x, lightPos.y, lightPos.z);

SimpleMath::Vector4 center((maxPoint.x + minPoint.x) / 2.0f, (maxPoint.y + minPoint.y) / 2.0f, (maxPoint.z + minPoint.z) / 2.0f, 1.0f);
center = SimpleMath::Vector4::Transform(center, view.Invert());
mLightInfo.Position = center + 50.0f * SimpleMath::Vector3(1.0f, 1.0f, 1.0f);

view = SimpleMath::Matrix::CreateLookAt(
    mLightInfo.Position,
    SimpleMath::Vector3(center.x, center.y, center.z),
    SimpleMath::Vector3(0.0f, 1.0f, 0.0f)
);



SimpleMath::Matrix proj = SimpleMath::Matrix::CreateOrthographic(mShadowMapWidth, mShadowMapWidth, 1.0f, 800.0f);

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744251238a4565176.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信