I have a few objects on the scene and even if I specify that the object A have y= 10 (the highest object), from the TOP camera I can see the bottom objects through the object A. Here is an image from my scene.
And only today I found an interesting property that draw order of models matters, I may be wrong. Here is another image where I change the draw order of "ship1", attention: "ship1" is way bellow my scene, if I do ship1.draw(); first, the ship disappears (correct), but if I do ship1.draw(); in last, he appears on top (incorrect).
Video: Opengl Depth Problem video
Q1) Does the draw order always matter?
Q2) How do I fix this, should I change draw order every time I change camera position?
Edit: I also compared my class of Perspective Projection with the glm library, just to be sure that it´s not the problem with my projection Matrix. Everything is correct.
Edit1: I have my project on git: Arkanoid git repository (windows, project is ready to run at any computer with VS installed)
Edit2: I don´t use normals or texture. Just vertices and indices.
Edit3: Is there a problem, if every object on the scene uses(share) vertices from the same file ?
Edit4: I also changed my Perspective Projection values. I had near plane at 0.0f, now I have near=20.0f and far=500.0f, angle=60º. But nothing changes, view does but the depth not. =/
Edit5: Here is my Vertex and Fragment shaders.
Edit6: contact me any time, I am here all day, so ask me anything. At the moment I am rewriting all project from zero. I have two cubes which renders well, one in front of another. Already added mine class for: camera, projections, handler for shaders. Moving to Class which creates and draws objects.
// Vertex shader
in vec4 in_Position;
out vec4 color;
uniform mat4 Model;
uniform mat4 View;
uniform mat4 Projection;
void main(void)
{
color = in_Position;
gl_Position = Projection * View * Model * in_Position;
}
// Fragment shader
#version 330 core
in vec4 color;
out vec4 out_Color;
void main(void)
{
out_Color = color;
}
Some code:
void setupOpenGL() {
std::cerr << "CONTEXT: OpenGL v" << glGetString(GL_VERSION) << std::endl;
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glDepthMask(GL_TRUE);
glDepthRange(0.0, 1.0);
glClearDepth(1.0);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glFrontFace(GL_CCW);
}
void display()
{
++FrameCount;
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
renderScene();
glutSwapBuffers();
}
void renderScene()
{
wallNorth.draw(shader);
obstacle1.draw(shader);
wallEast.draw(shader);
wallWest.draw(shader);
ship1.draw(shader);
plane.draw(shader);
}
I have cloned the repository you have linked to see if the issue was located somewhere else. In your most recent version the Object3D::draw function looks like this:
glBindVertexArray(this->vaoID);
glUseProgram(shader.getProgramID());
glUniformMatrix4fv(this->currentshader.getUniformID_Model(), 1, GL_TRUE, this->currentMatrix.getMatrix()); // PPmat é matriz identidade
glDrawElements(GL_TRIANGLES, 40, GL_UNSIGNED_INT, (GLvoid*)0);
glBindVertexArray(0);
glUseProgram(0);
glClear( GL_DEPTH_BUFFER_BIT); <<< clears the current depth buffer.
The last line clears the depth buffer after each object that is drawn, meaning that the next object drawn is not occluded properly. You should only clear the depth buffer once every frame.
Related
I'm trying to implement a HUD in OpenGL which will display text in 2D on the front of the viewing window and a 3D perspective view behind (similar to a HUD).
I'm creating my 3D fragments using a projectionView matrix then switch to an ortho matrix to render my quads. I've managed to get this to work without the ortho matrix (see below), but for some reason when using the matrix if I draw 3D objects my 2D text disappears, if rendering the text alone it is present
and displays correctly.
Basic rendering loop:
glm::mat4 projection, projectionView, windowMatrix;
projection = glm::perspective(glm::radians(camera.Zoom), 800.0f / 600.0f, 0.1f, 100.0f);
windowMatrix = glm::ortho(0.0f,800.0f,0.0f,600.0f);
while (!glfwWindowShouldClose(window)) //Render loop
{
glm::mat4 view = camera.GetViewMatrix();
projectionView = projection * view;
//Update the Uniform
threeDShader->setMat4("projection", projectionView);
//Render() calls glDrawElements()
threeDObject->Render();
//Update the Uniform
textShader->setMat4("projection", windowMatrix);
//Render params = text, xPos, yPos, scale, color
//RenderText() calls glDrawArrays()
textHUD->RenderText("Hello World!", 25.0f, 25.0f, 1.0f, glm::vec3(0.9, 0.2f, 0.8f));
}
The textShader vertex shader is:
#version 420 core
layout (location = 0) in vec4 vertex; // <vec2 pos, vec2 tex>
out vec2 TexCoords;
uniform mat4 projection;
void main()
{
gl_Position = vec4(vertex.xy * vec2(2.0/800,2.0/600) - vec2(1,1), 0.0f, 1.0f); <----(1)
//gl_Position = projection * vec4(vertex.xy, 0.0f, 1.0f); <----(2)
TexCoords = vertex.zw;
}
The line (1) in the vertex shader code that explicitly states the location on the screen works displaying the text with other 3D objects being in the background.
I would prefer to use line (2) which uses the orthographic matrix (which would be neater to change for the resolution), but for some reason works when no other 3D objects are rendered, but disappears when a 3D object is rendered in the scene. They both use separate matricies then draw their vertices/fragments, so in my opinion they should not be interfering with each other.
The fragment shader is the same for each and should not be an issue. I thought it might be something to do with the near clipping plane for the perspective matrix, but with the independent draw calls it shouldn't be an issue.
I've also tried implementing the ortho matrix with a near and far clipping plane similar to the perspective matrix, but to no success.
but for some reason works when no other 3D objects are rendered
I guess, that threeDObject->Render(); respectively textHUD->RenderText install the shader program by glUseProgram.
glUniform* changes a uniform variable in the default uniform block of the currently installed program.
You've install the shader program before you can change the uniform:
(In the following I suggest, that the sahder program class has a method use(), which installs the program)
while (!glfwWindowShouldClose(window)) //Render loop
{
glm::mat4 view = camera.GetViewMatrix();
projectionView = projection * view;
// Install 3D shader program and update the Uniform
threeDShader->use();
threeDShader->setMat4("projection", projectionView);
//Render() calls glDrawElements()
threeDObject->Render();
// Install text shader program and update the Uniform
textShader->use();
textShader->setMat4("projection", windowMatrix);
//Render params = text, xPos, yPos, scale, color
//RenderText() calls glDrawArrays()
textHUD->RenderText("Hello World!", 25.0f, 25.0f, 1.0f, glm::vec3(0.9, 0.2f, 0.8f));
}
Hi I am doing an assignment and can't figure out how to render a background.
I've drawn the triangles and every thing renders to the screen ok but it always becomes the foreground and blocks everything else from view.
Here is my code for rendering the back ground.
void render(){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(bgShaderID);
glBindVertexArray(bgArrayID);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindVertexArray(0);
// draw everything else
glutSwapBuffers();
glFlush();
}
In my vertex shader I have the following:
in vec3 a_vertex;
in vec3 a_colour;
out vec3 fragmentColor;
void main(){
gl_Position = vec4(a_vertex.xy, 0.0 ,1);
fragmentColor = a_colour;
}
It seems like you have the GL_DEPTH_TEST enabled. I don't know what projection matrix and z values you use for drawing your foreground objects, but
gl_Position = vec4(a_vertex.xy, 0.0 ,1);
is setting clip space z of the background to 0. Assuming a perspecitve projection, this is redicolously close to the front plane. Assuming some prthographic projection, this is still in the middle of the depth range.
You could of course try to set z=1.0 to set it to the far plane in the shader. However, since you draw the background first, you might be better off just disabling the GL_DEPTH_TEST (or disabling depth writes via glDepthMask(GL_FALSE)) temporarily during drawing of your backgorund.
Using QT 4.7 and QGLWidget, I want to use QGLWidget::paintGL() to render a scene into a QGLFramebufferObject and then - using the texture generated by the QGLFramebufferObject - onto the screen. For the second step I render a full-screen quad with an orthographic projection and use an own shader to render the texture onto it.
Rendering into the QGLFramebufferObject seems to work fine (at least I can call QGLFramebufferObject::toImage().save(filename) and I get the correctly rendered image), but I can't get the rendered texture to be drawn onto the screen.
Here the code I use to render into the framebuffer object:
//Draw into framebufferobject
_fbo->bind();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
_camera->applyModelviewMatrix();
_scene->glDraw();
glFlush();
_fbo->release();
_fbo->toImage().save("image.jpg");
As said, the image saved here contains the correctly rendered image.
Here the code I try to render the framebuffer object onto the screen. I'm using an own shader to render it.
//Draw framebufferobject to a full-screen quad on the screen
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0,1.0,0.0,1.0,-1.0,1.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_TEXTURE_2D);
_selectionShader->bind();
glBindTexture(GL_TEXTURE_2D, _fbo->texture());
_selectionShader->setUniformValue("renderedTexture", _fbo->texture());
glBegin(GL_QUADS);
glTexCoord2f(0.0,0.0);
glVertex3f(0.0f,0.0f,0.0f);
glTexCoord2f(1.0,0.0);
glVertex3f(1.0f,0.0f,0.0f);
glTexCoord2f(1.0,1.0);
glVertex3f(1.0f,1.0f,0.0f);
glTexCoord2f(0.0,1.0);
glVertex3f(0.0f,1.0f,0.0f);
glEnd();
glDisable(GL_TEXTURE_2D);
glFlush();
}
The vertex shader simply passes through the position it uses as texture coordinates
varying vec2 position;
void main()
{
gl_Position = ftransform();
position = gl_Vertex.xy;
}
And the fragment shader draws the texture
varying vec2 position;
uniform sampler2D renderedTexture;
void main()
{
gl_FragColor = texture2D(renderedTexture, position);
}
The projection I'm doing is correct, for when I exchange the fragment shader with the following one, it draws the expected color gradient:
varying vec2 position;
uniform sampler2D renderedTexture;
void main()
{
gl_FragColor = vec4(position.x, 0.0f, position.y, 1.0f);
}
But using the other fragment shader that should render the texture, I only get a blank screen (that was made blank by glClear() in the beginning of the rendering). So the fragment shader seems to draw either black or nothing.
Am I missing anything? Am I passing the texture correctly to the shader? Do I have to do anything else to prepare the texture?
_selectionShader->setUniformValue("renderedTexture", _fbo->texture());
This is the (or a) wrong part. A sampler uniform in a shader is not set to the texture object, but to the texture unit that this object is bound as texture to (which you already did with glBindTexture(GL_TEXTURE_2D, _fbo->texture()). So since you seem to use GL_TEXTURE0 all the time, you just have to set it to texture unit 0:
_selectionShader->setUniformValue("renderedTexture", 0);
By the way, no need to glEnable(GL_TEXTURE_2D), that isn't necessary when using shaders. And why use glTexCoord2f if you're just using the vertex position as texture coordinate anyway?
Edit: This turned out to be correct, hopefully it still helps others with similar issues.
Is there a piece I'm missing in setting up the depth testing pipeline in OpenGL ES 2.0 (using EGL)?
I've found many questions about this but all were solved by either correctly setting up the depth buffer on context initialization:
EGLint egl_attributes[] = {
...
EGL_DEPTH_SIZE, 16,
...
EGL_NONE };
if (!eglChooseConfig(
m_eglDisplay, egl_attributes, &m_eglConfig, 1, &numConfigs)) {
cerr << "Failed to set EGL configuration" << endl;
return EGL_FALSE;
}
or by properly enabling and clearing the depth buffer, and doing so after the context has been initialized:
// Set the viewport
glViewport(0, 0, m_display->width(), m_display->height());
// Enable culling and depth testing
glEnable(GL_CULL_FACE);
glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);
// Clear the color and depth buffers
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepthf(1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Draw elements
m_Program->drawAll();
Commenting out the glEnable(GL_DEPTH_TEST) I have a scene but without the depth test occlusion I would love to have.
In a shader, outputting the z component of gl_Position visually works as expected (z values are in the range [0, 1]):
// Vertex Shader
uniform mat4 u_matrix;
attribute vec4 a_position;
varying float v_depth;
void main() {
vec4 v_position = u_matrix * a_position;
v_depth = v_position.z / v_position.w;
gl_Position = v_position;
}
// Fragment shader
varying float v_depth;
void main() {
gl_FragColor = vec4((v_depth < 0.0) ? 1.0 : 0.0,
v_depth,
(v_depth > 1.0) ? 1.0 : 0.0,
1.0);
}
All objects are a shade of pure green, darker for nearer and brighter for further, as expected. Sadly some further (brighter) objects are drawn over nearer (darker) objects.
Any ideas what I'm missing? (If nothing else I hope this summarises some issues others have been having).
It appears I wasn't missing anything. I had a rogue polygon (in a different shader program) that, when depth was enabled occluded everything. The above is a correct setup.
My program was meant to draw a simple textured cube on screen, however, I cannot get it to render anything other than the clear color. This is my draw function:
void testRender() {
glClearColor(.25f, 0.35f, 0.15f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUniformMatrix4fv(resources.uniforms.m4ModelViewProjection, 1, GL_FALSE, (const GLfloat*)resources.modelviewProjection.modelViewProjection);
glEnableVertexAttribArray(resources.attributes.vTexCoord);
glEnableVertexAttribArray(resources.attributes.vVertex);
//deal with vTexCoord first
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,resources.hiBuffer);
glBindBuffer(GL_ARRAY_BUFFER, resources.htcBuffer);
glVertexAttribPointer(resources.attributes.vTexCoord,2,GL_FLOAT,GL_FALSE,sizeof(GLfloat)*2,(void*)0);
//now the other one
glBindBuffer(GL_ARRAY_BUFFER,resources.hvBuffer);
glVertexAttribPointer(resources.attributes.vVertex,3,GL_FLOAT,GL_FALSE,sizeof(GLfloat)*3,(void*)0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, resources.htextures[0]);
glUniform1i(resources.uniforms.colorMap, 0);
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, (void*)0);
//clean up a bit
};
In addition, here is the vertex shader:
#version 330
in vec3 vVertex;
in vec2 vTexCoord;
uniform mat4 m4ModelViewProjection;
smooth out vec2 vVarryingTexCoord;
void main(void) {
vVarryingTexCoord = vTexCoord;
gl_Position = m4ModelViewProjection * vec4(vVertex, 1.0);
};
and the fragment shader (I have given up on textures for now):
#version 330
uniform sampler2D colorMap;
in vec2 vVarryingTexCoord;
out vec4 vVaryingFragColor;
void main(void) {
vVaryingFragColor = texture(colorMap, vVarryingTexCoord);
vVaryingFragColor = vec4(1.0,1.0,1.0,1.0);
};
the vertex array buffer for the position coordinates make a simple cube (with all coordinates a signed 0.25) while the modelview projection is just the inverse camera matrix (moved back by a factor of two) applied to a perspective matrix. However, even without the matrix transformation, I am unable to see anything onscreen. Originally, I had two different buffers that needed two different element index lists, but now both buffers (containing the vertex and texture coordinate data) are the same length and in order. The code itself is derived from the Durian Software Tutorial and the latest OpenGL Superbible. The rest of the code is here.
By this point, I have tried nearly everything I can think of. Is this code even remotely close? If so, why can't I get anything to render onscreen?
You're looking pretty good so far.
The only thing that I see right now is that you've got DEPTH_TEST enabled, but you don't clear the depth buffer. Even if the buffer initialized to a good value, you would be drawing empty scenes on every frame after the first one, because the depth buffer's not being cleared.
If that does not help, can you make sure that you have no glGetError() errors? You may have to clean up your unused texturing attributes/uniforms to get the errors to be clean, but that would be my next step.