0
\$\begingroup\$

My VAO is simply not showing up and i'm not sure if my matrices are wrong or if the shader is wrong… Please have a look a see what is wrong… My code is big so i'll post the essential.

Matrix4 Matrix4::LookAt(Vector3 eye, Vector3 target, Vector3 up)
{
    Vector3 z = Vector3::Normalize(eye - target);
    Vector3 x = Vector3::Normalize(Vector3::Cross(up, z));
    Vector3 y = Vector3::Normalize(Vector3::Cross(z, x));

    Matrix4 result;

    result.row0.x = x.x;
    result.row0.y = y.x;
    result.row0.z = z.x;
    result.row0.w = 0;
    result.row1.x = x.y;
    result.row1.y = y.y;
    result.row1.z = z.y;
    result.row1.w = 0;
    result.row2.x = x.z;
    result.row2.y = y.z;
    result.row2.z = z.z;
    result.row2.w = 0;
    result.row3.x = -((x.x * eye.x) + (x.y * eye.y) + (x.z * eye.z));
    result.row3.y = -((y.x * eye.x) + (y.y * eye.y) + (y.z * eye.z));
    result.row3.z = -((z.x * eye.x) + (z.y * eye.y) + (z.z * eye.z));
    result.row3.w = 1;

    return result;
}

Matrix4 Matrix4::CreatePerspectiveOffCenter(
float left, float right, float bottom, float top,
float near, float far)
{
    float x = 2.0f * near / (right - left);
    float y = 2.0f * near / (top - bottom);
    float a = (right + left) / (right - left);
    float b = (top + bottom) / (top - bottom);
    float c = -(far + near) / (far - near);
    float d = -(2.0f * far * near) / (far - near);

   Matrix4 result;

   result.row0.x = x;
   result.row0.y = 0;
   result.row0.z = 0;
   result.row0.w = 0;
   result.row1.x = 0;
   result.row1.y = y;
   result.row1.z = 0;
   result.row1.w = 0;
   result.row2.x = a;
   result.row2.y = b;
   result.row2.z = c;
   result.row2.w = -1;
   result.row3.x = 0;
   result.row3.y = 0;
   result.row3.z = d;
   result.row3.w = 0;

   return result;
}

Matrix4 Matrix4::CreatePerspectiveFieldOfView(
float fovy, float aspect,
float near, float far)
{
float maxY = near * tanf(0.5f * fovy);
float minY = -maxY;
float minX = minY * aspect;
float maxX = maxY * aspect;

return CreatePerspectiveOffCenter(
    minX, maxX, minY, maxY, near, far);
}


Matrix4 Matrix4::CreateTranslation(Vector3 position)
{
    Matrix4 result = Matrix4::Identity();
    result.row3.x = position.x;
    result.row3.y = position.y;
    result.row3.z = position.z;
    return result;
}

GLfloat* Matrix4::ToGlArray()
{
    GLfloat result[16] =
    {
        row0.x, row0.y, row0.z, row0.w,
        row1.x, row1.y, row1.z, row1.w,
        row2.x, row2.y, row2.z, row2.w,
        row3.x, row3.y, row3.z, row3.w,
    };
    return result;
}

This is How I'm setting up the shader matrices

void MeshRenderer::Render(Shader* shader)
{
    glProgramUniformMatrix4fv(
        shader->GetID(),
        shader->GetUniformLocation("model"),
        1, GL_TRUE,
        GetGameObject()->GetTransform()->
        GetTransformation().ToGlArray());

        mesh->Render(shader);
}


void Camera::Render(Shader *shader)
{

glClearColor(
        backgroundColor.GetR(),
    backgroundColor.GetG(),
    backgroundColor.GetB(),
    backgroundColor.GetA());

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glLoadIdentity();

float aspect = (float)Screen::GetWidth() / (float)Screen::GetHeight();

projection = Matrix4::CreatePerspectiveFieldOfView(
    60 * Mathf::DegreesToRadians(),
    aspect,
    near, far);

view = Matrix4::LookAt(
    GetGameObject()->GetTransform()->GetPosition(),
    GetGameObject()->GetTransform()->GetPosition() +
    GetGameObject()->GetTransform()->GetForward(),
    GetGameObject()->GetTransform()->GetUp());

glProgramUniformMatrix4fv(
    shader->GetID(), 
    shader->GetUniformLocation("view"), 
    1, GL_TRUE, view.ToGlArray());

glProgramUniformMatrix4fv(
    shader->GetID(),
    shader->GetUniformLocation("projection"),
    1, GL_TRUE, projection.ToGlArray());
}

Here is my vertex shader

#version 330 core

layout (location = 0) in vec3 position;
layout (location = 1) in vec2 texCoords;
layout (location = 2) in vec3 normals;

out vec2 TexCoords;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main()
{
    gl_Position = model * view * projection * vec4(position, 1.0);
    TexCoords = texCoords;
}

This is how I'm setting the vao etc...

void Mesh::Entry::SetupEntry()
{
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);

glGenBuffers(1, &VBO1);
glBindBuffer(GL_ARRAY_BUFFER, VBO1);
glBufferData(
    GL_ARRAY_BUFFER, 
    sizeof(float) * vertices.size(),
    &this->vertices[0], 
    GL_STATIC_DRAW);
glVertexAttribPointer(
    0, 3, 
    GL_FLOAT, GL_FALSE,
    sizeof(float) * 3, NULL);
glEnableVertexAttribArray(0);

glGenBuffers(1, &VBO2);
glBindBuffer(GL_ARRAY_BUFFER, VBO2);
glBufferData(
    GL_ARRAY_BUFFER, 
    sizeof(float) * uvs.size(), 
    &this->uvs[0], GL_STATIC_DRAW);
glVertexAttribPointer(
    1, 2, GL_FLOAT, 
    GL_FALSE, sizeof(float) * 2, 
    NULL);
glEnableVertexAttribArray(1);

glGenBuffers(1, &VBO3);
glBindBuffer(GL_ARRAY_BUFFER, VBO3);
glBufferData(
    GL_ARRAY_BUFFER,
    sizeof(float) * normals.size(),
    &this->normals[0], GL_STATIC_DRAW);
glVertexAttribPointer(
    2, 3, 
    GL_FLOAT, GL_FALSE, 
    sizeof(float) * 3, 
    NULL);
glEnableVertexAttribArray(2);

glGenBuffers(1, &VBO4);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, VBO4);
glBufferData(
    GL_ELEMENT_ARRAY_BUFFER, 
    sizeof(unsigned int) * indices.size(),
    &this->indices[0], 
    GL_STATIC_DRAW);

glBindVertexArray(0);
}

EIDT :

void Mesh::Entry::Render(Shader *shader)
{
glBindVertexArray(VAO);
glDrawElements(
    GL_TRIANGLES,
    indices.size(),
    GL_UNSIGNED_INT,
    (void*)0);
glBindVertexArray(0);
}
\$\endgroup\$
5
  • 1
    \$\begingroup\$ Can you show your draw call as well, please? \$\endgroup\$ Jan 19 '20 at 17:28
  • \$\begingroup\$ the question has been edited to show the rendering mtehod \$\endgroup\$ Jan 19 '20 at 17:37
  • \$\begingroup\$ So I tried getting my mtatrices thorugh glm and the mesh is rendering ok…. But i wanted to use my won matrix class…. I think the problema is with ToGlArray() method I'm not sure HOw to correctly build the matrix. And also… i'm not sure if I have to transpose it or not when I pass the matrix to the shader Looking at Matrix4::CreateTranslation Might solve this for anyone who knows better…. I say that the third row is filled with position…. But i think I has to be the the thrid column. So I think it has to be transposed… But still I'm getting no rendering \$\endgroup\$ Jan 19 '20 at 18:23
  • \$\begingroup\$ Could you check if model * view * projection is correct. They are applied from right to left, it makes more sense to me to apply the model transformation first then view then projection. \$\endgroup\$
    – Heckel
    Jan 19 '20 at 20:26
  • 1
    \$\begingroup\$ Verify that the GLFloat pointer that's being returned in the ToGlArray() function is actually valid, because I have a feeling that the result array being locally generated inside the function is going out of scope when the function returns, effectively making the GLFloat pointer invalid. \$\endgroup\$ Jan 20 '20 at 1:38
1
\$\begingroup\$

So as Daniel_1985 pointed out the function was returning an array that was getting out of scope.

So I've changed my method to this:

GLfloat* Matrix4::ToGlArray()
{
    GLfloat* result = new GLfloat[16]
    {
        row0.x, row0.y, row0.z, row0.w,
        row1.x, row1.y, row1.z, row1.w,
        row2.x, row2.y, row2.z, row2.w,
        row3.x, row3.y, row3.z, row3.w,
    };
    return result;
}

EDIT :

For anyone having the same problem the method above is alocating to the heap which a delete cal is necessary. If you don't want to deal with that and possibly have leaks there is a better solution for this:

Matrix4.h

static void ValuePointer(Matrix4 mat, GLfloat* array);

Matrix4.cpp

void Matrix4::ValuePointer(Matrix4 mat, GLfloat* array)
{
    array[0] = mat.M11(); array[1] = mat.M12();
    array[2] = mat.M13(); array[3] = mat.M14();
    array[4] = mat.M21(); array[5] = mat.M22();
    array[6] = mat.M23(); array[7] = mat.M24();
    array[8] = mat.M31(); array[9] = mat.M32();
    array[10] = mat.M33(); array[11] = mat.M34();
    array[12] = mat.M41(); array[13] = mat.M42(); 
    array[14] = mat.M43(); array[15] = mat.M44();
}

And should be used like this :

void MeshRenderer::Render(Shader* shader)
{
    GLfloat array[16];
    Matrix4::ValuePointer(
        GetGameObject()->GetTransform()->
        GetTransformation(), array);

    glProgramUniformMatrix4fv(
        shader->GetID(),
        shader->GetUniformLocation("model"),
        1, GL_FALSE,
        array);

    mesh->Render(shader);
}
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Since this function is called every frame, instantiating a float array might not be the most optimized way of doing it. There's also the issue of potential memory leak(s) if you're not cleaning up the float array after it has been used. Consider generating this array when the actual matrix object is created, inside the matrix object's constructor for example, and then delete it later, when the matrix is destroyed/not used anymore. \$\endgroup\$ Jan 20 '20 at 8:55
  • \$\begingroup\$ In Matrix4::ToGlArray you could also declare static GLfloat result[16], copy the matrix to that, then return it safely. It would mean that you couldn't call ToGlArray twice without consuming the result of the first call in between, however, as the second call would stomp over the result of the first, but otherwise it would work. Personally I'd put it on a per-frame stack-based custom allocator, but that would require you having such a beast to begin with. \$\endgroup\$ Feb 19 '20 at 12:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.