The project I am working on is not working due to “GL_INVALID_OPERATION” error when calling glDrawElements. I am using OpenGL version 4.1
My code:
main.cpp
#include "Window.h"
#include "Renderer.h"
int main() {
Androneder::Window win("Hello World!");
float vertices[] = {
-0.5f, -0.5f, 0.0f, // 0
0.5f, -0.5f, 0.0f, // 1
0.5f, 0.5f, 0.0f // 2
};
unsigned int indices[] = {
0, 1, 2
};
Androneder::VertexBuffer vbo;
Androneder::IndexBuffer ibo;
ibo.CreateBuffer(indices);
vbo.CreateBuffer(vertices);
vbo.AddIBuff(ibo);
vbo.GetVAO().Bind();
ibo.Bind();
std::string vertexShader =
"#version 330 core\n"
"\n"
"layout(location = 0) in vec4 position;\n"
"\n"
"void main()\n"
"{\n"
" gl_Position = position;\n"
"}\n";
std::string fragmentShader =
"#version 330 core\n"
"\n"
"layout(location = 0) out vec4 color;\n"
"\n"
"void main()\n"
"{\n"
" color = vec4(0.0, 0.0, 1.0, 1.0);\n"
"}\n";
Androneder::ShaderProgram shaderProgram;
shaderProgram.CreateShader(vertexShader, fragmentShader);
shaderProgram.Use();
while (!win.ShouldClose()) {
glEnable(GL_SCISSOR_TEST);
glViewport(0, 0, 1280, 920);
glScissor(0, 0, 1280, 920);
glDisable(GL_SCISSOR_TEST);
Androneder::Renderer::ClearSolid(1, 0, 0, 1);
//Androneder::Renderer::Draw(ibo, vbo.GetVAO());
std::cout << glGetError() << std::endl;
glDrawElements(GL_TRIANGLES, ibo.length, GL_UNSIGNED_INT, indices);
win.Poll();
}
ibo.Unbind();
vbo.GetVAO().Unbind();
vbo.Destroy();
return 0;
}
IndexBuffer.cpp
#include "IndexBuffer.h"
namespace Androneder {
void IndexBuffer::CreateBuffer(unsigned int indices[])
{
glGenBuffers(1, &buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_DYNAMIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
length = (sizeof(indices) / sizeof(indices[0])) + 1;
}
void IndexBuffer::ChangeIndices(unsigned int indices[])
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(indices), indices);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
void IndexBuffer::Destroy()
{
glDeleteBuffers(1, &buffer);
}
void IndexBuffer::Bind()
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
}
void IndexBuffer::Unbind()
{
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
}
IndexBuffer.h
#pragma once
#include "glad/glad.h"
#include <iostream>
namespace Androneder {
class IndexBuffer
{
private:
GLuint buffer;
public:
int length;
void CreateBuffer(unsigned int indices[]);
void ChangeIndices(unsigned int indices[]);
const GLuint* GetBuffer() { return &buffer; }
void Destroy();
void Bind();
void Unbind();
};
}
VertexBuffer.h
#pragma once
#include "glad/glad.h"
#include "IndexBuffer.h"
#include "VertexArrayObject.h"
#include <iostream>
#include <vector>
namespace Androneder{
class VertexBuffer
{
private:
std::vector<IndexBuffer> ibuffers;
VertexArrayObject vao;
GLuint buffer;
std::vector<float> currentVertices;
public:
void CreateBuffer(float vertices[]);
void ChangeVertices(float vertices[]);
void AddIBuff(IndexBuffer buff);
void SetIBuffs();
void Bind();
void Unbind();
void Destroy();
VertexArrayObject GetVAO() { return vao; }
};
}
VertexBuffer.cpp
#include "VertexBuffer.h"
namespace Androneder {
void VertexBuffer::CreateBuffer(float vertices[]) {
vao.CreateVAO();
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_DYNAMIC_DRAW);
int bsize = 0;
glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &bsize);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
if (bsize == 0)
{
std::cout << "Vertex buffer is empty\n";
return;
}
std::copy(currentVertices.begin(), currentVertices.end(), vertices);
}
void VertexBuffer::ChangeVertices(float vertices[]) {
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
int bsize = 0;
glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &bsize);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
if (bsize == 0)
{
std::cout << "Vertex buffer is empty\n";
return;
}
std::copy(currentVertices.begin(), currentVertices.end(), vertices);
}
void VertexBuffer::AddIBuff(IndexBuffer buff)
{
ibuffers.push_back(buff);
SetIBuffs();
}
void VertexBuffer::SetIBuffs()
{
vao.Bind();
Bind();
for (int i = 0; i < ibuffers.size(); i++) {
glEnableVertexAttribArray(i);
glVertexAttribPointer(i, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), 0);
}
Unbind();
vao.Unbind();
}
void VertexBuffer::Bind() {
glBindBuffer(GL_ARRAY_BUFFER, buffer);
}
void VertexBuffer::Unbind() {
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void VertexBuffer::Destroy() {
for (IndexBuffer ibo : ibuffers)
{
glDeleteBuffers(1, ibo.GetBuffer());
}
glDeleteBuffers(1, &buffer);
}
}
VertexArrayObject.h
#pragma once
#include "glad/glad.h"
#include <iostream>
namespace Androneder {
class VertexArrayObject
{
private:
GLuint vao;
public:
virtual ~VertexArrayObject();
void CreateVAO();
void Bind();
void Unbind();
};
}
VertexArrayObject.cpp
#include "VertexArrayObject.h"
namespace Androneder {
VertexArrayObject::~VertexArrayObject() {
glDeleteVertexArrays(1, &vao);
}
void VertexArrayObject::CreateVAO() {
glGenVertexArrays(1, &vao);
}
void VertexArrayObject::Bind() {
glBindVertexArray(vao);
}
void VertexArrayObject::Unbind() {
glBindVertexArray(0);
}
}
ShaderProgram.h
#pragma once
#include "glad/glad.h"
#include <iostream>
namespace Androneder{
class ShaderProgram
{
private:
unsigned int program;
public:
void CreateShader(const std::string vertexShader, const std::string fragmentShader);
unsigned int CompileShader(const int type, const std::string source);
void Use();
};
}
ShaderProgram.cpp
#pragma once
#include "glad/glad.h"
#include <iostream>
namespace Androneder{
class ShaderProgram
{
private:
unsigned int program;
public:
void CreateShader(const std::string vertexShader, const std::string fragmentShader);
unsigned int CompileShader(const int type, const std::string source);
void Use();
};
}