title: Setting up perspective projection on Opengl ES 2.0 makes objects disappear
body: <p>I'm working on a project using opengl-es 2.0, and I'm having some trouble setting up perspective projection. </p>
  
  <p>If I don't set up the perspective projection and simply multiply the object-to-world matrix (I believe it's also called model matrix) by the vertex positions, the objects on screen are rendered correctly, they appear stretched, but as far as I know, that's something the projection matrix would fix. The problem is, whenever I set the perspective matrix and use it, the objects on screen disappear, and no matter how much I move them around they never show up in screen. </p>
  
  <p>The calculations to get the Model-View-Projection matrix are done in CPU and the last multiplication the MVP-Matrix by the actual object-space vertex data is done in the vertex shader, this is why I believe the problem might be on the process to get that MVP-Matrix. I've run a bunch of unit tests, but according to those tests (and my basic knowledge of linear algebra) those matrices are being correctly calculated, and my internet-research throughout the day isn't helping for now. :-/</p>
  
  <p>This is the code I use to calculate the MVP-Matrix:</p>
  
  <pre><code>Matrix4D projection_matrix;
  projection_matrix.makePerspective(45.0f, 0.001f, 100.0f, 480.0f/320.0f);
  
  Matrix4D view_matrix;
  view_matrix.makeIdentity(); //Should be a real view matrix. TODO.
  
  Matrix4D model_matrix(getWorldMatrix());
  
  Matrix4D mvp_matrix(projection_matrix);
  mvp_matrix *= view_matrix;
  mvp_matrix *= model_matrix;
  
  mMesh-&gt;draw(time, mvp_matrix.getRawData());
  </code></pre>
  
  <p>I think this code is pretty self-explanatory, but just in case, those Matrix4D are 4x4 matrices, and calling makePerspective/makeIdentity on them will make that matrix the Perspective or Identity matrix. The getRawData() call on Matrix4D objects returns the matrix data as a float array in column-major notation, and the mMesh variable is another object which, when draw is called, will simply send all the vertex and material data to the shaders.</p>
  
  <p>The makePerspective function's code is the following:</p>
  
  <pre><code>Matrix4D&amp; Matrix4D::makePerspective(const float field_of_view, 
          const float near, const float far, const float aspect_ratio) {
      float size = near * tanf(DEGREES_TO_RADIANS(field_of_view) / 2.0f); 
  
      return this-&gt;makeFrustum(-size, size, -size / aspect_ratio,
               size / aspect_ratio, near, far);
  }
  
  Matrix4D&amp; Matrix4D::makeFrustum(const float left, const float right, 
          const float bottom, const float top, const float near, 
          const float far) {
      this-&gt;mRawData[0] = 2.0f * near / (right - left);  
      this-&gt;mRawData[1] = 0.0f; 
      this-&gt;mRawData[2] = 0.0f; 
      this-&gt;mRawData[3] = 0.0f;
  
      this-&gt;mRawData[4] = 0.0f; 
      this-&gt;mRawData[5] = 2.0f * near / (top - bottom); 
      this-&gt;mRawData[6] = 0.0f; 
      this-&gt;mRawData[7] =  0.0f;
  
      this-&gt;mRawData[8] = (right + left) / (right - left);
      this-&gt;mRawData[9] = (top + bottom) / (top - bottom); 
      this-&gt;mRawData[10] = - (far + near) / (far - near); 
      this-&gt;mRawData[11] = -1.0f;
  
      this-&gt;mRawData[12] = 0.0f; 
      this-&gt;mRawData[13] = 0.0f; 
      this-&gt;mRawData[14] = -2.0f * far * near / (far - near); 
      this-&gt;mRawData[15] = 0.0f;
  
      return *this;
  }
  </code></pre>
  
  <p>And the getWorldMatrix() call does this(with some related code):</p>
  
  <pre><code>const Matrix4D&amp; getWorldMatrix() {
      return mWorldMatrix = 
              getTranslationMatrix() *
              getRotationMatrix() *
              getScaleMatrix();
  }
  
  const Matrix4D&amp; getRotationMatrix() {
      return this-&gt;mRotationMatrix.makeRotationFromEuler(this-&gt;mPitchAngle,
          this-&gt;mRollAngle, this-&gt;mYawAngle);
  }
  
  const Matrix4D&amp; getTranslationMatrix() {
      return this-&gt;mTranslationMatrix.makeTranslation(this-&gt;mPosition.x,
          this-&gt;mPosition.y, this-&gt;mPosition.z);
  }
  
  const Matrix4D&amp; getScaleMatrix() {
      return this-&gt;mScaleMatrix.makeScale(this-&gt;mScaleX, this-&gt;mScaleY, this-&gt;mScaleZ);
  }
  
  
  ///This code goes in the Matrix4D class.
  Matrix4D&amp; Matrix4D::makeTranslation(const float x, const float y, 
          const float z) {
      this-&gt;mRawData[0] = 1.0f; 
      this-&gt;mRawData[1] = 0.0f; 
      this-&gt;mRawData[2] = 0.0f; 
      this-&gt;mRawData[3] = 0.0f;
  
      this-&gt;mRawData[4] = 0.0f; 
      this-&gt;mRawData[5] = 1.0f; 
      this-&gt;mRawData[6] = 0.0f; 
      this-&gt;mRawData[7] = 0.0f;
  
      this-&gt;mRawData[8] = 0.0f; 
      this-&gt;mRawData[9] = 0.0f; 
      this-&gt;mRawData[10] = 1.0f; 
      this-&gt;mRawData[11] = 0.0f;
  
      this-&gt;mRawData[12] =    x; 
      this-&gt;mRawData[13] =    y; 
      this-&gt;mRawData[14] =    z; 
      this-&gt;mRawData[15] = 1.0f;
  
      return *this;
  }
  
  Matrix4D&amp; Matrix4D::makeScale(const float x, const float y, 
          const float z) {
      this-&gt;mRawData[0] =    x; 
      this-&gt;mRawData[1] = 0.0f; 
      this-&gt;mRawData[2] = 0.0f; 
      this-&gt;mRawData[3] = 0.0f;
  
      this-&gt;mRawData[4] = 0.0f; 
      this-&gt;mRawData[5] =    y; 
      this-&gt;mRawData[6] = 0.0f; 
      this-&gt;mRawData[7] = 0.0f;
  
      this-&gt;mRawData[8] = 0.0f; 
      this-&gt;mRawData[9] = 0.0f; 
      this-&gt;mRawData[10] =    z; 
      this-&gt;mRawData[11] = 0.0f;
  
      this-&gt;mRawData[12] = 0.0f; 
      this-&gt;mRawData[13] = 0.0f; 
      this-&gt;mRawData[14] = 0.0f; 
      this-&gt;mRawData[15] = 1.0f;
  
      return *this;
  } 
  
  Matrix4D&amp; Matrix4D::makeRotationFromEuler(const float angle_x, 
          const float angle_y, const float angle_z) {
      float a = cosf(angle_x);
      float b = sinf(angle_x);
      float c = cosf(angle_y);
      float d = sinf(angle_y);
      float e = cosf(angle_z);
      float f = sinf(angle_z);
      float ad = a * d;
      float bd = b * d;
  
      this-&gt;mRawData[0] = c * e;
      this-&gt;mRawData[1] = -bd * e + a * f;
      this-&gt;mRawData[2] = ad * e + b * f;
      this-&gt;mRawData[3] = 0.0f;
  
      this-&gt;mRawData[4] = -c * f; 
      this-&gt;mRawData[5] = bd * f + a * e;
      this-&gt;mRawData[6] = -ad * f + b * e; 
      this-&gt;mRawData[7] = 0.0f;
  
      this-&gt;mRawData[8] = -d; 
      this-&gt;mRawData[9] = -b * c;
      this-&gt;mRawData[10] = a * c; 
      this-&gt;mRawData[11] = 0.0f;
  
      this-&gt;mRawData[12] = 0.0f; 
      this-&gt;mRawData[13] = 0.0f;
      this-&gt;mRawData[14] = 0.0f; 
      this-&gt;mRawData[15] = 1.0f;
  
      return *this;
  }
  </code></pre>
  
  <p>Finally, the vertex shader is pretty much this:</p>
  
  <pre><code>#version 110
  
  const float c_one = 1.0;
  const float c_cero = 0.0;
  
  uniform float time;
  uniform mat4 mvp_matrix;
  
  attribute vec3 position;
  attribute vec3 normal;
  attribute vec2 texture_coordinate;
  
  varying vec2 v_texture_coordinate;
  
  void main()
  {   
      gl_Position = mvp_matrix * vec4(position, c_one);
      v_texture_coordinate = texture_coordinate;
  }
  </code></pre>
  
  <p>Just in case, the object being rendered is rendered on position (0.0f, 0.0f, -3.0f) with 0.5f scale applied to all the three axis's.</p>
  
  <p>I don't really know what could be wrong, I'm hoping someone can spot what I may be missing, and any help would be appreciated. Debugging this would be a lot easier if I could get per-vertex results on the shader :-/.</p>
  
  <p>As a side note, I'm having doubts on how to calculate the View or camera matrix, as far as I know it's simply a matrix with the inverted transformations the camera has to do, by which I understand something like, if I want to move the camera 100 units to the right, I move it 100 units to the left, is that right? </p>
  
  <p><strong>EDIT:</strong> Just trying to give more information, maybe that way someone will be able to help me. I've noticed the model matrix is incorrect with the code above, mostly because of the matrix order, I've changed it to the following and now the model matrix seems good:</p>
  
  <pre><code>const Matrix4D&amp; getWorldMatrix() {
      return mWorldMatrix = 
              getScaleMatrix() * getRotationMatrix() * getTranslationMatrix();
  }
  </code></pre>
  
  <p>Despite this, still no luck. The matrices resulting from my test data are these:</p>
  
  <pre><code>Projection matrix:
  [1.609506,0.000000,0.000000,0.000000]
  [0.000000,2.414258,0.000000,0.000000]
  [0.000000,0.000000,-1.000020,-0.002000]
  [0.000000,0.000000,-1.000000,0.000000]
  
  
  
  Model matrix:
  [0.500000,0.000000,0.000000,0.000000]
  [0.000000,0.500000,0.000000,0.000000]
  [0.000000,0.000000,0.500000,-3.000000]
  [0.000000,0.000000,0.000000,1.000000]
  
  
  
  MVP matrix:
  [0.804753,0.000000,0.000000,0.000000]
  [0.000000,1.207129,0.000000,0.000000]
  [0.000000,0.000000,2.499990,-0.001000]
  [0.000000,0.000000,-1.000000,0.000000]
  </code></pre>
  
  <p>And the mesh I'm using to test all this is a simple cube going from 1.0f to -1.0f on each axis, centered on the origin. As far as I know, this should position the vertex closest to the near limit (0.0001f) on position -2.0f along the z axis, so the cube is in front of the camera and withing the view frustum. Any clues someone?</p>