Frustum Culling
Frustum Culling
void Frustum::FinalUpdate()
{
Matrix matViewInv = Camera::S_MatView.Invert();
Matrix matProjectionInv = Camera::S_MatProjection.Invert();
Matrix matInv = matProjectionInv * matViewInv;
vector<Vec3> worldPos =
{
::XMVector3TransformCoord(Vec3(-1.f, 1.f, 0.f), matInv),
::XMVector3TransformCoord(Vec3(1.f, 1.f, 0.f), matInv),
::XMVector3TransformCoord(Vec3(1.f, -1.f, 0.f), matInv),
::XMVector3TransformCoord(Vec3(-1.f, -1.f, 0.f), matInv),
::XMVector3TransformCoord(Vec3(-1.f, 1.f, 1.f), matInv),
::XMVector3TransformCoord(Vec3(1.f, 1.f, 1.f), matInv),
::XMVector3TransformCoord(Vec3(1.f, -1.f, 1.f), matInv),
::XMVector3TransformCoord(Vec3(-1.f, -1.f, 1.f), matInv)
};
// 평면을 만듦
_planes[PLANE_FRONT] = ::XMPlaneFromPoints(worldPos[0], worldPos[1], worldPos[2]); // CW
_planes[PLANE_BACK] = ::XMPlaneFromPoints(worldPos[4], worldPos[7], worldPos[5]); // CCW
_planes[PLANE_UP] = ::XMPlaneFromPoints(worldPos[4], worldPos[5], worldPos[1]); // CW
_planes[PLANE_DOWN] = ::XMPlaneFromPoints(worldPos[7], worldPos[3], worldPos[6]); // CCW
_planes[PLANE_LEFT] = ::XMPlaneFromPoints(worldPos[4], worldPos[0], worldPos[7]); // CW
_planes[PLANE_RIGHT] = ::XMPlaneFromPoints(worldPos[5], worldPos[6], worldPos[1]); // CCW
}
bool Frustum::ContainsSphere(const Vec3& pos, float radius)
{
for (const Vec4& plane : _planes)
{
// n = (a, b, c)
Vec3 normal = Vec3(plane.x, plane.y, plane.z);
// ax + by + cz + d > radius
if (normal.Dot(pos) + plane.w > radius)
return false;
}
return true;
}
void Camera::Render()
{
shared_ptr<Scene> scene = GET_SINGLE(SceneManager)->GetActiveScene();
// TODO : Layer 구분
const vector<shared_ptr<GameObject>>& gameObjects = scene->GetGameObjects();
for (auto& gameObject : gameObjects)
{
if (gameObject->GetMeshRenderer() == nullptr)
continue;
if (gameObject->GetCheckFrustum())
{
if (_frustum.ContainsSphere(
gameObject->GetTransform()->GetWorldPosition(),
gameObject->GetTransform()->GetBoundingSphereRadius()) == false)
{
continue;
}
}
gameObject->GetMeshRenderer()->Render();
}
}
投影空間の各平面を求めることで、平面オブジェクトが内部に存在するかどうかを確認します.
SkyBoxのようにCulingに関係のないオブジェクトに対して、Frustum Culingのcheck値を適用するかどうかを作成し、管理します.
Reference
この問題について(Frustum Culling), 我々は、より多くの情報をここで見つけました https://velog.io/@sansam41/Frustum-Cullingテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol