c++opengl-esopengl-es-2.0egl

Cube getting squashed and rendering as trapezium


I'm trying to render a cube and rotate it along it's Y axis using OpenGL ES 2.0, however the cube does not render as a cube but rather as some sort of very flat trapezium. A few images showing the odd behaviour:

Very flat:
Very flat

beginning to rotate:
beginning to rotate

mid-rotation:
mid-rotation

and after rotation:
after rotation

I'm not exactly sure what is causing the strange behaviour. I am utilising the Pigs in a Blanket library for rendering on PS Vita.

These are my cube vertices. The first 3 values in each row are the vertex data, the last 2 values are for texture mapping

GLfloat vertices[] = {
    -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,
    0.5f, -0.5f, -0.5f,  1.0f, 0.0f,
    0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
    0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
    -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,
    -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,

    -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
    0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
    0.5f,  0.5f,  0.5f,  1.0f, 1.0f,
    0.5f,  0.5f,  0.5f,  1.0f, 1.0f,
    -0.5f,  0.5f,  0.5f,  0.0f, 1.0f,
    -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,

    -0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
    -0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
    -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
    -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
    -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
    -0.5f,  0.5f,  0.5f,  1.0f, 0.0f,

    0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
    0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
    0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
    0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
    0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
    0.5f,  0.5f,  0.5f,  1.0f, 0.0f,

    -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
    0.5f, -0.5f, -0.5f,  1.0f, 1.0f,
    0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
    0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
    -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
    -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,

    -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,
    0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
    0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
    0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
    -0.5f,  0.5f,  0.5f,  0.0f, 0.0f,
    -0.5f,  0.5f, -0.5f,  0.0f, 1.0f
};

This is my initialization function. surface_width = 960, surface_height = 544 and aspect = 1.764706

void TestScene::init(EGLint s_width, EGLint s_height)
{
    surface_height = s_height;
    surface_width = s_width;
    model = glm::mat4(1.0f);
    projection = glm::mat4(1.0f);

    glGenBuffers(1, &VBO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);


    texture.load_texture("app0:assets/wall.jpg");

    if (!shader.load_shaders("app0:shaders/vert.cg", "app0:shaders/frag.cg"))
        sceKernelExitProcess(0);
}

This is my rendering function

void TestScene::render(EGLDisplay display, EGLSurface surface, double deltaTime)
{
    glViewport(0, 0, surface_width, surface_height);
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glEnable(GL_DEPTH_TEST);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture.ID);
    glUseProgram(shader.ID);

    GLint mvpLoc = glGetUniformLocation(shader.ID, "mvp");
    GLint position = glGetAttribLocation(shader.ID, "vPosition");
    GLint texLoc = glGetAttribLocation(shader.ID, "vTexCoord");
    
    GLfloat aspect = (GLfloat)surface_width/(GLfloat)surface_height;
    projection = glm::perspective(glm::radians(camera.Zoom), aspect, 0.1f, 100.0f);
   

    view = camera.GetViewMatrix();
    model = glm::rotate(model, glm::radians(1.0f), glm::vec3(0.0f, -1.0f, 0.0f));

    glm::mat4 mvp = projection * view * model;
    glUniformMatrix4fv(mvpLoc, 1, GL_FALSE, glm::value_ptr(mvp));

    // Bind vertex positions
    glEnableVertexAttribArray(position);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
    // Bind texture positions
    glEnableVertexAttribArray(texLoc);
    glVertexAttribPointer(texLoc, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
    glDrawArrays(GL_TRIANGLES, 0, 36);
    glDisableVertexAttribArray(position);
    glDisableVertexAttribArray(texLoc);
    eglSwapBuffers(display, surface);
}

My cameras zoom value is 45.0f and this is the GetViewMatrix method:

glm::mat4 Camera::GetViewMatrix()
{
    return glm::lookAt(Position, Position + Front, Up);
}

and finally the shaders: vert.cg

void main
(
uniform float4x4 mvp,
float4 vPosition,
float2 vTexCoord: TEXCOORD0,
out float4 oPosition: POSITION,
out float2 fTexCoord: TEXCOORD
)
{
    oPosition = mul(mvp, vPosition);
    fTexCoord = vTexCoord;
};

frag.cg

float4 main
(
in float2 fTexCoord: TEXCOORD0,
uniform sampler2D texture1: TEXUNIT0
)
{
    float4 col;
    col = tex2D(texture1, fTexCoord);
    return col;
}

I have a feeling it has something to do with my projection matrix but I'm not entirely sure. Any help is greatly appreciated, thank you

UPDATE:

If I update the near value in glm::perspective from 0.1f to 1.0f it produces a better looking but still false result, so I'm pretty sure the issue is in my projection matrix. What am I doing wrong here?

projection = glm::perspective(glm::radians(camera.Zoom), aspect, 0.1f, 100.0f);

becomes

projection = glm::perspective(glm::radians(camera.Zoom), aspect, 1.0f, 100.0f);

for the following results:

Wider but still incorrect Wider but still incorrect Another angle Another angle Again Again


Solution

  • I've found the issue. I was multiplying the model view projection matrix incorrectly in the vert shader.

    oPosition = mul(mvp, vPosition);

    should be

    oPosition = mul(vPosition, mvp);

    this works with a near value of 0.1f

    EDIT

    Also the missing faces were due to incorrect winding order with my vertices. Here is a corrected set of vertices, they are in clockwise order glFrontFace(GL_CW);

    GLfloat vertices[] = {
            // Back face
            -0.5f, -0.5f, -0.5f,  0.0f, 0.0f, // Bottom-left
            0.5f, -0.5f, -0.5f,  1.0f, 0.0f, // bottom-right
            0.5f,  0.5f, -0.5f,  1.0f, 1.0f, // top-right
            0.5f,  0.5f, -0.5f,  1.0f, 1.0f, // top-right
            -0.5f,  0.5f, -0.5f,  0.0f, 1.0f, // top-left
            -0.5f, -0.5f, -0.5f,  0.0f, 0.0f, // bottom-left
            // Front face
            -0.5f, -0.5f,  0.5f,  0.0f, 0.0f, // bottom-left
            0.5f,  0.5f,  0.5f,  1.0f, 1.0f, // top-right
            0.5f, -0.5f,  0.5f,  1.0f, 0.0f, // bottom-right
            0.5f,  0.5f,  0.5f,  1.0f, 1.0f, // top-right
            -0.5f, -0.5f,  0.5f,  0.0f, 0.0f, // bottom-left
            -0.5f,  0.5f,  0.5f,  0.0f, 1.0f, // top-left
            // Left face
            -0.5f,  0.5f,  0.5f,  1.0f, 0.0f, // top-right
            -0.5f, -0.5f, -0.5f,  0.0f, 1.0f, // bottom-left
            -0.5f,  0.5f, -0.5f,  1.0f, 1.0f, // top-left
            -0.5f, -0.5f, -0.5f,  0.0f, 1.0f, // bottom-left
            -0.5f,  0.5f,  0.5f,  1.0f, 0.0f, // top-right
            -0.5f, -0.5f,  0.5f,  0.0f, 0.0f, // bottom-right
            // Right face
            0.5f,  0.5f,  0.5f,  1.0f, 0.0f, // top-left
            0.5f,  0.5f, -0.5f,  1.0f, 1.0f, // top-right
            0.5f, -0.5f, -0.5f,  0.0f, 1.0f, // bottom-right
            0.5f, -0.5f, -0.5f,  0.0f, 1.0f, // bottom-right
            0.5f, -0.5f,  0.5f,  0.0f, 0.0f, // bottom-left
            0.5f,  0.5f,  0.5f,  1.0f, 0.0f, // top-left
            // Bottom face
            -0.5f, -0.5f, -0.5f,  0.0f, 1.0f, // top-right
            0.5f, -0.5f,  0.5f,  1.0f, 0.0f, // bottom-left
            0.5f, -0.5f, -0.5f,  1.0f, 1.0f, // top-left
            0.5f, -0.5f,  0.5f,  1.0f, 0.0f, // bottom-left
            -0.5f, -0.5f, -0.5f,  0.0f, 1.0f, // top-right
            -0.5f, -0.5f,  0.5f,  0.0f, 0.0f, // bottom-right
            // Top face
            -0.5f,  0.5f, -0.5f,  0.0f, 1.0f, // top-left
            0.5f,  0.5f, -0.5f,  1.0f, 1.0f, // top-right
            0.5f,  0.5f,  0.5f,  1.0f, 0.0f, // bottom-right
            0.5f,  0.5f,  0.5f,  1.0f, 0.0f, // bottom-right
            -0.5f,  0.5f,  0.5f,  0.0f, 0.0f, // bottom-left
            -0.5f,  0.5f, -0.5f,  0.0f, 1.0f  // top-left
    };