public static Matrix frustum(float left, float right, float bottom,
      float top, float zNear, float zFar) {
    if (zNear <= 0.0f || zFar < 0.0f) {
      throw new RuntimeException(
        "Frustum: zNear and zFar must be positive, and zNear>0");
    }
    if (left == right || top == bottom) {
      throw new RuntimeException(
        "Frustum: top,bottom and left,right must not be equal");
    }
    // Frustum matrix:
    // 2*zNear/dx 0 A 0
    // 0 2*zNear/dy B 0
    // 0 0 C D
    // 0 0 −1 0
    float zNear2 = 2.0f * zNear;
    float dx = right - left;
    float dy = top - bottom;
    float dz = zFar - zNear;
    float A = (right + left) / dx;
    float B = (top + bottom) / dy;
    float C = -1.0f * (zFar + zNear) / dz;
    float D = -2.0f * (zFar * zNear) / dz;

    return new Matrix(zNear2 / dx, 0, 0, 0, 0, zNear2 / dy, 0, 0, A, B, C, -1,
      0, 0, D, 0);
  }