code: public Vector3fc dir(float x, float y, Vector3f dir) {
          float y1x = nxnyX + (nxpyX - nxnyX) * y;
          float y1y = nxnyY + (nxpyY - nxnyY) * y;
          float y1z = nxnyZ + (nxpyZ - nxnyZ) * y;
          float y2x = pxnyX + (pxpyX - pxnyX) * y;
          float y2y = pxnyY + (pxpyY - pxnyY) * y;
          float y2z = pxnyZ + (pxpyZ - pxnyZ) * y;
          float dx = y1x + (y2x - y1x) * x;
          float dy = y1y + (y2y - y1y) * x;
          float dz = y1z + (y2z - y1z) * x;
          // normalize the vector
          float invLen = (float) (1.0 / Math.sqrt(dx * dx + dy * dy + dz * dz));
          dir.x = dx * invLen;
          dir.y = dy * invLen;
          dir.z = dz * invLen;
          return dir;
      }
docs: Obtain the normalized direction of a ray starting at the center of the coordinate system and going
  through the near frustum plane.
  <p>
  The parameters <code>x</code> and <code>y</code> are used to interpolate the generated ray direction
  from the bottom-left to the top-right frustum corners.
  
  @param x
  the interpolation factor along the left-to-right frustum planes, within <code>[0..1]</code>
  @param y
  the interpolation factor along the bottom-to-top frustum planes, within <code>[0..1]</code>
  @param dir
  will hold the normalized ray direction
  @return the <code>dir</code> vector