-1

I must be overlooking something painfully simple, though I'm unsure as to what it is. This code is comparable to other variants I have written before that have worked just fine. But for some reason, I can't get anything to render on screen. I have even simplified the code back to "hello triangle", but still cannot get anything to display.

I was wondering if anyone would be kind enough to look over my code and offer any insight as to why it is failing. I would greatly appreciate any help on offer.

Definition for Triangle shape data

ShapeData ShapeFactory::MakeTriangle() {

    ShapeData result;

    Vertex t1Verts[] = {
        Vector3(-1.0f,-1.0f, 0.0f),         //0
        Vector3(1.0f,0.0f,0.0f),            //colour
        Vector3(+0.0f, +0.0f, +1.0f),       //normal
        Vector2(0.0f,0.0f),                 //uvCoord
        Vector3(0.0f,1.0f, 0.0f),           //1
        Vector3(0.0f,1.0f,0.0f),            //colour
        Vector3(+0.0f, +0.0f, +1.0f),       //normal
        Vector2(0.0f,0.0f),                 //uvCoord
        Vector3(1.0f, -1.0f, 0),            //2
        Vector3(0.0f,0.0f,1.0f),            //colour
        Vector3(+0.0f, +0.0f, +1.0f),       //normal
        Vector2(0.0f,0.0f)                  //uvCoord
    };

    GLushort  iArr[]{ 0,1,2 };

    result.numVertices = GET_ARRAY_SIZE(t1Verts);
    result.numIndices = GET_ARRAY_SIZE(iArr);

    result.vertices = new Vertex[result.numVertices];
    result.indices = new GLushort[result.numIndices];
    memcpy(result.vertices, t1Verts, sizeof(t1Verts));
    memcpy(result.indices, iArr, sizeof(iArr));

    return result;
}

Shape data is copied a into mesh object and loaded to OpenGL

void Mesh::Load(const ShapeData data)
{
    m_shapeData = data;
    m_drawCount = data.numIndices;
    BufferGeometry();
}

void Mesh::BufferGeometry()
{
    glGenVertexArrays(1, &m_vertexBufferId); // Create a VAO, and assign it's Id
    glBindVertexArray(m_vertexBufferId); //Bind the newly created VAO

    glGenBuffers(BUFFER_COUNT, m_arrayBuffers); //Create Buffers

    //Bind the vertex buffer Id and create buffers within OpenGL
    glBindBuffer(GL_ARRAY_BUFFER, m_arrayBuffers[VERTEX_BUFFER]);
    glBufferData(GL_ARRAY_BUFFER, m_shapeData.GetVertexBufferSize(), &m_shapeData.vertices, GL_STATIC_DRAW);

    glEnableVertexAttribArray(0);   //Attrib pointer for Vertex Position
    glEnableVertexAttribArray(1);   //Attrib pointer for Vertex Colour
    glEnableVertexAttribArray(2);   //Attrib pointer for Vertex Normal
    glEnableVertexAttribArray(3);   //Attrib pointer for Vertex Texture Coord

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, VERTEX_BYTE_SIZE, 0);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, VERTEX_BYTE_SIZE, (char*)(sizeof(float) * 3));
    glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, VERTEX_BYTE_SIZE, (char*)(sizeof(float) * 6));
    glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, VERTEX_BYTE_SIZE, (char*)(sizeof(float) * 9));

    //Bind the index buffer Id and create buffers within OpenGL
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_arrayBuffers[VERTEX_BUFFER]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_shapeData.GetIndexBufferSize(), &m_shapeData.indices, GL_STATIC_DRAW);

    glBindVertexArray(0); //Unbind VAO once we're done.
}

Constants used

static const GLuint NUM_FLOAT_PER_VERT = 11;
static const GLuint VERTEX_BYTE_SIZE = NUM_FLOAT_PER_VERT * sizeof(float);

Draw Methods Shader bind and unbind call glUseProgram(shaderId / 0) respectively. Renderer draw does nothing but clear screen to colour black.

void Game::Draw()
{
    m_display->SwapBuffer();
    m_renderer.Draw();
    m_shader.Bind();
    //m_shader.SetSharderMatrixUniform("transform", m_transform.GetTranslation());
    m_renderer.DrawMesh(m_mesh);
    m_shader.UnBind();
    assert(glGetError() == GL_NO_ERROR);
}

Renderer::Draw

void Renderer::DrawMesh(Mesh& model)
{
    glBindVertexArray(model.GetVertexBufferId());
    glDrawElements(GL_TRIANGLES, model.GetDrawCount(), GL_UNSIGNED_SHORT, 0);
    glBindVertexArray(0);
    assert(glGetError() == GL_NO_ERROR);
}

I believe the Shader is loading & compiling correctly. But, but i'll include the code for that as well.

void Shader::LoadFileData(const string& fileName) {
    const GLchar* charArr[1];
    string filePath = fileName;
    string vertexShader = File::LoadFile("res\\Shaders\\" + filePath + ".vert");
    string fragmentShader = File::LoadFile("res\\Shaders\\" + filePath + ".frag");

    m_shaders[VERTEX_SHADER] = glCreateShader(GL_VERTEX_SHADER);
    m_shaders[FRAGMENT_SHADER] = glCreateShader(GL_FRAGMENT_SHADER);

    charArr[0] = vertexShader.c_str();
    glShaderSource(m_shaders[VERTEX_SHADER], 1, charArr, 0);
    charArr[0] = fragmentShader.c_str();
    glShaderSource(m_shaders[FRAGMENT_SHADER], 1, charArr, 0);

    glCompileShader(m_shaders[VERTEX_SHADER]);
    glCompileShader(m_shaders[FRAGMENT_SHADER]);

    bool bSuccess = (CheckShaderCompileStatus(m_shaders[VERTEX_SHADER]) && CheckShaderCompileStatus(m_shaders[FRAGMENT_SHADER]));

    if (bSuccess) {
        m_programId = glCreateProgram();
        glAttachShader(m_programId, m_shaders[VERTEX_SHADER]);
        glAttachShader(m_programId, m_shaders[FRAGMENT_SHADER]);
        glLinkProgram(m_programId);

        if (!CheckProgramLinkStatus(m_programId))
            return;

        glDeleteShader(m_shaders[VERTEX_SHADER]);
        glDeleteShader(m_shaders[FRAGMENT_SHADER]);
    }
#if DEBUG
    assert(glGetError() == GL_NO_ERROR);
#endif
}

I think the problem is probably within the BufferGeometry method in that the glVertexAttribPointer calls are wrong in some way but I don't see it.

struct Vector3 
{
    float x;
    float y;
    float z;
}

struct Vector2 {
    float x;
    float y;
}

@Vallentin - here is the shader code. It's more or less piping position & colour data straight through from the vertex attribs. Shader code : .frag

#version 430

in vec4 vertColour;
out vec4 fragColour;

void main()
{
    fragColour = vertColour;
}

.vert

#version 430

layout (location=0) in vec3 position;
layout (location=1) in vec3 colour;

out vec4 vertColour;

uniform mat4 transform;

void main(){
    vertColour = vec4(colour,1.0f);
    gl_Position = vec4(position,1.0);
}

2 Answers2

0

If your buffer geometry is "position, color, normal, uv" and repeat for each vertex then the four calls like

glVertexAttribPointer(L, 3, GL_FLOAT, GL_FALSE, VERTEX_BYTE_SIZE, (char*)(sizeof(float) * K));

are wrong.

Take a look at glVertexAttribPointer docs

What you call VERTEX_BYTE_SIZE must be the stride in bytes: (3+3+3+2)* sizeof(float) = 44

To read the buffer from its beginning the last parameter must be 0.

Ripi2
  • 7,031
  • 1
  • 17
  • 33
  • Thanks for the reply. VERTEX_BYTE_SIZE is defined as 11 * sizeof(float) because summing the floats within each data type makes 11. v3 pos v3 colour v3 normal v2 uvCoord 3+3+3+2 = 11... is that wrong? – Andrew McCallum Mar 26 '17 at 20:49
0

Thanks for all your help guys.

It turns out that it WAS something mind-numbingly stupid.

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_arrayBuffers[VERTEX_BUFFER]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_shapeData.GetIndexBufferSize(), &m_shapeData.indices[0], GL_STATIC_DRAW);

Should have been

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_arrayBuffers[INDEX_BUFFER]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_shapeData.GetIndexBufferSize(), &m_shapeData.indices[0], GL_STATIC_DRAW);

I must have looked at that method a thousand times and not seen it.

Thanks anyway :)