Search code examples
androidc++opengl-esandroid-ndk

android opengl es 2.0 glm projection not working


I am using c/c++ (NDK) for android to program in opengl es 2.0. Since there is no official C++ library for android I am using the GLM library !

so far I can draw a white triangle on a black background without any projection/frustum or camera/view matrix applied. Of course this causes the triangle to appear scaled along the width of the screen.

however as soon as I apply the camera and projection transformation the triangle vanishes from the scene and only background color appears.

This is the relevant code:

float triangleCoords[] = {   // in counterclockwise order:
           0,  1, 0, // top
          -1, 0, 0, // bottom left
           1, 0, 0  // bottom right
  };

std::string vertexShaderCode =
        "attribute vec4 vPosition; "
        "uniform mat4 uMVPMatrix;  "
        "void main() {"
        "  gl_Position = uMVPMatrix*vPosition;"
        "}";

    std::string fragmentShaderCode =
        "precision mediump float;"
        "uniform vec4 vColor;"
        "void main() {"
        "  gl_FragColor = vColor;"
        "}";

    mvpMatrix=glm::translate(mvpMatrix,vec3(0,-0.5,0));

    mvpMatrix*=glm::lookAt(vec3(0,0,-3),vec3(0,0,0),vec3(0,1,0));

    mvpMatrix*=glm::frustum(-1.0f,1.0f,-ratio,ratio,3.0f,7.0f);

where vec3 is "typedef glm::vec3" and mvpMatrix is "glm::mat4x4"

I have tried it many ways e.g multiplying lookAt before frustum and changing near far values for frustum etc etc.

Also I tried changing the triangle co-ordinates to see if it was getting clipped but to no avail

However the translation of 0.5 units works correctly if if lookAt and frustum are not applied which means that passage of values from matrix to the shader is correct.

Help me out on this one


Solution

  • You are using the glm library improperly.

    The conventions you use in your shader (which match the default conventions of the old fixed-function pipeline and also the conventions of glm) is matrix * vector.

    When you compose several transforms to a single matrix, you get the following: M=A*B*C and apply it to some vector v as v' = M * v. But this is the same as v' = A * ( B * ( C * v)), so C is actually applied first. In your case, you have M * V * P, but the correct "ModelViewProjection" transform is first applying the model transform (to get to world space), after than the view transform (to get to eye space) and finally the projection transform to get to clip space, so you need P * V * M.

    Please note that with the numbers as you choose them, the triangle will end up exactly at the near plane - but with a bit of numerical imprecision, it might still be culled away.