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);
Related
I am trying to display a sphere and a torus on the same screen, but it seems like the "glutInitDisplayMode" is what is causing me to display only one.
When I keep it as glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA |GLUT_DEPTH) the torus displays.
When I keep it as glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH) the sphere displays. What can I do to display both?
The render code is below:
static void render(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
// clear the drawing buffer.
glClear(GL_COLOR_BUFFER_BIT);
// clear the identity matrix.
glLoadIdentity();
glTranslatef(0.0, 0.0, -5.0);
glColor3f(0.0, 0.0, 0.0);
glRotatef(zRotated, 0.0, 0.0, 1.0);
// scaling transfomation
glScalef(1.0, 1.0, 1.0);
// built-in (glut library) function , draw you a sphere.
glutSolidTorus(innerRadius, outerRadius, sides, rings);
// Flush buffers to screen
glFlush();
// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// activate our shader program
glUseProgram(programId);
// turn on depth buffering
glEnable(GL_DEPTH_TEST);
float aspectRatio = (float)width / (float)height;
glm::mat4 projection = glm::perspective(glm::radians(45.0f), aspectRatio, 0.1f, 1000.0f);
// view matrix - orient everything around our preferred view
glm::mat4 view = glm::lookAt(
glm::vec3(40,30,30), // eye/camera location
glm::vec3(0,0,0), // where to look
glm::vec3(0,1,0) // up
);
// model matrix: translate, scale, and rotate the model
glm::vec3 rotationAxis(0,1,0);
glm::mat4 model = glm::mat4(1.0f);
model = glm::rotate(model, glm::radians(angle), glm::vec3(0, 1, 0)); // rotate about the y-axis
model = glm::scale(model, glm::vec3(25.0f, 25.0f, 25.0f));
// model-view-projection matrix
glm::mat4 mvp = projection * view * model;
GLuint mvpMatrixId = glGetUniformLocation(programId, "MVP");
glUniformMatrix4fv(mvpMatrixId, 1, GL_FALSE, &mvp[0][0]);
// texture sampler - a reference to the texture we've previously created
// send the texture id to the texture sampler
GLuint textureUniformId = glGetUniformLocation(programId, "textureSampler");
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureId);
glUniform1i(textureUniformId, 0);
// find the names (ids) of each vertex attribute
GLint positionAttribId = glGetAttribLocation(programId, "position");
GLint colourAttribId = glGetAttribLocation(programId, "colour");
GLint textureCoordsAttribId = glGetAttribLocation(programId, "textureCoords");
GLint normalAttribId = glGetAttribLocation(programId, "normal");
// provide the vertex positions to the shaders
glBindBuffer(GL_ARRAY_BUFFER, positions_vbo);
glEnableVertexAttribArray(positionAttribId);
glVertexAttribPointer(positionAttribId, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
// provide the vertex texture coordinates to the shaders
glBindBuffer(GL_ARRAY_BUFFER, textureCoords_vbo);
glEnableVertexAttribArray(textureCoordsAttribId);
glVertexAttribPointer(textureCoordsAttribId, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
// provide the vertex normals to the shaders
glBindBuffer(GL_ARRAY_BUFFER, normals_vbo);
glEnableVertexAttribArray(normalAttribId);
glVertexAttribPointer(normalAttribId, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
// draw the triangles
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glDrawElements(GL_TRIANGLES, numVertices, GL_UNSIGNED_INT, (void*)0);
// disable the attribute arrays
glDisableVertexAttribArray(positionAttribId);
glDisableVertexAttribArray(textureCoordsAttribId);
glDisableVertexAttribArray(normalAttribId);
glDisableVertexAttribArray(colourAttribId);
// make the draw buffer to display buffer (i.e. display what we have drawn)
glutSwapBuffers();
}
glutSolidTorus draws a torus, by the use of the fixed function attributes. For this a compatibility profile OpenGL Context indispensable.
glutSolidTorus is not compatible with you shader program. Invalidate the currently installed program, before glutSolidTorus:
glUseProgram(0);
glutSolidTorus(innerRadius, outerRadius, sides, rings);
Note, OpenGL is a state engine. If a program is installed, it is kept, until another program is installed or it is invalidated, even beyond frames. In you case is is not an issue in the first frame, but it would be still installed at the begin of the 2nd frame, when glutSolidTorus is called.
If you are use a double buffered window (GLUT_DOUBLE) you have to call glutSwapBuffers. glutSwapBuffers swaps the buffers. The buffer in which was drawn, is shown in the window. The buffer which was show int eh window is prepared for drawing in the next frame.
In a single buffered window you can do glFlush. This forces OpenGL to finish drawing. Since the buffer which is draw to is the same, which is shown on the window, this causes that all what is drawing to the buffer is immediately shown in the window.
Move the singe glFlush call form the middle of the render function to its end, right before glutSwapBuffers:
void render()
{
// ...
glUseProgram(0);
glutSolidTorus(innerRadius, outerRadius, sides, rings);
// glFlush(); <---- delete
// ...
glUseProgram(programId);
// ...
glDrawElements(GL_TRIANGLES, numVertices, GL_UNSIGNED_INT, (void*)0);
// ...
glFlush();
glutSwapBuffers();
}
I'm using opengl, glfw and glew. I want to rotate the tip of the spaceship without moving the whole spaceship when users press on the left and right arrow respectively. I've tried using gltransform glrotate, it does rotate but it also move my spaceship along. The output of the movement of spaces
objects objects::rotateSpaceship(GLFWwindow * window, objects & sp)
{
GLfloat spaceship_angle = sp.getAngle();
GLfloat newAngle = sp.getAngle() + 0.5;
sp.setAngle(newAngle);
while (!glfwWindowShouldClose(window))
{
glClear(GL_COLOR_BUFFER_BIT);
GLfloat spaceShipRightLine[] =
{
x, y + 80, 0,
x - 50, y - 50, 0
};
GLfloat spaceShipLeftLine[] = {
x, y + 80, 0,
x + 50, y - 50, 0
};
GLfloat spaceShipMiddleLine[] = {
sp.x - 30 ,sp.y,0,
sp.x + 35,sp.y,0
};
glPushMatrix();
glTranslatef(0.0, 0.01, 0.0); // 3. Translate to the object's position.
glRotatef(sp.getAngle(), 0.0, 0.0, 1.0); // 2. Rotate the object.
glTranslatef(0.0, 0.01, 0.0); // 1. Translate to the origin.
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, spaceShipRightLine);
glDrawArrays(GL_LINES, 0, 2);
glDisableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, spaceShipLeftLine);
glDrawArrays(GL_LINES, 0, 2);
glDisableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, spaceShipMiddleLine);
glDrawArrays(GL_LINES, 0, 2);
glDisableClientState(GL_VERTEX_ARRAY);
glPopMatrix();
// Swap front and back buffers
glfwSwapBuffers(window);
// Poll for and process events
glfwPollEvents();
}
glfwTerminate();
return sp;
}
Note, that drawing by glBegin/glEnd sequences and the fixed function matrix stack is deprecated since decades.
Read about Fixed Function Pipeline and see Vertex Specification and Shader for a state of the art way of rendering.
I want to rotate the tip of the spaceship without moving the whole spaceship [...]
First you have to define the pivot, which is the "tip" of the spaceship:
float pivot_x = sp.x;
float pivot_y = sp.y + 80.0f;
To rotate around a pivot you have to define a model matrix, which displaces by the inverted pivot, then rotate (glRotatef) and final transforms back by to the pivot (glTranslate):
glTranslatef(pivot_x, pivot_y, 0);
glRotatef(angle, 0, 0, 1);
glTranslatef(-pivot_x, -pivot_y, 0);
The final code may look like that:
float pivot_x = x;
float pivot_y = y + 80.0f;
glPushMatrix();
glTranslatef(pivot_x, pivot_y, 0 ); // 3. Translate to the object's position.
glRotatef(sp.getAngle(), 0.0, 0.0, 1.0); // 2. Rotate the object.
glTranslatef(-pivot_x, -pivot_y, 0.0); // 1. Translate to the origin.
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, spaceShipRightLine);
glDrawArrays(GL_LINES, 0, 2);
glDisableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, spaceShipLeftLine);
glDrawArrays(GL_LINES, 0, 2);
glDisableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, spaceShipMiddleLine);
glDrawArrays(GL_LINES, 0, 2);
glDisableClientState(GL_VERTEX_ARRAY);
glPopMatrix();
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.
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.
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.