How to create VAO for multiple objects - opengl

I am drawing two triangles using two different VAO.
This is the data set for the triangles.
float TriangleRight[] = {
// positions // Tex Coords // Normals
0.0f , 0.0f , 0.0f , 0.0f,0.0, 1.0, 0.0,0.0,
xWidth , yHeight , 0.0f, 0.0f,0.0, 1.0 , 0.0,0.0,
xWidth , -yHeight ,0.0f, 0.0f,0.0, 1.0 , 0.0,0.0
};
float TriangleLeft[] = {
// positions
0.0f , 0.0f , 0.0f , 0.0f,0.0, 1.0, 0.0,0.0,
-xWidth , yHeight ,0.0f, 0.0f,0.0, 1.0 , 0.0,0.0,
-xWidth , -yHeight ,0.0f, 0.0f,0.0, 1.0 , 0.0,0.0,
};
I define two different VAO objects along with VBO and call both of them for drawing.
glBindVertexArray(m_VAOTriangleRight);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
glBindVertexArray(m_VAOTriangleLeft);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
How can I configure my data so that I can do this in just one VAO object.
This is the rendered output.

Related

How to change buffers for glDrawElements

I am drawing to rectangle using glDrawElements.
glBindVertexArray(m_VAO);
glDrawElements(GL_TRIANGLES, 6 , GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
I want to draw two different geometry one facing the camera and one on the backside.
This is the data for drawing.
verticesRect = {
// Positions // Normal Coords // Texture Coords
(width / 2.0f) + taper, height / 2.0f, 0.0f, 0.0 , 0.0, 1.0 , 1.0f, 0.0f, // Top Right
width / 2.0f, -height / 2.0f, 0.0f, 0.0 , 0.0, 1.0 , 1.0f, 1.0f, // Bottom Right
-width / 2.0f, -height / 2.0f, 0.0f, 0.0 , 0.0, 1.0 , 0.0f, 1.0f, // Bottom Left
(-width / 2.0f) - taper, height / 2.0f, 0.0f, 0.0 , 0.0, 1.0 , 0.0f, 0.0f // Top Left
};
std::vector<float> verticesRectBack = {
// Positions // Normal Coords // Texture Coords
(width / 2.0f) + taper, height / 2.0f, 0.0f, 0.0 , 0.0, -1.0 , 1.0f, 0.0f, // Top Right
width / 2.0f, -height / 2.0f, 0.0f, 0.0 , 0.0, -1.0 , 1.0f, 1.0f, // Bottom Right
-width / 2.0f, -height / 2.0f, 0.0f, 0.0 , 0.0, -1.0 , 0.0f, 1.0f, // Bottom Left
(-width / 2.0f) - taper, height / 2.0f, 0.0f, 0.0 , 0.0, -1.0 , 0.0f, 0.0f // Top Left
};
verticesRect.insert(verticesRect.end(), verticesRectBack.begin(), verticesRectBack.end()); // Combining both the data sets.
This is the VAO , VBO configuration of data.
glGenVertexArrays(1, &m_VAO);
glGenBuffers(1, &m_VBO);
glGenBuffers(1 , &m_EBO);
glBindVertexArray(m_VAO);
glBindBuffer(GL_ARRAY_BUFFER, m_VBO);
glBufferData(GL_ARRAY_BUFFER,verticesRect.size() * sizeof(float), &verticesRect[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indicesTaperRectangle), indicesTaperRectangle, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
This is the data for indices.
GLuint indicesTaperRectangle[] = { // Note that we start from 0!
0, 1, 3, // First Triangle
1, 2, 3 // Second Triangle
};
Currently i am only able to draw the first rectangle how can i draw the second rectangle.
This has nothing to do with buffers. What you're experiencing is back face culling and you can go by with just a single draw call if you disable it using glDisable(GL_CULL_FACE).
Another option is to make your geometry two rectangles, and flip its winding. For that you can reuse the vertex positions and just duplicate and flip the indices:
GLuint indicesTaperRectangle_FrontAndBack[] = {
0, 1, 3,
1, 2, 3,
3, 2, 1,
3, 1, 0
};

opengl glDepthRange object disappearing on Z depth

Lines are dissapearing when z depth increases while rotating the object around x axis by 10 degrees. I edited the glDepthRange value to -100,100 or higher but nothing changes. How can i solve this?
void render()
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
if( gRenderQuad )
{
glBegin( GL_LINE_LOOP );
glVertex3f(0.3f, 0.5f, 0.4f );
glVertex2f( -0.5f, -0.9f );
glVertex2f( 0.5f, -0.5f );
glVertex2f( 0.5f, 0.5f );
glVertex2f( -0.5f, 0.5f );
glEnd();
}
glDepthRange(-100,100);
glEnable(GL_DEPTH_TEST);
}
I edited the glDepthRange value to -100, 100
This is not possible. The values for the depth range must be in [0.0, 1.0]. You can just set a sub range of the range [0.0, 1.0]. See glDepthRange.
If you want to increase the viewing volume, you need to use a projection matrix. An Orthographic projection can be set with glOrtho:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1.0, 1.0, -1.0, 1.0, -100.0, 100.0);
glMatrixMode(GL_MODELVIEW);

How can assign values to a array after initialization

I am initializing an array
float verticesRect[] = {
// Positions // Normal Coords // Texture Coords
width, height, 0.0f, 0.0 , 0.0, 1.0 , 1.0f, 0.0f, // Top Right
width, -height, 0.0f, 0.0 , 0.0, 1.0 , 1.0f, 1.0f, // Bottom Right
-width, -height, 0.0f, 0.0 , 0.0, 1.0 , 0.0f, 1.0f, // Bottom Left
-width, height, 0.0f, 0.0 , 0.0, 1.0 , 0.0f, 0.0f // Top Left
};
after initializing i can again write values to the array using array index operator []
verticesRect[0] = 3;
but to change all the values i would have to go through all the indices , can i do something like this ?
verticesRect = {
// Positions // Normal Coords // Texture Coords
0.0, height, 0.0f, 0.0 , 0.0, 1.0 , 1.0f, 0.0f, // Top Right
0.0, -height, 0.0f, 0.0 , 0.0, 1.0 , 1.0f, 1.0f, // Bottom Right
-10.0, -height, 0.0f, 0.0 , 0.0, 1.0 , 0.0f, 1.0f, // Bottom Left
-10.0, height, 0.0f, 0.0 , 0.0, 1.0 , 0.0f, 0.0f // Top Left
};
You can use std::vector for this.
std::vector<float> verticesRect = {
// Positions // Normal Coords // Texture Coords
width, height, 0.0f, 0.0 , 0.0, 1.0 , 1.0f, 0.0f, // Top Right
width, -height, 0.0f, 0.0 , 0.0, 1.0 , 1.0f, 1.0f, // Bottom Right
-width, -height, 0.0f, 0.0 , 0.0, 1.0 , 0.0f, 1.0f, // Bottom Left
-width, height, 0.0f, 0.0 , 0.0, 1.0 , 0.0f, 0.0f // Top Left
};
verticesRect = {
// Positions // Normal Coords // Texture Coords
width, height, 0.0f, 0.0 , 0.0, 1.0 , 1.0f, 0.0f, // Top Right
width, -height, 0.0f, 0.0 , 0.0, 1.0 , 1.0f, 1.0f, // Bottom Right
-width, -height, 0.0f, 0.0 , 0.0, 1.0 , 0.0f, 1.0f, // Bottom Left
-width, height, 0.0f, 0.0 , 0.0, 1.0 , 0.0f, 0.0f // Top Left
};
In case of c++ you should 100% of the time use an std::vector or even better an std::array if you know the size at compile time. But if you want to stick to using c-style arrays instead, you can do this using pointers and dynamic allocation instead:
float* verticesRect = new float[32]{
// Positions // Normal Coords // Texture Coords
width, height, 0.0f, 0.0 , 0.0, 1.0 , 1.0f, 0.0f, // Top Right
width, -height, 0.0f, 0.0 , 0.0, 1.0 , 1.0f, 1.0f, // Bottom Right
-width, -height, 0.0f, 0.0 , 0.0, 1.0 , 0.0f, 1.0f, // Bottom Left
-width, height, 0.0f, 0.0 , 0.0, 1.0 , 0.0f, 0.0f // Top Left
};
delete verticesRect;
verticesRect = new float[32]{
// Positions // Normal Coords // Texture Coords
0.0, height, 0.0f, 0.0 , 0.0, 1.0 , 1.0f, 0.0f, // Top Right
0.0, -height, 0.0f, 0.0 , 0.0, 1.0 , 1.0f, 1.0f, // Bottom Right
-10.0, -height, 0.0f, 0.0 , 0.0, 1.0 , 0.0f, 1.0f, // Bottom Left
-10.0, height, 0.0f, 0.0 , 0.0, 1.0 , 0.0f, 0.0f // Top Left
};

Textures have one boundary-line repeated

Here is my code that setups texture coords to draw symmetrical quads:
GLfloat defaultTexCoords[] = {
0.0f, 0.0f, // 0 (0,0)
1.0f, 0.0f, // 1 (1,0)
1.0f, 1.0f, // 2 (1,1)
0.0f, 1.0f // 3 (0,1)
};
// VERTEX ARRAY
GLfloat mainVertexArray[] = {
0.0f, 0.0f, // 0 1
0.0f /* size_x */, 0.0f, // 2 3
0.0f /* size_x */, 0.0f /* size_y */, // 4 5
0.0f, 0.0f /* size_y */ // 6 7
};
// VERTEX & TEXTURE INDEXES
GLushort defaultIndices[] = { 0, 1, 3, 2 };
glEnable( GL_TEXTURE_2D );
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
glBindTexture( GL_TEXTURE_2D, m_texId );
glTexCoordPointer( 2, GL_FLOAT, 0, defaultTexCoords );
// Here the cells size_x, size_y, etc. in VERTEX ARRAY
// are overwritten with dimensions of quad to draw
// ... some mainVertexArray[...] = ...
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer(2, GL_FLOAT, 0, mainVertexArray);
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, indices);
The problem is that in the drawed quad, the one, single line at top is basically copied from bottom of the texture. It is clearly visible that brightness of the y=0 line changes the same as the bottom (copied) line.
What can be the problem?
Switch your wrap mode to GL_CLAMP_TO_EDGE.

OpenGL perspective projection and camera location

I am rendering a scene with some map image in OpenGL and using lat, lon of the map as coordinates directly. So my scene does not start at 0,0 and goes up to width, height. Although I can see my polygon (very small), I can't zoom by changing the z-value of the eye in the gluLookAt().
/*
* My boundary for map quad with texture
*/
#define TOP 41.9061
#define BOTTOM 41.8546
#define LEFT -87.7012
#define RIGHT -87.6054
/*
* window size
*/
const unsigned int window_width = 1024;
const unsigned int window_height = 739;
/*
* drawing a polygon with texture
*/
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, mainMapTextureId);
glBegin( GL_POLYGON );
//bottom left
glTexCoord2f( 0.0f, 1.0f );
glVertex3f(LEFT, BOTTOM, 0.0);
//bottom right
glTexCoord2f( 1.0f, 1.0f );
glVertex3f(RIGHT, BOTTOM, 0.0);
//top right
glTexCoord2f( 1.0f, 0.0f );
glVertex3f(RIGHT, TOP, 0.0);
//top left
glTexCoord2f( 0.0f, 0.0f );
glVertex3f(LEFT, TOP, 0.0);
glEnd();
/*
* Setting up the camera
*/
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, (GLfloat)window_width/(GLfloat)window_height, 0.0, 10.0);
gluLookAt( (float)(LEFT+RIGHT)/2.0, (float)(TOP+BOTTOM)/2.0, 1.0,
(float)(LEFT+RIGHT)/2.0, (float)(TOP+BOTTOM)/2.0, 0.0,
0.0f, 1.0f, 0.0f);
It is not legal to have a value of 0.0 for the near plane of gluPerspective. Try replacing it with a nominal small value (0.1f).
Also always put a glGetError call in your code at the end, it will alert you to problems.