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:
Related
So I was playing around with an OpenGL project of mine when I noticed something strange. I was drawing multiple meshes to test some shaders but when I ran the code only one of the meshes was rendered.
I stepped through all my code and everything was being called and working correctly. The strangest part was that the two meshes would be drawn independently of each other but never together. After some digging I discovered what happened.
These meshes used different drawing methods. One was a "cube" mesh that was drawn with a VAO and glDrawElementsBaseVertex like so.
void ElementMesh::GenerateBuffers( const std::vector<unsigned short> &pIndices, const std::vector<Vector3<float>> &pVertices, const std::vector<Vector2<float>> pUVs, const std::vector<Vector3<float>> pNormals ) {
glGenVertexArrays( 1, &m_vao );
glBindVertexArray( m_vao );
glGenBuffers( NUM_BUFFERS, m_buffers );
glBindBuffer( GL_ARRAY_BUFFER, m_buffers[ VERTEX_BUFFER ] );
glBufferData( GL_ARRAY_BUFFER, pVertices.size() * sizeof( Vector3<float> ), &pVertices[ 0 ], GL_STATIC_DRAW );
glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 0, 0 );
glEnableVertexAttribArray( 0 );
glBindBuffer( GL_ARRAY_BUFFER, m_buffers[ TEX_COORD_BUFFER ] );
glBufferData( GL_ARRAY_BUFFER, pUVs.size() * sizeof( Vector2<float> ), &pUVs[ 0 ], GL_STATIC_DRAW );
glVertexAttribPointer( 1, 2, GL_FLOAT, GL_FALSE, 0, 0 );
glEnableVertexAttribArray( 1 );
glBindBuffer( GL_ARRAY_BUFFER, m_buffers[ NORMAL_BUFFER ] );
glBufferData( GL_ARRAY_BUFFER, pNormals.size() * sizeof( Vector3<float> ), &pNormals[ 0 ], GL_STATIC_DRAW );
glVertexAttribPointer( 2, 3, GL_FLOAT, GL_FALSE, 0, 0 );
glEnableVertexAttribArray( 2 );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, m_buffers[ INDEX_BUFFER ] );
glBufferData( GL_ELEMENT_ARRAY_BUFFER, pIndices.size() * sizeof( unsigned short ), &pIndices[ 0 ], GL_STATIC_DRAW );
glBindVertexArray( 0 );
}
void ElementMesh::Render() const {
glBindVertexArray( m_vao );
glDrawElementsBaseVertex( GL_TRIANGLES, m_numIndices, GL_UNSIGNED_SHORT, ( void* ) ( sizeof( unsigned short ) * m_baseIndex ), m_baseVertex );
glBindVertexArray( 0 );
}
The code works and draws correctly, I've added it here as an example. The other "cube" mesh was made of just vertices though and is drawn with glDrawArrays like so.
void ArrayMesh::GenerateBuffers( Vector3<GLushort> *pVertex ) {
glBindBuffer( GL_ARRAY_BUFFER, m_vbo );
glBufferData( GL_ARRAY_BUFFER, m_elements * sizeof *vertex, vertex, GL_STATIC_DRAW );
glVertexAttribPointer( 0, 3, GL_UNSIGNED_SHORT, GL_FALSE, 0, 0 );
glEnableVertexAttribArray( 0 );
}
void ArrayMesh::Render() const {
glEnableVertexAttribArray( 0 );
glBindBuffer( GL_ARRAY_BUFFER, m_vbo );
glVertexAttribPointer( 0, 3, GL_UNSIGNED_SHORT, GL_FALSE, 0, 0 );
glDrawArrays( GL_TRIANGLES, 0, m_elements );
glDisableVertexAttribArray( 0 );
}
Rendering...
void Renderer:Render() {
m_shader1->Bind();
m_shader1->UpdateUniforms( m_entity1->GetMVP(), m_entity1->GetTexture() );
m_entity1->GetMesh()->Render();
m_shader2->Bind();
m_shader2->UpdateUnforms( m_entity2->GetMVP(), m_entity2->GetTexture() );
m_entity2->GetMesh()->Render();
}
Like I said, both of these work independently of one another and only fail when used together.
So my question is, can glDrawElements and its other forms be used in conjunction with glDrawArrays and its other forms? And if so, what am I doing incorrectly that mine don't work? Is it the lake of a VAO in the second render?
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 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.
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.