PDA

View Full Version : Depth testing for multiple objects



Blizzard_jedi
05-04-2014, 03:44 PM
Hello everybody. I'm pretty new to OpenGL and my question is definitely a simple one. Anyway, I've already spent about two days trying to find the answer. So I will be grateful, if someone could help me...

I've created a simple scene and placed several objects there. Each object is wrapped in a C++-class (say class Foo), which contains all the data needed: the mesh of the object (an array of vertices, an array of indices, an array of normals, ...), the associated material, the local coordinate system of the object and so on. The Foo-class has a method, called Draw, which sets all the data to the shader and calls glDrawArrays:


glDrawElements (_mesh->GetRenderMode (), _mesh->GetIndexArray ().size (), GL_UNSIGNED_INT, 0);

Next, I've registered the following function as a callback to call it every frame (as a render and idle function):


void GLWrapper::RenderCallback () const
{
glClear (GL_COLOR_BUFFER_BIT);

if (_scene != nullptr)
_scene->Draw ();

glutSwapBuffers ();
}

Here I just call the Draw-method of the Scene class, which simply calls the Draw-method of Foo class (described above) for every object in the scene.

And here I encounter my problem: how to switch on the depth test? It seems, that because each object is drawn separately, something is wrong conceptually with my approach. On the other hand, all the objects should be drawn to the same framebuffer, so they should share the same DepthBuffer. Keeping that in my mind, I thought, that simply swithing the depth test on would work correctly. So, I placed the following calls to my code:


glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);

glClearDepth (1.0f);

glEnable (GL_DEPTH_TEST);

glDepthFunc (GL_LEQUAL);

glDepthRange (0.0f, 1.0f);

glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

...and nothing changed. Nothing happens at all.

So the question is: how to implement the depth test properly in the given conditions (described above)?

Agent D
05-04-2014, 04:46 PM
You are not clearing the depth buffer in the draw loop. The correct glClear call would be: glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

Blizzard_jedi
05-05-2014, 01:11 AM
Perhaps, I haven't managed to describe what I did clearly. Sorry for that. So, when I wrote "I placed the following calls to my code", I meant, that I placed these lines of code to the proper positions. For example, the draw callback now looks like the following:


void GLWrapper::RenderCallback () const
{
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

if (_scene != nullptr)
_scene->Draw ();

glutSwapBuffers ();
}

Agent D
05-05-2014, 04:40 AM
Are you sure that _scene is not equal to nullptr (whatever value that has)? Are any objects drawn at all? Did it ever work in the first place? What does "nothing changed" look like?

Blizzard_jedi
05-05-2014, 05:43 AM
Yeah, it just draws a ball and a square segment of a plane. The plane is placed under the ball, but the ball is drawn first. So the plane happens to cover the ball partially. And here's the work for depth testing, but simply switching it on doesn't change the final pic: the plane still covers the ball. If you wish, I can place a screenshot here after a while.

Blizzard_jedi
05-05-2014, 03:42 PM
Ok, so, I've just solved the problem. The zNear value was 0.

Btw, it is now clear for me, that I don't really have to use functions, like gluPerspective, in order to make the depth testing work correctly. And now it is clear, how multiple objects correspond with the depth testing. All, that is needed, is to provide correct transformation matrices: (LocalObjectSpace->)WorldSpace->LocalCameraSpace->PerspectiveProjectionToTheScreen. Using these matrices allows to calculate correct point coordinates for the fragment shader for each object. And here's where opengl updates the current depth buffer (if it is enabled). So if you make multiple draw calls, but all the rendering goes to the same framebuffer object, you'll have the correct depth buffer generated.