2
votes

I'm having some trouble with rendering Master Cheif in Java using LWJGL and GLSL shaders where the is some flickering, dissapearing of polygons and strange colouring. And for the life of me I can't figure out why.

What it should look like: enter image description here

What it does look like when I move the camera a little: enter image description here

Shaders: https://github.com/marko5049/LucidEngine/tree/master/src/res/shaders

MainShaders: LightingMain ShdaowMapping Smapler Filters

All the code: https://github.com/marko5049/LucidEngine

StaticMesh:

public void addVertices(Vertex[] vertices, int[] indices, boolean calcNorm) {
    if(calcNorm) {
        vertices = calcNormals(vertices, indices);
    }

    handler.setSize(indices.length);
    EngineCore.polycount += indices.length/3;

    glBindBuffer(GL_ARRAY_BUFFER, handler.getVbo());
    glBufferData(GL_ARRAY_BUFFER, Util.createFlippedBuffer(vertices), GL_STATIC_DRAW);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, handler.getIbo());
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, Util.createFlippedBuffer(indices), GL_STATIC_DRAW);
}

private void finalDraw(int typeIndex) {
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);
    glEnableVertexAttribArray(2);
    glEnableVertexAttribArray(3);

    glBindBuffer(GL_ARRAY_BUFFER, handler.getVbo());
    glVertexAttribPointer(0, 3, GL_FLOAT, false, Vertex.SIZE * 4, 0);
    glVertexAttribPointer(1, 2, GL_FLOAT, false, Vertex.SIZE * 4, 12);
    glVertexAttribPointer(2, 3, GL_FLOAT, false, Vertex.SIZE * 4, 20);
    glVertexAttribPointer(3, 3, GL_FLOAT, false, Vertex.SIZE * 4, 32);
    glVertexAttribPointer(3, 3, GL_FLOAT, false, Vertex.SIZE * 4, 44);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, handler.getIbo());
    glDrawElements(typeIndex, handler.getSize(), GL_UNSIGNED_INT, 0);

    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);
    glDisableVertexAttribArray(2);
    glDisableVertexAttribArray(3);
}
1
From the visual appearance, it looks like it could be depth fighting. Can you try moving the near plane farther away, and/or the far plane closer? Line 54 in RenderingEngine.java. For example, try 1.0 and 100.0 instead of 0.1 and 1000.0.Reto Koradi
@RetoKoradi Totaly fixed it thanks so much!user2693587

1 Answers

2
votes

What you describe and is shown in your sample images are typical symptoms of a problem that is often called "depth fighting" or "z-fighting". This is caused by precision limitations of the depth buffer.

The most common scenario where this becomes an issue is if the range covered by the depth buffer is large, and the scene contains polygons with very similar depth values.

For example, picture a polygon A that is slightly in front of polygon B in world space. Pixels from polygon A and polygon B can end up with the same depth value after all transformations are applied, and the resulting depth is rounded to the available depth buffer precision. Depending on the order of drawing, the pixel from polygon A or polygon B will be visible in this case. The typical result is that a mix of pixels from polygon A and polygon B will show up where polygon A should cover polygon B.

There are a number of ways to address this:

  • Reduce the depth range. In a standard perspective projection, this is controlled by the near and far plane distances, where the relative far/near value is the critical quantity. Which values cause depth fighting depends heavily on the scene and depth buffer precision. The safest bet is to keep the relative value as small as possible. In most cases, values up to about 100 tend to rarely cause problems, and values of 1000 and higher can start causing issues.
  • Increase the depth buffer precision. The most common depth buffer sizes are 16-bit and 24-bit, and many GPUs support both. If things get problematic, choose at least 24-bit. Depending on hardware and OpenGL version, higher resolution depth buffers might be available.
  • Avoid rendering polygons with almost identical depth. Either remove hidden polygons that are very close in depth to visible polygons, or at least move them farther apart.

If the above is not enough, the solutions get more complex. There are scenarios where there is really geometry with a large range of depth that must be visible at the same time. Methods for dealing with these (relatively rare) cases include logarithmic depth buffers, and multi-pass rendering approaches.

Note that my answer is purely about the case where the original polygons in world space have different depth. If polygons with exactly the same depth (i.e. coplanar polygons) are drawn, depth fighting will almost always be the result, and this situation needs to be avoided with other methods. Since this doesn't look like the scenario here, I intentionally did not cover it.