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条)