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\$
  • \$\begingroup\$ I can't figure out which triangle you're talking about, here. \$\endgroup\$ – Trevor Powell Dec 26 '13 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 '13 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\$ – Trevor Powell Dec 26 '13 at 23:00
  • 1
    \$\begingroup\$ Could you show us the code thats causing this? \$\endgroup\$ – akaltar Dec 27 '13 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 '13 at 11:00
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\$
  • \$\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 '13 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 '13 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 '13 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 '13 at 14:22
4
\$\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\$
  • \$\begingroup\$ I accept this, the problem doesn't happen on my Desktop box nor on other computers. \$\endgroup\$ – Calmarius Jan 2 '14 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\$
  • \$\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 '13 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\$
  • \$\begingroup\$ yes looks so, and has nothing to do with backface culling. \$\endgroup\$ – concept3d Dec 27 '13 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 '13 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\$ – Trevor Powell Dec 27 '13 at 6:01
  • \$\begingroup\$ @TrevorPowell Yes I think you are correct, I retracted my vote. \$\endgroup\$ – concept3d Dec 27 '13 at 11:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.