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);
}