Now we use OpenGL to draw the following cube:

No matter how we rotate the cube, if we look at it from any direction, we can only see three faces at most.

So for OpenGL, the other three faces that you can’t see can be drawn at all without drawing it, thereby improving the performance of drawing.

Surface to eliminate

Now that we’re getting rid of the invisible side, the question is:

How do you determine which side you can see and which side you can’t?

In OpenGL, it is possible to check all faces facing the observer and render them, while discarding all faces facing away from the observer, which saves the fragment shader running.

So, all we have to do is tell OpenGL which side is heads and which side is tails.

Heads and tails are determined by vertex join order

When we draw shapes through triangles, we define the order in which vertices are joined, which can be clockwise or counterclockwise.

In the figure above, the left triangle is clockwise and the right triangle is counterclockwise.

And OpenGL uses the clockwise or counterclockwise direction of the triangle to determine whether the triangle is heads or tails.

By default, the counterclockwise vertex join order is defined as the face of the triangle

Either counterclockwise or clockwise is relative to the direction of the observer

When defining the order of vertices, you should imagine that the corresponding triangle is facing you, so you should define the vertices of the triangle counterclockwise.

The advantage of this definition is that the actual joining order of the triangle vertices takes place during the rasterization phase, after the vertex shader runs, and the vertices are visible from the observer’s perspective.

For the figure above, the left triangle 1 -> 2 ->3 is connected clockwise when the observer is in front of the screen. If the observer is behind the screen, the connection order is 1 -> 2 ->3, which is counterclockwise.

This is why it is important to define the order of the vertices of a triangle as if the triangle is facing you, and ensure that the triangle is defined counterclockwise and can be changed depending on the direction of the observer.

The diagram below:

The order of vertices is 1 -> 2 -> 3, and when we define this order, we assume that the observer is facing the triangle, so we define it counterclockwise.

But to observe, from the right side of the glasses on the right side of the triangle direction is counterclockwise, the left side of the triangle is the clockwise direction, this is because for the right side of the triangle, the direction of the observer and the hypothesis that when defined sequence in the same direction, and to the left side of the triangle, the observer and define direction order hypothesis in the opposite direction, so from the opposite direction is clockwise.

In this way, the right side is visible and the left side is not, i.e., the front side facing the observer is visible and the back side is not.

I have read a lot of articles, but I did not explain why the triangle direction is defined counterclockwise, but it is clockwise when observing, because the original definition of counterclockwise direction is actually linked to the direction of the observer.

When the observer direction in the figure above is changed to the left, and the vertex connection order is still 1 -> 2 -> 3, the left triangle is visible counterclockwise as originally defined, while the right triangle is invisible clockwise.

Knowing this, it becomes clearer to face culling.

The specific use

You can enable face culling in OpenGL by using the following methods:

glEnable(GLES20.GL_CULL_FACE)
Copy the code

Face culling is turned off by default.

When face culling is enabled, all faces facing away from the viewer are discarded, saving rendering performance.

In addition, OpenGL provides additional functionality to select faces to cull.

    public static native void glCullFace(
        int mode
    );
Copy the code

Three modes are available:

  • GL_BACK: Only the back faces are removed
  • GL_FRONT: only forward planes are removed
  • GL_FRONT_AND_BACK: removes forward and back faces

The initial value of glCullFace is GL_BACK and only the back faces are excluded.

In addition to the faces that need to be removed, you can also tell OpenGL to define clockwise (rather than counterclockwise) faces as positive ones by calling the glFrontFace method.

    public static native void glFrontFace(
        int mode
    );
Copy the code

It has two options:

  • GL_CCW: indicates that the counterclockwise direction is the forward plane
  • GL_CW: indicates the positive plane in the clockwise direction

The glFrontFace mode value is GL_CCW, and the counterclockwise direction is the forward plane.

Now it is assumed that the opening surface is eliminated and the positive direction is eliminated. Clockwise is the positive direction:

    glEnable(GL_CULL_FACE);
    glCullFace(GL_FRONT);
    glFrontFace(GL_CW);
Copy the code

For specific code implementation, refer to my Github project:

Github.com/glumes/Andr…

summary

Using face culling can optimize the rendering process, saving more than 50 percent of the fragment shader execution.

Vertices are defined counterclockwise when using face culling.

Either counterclockwise or clockwise is relative to the direction of the observer.