最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

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

programmeradmin4浏览0评论

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);
发布评论

评论列表(0)

  1. 暂无评论