Es scheint jedoch perfekt zu funktionieren, wenn ich nur mit der Projektionsmatrix arbeite (und dabei jeden einzelnen Punkt, den ich testen möchte, durch Ansicht * Modell statt nur durch Modell transformiere). Ich möchte dies nicht tun, da die Eine zusätzliche Matrixmultiplikation pro Objekt macht diesen View-Space-Ansatz deutlich langsamer – es scheint den Unterschied zwischen 60 und 120 FPS in einer Szene mit 15.000 Objekten auszumachen.
Dies ist mein Code zur Kegelstumpf- und Kegelstumpfkugelprüfung:
Code: Select all
using Plane = glm::vec4;
using Frustum = std::array;
/// Generate a camera frustum from a projection-view matrix.
inline Frustum frustumFromMatrix(const glm::mat4& matrix)
{
Frustum frustum{};
frustum[0].x = matrix[0][3] + matrix[0][0];
frustum[0].y = matrix[1][3] + matrix[1][0];
frustum[0].z = matrix[2][3] + matrix[2][0];
frustum[0].w = matrix[3][3] + matrix[3][0];
frustum[1].x = matrix[0][3] - matrix[0][0];
frustum[1].y = matrix[1][3] - matrix[1][0];
frustum[1].z = matrix[2][3] - matrix[2][0];
frustum[1].w = matrix[3][3] - matrix[3][0];
frustum[2].x = matrix[0][3] - matrix[0][1];
frustum[2].y = matrix[1][3] - matrix[1][1];
frustum[2].z = matrix[2][3] - matrix[2][1];
frustum[2].w = matrix[3][3] - matrix[3][1];
frustum[3].x = matrix[0][3] + matrix[0][1];
frustum[3].y = matrix[1][3] + matrix[1][1];
frustum[3].z = matrix[2][3] + matrix[2][1];
frustum[3].w = matrix[3][3] + matrix[3][1];
frustum[4].x = matrix[0][3] + matrix[0][2];
frustum[4].y = matrix[1][3] + matrix[1][2];
frustum[4].z = matrix[2][3] + matrix[2][2];
frustum[4].w = matrix[3][3] + matrix[3][2];
frustum[5].x = matrix[0][3] - matrix[0][2];
frustum[5].y = matrix[1][3] - matrix[1][2];
frustum[5].z = matrix[2][3] - matrix[2][2];
frustum[5].w = matrix[3][3] - matrix[3][2];
return frustum;
}
inline bool sphereInHalfSpace(const glm::vec3 point, const float radius, const Plane plane)
{
return glm::dot(glm::vec3(plane), point) - plane.w > -radius;
}
inline bool sphereInFrustum(const glm::vec3 point, const float radius, const Frustum& frustum)
{
for (int i = 0; i < 6; i++)
if (!sphereInHalfSpace(point, radius, frustum[i])) return false;
return true;
}
Code: Select all
const auto frustum = frustumFromMatrix(projection_mat * view_mat);
for (int i = 0; i < count; i++) {
const auto radius = models[i].radius;
const auto pos = model_transforms[i] * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f);
if (!sphereInFrustum(pos, radius, frustum)) {
excludeFromDrawing(i);
}
}
Mobile version