title: How does near/far clipping planes in gluPerspective()/glm::perspective() work?
body: <p>I have a question about how the standard perspective projection matrix works, the one you get from <code>gluPerspective()</code> or <code>glm::perspective()</code>. Specifically, I'm wondering about the near/far clipping planes. </p>
  
  <p>I was under the impression that after transforming a point with the perspective matrix, objects on the near clip plane mapped to a Z value of -1, and objects near the far clip plane mapped to a Z value of 1. </p>
  
  <p>For instance, lets say you have a camera located at the origin, looking in the direction of the positive Z axis, with near clip plane at 1.0 and far clip plane set to 2.0. I would then expect that a things having "world" Z coordinates between 1.0 and 2.0 would be transformed as having projected coordinates between -1.0 and 1.0. </p>
  
  <p>In other words, i would expect this C++ code: </p>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;glm/glm.hpp&gt;
  #include &lt;glm/gtc/matrix_transform.hpp&gt;
  
  using namespace glm;
  
  void print_vec(vec4 pnt) {
      std::cout &lt;&lt; "(" &lt;&lt; pnt.x &lt;&lt; ", " &lt;&lt; pnt.y &lt;&lt; ", " &lt;&lt; pnt.z &lt;&lt; ")" &lt;&lt; "\n";
  }
  
  int main() {
      mat4x4 view = lookAt(
              vec3(0.0f, 0.0f, 0.0f),   // eye at origin
              vec3(0.0f, 0.0f, 1.0f),   // looking towards +Z
              vec3(0.0f, 1.0f, 0.0f));  // up is +Y
  
      mat4x4 projection = perspective(
              radians(90.0f),  // field of view
              1.0f,            // aspect ratio
              1.0f,            // near clipping plane
              2.0f);           // far clipping plane
  
      // transformation matrix for world coordinates
      mat4x4 vp = projection * view; 
  
      // points (0,0,1), (0,0,1.5) and (0,0,2) in homogeneous coordinates
      print_vec(vp * vec4(0.0f, 0.0f, 1.0f, 1.0f));
      print_vec(vp * vec4(0.0f, 0.0f, 1.5f, 1.0f));
      print_vec(vp * vec4(0.0f, 0.0f, 2.0f, 1.0f));
  }
  </code></pre>
  
  <p>to print out this</p>
  
  <pre><code>(0, 0, -1)
  (0, 0, 0)
  (0, 0, 1)
  </code></pre>
  
  <p>But it doesn't. It prints out this: </p>
  
  <pre><code>(0, 0, -1)
  (0, 0, 0.5)
  (0, 0, 2)
  </code></pre>
  
  <p>And I don't understand why. The near clip plane projects like I would expect, but a point exactly midway between the planes are closer to the back when projected, and a point on the far clip plane is outside the [-1,1] range entirely. </p>
  
  <p>I figure there's some basic math thing i'm just missing, so that's why I'm asking you fine fellows.</p>
  
  <p>(incidentally, the thing I'm working on is actually written in Rust, not C++, but I switched to C++ for this test, just to be sure there wasn't a bug in the Rust implementation or something.)</p>