I am drawing a frame with pendulums hanging off of it, the pendulums have a texture applied but the frame has no textures. When I display both i get
But when i render only the pendulums they draw correctly and i get
I'm unsure of why this is. I blew the pendulums up and the textures seem to be mapping to the vertices from the frame. Here is the vao decleration
// Create a vertex array object
glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );
// Create and initialize two buffer objects
glGenBuffers( 2, buffers);
//one buffer for the vertices and colours
glBindBuffer( GL_ARRAY_BUFFER, buffers[0]);
glBufferData( GL_ARRAY_BUFFER, numFPointBytes + numVertexColourBytes,NULL, GL_STATIC_DRAW );
glBufferSubData( GL_ARRAY_BUFFER, 0, numFPointBytes, fPoints );
glBufferSubData( GL_ARRAY_BUFFER, numVertexPositionBytes, numVertexColourBytes, frameVertexColours);
//one buffer for the indices
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, buffers[1]);
glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof(frameIndices),frameIndices, GL_STATIC_DRAW );
// set up vertex arrays
GLuint fVPosition = glGetAttribLocation( program, "vPosition" );
glEnableVertexAttribArray( fVPosition );
glVertexAttribPointer( fVPosition, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0) );
GLuint fVColor = glGetAttribLocation( program, "vColor" );
glEnableVertexAttribArray( fVColor );
glVertexAttribPointer( fVColor, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(numVertexPositionBytes) );
glBindVertexArray(0);
glGenVertexArrays( 2, &pVao );
glBindVertexArray( pVao );
// Create and initialize two buffer objects
glGenBuffers( 1, pBuffers);
//glBufferSubData( GL_ARRAY_BUFFER, numPVertexPositionBytes, numPVertexColourBytes, pCols);
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, pBuffers[0]);
glEnableVertexAttribArray(0);
glBufferData( GL_ELEMENT_ARRAY_BUFFER,numPVertexPositionBytes+ numPVertexColourBytes+numTexCoordBytes, NULL, GL_STATIC_DRAW );
glBufferSubData( GL_ARRAY_BUFFER, 0, numPVertexPositionBytes, pendulumVertexPos );
glBufferSubData( GL_ARRAY_BUFFER, numPVertexPositionBytes, numPVertexColourBytes, pCols);
glBufferSubData( GL_ARRAY_BUFFER, numPVertexPositionBytes+numPVertexColourBytes, numTexCoordBytes, texCoords);
// set up vertex arrays
GLuint pVPosition = glGetAttribLocation( program, "vPosition" );
glEnableVertexAttribArray( pVPosition );
glVertexAttribPointer( pVPosition, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0) );
GLuint pVColor = glGetAttribLocation( program, "vColor" );
glEnableVertexAttribArray( pVColor );
glVertexAttribPointer( pVColor, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(numPVertexPositionBytes) );
GLuint vTexCoord = glGetAttribLocation( program, "vTexCoord" );
glEnableVertexAttribArray(vTexCoord);
glVertexAttribPointer( vTexCoord, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(numPVertexPositionBytes+numPVertexColourBytes) );
and the display
void
display( void )
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
modelViewStack.loadIdentity();
modelViewStack.pushMatrix();
glDisable(GL_TEXTURE_2D);
modelViewStack.lookAt(radius*sin(theta)*cos(phi),
radius*sin(theta)*sin(phi),
radius*cos(theta),
0.0,0.0,0.0,
0.0,1.0,0.0);
modelViewStack.rotatef(rotate,0.0,1.0,0.0);
glUniformMatrix4fv(modelView, 1, GL_FALSE, modelViewStack.getMatrixf());
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
glBufferSubData(GL_ARRAY_BUFFER, 0, numVertexPositionBytes, frameVertexPositions );
glBufferSubData( GL_ARRAY_BUFFER, numVertexPositionBytes, numVertexColourBytes, frameVertexColours);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]);
//Indexing into vertices we need to use glDrawElements
glDrawElements(GL_TRIANGLES, NumFIndices, GL_UNSIGNED_BYTE, 0);
modelViewStack.popMatrix();
lineScale = 1.0/8.0;
pendulumScale = 1.0/8.0;
for(int i = 0; i<NumPendulums; i++){
if(!active[i]){
currentTheta[i] = 0.0;
}
modelViewStack.loadIdentity();
modelViewStack.pushMatrix();
glEnable(GL_TEXTURE_2D);
modelViewStack.lookAt(radius*sin(theta)*cos(phi),
radius*sin(theta)*sin(phi),
radius*cos(theta),
0.0,0.0,0.0,
0.0,1.0,0.0);
modelViewStack.scalef(pendulumScale,pendulumScale,pendulumScale);
modelViewStack.rotatef(currentTheta[i],0.0,0.0,1.0);
modelViewStack.rotatef(rotate,0.0,1.0,0.0);
modelViewStack.translatef(dhVals[i][1],dhVals[i][4],0.0);
glUniformMatrix4fv(modelView, 1, GL_FALSE, modelViewStack.getMatrixf());
glBindVertexArray(pVao);
glBindBuffer(GL_ARRAY_BUFFER, pBuffers[0]);
glDrawArrays(GL_TRIANGLES,0,NumPVertices);
glBindVertexArray(0);
glDisable(GL_TEXTURE_2D);
modelViewStack.popMatrix();
modelViewStack.loadIdentity();
modelViewStack.pushMatrix();
modelViewStack.lookAt(radius*sin(theta)*cos(phi),
radius*sin(theta)*sin(phi),
radius*cos(theta),
0.0,0.0,0.0,
0.0,1.0,0.0);
modelViewStack.rotatef(currentTheta[i],0.0,0.0,1.0);
modelViewStack.rotatef(rotate,0.0,1.0,0.0);
modelViewStack.scalef(pendulumScale,lineScale,pendulumScale);
modelViewStack.translatef(dhVals[i][1],0.0,0.0);
glUniformMatrix4fv(modelView, 1, GL_FALSE, modelViewStack.getMatrixf());
glEnableVertexAttribArray(0);
glBindVertexArray(lineVao);
glDrawArrays(GL_LINES,0,NumLVertices);
glBindVertexArray(0);
modelViewStack.popMatrix();
float temp = changeAngle(currentTheta[i], dhVals[i][5], dhVals[i][6], dhVals[i][7], i);
currentTheta[i] = temp;
lineScale+=0.09;
}
projectionStack.loadIdentity();
projectionStack.ortho(-20.0,20.0,-20.0,10.0,-20.0,20.0);
calculateLighting(fPoints,frameVertexColours,NumFSides,6);
calculateLighting(pPoints,pCols,NumPSides,6);
glUniformMatrix4fv(projection, 1, GL_FALSE, projectionStack.getMatrixf());
glutSwapBuffers();
}
Is this a problem with maintaining verteces or is it something else?
I don't see glDisableVertexAttribArray calls in your code. Which would mean, that there's still texture coordinates read from the texcoord buffer. Also you'll have to either unbind the texture or at least use a shader that doesn't read from the texture.
Related
I can render with multiple programs with the following code:
snippet from near end of main loop in main.cpp
. . .
glUseProgram( programID1 );
glEnableVertexAttribArray( 0 );
glBindBuffer( GL_ARRAY_BUFFER, vertuvbuffer[0] );
glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, 20, (void*)0 );
//only needed XY coordinates for the simple 2D I'm making
glEnableVertexAttribArray( 1 );
glBindBuffer( GL_ARRAY_BUFFER, vertuvbuffer[0] );
glVertexAttribPointer( 1, 3, GL_FLOAT, GL_FALSE, 20, (void*)8 );
//the third 'UV' coordinate chooses a tile from my 2d texture array
glDrawArrays( GL_TRIANGLES, 0, sizeof( vertuvbuffer0_data ) / 5 );
//every vertex takes 5 floats, so to get total number I divide by 5
glDisableVertexAttribArray( 0 );
glDisableVertexAttribArray( 1 );
glUseProgram( programID2 );
glEnableVertexAttribArray( 2 );
glBindBuffer( GL_ARRAY_BUFFER, vertuvbuffer[1] );
glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, 20, (void*)0 );
glEnableVertexAttribArray( 3 );
glBindBuffer( GL_ARRAY_BUFFER, vertuvbuffer[1] );
glVertexAttribPointer( 1, 3, GL_FLOAT, GL_FALSE, 20, (void*)8 );
glDrawArrays( GL_TRIANGLES, 0, sizeof( vertuvbuffer1_data ) / 5 );
...
glDisableVertexAttribArray( 2 );
glDisableVertexAttribArray( 3 );
. . .
This is obviously with separate layouts inside the different shaders, what I'm having trouble doing is trying to do this:
. . .
glUseProgram( programID1 );
glEnableVertexAttribArray( 0 );
glBindBuffer( GL_ARRAY_BUFFER, vertuvbuffer[0] );
glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, 20, (void*)0 );
glEnableVertexAttribArray( 1 );
glBindBuffer( GL_ARRAY_BUFFER, vertuvbuffer[0] );
glVertexAttribPointer( 1, 3, GL_FLOAT, GL_FALSE, 20, (void*)8 );
glDrawArrays( GL_TRIANGLES, 0, sizeof( vertuvbuffer0_data ) / 5 );
glDisableVertexAttribArray( 0 );
glDisableVertexAttribArray( 1 );
glUseProgram( programID2 );
glEnableVertexAttribArray( 0 );
glBindBuffer( GL_ARRAY_BUFFER, vertuvbuffer[1] );
glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, 20, (void*)0 );
glEnableVertexAttribArray( 1 );
glBindBuffer( GL_ARRAY_BUFFER, vertuvbuffer[1] );
glVertexAttribPointer( 1, 3, GL_FLOAT, GL_FALSE, 20, (void*)8 );
glDrawArrays( GL_TRIANGLES, 0, sizeof( vertuvbuffer1_data ) / 5 );
...
glDisableVertexAttribArray( 0 );
glDisableVertexAttribArray( 1 );
. . .
The vertex shaders have their respective layout locations.
I'm not sure about how to achieve something similar, if there's no way to do this I would have to write different vertex shaders for every object I want to draw, and I can't imagine that would be the case.
I hope this makes sense, so what can I possibly do at this point?
EDIT:
After digging around in my code I decided to rewrite all ~500 lines of actual code that was my main program. It was simply too broken to rescue, mixed random commenting all over the place and weird behaviours didn't work out for me at all. I also opted to render using VAO's instead of straight up VBO's and glVertexAttribPointer() since that really only worked for one single VAO in my mess of code. Now I can render multiple VBO's (and several VAO's for that matter) using the same program/vertex shader which is the behaviour I wanted.
Using the following code:
Right before linking the program in the shader creation:
glBindAttribLocation( ProgramID, 0, "in_Position" );
//0 being the lication in the shader and
//"in_Position" being the name inside the shader
Before "do while" loop:
. . .
GLuint vao[2];
glGenVertexArrays( 2, vao );
glBindVertexArray( vao[0] );
GLfloat vbo0_data[] = {
// Positions
-1.0f, -1.0f,
1.0f, -1.0f,
0.0f, 1.0f
}
GLuint vbo[2];
glGenBuffers( 2, vbo );
glBindBuffer( GL_ARRAY_BUFFER, vbo[0] );
glBufferData( GL_ARRAY_BUFFER, sizeof( vbo0_data ), vbo0_data, GL_STATIC_DRAW );
glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0 );
glEnableVertexAttribArray( 0 );
glBindVertexArray( vao[1] );
GLfloat vbo1_data[] = {
// Positions
-1.0f, 1.0f,
1.0f, 1.0f,
0.0f, -1.0f
}
glBindBuffer( GL_ARRAY_BUFFER, vbo[1] );
glBufferData( GL_ARRAY_BUFFER, sizeof( vbo1_data ), vbo1_data, GL_STATIC_DRAW );
glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0 );
glEnableVertexAttribArray( 0 );
. . .
Inside drawing loop:
. . .
glClear( GL_COLOR_BUFFER_BIT );
glUseProgram( ProgramID );
glBindVertexArrays( vao[0] );
glDrawArrays( GL_TRIANGLES, 0, 3 );
GlBindVertexArrays( vao[1] );
glDrawArrays( GL_TRIANGLES, 0, 3 );
. . .
The pass-through shaders just writes a half transparent red color that becomes solid red where the triangles intersect, I know I could have put the VAO's inside a loop for drawing but this was more of a proof of concept to show that it worked for me.
Now comes the tedious part of rewriting the rest of my code...
I'm trying to render two different objects on screen. The problem I as far as I can tell is OpenGL is using the wrong Vertex Buffer but the correct Index Buffer, but I'm not too sure about anything I'm currently doing as I've pretty much started learning OpenGL again.
This is what currently gets displayed: http://puu.sh/ekhd7/cca60981ab.jpg
If its a bad idea having classes for objects, or how it should be done, please tell me - I'm going off nothing.
struct point4{
vec4 vertex;
vec4 color;
};
class Pyramid
{
public:
//Variables and Contructor here
void init(){
glGenBuffers( 1, &Arraybufferx );
glBindBuffer( GL_ARRAY_BUFFER, Arraybufferx );
glBufferData( GL_ARRAY_BUFFER, sizeof(point4)*16, NULL, GL_STATIC_DRAW );
glBufferSubData( GL_ARRAY_BUFFER, 0, sizeof(left), left );
glBufferSubData( GL_ARRAY_BUFFER, sizeof(left) , sizeof(right), right );
glBufferSubData( GL_ARRAY_BUFFER, sizeof(left)*2, sizeof(back), back );
glBufferSubData( GL_ARRAY_BUFFER, sizeof(left)*3, sizeof(front), front );
glBufferSubData( GL_ARRAY_BUFFER, sizeof(left)*4, sizeof(bottom), bottom );
glGenBuffers( 1, &IndexBuffer );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, IndexBuffer );
glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof(gIndices), gIndices, GL_STATIC_DRAW );
}
void display(GLint tr,GLint theta, GLfloat rt1[], GLfloat Theta1[]){
glBindBuffer( GL_ARRAY_BUFFER, Arraybufferx );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, IndexBuffer );
glUniform3fv( tr, 1, rt1 );
glUniform3fv( theta, 1, Theta1 );
glDrawElements( GL_TRIANGLES, sizeof(gIndices), GL_UNSIGNED_INT, 0 );
glBindBuffer( GL_ARRAY_BUFFER, 0 );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
}
};
class cube{
public:
//Variables and Contructor here
void init(){
glGenBuffers( 1, &Arraybuffer );
glBindBuffer( GL_ARRAY_BUFFER, Arraybuffer );
glBufferData( GL_ARRAY_BUFFER, sizeof(left)*6, NULL, GL_STATIC_DRAW );
glBufferSubData( GL_ARRAY_BUFFER, 0, sizeof(left), left );
glBufferSubData( GL_ARRAY_BUFFER, sizeof(point4)*4, sizeof(right), right );
glBufferSubData( GL_ARRAY_BUFFER, sizeof(point4)*8, sizeof(top), top );
glBufferSubData( GL_ARRAY_BUFFER, sizeof(point4)*12, sizeof(bottom), bottom );
glBufferSubData( GL_ARRAY_BUFFER, sizeof(point4)*16, sizeof(back), back );
glBufferSubData( GL_ARRAY_BUFFER, sizeof(point4)*20, sizeof(front), front );
glGenBuffers( 1, &IndexBuffer );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, IndexBuffer );
glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof(gIndices), gIndices, GL_STATIC_DRAW );
}
void display(GLint tr,GLint theta, GLfloat rt1[], GLfloat Theta1[]){
glBindBuffer( GL_ARRAY_BUFFER, Arraybuffer );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, IndexBuffer );
glUniform3fv( tr, 1, rt1 );
glUniform3fv( theta, 1, Theta1 );
glDrawElements( GL_TRIANGLES, sizeof(gIndices), GL_UNSIGNED_INT, 0 );
glBindBuffer( GL_ARRAY_BUFFER, 0 );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
}
};
void init()
{
// Create a vertex array object
GLuint vao;
glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );
pyramid.init();
Cube.init();
GLuint program = InitShader( "vshader36.glsl", "fshader36.glsl" );
glUseProgram( program );
GLuint vPosition = glGetAttribLocation( program, "vPosition" );
glEnableVertexAttribArray( vPosition );
GLuint vColor = glGetAttribLocation( program, "vColor" );
glEnableVertexAttribArray( vColor );
model_view = glGetUniformLocation(program, "model_view");
GLuint projection = glGetUniformLocation(program, "projection");
glVertexAttribPointer( vPosition, 4, GL_FLOAT, GL_FALSE, sizeof(point4), 0 );
glVertexAttribPointer(vColor,4,GL_FLOAT,GL_FALSE,sizeof(point4),(void*)sizeof(vec4));
// Create and send the model view matrix
mat4 mv = LookAt(eye, at, up);
glUniformMatrix4fv(model_view, 1, GL_TRUE, mv);
theta = glGetUniformLocation( program, "theta" );
tr = glGetUniformLocation( program, "tr" );
glEnableClientState (GL_VERTEX_ARRAY);
mat4 p = Frustum(-1.0, 1.0, -1.0, 1.0, 10.0, -20.0);
glUniformMatrix4fv(projection, 1, GL_TRUE, p);
glEnable( GL_DEPTH_TEST );
glClearColor( 1.0, 1.0, 1.0, 1.0 );
}
//----------------------------------------------------------------------------
void display( void )
{
mat4 mv = LookAt(eye, at, up);
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glUniformMatrix4fv(model_view, 1, GL_TRUE, mv);
Cube.display(tr,theta,Translate1,Theta);
pyramid.display(tr,theta,Translate2,Theta);
glutSwapBuffers();
}
You misunderstood how Vertex Array Pointers (and VAOs) work. glDraw*() commands never care about the current GL_ARRAY_BUFFER binding. That binding is relevant at the time of the glVertexAtrrib*Pointer() calls - a reference to the currently bound GL_ARRARY_BUFFER becomes part of the attribute pointer. This also means that you can set up each attribute to be fetched from a different buffer.
Consequently, your code will only use the VBO of the cube object, as this is the one that is bound at the time you set vertex attrib pointers.
When you want to draw your different objects, you have to switch
the vertex attrib pointers, so it will look like this:
drawObject() {
glBindBuffer(GL_ARRAY_BUFFER,vbo_for_attr0);
glVertexAttribPointer(0,...);
glBindBuffer(GL_ARRAY_BUFFER,vbo_for_attr1);
glVertexAttribPointer(1,...);
[...]
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glDrawElements(...);
(This is assuming you are using the same attribs for all objects. If this is not the case, you may also have to enable/disable the attrib arrays in this function).
This is where VAOs enter the picture. VAOs are container objects stroing the complete vertex array pointer states for each attribute (including the buffer binding and enable/disable state), and the GL_ELEMENT_ARRAY buffer binding. Conceptually, you can create a VAO per object, and move the vertex pointer setup to yout init() function, reducing the draw code to
drawObject() {
glBindVertexArray(vao);
glDrawElements(...);
So conceptually, it looks like this:
my problem is not properly drawing simple plane;
I dont know why i get once error at begining : Invalid Operation 1282.
Can someone check that?
My variables :
GLfloat *tab for verticies plane
int *tab2 for indecies
this is my init funcion:
// kolor tła - zawartość bufora koloru
glClearColor( 1.0f, 1.0f, 1.0f, 1.0f );
// wczytanie shaderów i przygotowanie obsługi programu
program=LoadShaders("shader.vert","shader.frag" );
//Vertexy
//VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
//Verticies;
glGenBuffers(1, &Verticies);
glBindBuffer(GL_ARRAY_BUFFER, Verticies);
glBufferData( GL_ARRAY_BUFFER,foo*sizeof(GLfloat), tab, GL_STATIC_DRAW );
unsigned int m_ciezarkow[]={0,1,0};
//Indicies
glGenBuffers(1,&Indeksy);
glBindBuffer(GL_ARRAY_BUFFER,Indeksy);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int)*size, tab2, GL_STATIC_DRAW);
glUseProgram( program );
pos_cam=glGetUniformLocation( program, "camera" );
pos_color=glGetUniformLocation( program, "_color" );
glUseProgram(0);
This is my draw function:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(program);
//my camera
glUniformMatrix4fv(pos_cam,1,GL_FALSE,&cam.matrix()[0][0]);
//Verticies
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, Verticies);
glVertexAttribPointer( 0, 3 , GL_FLOAT, GL_FALSE, 0, (void*)0 );
//Masa
//glEnableVertexAttribArray(1);
//glBindBuffer(GL_ARRAY_BUFFER, Masa);
//glVertexAttribPointer( 0, 3 , GL_FLOAT, GL_FALSE, 0, (void*)0 );
//Indicies
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,Indeksy);
glDrawElements(GL_TRIANGLES,size,GL_UNSIGNED_INT,(void*)0);
glUseProgram( 0 );
glDisableVertexAttribArray(0);`
There is a mistake here:
//Indicies
glGenBuffers(1,&Indeksy);
glBindBuffer(GL_ARRAY_BUFFER,Indeksy);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned int)*size, tab2, GL_STATIC_DRAW);
You bind Indeksy as GL_ARRAY_BUFFER, but it should be GL_ELEMENT_ARRAY_BUFFER. With your code, there is probably 0 bound as index buffer, and the glBufferData for that target will fail with GL_INVALID_OPERATION.
I'm pretty new to opengl and I don't really understand what's going on here. I'm trying to use two VAOs to create multiple objects and am using a custom matrix to rotate/translate them. The image is fine when I load up one, but when I load up two they both flicker. My init is this, where I have a different array for each buffer, vertex position, vertex indices and vertex colours.
void init()
{
readFile();
//glEnable(GL_DEPTH);
glEnable( GL_DEPTH_TEST );
//make background yerpul in colour
glClearColor( 0.235, 0.194, 0.314, 1.0 );
// Load shaders and use the resulting shader program
program = InitShader( "aVertexShader61.glsl", "aFragShader61.glsl" );
glUseProgram( program );
// Create a vertex array object
glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );
// Create and initialize two buffer objects
glGenBuffers( 2, buffers);
//one buffer for the vertexPositions and colours
glBindBuffer( GL_ARRAY_BUFFER, buffers[0]);
glBufferData( GL_ARRAY_BUFFER, numVertexPositionBytes + numVertexColourBytes,NULL, GL_STATIC_DRAW );
glBufferSubData( GL_ARRAY_BUFFER, 0, numVertexPositionBytes, vertexPositions );
glBufferSubData( GL_ARRAY_BUFFER, numVertexPositionBytes, numVertexColourBytes, vertexColours);
//one buffer for the indices
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, buffers[1]);
glBufferData( GL_ELEMENT_ARRAY_BUFFER, numVertexIndexBytes,vertexIndicies, GL_STATIC_DRAW );
// set up vertex arrays
GLuint vPosition = glGetAttribLocation( program, "vPosition" );
glEnableVertexAttribArray( vPosition );
glVertexAttribPointer( vPosition, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0) );
GLuint vColor = glGetAttribLocation( program, "vColor" );
glEnableVertexAttribArray( vColor );
glVertexAttribPointer( vColor, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(numVertexPositionBytes) );
// Second object
glGenVertexArrays( 1, &vao2 );
glBindVertexArray( vao2 );
glGenBuffers( 2, buffers2);
//one buffer for the vertexPositions and colours
glBindBuffer( GL_ARRAY_BUFFER, buffers2[0]);
glBufferData( GL_ARRAY_BUFFER, numVertexPositionBytes + numVertexColourBytes,NULL, GL_STATIC_DRAW );
glBufferSubData( GL_ARRAY_BUFFER, 0, numVertexPositionBytes, vertexPositions2 );
glBufferSubData( GL_ARRAY_BUFFER, numVertexPositionBytes, numVertexColourBytes, vertexColours2);
//one buffer for the indices
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, buffers2[1]);
glBufferData( GL_ELEMENT_ARRAY_BUFFER, numVertexIndexBytes,vertexIndicies2, GL_STATIC_DRAW );
// set up vertex arrays
GLuint vPosition2 = glGetAttribLocation( program, "vPosition" );
glEnableVertexAttribArray( vPosition2 );
glVertexAttribPointer( vPosition2, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0) );
GLuint vColor2 = glGetAttribLocation( program, "vColor" );
glEnableVertexAttribArray( vColor2 );
glVertexAttribPointer( vColor2, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(numVertexPositionBytes) );
glBindVertexArray(0);
}
This is my display that gets called with glutPostRedisplay(); in my idle function, no other calls to anything are made from the idle. mStack is a matrix stack object created from an external file
void
display( void )
{
//clear for first object, generate matrix and apply to object
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
mStack.loadIdentity();
mStack.translatef(0,yDisplace,0);
mStack.rotatef(Theta[Yaxis], 0.0,1.0,0.0);
for (unsigned char i=0; i<NumVertices; i++){
mStack.transformf(&vertexPositionsInit[i*4],&vertexPositions[i*4]);
}
//Apply to second object
for (unsigned char i=0; i<NumVertices; i++){
mStack.transformf(&vertexPositionsInit2[i*4],&vertexPositions2[i*4]);
}
//Draw first object
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
glBufferSubData(GL_ARRAY_BUFFER, 0, numVertexPositionBytes, vertexPositions );
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]);
//Indexing into vertices we need to use glDrawElements
glDrawElements(GL_TRIANGLES, NumIndicies, GL_UNSIGNED_BYTE, 0);
glutSwapBuffers();
//Clear and draw second object
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glutSwapBuffers();
glBindVertexArray(vao2);
glBindBuffer(GL_ARRAY_BUFFER, buffers2[0]);
glBufferSubData(GL_ARRAY_BUFFER, 0, numVertexPositionBytes, vertexPositions2 );
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers2[1]);
//Indexing into vertices we need to use glDrawElements
glDrawElements(GL_TRIANGLES, NumIndicies, GL_UNSIGNED_BYTE, 0);
glutSwapBuffers();
}
I'm using simple vertex and fragment shaders.
The vertex shader,
in vec4 vPosition;
in vec4 vColor;
out vec4 color;
void main()
{
gl_Position = vPosition;
color = vColor;
}
And fragment shader,
in vec4 color;
out vec4 fColor;
void main()
{
fColor = color;
}
Any help would be appreciated, and I can post the Matrix file if need be.
Thanks
Don't call glutSwapBuffers() or glClear() in between objects. Swapping buffers is a way to tell GLUT "Okay, I'm done with this frame, let's start with the next one."
Usually you'll want to split out the code that sets up and completes each frame (like the calls to glClear() and glutSwapBuffers()) from the code that renders each object, because OpenGL is basically a gigantic box of global variables and it's hard to write good OpenGL code without breaking your methods up into small pieces.
I'm trying to render a model's UV map by treating its texture coordinates as an array of vertex positions. I set up a VAO for the model which renders perfectly, then tried adding a second VAO and binding the texture coordinate buffer to it. Unfortunately it doesn't render anything.
I've written a second set of vertex and fragment shaders for the UV map which compile just fine. The buffer is bound in the same way as with the model VAO and the vertex attributes set. The only difference I can see is I'm not re-specifying the buffer data.
This is my code for setting up the model VAO:
// Create model VAO
glGenVertexArrays( 1, &modelVAO );
glBindVertexArray( modelVAO );
// Create position buffer
glGenBuffers( 1, &positionBuffer );
glBindBuffer( GL_ARRAY_BUFFER, positionBuffer );
glBufferData( GL_ARRAY_BUFFER, sizeof( GLfloat ) * vertexCount * 4, positions, GL_STATIC_DRAW );
glVertexAttribPointer( 0, 4, GL_FLOAT, GL_FALSE, 0, 0 );
glEnableVertexAttribArray( 0 );
// Create normal buffer
glGenBuffers( 1, &normalBuffer );
glBindBuffer( GL_ARRAY_BUFFER, normalBuffer );
glBufferData( GL_ARRAY_BUFFER, sizeof( GLfloat ) * vertexCount * 3, normals, GL_STATIC_DRAW );
glVertexAttribPointer( 1, 3, GL_FLOAT, GL_FALSE, 0, 0 );
glEnableVertexAttribArray( 1 );
// Create texture coordinate buffer
glGenBuffers( 1, &textureCoordinateBuffer );
glBindBuffer( GL_ARRAY_BUFFER, textureCoordinateBuffer );
glBufferData( GL_ARRAY_BUFFER, sizeof( GLfloat ) * vertexCount * 2, textureCoordinates, GL_DYNAMIC_DRAW );
glVertexAttribPointer( 2, 2, GL_FLOAT, GL_FALSE, 0, 0 );
glEnableVertexAttribArray( 2 );
// Unbind model VAO
glBindVertexArray( 0 );
Then I set up the UV map VAO like this:
// Create new UV map VAO
glGenVertexArrays( 1, &uvMapVAO );
glBindVertexArray( uvMapVAO );
// Bind texture coordinate buffer
glBindBuffer( GL_ARRAY_BUFFER, textureCoordinateBuffer );
glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, 0, 0 );
glEnableVertexAttribArray( 0 );
// Unbind UV map VAO
glBindVertexArray( 0 );
Is it possible to use the same VBO with more than one VAO like this?
Yes. VAOs just store references to VBOs, with the associated data for format, offsets, etc., as specified by glVertexAttribPointer. Index VBOs have slightly different semantics.