Translate Previously Drawn Elements (OpenGL) - c++

How do I transform previously drawn elements? I've drawn a rough 4 million vertices to the screen, and I'd like to translate them after they are drawn. I'd prefer not to redraw them each time I want to translate them (4 million!)
Here is the relevant code.
glOrtho(0, 1024, 0, 576, 0, -4096);
glTranslatef(-512, -288, 512);
glRotatef(45, 1, 0, 0);
glTranslatef(512, 0, -512);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glColor3f(1.F, 1.F, 1.F);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_INT, 0, &vertices[0]);
glDrawElements(GL_QUADS, vertexIndex.size(), GL_UNSIGNED_INT, &vertexIndex[0]);
glDisableClientState(GL_VERTEX_ARRAY);
// I would like to translate here

It is not possible, your vertex positions are internally multiplied with a transformation matrix to get the final position which is drawn on the screen.
So if you try to change the matrix after drawing it doesn't have any effect on the drawn vertices, and its goo that way.
To solve your problem just transform it before drawing... its the standard way, there is no other way to do it.

Related

Unable to draw using glDrawElements correctly

I'm trying to draw a rectangle and apply a texture unto it. The code was copied from a book I'm reading, I just passed to C++(from Java), here it is:
void draw(){
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 4, vertices.data());//vertexSize is 4
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 2, vertices.data() + 2);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices.data());
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
}
the vertices is a std::vector of size 16 and the following values:
[-0.25,-0.25,0.0,0.25,0.25,-0.25,0.25,0.25,0.25,0.25,0.25,0.0,-0.25,0.25,0.0,0.0]
each 4 floats specifies a vertex coord and a texture coord,
and the indices is a std::vector of size 6 with the following values:
[0,1,2,2,3,0]
which specifies two triangles(with textures) in the vertices array.
This two arrays are always set before calling draw.
The problem is that the rendered object is not right, instead of a rectangle I have a trapezium rotated. The vectors seems correct, as I'm new to OpenGL, I've no idea of what is going wrong in this code.
Thank you for your attention.
---EDITED---
The opengl matrices are set right before enter the application loop:
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClearColor(0.0, 1.0, 0.0, 1.0);
glEnable(GL_TEXTURE_2D);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
/*application loop, no more matrices use*/
glVertexPointer(2, GL_FLOAT, 4, vertices.data());//vertexSize is 4
Yes, there are 4 floats per-vertex. But that's not what the fourth parameter is. It's the number of bytes from one position to the next. That's not 4; it's 4 * sizeof(GLfloat).
Also:
glTexCoordPointer(2, GL_FLOAT, 2, vertices.data() + 2);
The second 2 here should also be 4 * sizeof(GLfloat). The byte stride for your array is the same for positions and texture coordinates.

My image keeps disappearing when I add Opengl transformations

My image disappears if I add Opengl transformations.
void renderFileButton()
{
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glViewport(0.0f, 0.0f, SCREEN_WIDTH, SCREEN_HEIGHT);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glPushMatrix();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 320, 0, 240, -1, 1);
glMatrixMode(GL_MODELVIEW);
glGenBuffers(1, &vertexBufferID);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferID);
glBufferData(GL_ARRAY_BUFFER, sizeof(file_vertices), file_vertices,
GL_STATIC_DRAW);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, sizeof(fileButtonVertexData), (GLvoid *)
offsetof(fileButtonVertexData, fileButtonPositionCoordinates));
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, sizeof(fileButtonVertexData), (GLvoid *)
offsetof(fileButtonVertexData, fileButtonTextureCoordinates));
loadsprite("files/sprites/options.png");
glScalef(0, 0, 1);
glRotatef(180, 1, 0, 0);
glTranslatef(0, 0, 0);
glPopMatrix();
}
Could someone tell me where I'm in the wrong here?
You've scaled by zero. That makes the object's size zero. No surprise that it disappears.
In the future, you can troubleshoot by adding one transformation at a time, and trying to add a transformation that doesn't do anything (scale by 1, rotate by 0, translate by 0). Then increase the transformation slowly until you get to your intended value.
Also, your glPopMatrix is undoing all your transformations.
Finally, I don't see any actual rendering. Just a lot of state manipulation.
I found the problem after playing with it all last night. The transformation order was the issue.
glTranslatef(100, 100, 0);
glRotatef(180.0f,0.0f,0.0f,1.0f);
glScalef(-1.0f,1.0f,1.0f);
This does the job, that is all.

A cube is rendered as a square in QGLWidget

I've been trying to render a cube in a QGLWidget, but it comes out wrong. No matter how I rotate it, it looks like a flat square. It's like it didn't notice the Z coordinates of its vertices. Just before I added clearing of the GL_DEPTH_BUFFER_BIT, the square looked like all of the cube's sides crammed into one. Now it seems to discard vertices which don't belong in the front side, but it still isn't a cube.!
Screenshots [link]
My initializeGL() and paintGL():
typedef struct
{
float XYZW[4];
float RGBA[4];
} Vertex;
Vertex Vertices[8] =
{
//vertices
};
const GLubyte Indices[36] =
{
//indices
};
void ModelView::initializeGL()
{
m_program = new QGLShaderProgram(this);
m_program->addShaderFromSourceCode(QGLShader::Vertex, vertexShaderSource);
m_program->addShaderFromSourceCode(QGLShader::Fragment, fragmentShaderSource);
m_program->link();
}
void ModelView::paintGL()
{
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glClearColor(.5f, .5f, .5f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0, 0, width(), height());
m_program->bind();
QMatrix4x4 matrix;
matrix.perspective(60, 4.0/3.0, 0.1, 100.0);
matrix.translate(0, 0, -2);
matrix.rotate(50.0, 1, 1, 1);
m_program->setUniformValue(m_matrixUniform, matrix);
m_posAttr = m_program->attributeLocation("posAttr");
m_colAttr = m_program->attributeLocation("colAttr");
m_matrixUniform = m_program->uniformLocation("matrix");
glGenBuffers(1, &BufferId);
glGenBuffers(1, &IndexBufferId);
glBindBuffer(GL_ARRAY_BUFFER, BufferId);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBufferId);
glBufferData(GL_ARRAY_BUFFER, BufferSize, Vertices, GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices), Indices, GL_STATIC_DRAW);
glVertexAttribPointer(m_posAttr, 2, GL_FLOAT, GL_FALSE, VertexSize, 0);
glVertexAttribPointer(m_colAttr, 3, GL_FLOAT, GL_FALSE, VertexSize, (GLvoid *)RgbOffset);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, NULL);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(0);
m_program->release();
}
Vertices and Indices should be defined correctly, they're taken from a tutorial, as is most of the code. Rendering of 2D object seems to be just fine, though.
Also, why does the tutorial call matrix.translate with the -2 argument? If I change it to anything else greater than 1 or remove it, the rendered object disappears.
Qt5, Windows Vista 32-bit.
Also, why does the tutorial call matrix.translate with the -2
argument? If I change it to anything else greater than 1 or remove it,
the rendered object disappears.
This is due to clipping. When you render objects, things that are "too close" or "too far" are discarded, via the near and far clipping planes (respectively).
By moving the cube closer (changing -2 to 1 or 0), you are bringing the cube forward, past the near clipping plane, and it consequently disappears.
glVertexAttribPointer() has a size parameter, which specifies the number of components per vertex. In the code it is 2, therefore everything is 2D. Changing to 3 solves the issue.

Opengl weird viewing

As you can see from the images below, I have two triangles side by side (viewed from front). But when I view it from the right, the yellow triangle shows as if it is in front of the green triangle where it should not be visible because it is behind the green one (see right view), why is this happening? Viewing it from the left is fine (see left view). Thanks.
FrontView:
Right View (why is the yellow triangle is still visible?):
Left view (viewing from here is fine):
This is my render method. Even though I don't use glColor4f and do the coloring in a modern way, I still have the same result. I have also set glEnable(GL_DEPTH); and
glDepthFunc(GL_LESS);
void display(){
glClear(GL_COLOR_BUFFER_BIT);
control(0.2, 0.2, mi);
view = updateCam();
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableClientState(GL_VERTEX_ARRAY);
model = glm::rotate(glm::mat4(1.0), 45, glm::vec3(0, 1, 0));
glColor4f(0, 1, 0, 1);
glDrawArrays(GL_TRIANGLES, 0, 3);
resetMatrix();
model = glm::translate(glm::mat4(1.0), glm::vec3(5, 0, 0));
model = glm::rotate(model, 45, glm::vec3(0, 1, 0));
glColor4f(1, 1, 0, 1);
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(0);
resetMatrix();
SDL_GL_SwapBuffers();
}
You're only clearing your color buffer. The depth buffer still contains the depth values from previous frames, so your Z-test doesn't work as intended.
Clear them both:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

How do you handle multiple textures in an OpenGL indexed buffer array for use with a data-shader?

I'm attempting to implement this paper. I've have most of it down, but the part about sending arbitrary, non-geometric data to the shader for use in determining and displaying geometric edges is causing me problems. I've managed to successfully send most of my data just fine using what I know of VBOs. However, I need to send a large amount of data, which necessitates the use of multiple texture coordinates.
I've already implemented several variations of what I believe to be the correct way of setting up multiple sets of texture coordinates, and followed the instructions of many forum posters. No solutions work thus far.
For context, the program is sending 4 nearly identical copies of a set of 4 vertices, 2 normal vectors, a float, and an integer (stored as a float) for each unique edge in the model. I've laid out the data like this:
v0 is stored in gl_Vertex (vec3)
v1 is stored in gl_Color (vec3)
v2 is stored in gl_MultiTexCoord0 (vec3)
v3 is stored in gl_MultiTexCoord1 (vec3)
n0 is stored in gl_Normal (vec3)
n1 is stored in gl_SecondaryColor (vec3)
r and i are stored in gl_MultiTexCoord2 (vec2)
The only difference between the 4 copies is the i value, which helps determine how to organize the vertices if and when a drawable edge is found.
As you can see, I need at least 3 texture coordinates. I was able to get the first one working (gl_MultiTexCoord0) just fine, but any following texture coordinates, though on the graphics card, appear to have uncontrollable behavior, sometimes working, but usually not.
My rendering function used to look like this:
void Mesh::RenderLineEdgesGPU()
{
// Enable client state
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_SECONDARY_COLOR_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
// Turn on edge shader
edgeProgram.Activate();
// Link buffers
// v0
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[0]);
glVertexPointer(3, GL_FLOAT, 0, 0);
// v1
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[1]);
glColorPointer(3, GL_FLOAT, 0, 0);
// v2
glClientActiveTextureARB(GL_TEXTURE0_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[2]);
glTexCoordPointer(3, GL_FLOAT, 0, 0);
// v3
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[3]);
glTexCoordPointer(3, GL_FLOAT, 0, 0);
// n0
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[4]);
glNormalPointer(GL_FLOAT, 0, 0);
// n1
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[5]);
glSecondaryColorPointer(3, GL_FLOAT, 0, 0);
// r and i
glClientActiveTextureARB(GL_TEXTURE2_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[6]);
glTexCoordPointer(2, GL_FLOAT, 0, 0);
// Indicies
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, edgeMeshHandles[7]);
// Draw
glDrawElements(GL_POINTS, EdgeVertexQuantity, GL_UNSIGNED_INT, 0);
// Turn off edge shader
edgeProgram.Deactivate();
// Disable client state
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
This was my original one. It definitely works for v0, v1, and v2. It appears to work for "r and i", but that could be an illusion. I don't have the ability to test n0 or n1 yet. v3 definitely DOES NOT work. As you can see, I'm drawing them as points, which tells me if they are there or not (via the shader). v0, v1, and v2 are all there. Attempting to do the same for v3 yields either a single point at the origin or nothing at all.
After looking at suggestions online, here's my new setup:
void Mesh::RenderLineEdgesGPU()
{
// Enable client state
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_SECONDARY_COLOR_ARRAY);
// Turn on edge shader
edgeProgram.Activate();
// Link buffers
// v0
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[0]);
glVertexPointer(3, GL_FLOAT, 0, 0);
// v1
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[1]);
glColorPointer(3, GL_FLOAT, 0, 0);
// v2
glClientActiveTextureARB(GL_TEXTURE0_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glActiveTextureARB(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[2]);
glTexCoordPointer(3, GL_FLOAT, 0, 0);
glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
// v3
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glActiveTextureARB(GL_TEXTURE1_ARB);
glEnable(GL_TEXTURE_2D);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[3]);
glTexCoordPointer(3, GL_FLOAT, 0, 0);
glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
// n0
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[4]);
glNormalPointer(GL_FLOAT, 0, 0);
// n1
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[5]);
glSecondaryColorPointer(3, GL_FLOAT, 0, 0);
// r and i
glClientActiveTextureARB(GL_TEXTURE2_ARB);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, edgeMeshHandles[6]);
glTexCoordPointer(2, GL_FLOAT, 0, 0);
// Indicies
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, edgeMeshHandles[7]);
// Draw
glDrawElements(GL_POINTS, EdgeVertexQuantity, GL_UNSIGNED_INT, 0);
// Turn off edge shader
edgeProgram.Deactivate();
// Disable client state
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
}
Notice how I've done the glEnableClientState / glDisableClientState calls around the actual "loading" of each texture coordinate list. I also use glActiveTextureARB and glEnable(GL_TEXTURE_2D). While I think I might understand why glActiveTextureARB is needed here, the other one baffles me. According to the GLSL Common Mistakes page, you're not supposed to use glEnable(GL_TEXTURE_2D) when you make your own shaders, since the use of shaders ignores this call anyway.
So that's it. I've gotten this far without being able to find any tutorials specifically addressing how to send non-texture coordinate data in texture coordinates. Perhaps if someone knows a tutorial on that, my problem would be alleviated. Thanks for your time!
glClientActiveTextureARB changes which specific texture coordinate unit following calls to glEnableClientState(GL_TEX_COORD_ARRAY) and glTexCoordPointer will alter.
glActiveTextureARB affects glEnable(GL_TEXTURE_2D), which, as you mentioned, you don't need for shaders.
If you look at your code closely, picking only those 5 calls (and their equivalent Disable), here is what you have:
glClientActiveTextureARB(GL_TEXTURE0_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glActiveTextureARB(GL_TEXTURE0_ARB);
glEnable(GL_TEXTURE_2D);
glTexCoordPointer(3, GL_FLOAT, 0, 0);
glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glActiveTextureARB(GL_TEXTURE1_ARB);
glEnable(GL_TEXTURE_2D);
glTexCoordPointer(3, GL_FLOAT, 0, 0);
glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTextureARB(GL_TEXTURE2_ARB);
glTexCoordPointer(2, GL_FLOAT, 0, 0);
glDrawElements(GL_POINTS, EdgeVertexQuantity, GL_UNSIGNED_INT, 0);
Ok, we already said that glActiveTextureARB and glEnable are not useful (by the way, you enable/disable GL_TEXTURE_2D without any draw in between, that's not useful), so remove them:
glClientActiveTextureARB(GL_TEXTURE0_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(3, GL_FLOAT, 0, 0);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(3, GL_FLOAT, 0, 0);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTextureARB(GL_TEXTURE2_ARB);
glTexCoordPointer(2, GL_FLOAT, 0, 0);
glDrawElements(GL_POINTS, EdgeVertexQuantity, GL_UNSIGNED_INT, 0);
What stands out now ? 2 issues:
You Disable your client state before ever executing Draw
You don't set the Enable bit for TEXTURE2
What should you write ? Something along those lines: (Beware, you'll need to add the BindBuffer calls back to each Pointer call):
// texture coord 0
glClientActiveTextureARB(GL_TEXTURE0_ARB); // program texcoord unit 0
glEnableClientState(GL_TEXTURE_COORD_ARRAY); // enable array data to shader
glTexCoordPointer(3, GL_FLOAT, 0, 0); // say what data
// texture coord 1
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(3, GL_FLOAT, 0, 0);
// texture coord 2
glClientActiveTextureARB(GL_TEXTURE2_ARB);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 0, 0);
glDrawElements(GL_POINTS, EdgeVertexQuantity, GL_UNSIGNED_INT, 0);
// done with those texcoord units, turn them off
glClientActiveTextureARB(GL_TEXTURE0_ARB);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTextureARB(GL_TEXTURE1_ARB);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glClientActiveTextureARB(GL_TEXTURE2_ARB);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
Some more comments on BindBuffer: glBindBufferARB(GL_ARRAY_BUFFER_ARB,...) does not get affected by the glClientActiveTextureARB, but it does affect the next glTexCoordPointer call. In essence, think of glClientActiveTextureARB and glBindBufferARB as providing extra arguments to glTexCoordPointer.
Last thing, you probably want to group some of those VBOs in less buffers. Something for another question maybe ? (Hint, the 2 arguments to glTexCoordPointer don't have to be 0)