Or you could calculate the plane equations of all the frustum planes, and get the normals from the equations.
A plane equation has the form:
Ax + By + Cz + D = 0
(A, B, C) represents the plane normal.
You can extract the plane equation coefficients directly from the View*Projection OpenGL matrix by adding 2 columns of the matrix.
This method is described here: http://www.cs.otago.ac.nz/postgrads/alexis/planeExtraction.pdf
Letting vp = View*Projection;
Here is some code I use;
struct Plane
{
float A, B, C, D;
};
struct Frustum
{
Plane top, bottom, right, left, zNear, zFar;
};
// column2 + column3
frustum.zNear.A = vp(2, 0) + vp(3, 0);
frustum.zNear.B = vp(2, 1) + vp(3, 1);
frustum.zNear.C = vp(2, 2) + vp(3, 2);
frustum.zNear.D = vp(2, 3) + vp(3, 3);
// column3 - column2
frustum.zFar.A = -vp(2, 0) + vp(3, 0);
frustum.zFar.B = -vp(2, 1) + vp(3, 1);
frustum.zFar.C = -vp(2, 2) + vp(3, 2);
frustum.zFar.D = -vp(2, 3) + vp(3, 3);
// column1 + column3
frustum.bottom.A = vp(1, 0) + vp(3, 0);
frustum.bottom.B = vp(1, 1) + vp(3, 1);
frustum.bottom.C = vp(1, 2) + vp(3, 2);
frustum.bottom.D = vp(1, 3) + vp(3, 3);
// column3 - column1
frustum.top.A = -vp(1, 0) + vp(3, 0);
frustum.top.B = -vp(1, 1) + vp(3, 1);
frustum.top.C = -vp(1, 2) + vp(3, 2);
frustum.top.D = -vp(1, 3) + vp(3, 3);
// column0 + column3
frustum.left.A = vp(0, 0) + vp(3, 0);
frustum.left.B = vp(0, 1) + vp(3, 1);
frustum.left.C = vp(0, 2) + vp(3, 2);
frustum.left.D = vp(0, 3) + vp(3, 3);
// column3 - column0
frustum.right.A = -vp(0, 0) + vp(3, 0);
frustum.right.B = -vp(0, 1) + vp(3, 1);
frustum.right.C = -vp(0, 2) + vp(3, 2);
frustum.right.D = -vp(0, 3) + vp(3, 3);
Then you normalize each plane's A,B,C,D by dividing by sqrt(A * A + B * B + C * C) if you want normals of length equal to 1.