8
\$\begingroup\$

I've just enabled back face culling and I'm noticing a weird behavior: when all vertices of my triangle is outside the view and 2 of them is behind me (I think) the triangle disappears.

So to see it, here is a GIF.

enter image description here

I suspect the projection matrix reverses the order of the two vertices when they fall behind me, and changes the winding of my triangle.

But it's unclear why does the triangles disappear only if all vertices out of view...

How can I work around this problem, if possible?

I develop on Linux if that matters.

UPDATE:

It's pointed out it might not be due to the back face culling. I disabled it and I can indeed reproduce it. The cubes are 20×20 and the vertical field view is 90°. Its vertical apparent size roughly fills the window.

UPDATE 2:

Ok I'll post the relevant part of the code, projection and view matrixes are set up using my own functions:

void createViewMatrix(
    GLfloat matrix[16],
    const Vector3 *forward,
    const Vector3 *up,
    const Vector3 *pos
)
{
    /* Setting up perpendicular axes */
    Vector3 rright;
    Vector3 rup = *up;
    Vector3 rforward = *forward;

    vbonorm(&rright, &rup, &rforward); /* Orthonormalization (right is computed from scratch) */

    /* Filling the matrix */
    matrix[0] = rright.x;
    matrix[1] = rup.x;
    matrix[2] = -rforward.x;
    matrix[3] = 0;

    matrix[4] = rright.y;
    matrix[5] = rup.y;
    matrix[6] = -rforward.y;
    matrix[7] = 0;

    matrix[8] = rright.z;
    matrix[9] = rup.z;
    matrix[10] = -rforward.z;
    matrix[11] = 0;

    matrix[12] = -vdp(pos, &rright);
    matrix[13] = -vdp(pos, &rup);
    matrix[14] = vdp(pos, &rforward);
    matrix[15] = 1;
}

void createProjectionMatrix(
    GLfloat matrix[16],
    GLfloat vfov,
    GLfloat aspect,
    GLfloat near,
    GLfloat far
)
{
    GLfloat vfovtan = 1 / tan(RAD(vfov * 0.5));

    memset(matrix, 0, sizeof(*matrix) * 16);
    matrix[0] = vfovtan / aspect;
    matrix[5] = vfovtan;
    matrix[10] = (near+far)/(near-far);
    matrix[11] = -1;
    matrix[14] = (2*near*far)/(near-far);
}

Projection matrix set up with this call:

createProjectionMatrix(projMatrix, VERTICAL_FOV, ASPECT_RATIO, Z_NEAR, 10000);

(VERTICAL_FOV = 90, ASPECT_RATIO = 4.0/3, Z_NEAR = 1)

Level drawing is simply:

void drawStuff()
{
    GLfloat projectView[16];

    glClearColor(0, 0, 0, 1);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    createViewMatrix(viewMatrix, &camera.forward, &camera.up, &camera.pos);

    multiplyMatrix(projectView, viewMatrix, projMatrix); /*< Row mayor multiplication. */

    glUniformMatrix4fv(renderingMatrixId, 1, GL_FALSE, projectView);
    bailOnGlError(__FILE__, __LINE__);

    renderLevel(&testLevel);
}

Cubes are rendered wall by wall (optimizing this will be another story):

    for (j = 0; j < 6; j++)
    {
        glBindTexture(GL_TEXTURE_2D, cube->wallTextureIds[j]);
        bailOnGlError(__FILE__, __LINE__);

        glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_INT, (void*)(sizeof(GLuint) * 4 * j));
        bailOnGlError(__FILE__, __LINE__);
        glUniform4f(extraColorId, 1, 1, 1, 1);
        bailOnGlError(__FILE__, __LINE__);
    }

Vertex shader:

#version 110

attribute vec3 position;
attribute vec3 color;
attribute vec2 texCoord;

varying vec4 f_color;
varying vec2 f_texCoord;

uniform mat4 renderingMatrix;

void main()
{
    gl_Position =  renderingMatrix * vec4(position, 1);
    f_color = vec4(color, 1);
    f_texCoord = texCoord;
}

Fragment shader:

#version 110

varying vec4 f_color;
varying vec2 f_texCoord;

uniform sampler2D tex;

uniform vec4 extraColor;

void main()
{
    gl_FragColor = texture2D(tex, f_texCoord) * vec4(f_color) * extraColor;
}

The depth buffer simply set up by enabling it.

\$\endgroup\$
15
  • \$\begingroup\$ I can't figure out which triangle you're talking about, here. \$\endgroup\$ Dec 26, 2013 at 22:28
  • \$\begingroup\$ @TrevorPowell The cube's square faces are composed of 2 triangles, half of the square disappears on the 2nd pic. \$\endgroup\$
    – Calmarius
    Dec 26, 2013 at 22:40
  • \$\begingroup\$ I understood that. But which square are you referring to? I can't tell which bit of the second image I'm supposed to be looking at, and which vertices in the second image correspond to which vertices in the first. It just looks like the rightmost blue wall is clipping through the near clip plane, maybe? Or are you talking about the rightmost white wall? Or what? \$\endgroup\$ Dec 26, 2013 at 23:00
  • 1
    \$\begingroup\$ Could you show us the code thats causing this? \$\endgroup\$
    – akaltar
    Dec 27, 2013 at 1:19
  • 1
    \$\begingroup\$ So it looks like the triangles disappear the moment the vertex at the bottom of the screen goes out of view. Did this definitely start happening only when you enabled back face culling, or is it possible you just noticed it afterwards? Are the faces of the cube very large relative to the part we can see (I'm thinking of a possible arithmetic overflow)? Any chance of trying it on different hardware (it could be a driver bug)? \$\endgroup\$
    – GuyRT
    Dec 27, 2013 at 11:00

4 Answers 4

6
\$\begingroup\$

Though similar issues are often caused by clipping, the near plane is not the issue here. If it would be, the disappearance would be per pixel and not per triangle.

In your animation the triangles exactly disappear at the moment all of its three vertices get outside of the screen. Your algorithm may be based on the false assumption that triangles are hidden when all their vertices are hidden.

Here is an article talking about a good frustum culling implementation.

\$\endgroup\$
4
  • \$\begingroup\$ The triangle doesn't always disappear when all vertices out of the view. Isn't this clipping the OpenGL's task? \$\endgroup\$
    – Calmarius
    Dec 27, 2013 at 20:57
  • \$\begingroup\$ @Calmarius what danijar is saying, is that it's a problem in your frustum culling algorithm, which I think you are not even performing, are you? To be honest I think it's a driver issue/bug. \$\endgroup\$
    – concept3d
    Dec 28, 2013 at 0:48
  • \$\begingroup\$ @Calmarius concept3d might be right, your are using Mesa and it might have a bug that causes your issue. Can you run your code on a machine with official Nvidia or AMD driver? \$\endgroup\$
    – danijar
    Dec 28, 2013 at 12:47
  • \$\begingroup\$ @danijar Maybe later, when I go back to work after holidays. I'm using old scrapped computers which don't have additional video card built in only the on-board one. \$\endgroup\$
    – Calmarius
    Dec 28, 2013 at 14:22
5
\$\begingroup\$

So far it seems it is an OpenGL driver issue. I don't have other computer to test this on to confirm.

If I force software rendering by

$ export LIBGL_ALWAYS_SOFTWARE=1

The problem goes away. Probably I need to look around bugs with Mesa.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ I accept this, the problem doesn't happen on my Desktop box nor on other computers. \$\endgroup\$
    – Calmarius
    Jan 2, 2014 at 1:02
-1
\$\begingroup\$

its purely related to the near clipping plane for camera and has nothing related to backface culling. U need to reduce the near clipping plane and the clipping will go off.

\$\endgroup\$
1
  • \$\begingroup\$ If you look carefully, you can see that a triangle simply disappear, it has nothing to do with the near clipping plane. \$\endgroup\$
    – Calmarius
    Dec 27, 2013 at 8:51
-1
\$\begingroup\$

The triangles are disappearing because of the camera frustrum's near plane. Everything that is closer to the camera than the near plane is automatically clipped. You just need to put your near plane even more close of the the camera location. How you can configure the near plane depends on your graphical library or engine. In OpenGL, for example you should set the zNear parameter of gluPerspective:

void gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar);
\$\endgroup\$
4
  • \$\begingroup\$ yes looks so, and has nothing to do with backface culling. \$\endgroup\$
    – concept3d
    Dec 27, 2013 at 2:57
  • 3
    \$\begingroup\$ would that cause the entire triangle which is crossing the near clipping plane to disappear? shouldn't it just clip some of the fragments? \$\endgroup\$
    – user13213
    Dec 27, 2013 at 4:50
  • 3
    \$\begingroup\$ I don't think this is it; that camera looks to be facing straight forward, and those walls are vertical, which means that anything being clipped by crossing the near clipping plane should make a vertical line on the screen, not these shallow angles. The images shown really do look like a triangle being culled erroneously. \$\endgroup\$ Dec 27, 2013 at 6:01
  • \$\begingroup\$ @TrevorPowell Yes I think you are correct, I retracted my vote. \$\endgroup\$
    – concept3d
    Dec 27, 2013 at 11:56

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .