I am trying to draw a cube with OPENGL by using EBO, VAO, and VBO.
the first function init the VAO of the cube
initVAO()
{
GLfloat cube_vertices[] = {
// front
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, 1.0, 1.0,
-1.0, 1.0, 1.0,
// back
-1.0, -1.0, -1.0,
1.0, -1.0, -1.0,
1.0, 1.0, -1.0,
-1.0, 1.0, -1.0
};
GLushort cube_elements[] = {
// front
0, 1, 2,
2, 3, 0,
// right
1, 5, 6,
6, 2, 1,
// back
7, 6, 5,
5, 4, 7,
// left
4, 0, 3,
3, 7, 4,
// bottom
4, 5, 1,
1, 0, 4,
// top
3, 2, 6,
6, 7, 3
};
vertices.insert(vertices.begin(), std::begin(cube_vertices), std::end(cube_vertices));
indices.insert(indices.begin(), std::begin(cube_elements), std::end(cube_elements));
/* create vao */
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
/* create ebo */
glGenBuffers(1, &EBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(cube_elements), cube_elements, GL_STATIC_DRAW);
/* create vbo */
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(cube_vertices), cube_vertices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
/* unbind buffers */
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
and the second function use it to draw
draw()
{
shader->activateShader();
/* calculate projection matrix */
//TODO:: find a new place for the projection matrix calculation
int width = (GLfloat)ResourceManager::getInstance()->getWindowSize().x;
int height = (GLfloat)ResourceManager::getInstance()->getWindowSize().y;
glm::mat4 proj = glm::perspective(glm::radians(45.0f), (float)width / height, 0.1f, 100.0f);
/* update shader uniforms*/
glUniformMatrix4fv(shader->projectionUniform, 1, GL_FALSE, glm::value_ptr(proj));
glUniformMatrix4fv(shader->viewUniform, 1, GL_FALSE, glm::value_ptr(Engine::getInstance()->camera->createViewMatrix()));
glUniformMatrix4fv(shader->modelUniform, 1, GL_FALSE, glm::value_ptr(transform->createModleMatrix()));
glUniform4f(shader->colorUniform, color.x, color.y, color.z, 1);
glBindVertexArray(VAO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glUseProgram(0);
}
right now the program is not drawing anything and I cant figure out what is wrong with it
I know that the other parts of the code works because I tested it without a EBO and it worked but I don't know what to do.
See Index buffers. The index buffer binding is stated within the Vertex Array Object. When a buffer is bound to the target ELEMENT_ARRAY_BUFFER, then this buffer is associated to the vertex array object which is currently bound. When calling glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); the binding of the element buffer to the currently bound VAO is broken. Remove this line of code:
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
The type specification in the glDrawElements must match the type of the indices. Since the type of the indexes is GLushort, the specified type must be GL_UNSIGNED_SHORT:
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_SHORT, 0);
Related
I'm working on a old code that used fixed function pipeline, the scene is a bit complex but works fine. For the sake of simplicity, I replaced it with one blue triangle :
void RenduOpenGL::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glViewport(0, 0, this->width(), this->height());
glBegin(GL_TRIANGLES);
glColor3d(0,0,1);
glVertex3d(0.7, 0.7, 0.0);
glVertex3d(-0.5, 0.7, 0.0);
glVertex3d(0.1, -0.7, 0.0);
glEnd();
}
Now I want to add shaders for new elements in the scene but keep the old elements of the scene like this blue triangle.
I've read here that I can mix the two to produce a scene containing the first then the second.
Therefore I want to add this code after the blue triangle :
float vertices[] = {
0.6, 0.6, 0.0,
-0.6, 0.6, 0.0,
0.0, -0.6, 0.0,
};
vbo.create(); // glGenBuffers(...);
vbo.bind(); // glBindBuffer(GL_ARRAY_BUFFER, vbo);
vbo.allocate(vertices, sizeof(vertices)); // glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(float), vertices, GL_STATIC_DRAW);
vbo.release(); // glBindBuffer(GL_ARRAY_BUFFER, 0);
prog.addShaderFromSourceFile(QOpenGLShader::Vertex, "shaders/base.vert");
prog.addShaderFromSourceFile(QOpenGLShader::Fragment, "shaders/base.frag");
vao.create(); // glGenVertexArrays(...)
vao.bind(); // glBindVertexArray(vao);
prog.enableAttributeArray("position"); // glEnableVertexAttribArray(VAO_position);
prog.setAttributeBuffer("position", GL_FLOAT, 0, 3); // (offset, size, stride=0); // glVertexAttribPointer(VAO_position, 4, GL_FLOAT, False, 0, reinterpret_cast<const void *>(offset)(0)); (False,
vao.release(); // glBindVertexArray(0);
// draw the triangle
prog.bind(); // glUseProgram(shader_program);
vao.bind(); // glBindVertexArray(vertex_array_object);
glDrawArrays(GL_TRIANGLES, 0, 3);
vao.release(); // glBindVertexArray(0);
prog.release(); // glUseProgram(0);
I use Qt to call the openGL functions, the corresponding opengl functions are in comments.
My shaders are very basic :
// base.vert
#version 330
// vertex shader
in vec3 position;
void main() {
gl_Position = vec4(position.xyz, 1);
}
// base.frag
#version 330
// fragment shader
out vec4 pixel;
void main() {
pixel = vec4(1, 0.5, 0, 1);
}
That is supposed to draw an orange triangle, but when I put the code after the blue triangle code, I don't see the orange triangle created from shaders.
Short (with code) answer:
The VBO and the prog.enableAttributeArray and prog.setAttributeBuffer should be in the VAO.
Something along the lines:
float vertices[] = {
0.6, 0.6, 0.0,
-0.6, 0.6, 0.0,
0.0, -0.6, 0.0,
};
prog.bind(); // glUseProgram(shader_program);
vao.create(); // glGenVertexArrays(...)
vao.bind(); // glBindVertexArray(vao);
vbo.create(); // glGenBuffers(...);
vbo.bind(); // glBindBuffer(GL_ARRAY_BUFFER, vbo);
vbo.allocate(vertices, sizeof(vertices)); // glBufferData(GL_ARRAY_BUFFER, 9 * sizeof(float), vertices, GL_STATIC_DRAW);
//vbo.release(); // glBindBuffer(GL_ARRAY_BUFFER, 0);
prog.addShaderFromSourceFile(QOpenGLShader::Vertex, "shaders/base.vert");
prog.addShaderFromSourceFile(QOpenGLShader::Fragment, "shaders/base.frag");
prog.enableAttributeArray("position"); // glEnableVertexAttribArray(VAO_position);
prog.setAttributeBuffer("position", GL_FLOAT, 0, 3); // (offset, size, stride=0); // glVertexAttribPointer(VAO_position, 4, GL_FLOAT, False, 0, reinterpret_cast<const void *>(offset)(0)); (False,
vao.release(); // glBindVertexArray(0);
// draw the triangle
prog.bind(); // glUseProgram(shader_program);
vao.bind(); // glBindVertexArray(vertex_array_object);
glDrawArrays(GL_TRIANGLES, 0, 3);
vao.release(); // glBindVertexArray(0);
prog.release(); // glUseProgram(0);
Not so long but textual answer: OpenGL is a state machine, you need to link together: the VBO and how to read its data, inside the VAO. However, IMHO, Qt people have sadly chosen their abstractions poorly: enableAttributeArray and setAttributeBuffer would be clearer as members of the VAO class instead of the prog class.
I want to draw multiple vertex arrays. This is the initialization:
unsigned int va1;
unsigned int vb1;
void init_va1() {
glGenVertexArrays(1, &va1);
glBindVertexArray(va1);
glGenBuffers(1, &vb1);
glBindBuffer(GL_ARRAY_BUFFER, vb1);
glBufferData(GL_ARRAY_BUFFER, 4 * sizeof(vec2), nullptr, GL_DYNAMIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, false, sizeof(vec2), nullptr);
glEnableVertexAttribArray(0);
}
unsigned int va2;
unsigned int vb2;
void init_va2() {
glGenVertexArrays(1, &va2);
glBindVertexArray(va2);
glGenBuffers(1, &vb2);
glBindBuffer(GL_ARRAY_BUFFER, vb2);
glBufferData(GL_ARRAY_BUFFER, 4 * sizeof(vec2), nullptr, GL_DYNAMIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, false, sizeof(vec2), nullptr);
glEnableVertexAttribArray(0);
}
At initialization:
init_va1();
init_va2();
At draw:
glBindVertexArray(va1);
vec2 a1[] = {
vec2(0.0, 0.0),
vec2(0.1, 0.0),
vec2(0.1, 0.1),
vec2(0.0, 0.1),
};
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(a1), a1);
glUniform3f(polygon_color_loc, 0, 1, 0);
glDrawArrays(GL_LINE_LOOP, 0, 4);
glBindVertexArray(va2);
vec2 a2[] = {
vec2(0.0, 0.0),
vec2(-0.1, 0.0),
vec2(-0.1, -0.1),
vec2(0.0, -0.1),
};
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(a2), a2);
glUniform3f(polygon_color_loc, 1, 0, 0);
glDrawArrays(GL_LINE_LOOP, 0, 4);
Whichever vertex array I initialize last will be drawn properly, and the other one will not be drawn. For example, if I call init_va1() and then init_va2(), the drawing using va2 will be shown, and the drawing using va1 will not. If I reorder the calls, then the drawing using va1 will be shown, and the drawing using va2 will not. How do I draw both vertex arrays?
glBufferSubData changes the data of the buffer that is currently bound to the specified target. The current ARRAY_BUFFER is a globale state. you need to bind the proper buffer object when you want to update the data store of the buffer:
glBindBuffer(GL_ARRAY_BUFFER, vb1);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(a1), a1);
glBindVertexArray(va1);
glDrawArrays(GL_LINE_LOOP, 0, 4);
glBindBuffer(GL_ARRAY_BUFFER, vb2);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(a2), a2);
glBindVertexArray(va2);
glDrawArrays(GL_LINE_LOOP, 0, 4);
In contrast to the ARRAY_BUFFER, the Index buffers (ELEMENT_ARRAY_BUFFER) is stated in the Vertex Array Object. If you want to change the contents of an index buffer, it is also possible just to bind the the VAO in which the index buffer is stated.
I'm learning openGL programming from tutorials of Chernov # sparky engine on youtube. currently I have a vertex & a fragment shader with required classes for window ,shader etc management. I can use single vertex array object to draw on screen but when the same is done by creating a vertexArray class , it fails.
vertex array class :
#include"vertexArray.h"
namespace graphics{
VertexArray::VertexArray(){
glGenVertexArrays(1,&arrayID);
}
void VertexArray::addBuffer(Buffer* buffer, GLint index){
bind();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, arrayID);
glEnableVertexAttribArray(index);
glVertexAttribPointer(index, buffer->getComCount(), GL_FLOAT, GL_FALSE, 0, 0);
}
void VertexArray::bind() const{
glBindVertexArray(arrayID);
}
void VertexArray::unbind() const{
glBindVertexArray(0);
}
VertexArray::~VertexArray(){
}
}
my main.cpp file
#include"graphics\window.h"
#include"utils\reader.h"
#include"graphics\shader.h"
#include"math\vec.h"
#include"math\mat4.h"
#include"graphics\buffers\buffer.h"
#include"graphics\buffers\indexbuffer.h"
#include"graphics\buffers\vertexArray.h"
using namespace graphics;
using namespace utils;
using namespace math;
int main(){
Window window;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0, 0, 0, 1);
Reader read1("src/shaders/test.vert");
Reader read2("src/shaders/test.frag");
char * r1 = read1.getData();
char * r2 = read2.getData();
GLfloat vert[] = {
0, 0, 0,
0, 3, 0,
8, 0, 0,
8, 3, 0,
};
Buffer* vbo = new Buffer(vert,4*3,3);
GLushort indices[] = {
0,1,2,
1,3,2
};
indexBuffer ibo(indices,6);
Shader shader(r1, r2);
shader.enable();
#if 0
GLuint sprite1;
glGenVertexArrays(1, &sprite1);
glBindVertexArray(sprite1);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, sprite1);
vbo->bind();
glVertexAttribPointer(0, vbo->getComCount(), GL_FLOAT, 0, 0, 0);
shader.setUniformMat4("pr_matrix", mat4::orthographic(0.0f, 16.0f, 0.0f, 9.0f, -1.0f, 1.0f));
shader.setUniformMat4("ml_matrix", mat4::translation(vec3(0, 0, 0)));
shader.setUniform2f("light_pos", vec2(8.0f, 4.5f));
shader.setUniform4f("colour", vec4(0.2, 0.0, 0.4, 1));
glEnableVertexAttribArray(0);
glBindVertexArray(0);
GLuint sprite2;
glGenVertexArrays(1, &sprite2);
glBindVertexArray(sprite2);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, sprite2);
vbo->bind();
glVertexAttribPointer(5, vbo->getComCount(), GL_FLOAT, 0, 0, 0);
shader.setUniformMat4("pr_matrix", mat4::orthographic(0.0f, 16.0f, 0.0f, 9.0f, -1.0f, 1.0f));
shader.setUniformMat4("ml_matrix", mat4::translation(vec3(4, 3, 0)));
shader.setUniform2f("light_pos", vec2(8.0f, 4.5f));
shader.setUniform4f("colour", vec4(0.3, 0.0, 0.2, 1));
glEnableVertexAttribArray(0);
glBindVertexArray(0);
#endif
VertexArray vao;
vao.addBuffer(vbo, 0);
while (!window.closed()){
#if 0
window.clear();
glDrawArrays(GL_TRIANGLES, 0,6);
#endif
double x, y;
x = window.getX();
y = window.getY();
vao.bind();
ibo.bind();
shader.setUniform2f("light_pos", vec2((float) (x*16.0f/960.0f) , (float) (9- 9*y/540.0f)));
glDrawElements(GL_TRIANGLES, ibo.getCount(), GL_UNSIGNED_SHORT, 0);
window.update();
vao.unbind();
ibo.unbind();
}
return 0;
}
Please note that Everything works if I just create a vertex array to an GLuint variable in the main & use it .
I cant seem to find the issue here.
Any help is highly appreciated ..
You have to bind the data to the buffer (See glBufferData).
Vertex attribute buffers can be created like this:
GLfloat vert[] = {
0, 0, 0,
0, 3, 0,
8, 0, 0,
8, 3, 0,
};
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*3*4, vert, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
Element buffers can be created like this:
GLushort indices[] = {
0,1,2,
1,3,2
};
GLuint ibo;
glGenBuffers(1, &ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort)*3*2, indices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
A Vertex Array Object and the vertex attribute pointers are specified like this:
GLuint attr_index = 0; // attribute index according to the shader program
GLuint vao;
glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(attr_index , 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(attr_index );
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBindVertexArray( 0 );
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
Note, a Vertex Array Object stores all the information which you specify about the vertex attributes (format, size, attribute index ...) and it refers to the element array buffer.
Finally you can draw the mesh like this:
glBindVertexArray( vao );
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
glBindVertexArray( 0 );
I am learning how to texture a quad in OpenGL. The idea is to have the image repeated across the whole quad, nevertheless I am getting the image stretched and the two triangles forming the quad are visible.
What am I missing? The code looks like follows
void GLViewer::initializeGL()
{
float vertices[] =
{
-0.5, 0.0, 0.0,
0.5, 0.0, 0.0,
0.5, 0.5, 0.0
};
// Setup viewport
glViewport(0, 0,this->width(), this->height());
// OpenGL configuration
glClearColor(0.0f,0.0f,0.0f,1.0f);
// Setup shaders
m_triangleShader.addShaderFromSourceFile(QGLShader::Vertex, ":/vshader.glsl");
m_triangleShader.addShaderFromSourceFile(QGLShader::Fragment, ":/fshader.glsl");
m_triangleShader.link();
glGenVertexArrays(1, &m_VAO);
glBindVertexArray(m_VAO);
glPointSize(10);
glGenBuffers(1, &m_VBO);
glBindBuffer(GL_ARRAY_BUFFER, m_VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
float quad[] =
{
-1.0, -1.0,
1.0, -1.0,
-1.0, 1.0,
1.0, 1.0
};
float uv[] =
{
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0
};
m_backgroundShader.addShaderFromSourceFile(QGLShader::Vertex, ":/vbackground.glsl");
m_backgroundShader.addShaderFromSourceFile(QGLShader::Fragment, ":/fbackground.glsl");
m_backgroundShader.link();
glGenVertexArrays(1, &m_backgroundVAO);
glBindVertexArray(m_backgroundVAO);
glGenBuffers(1, &m_quadVBO);
glBindBuffer(GL_ARRAY_BUFFER, m_quadVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(quad), quad, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
glGenBuffers(1, &m_uvVBO);
glBindBuffer(GL_ARRAY_BUFFER, m_uvVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(uv), uv, GL_STATIC_DRAW);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
glGenTextures(1, &m_textureID);
glBindTexture(GL_TEXTURE_2D, m_textureID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
QImage image(":/background.png");
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(),
0, GL_RGBA, GL_UNSIGNED_BYTE, image.bits());
glBindTexture(GL_TEXTURE_2D, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void GLViewer::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDepthMask(GL_TRUE);
glEnable(GL_DEPTH_TEST);
m_backgroundShader.bind();
glBindVertexArray(m_backgroundVAO);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_textureID);
glUniform1i(glGetUniformLocation(m_backgroundShader.programId(),"tex"),0);
glDrawArrays(GL_TRIANGLE_STRIP,0,4);
m_triangleShader.bind();
glBindVertexArray(m_VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
update();
}
Why do you expect your texture to be repeated (and how many times) by the code you are using?
However, the code as-is is consistent with your observation. You are using the texcoords in the range [0,1], so if you are not tweaking the texcoords before sampling the texture, you should only see the image strechted to the quads. You might do that via the shaders you have not pasted so far. If you want the texture to appear n-times tiled along the u dimension and m times along v, you need to use [0,n] for the u range and [0,m] for the v range, respectively.
The second issue is that your texcoords do not match your geometry. This is probably causing what you describe as "the two triangles forming the quad are visible". Your two trianges do not build up the quad in texture space you'd expect, you should swap the last two lines:
float uv[] =
{
0.0, 0.0,
1.0, 0.0,
1.0, 1.0, /* should be 0.0, 1.0 */
0.0, 1.0 /* should be 1.0, 1.0 */
};
I have been playing around with OpenGL for a while now and wanted to get familiar with Vertex Array Objects(VAO's). I am using the cube example here to test with. First of all I verified that I could draw a cube by manually binding the two Vertex Buffers and Element Array Buffer and Vertex Attribs for each call of the render function Here is my code
void Project::initTest(void)
{
GLfloat cube_vertices[] = {
// front
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, 1.0, 1.0,
-1.0, 1.0, 1.0,
// back
-1.0, -1.0, -1.0,
1.0, -1.0, -1.0,
1.0, 1.0, -1.0,
-1.0, 1.0, -1.0,
};
glGenBuffers(1, &vbo[0]);
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(cube_vertices), cube_vertices, GL_STATIC_DRAW);
GLfloat cube_colors[] = {
// front colors
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0,
1.0, 1.0, 1.0,
// back colors
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0,
1.0, 1.0, 1.0,
};
glGenBuffers(1, &vbo[1]);
glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(cube_colors), cube_colors, GL_STATIC_DRAW);
GLushort cube_elements[] = {
// front
0, 1, 2,
2, 3, 0,
// top
3, 2, 6,
6, 7, 3,
// back
7, 6, 5,
5, 4, 7,
// bottom
4, 5, 1,
1, 0, 4,
// left
4, 0, 3,
3, 7, 4,
// right
1, 5, 6,
6, 2, 1,
};
glGenBuffers(1, &ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(cube_elements), cube_elements, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
glBindBuffer(GL_ARRAY_BUFFER,0);
}
And here is the draw function
void Project::drawTest()
{
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glVertexAttribPointer(0, 3,GL_FLOAT,GL_FALSE,0,0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 1);
glVertexAttribPointer(1,3,GL_FLOAT,GL_FALSE,0,0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, 0);
}
The result is a cube as expected.
Using Vertex Array Object
This is my implementation of the buffers being packed into a VAO. The initTest() with the following code:
void Project::initTest()
{
//Upload Vertex Data into VBO's
//Upload Index Data into Element Array Buffer
//...
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER,vbo[0]);//Position Buffer
glBindBuffer(GL_ARRAY_BUFFER,vbo[1]);//Colour Buffer
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,ibo);
glBindVertexArray(0);
//Unbind ARRAY and ELEMENT_ARRAY Buffers like before
}
Then in my draw function I just call the VAO like this
void Project::drawDebug()
{
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES,36, GL_UNSIGNED_SHORT, 0);
glBindVertexArray(0);
}
However the result is this:
Ultimately, I would like to know where I am going wrong with this. I also would like to know if you bind an ELEMENT_ARRAY_BUFFER within the currently bound VAO, do you need to explicity rebind that ELEMENT_ARRAY_BUFFER before calling glDraw* or does the VAO detect that it has an index buffer and renders using indices.
It is going wrong here:
glBindBuffer(GL_ARRAY_BUFFER,vbo[0]);//Position Buffer
glBindBuffer(GL_ARRAY_BUFFER,vbo[1]);//Colour Buffer
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
This has nothing to do with VAOs at all, and would fail without VAOs the same way.
When switching to VAOs, you also seem to have switched from using two separate VBOs for your attributes. You can of course do that, and you could have done it that way without VAOs. But you have to do it correctly: glVertexAttribPointer() will make the currently bound GL_ARRAY_BUFFER part of the attrib pointer, which is vbo[1] in both cases. So you are using the color data as color and position.
However, your original code was also wrong: It did only use the postion data as color and position (which together with the clamping of the color values to the range [0,1] resulted in that asymmetrical coloring you get).
As I side note: whenever you see two GL binding operations for the same binding target right after another, the first one is always useless.
So the correct code would be (if you are acutally using two different VBOs now, which is unclear):
glBindBuffer(GL_ARRAY_BUFFER,vbo[0]);//Position Buffer
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER,vbo[1]);//Colour Buffer
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);