For GUI work, I use a single mesh and layer my gui components into it using the vertex buffers, i.e. each new image has a new Position and TexCoords, and incremented Indexes. These images are all co-planar, but when the mesh precisely faces the camera (as a GUI typically does) this isn’t a problem: high index vertexes are always drawn over the top of low index vertexes.
I’ve started using this GUI mesh within the 3d environment though (e.g. integrated into a wall), but since the mesh doesn’t always directly face the camera, my GUI components have started z-fighting.
Here is a simple demo. There is no Z-fighting unless you move the mouse.
public class GuiMeshTest extends SimpleApplication {
public static void main(String[] args) {
GuiMeshTest test = new GuiMeshTest();
test.setSettings(new AppSettings(true));
test.start();
}
@Override
public void simpleInitApp() {
assetManager.registerLocator("assets", FileLocator.class);
getStateManager().getState(FlyCamAppState.class).getCamera().setMoveSpeed(50f);
GuiMesh guiMesh = new GuiMesh();
guiMesh.addSprite(0, 0, 3, 3);
guiMesh.addSprite(2, 0, 3, 3);
guiMesh.updateBuffers();
Material material = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
material.setTexture("ColorMap", assetManager.loadTexture("Interface/Logo/Monkey.jpg"));
Geometry geometry = new Geometry("test", guiMesh);
geometry.setMaterial(material);
rootNode.attachChild(geometry);
}
private static class GuiMesh extends Mesh {
private final int maxSprites = 2;
private int spriteIndex = 0;
private float[] positions = new float[maxSprites * 8];
private float[] texCoords = new float[maxSprites * 8];
private short[] indexes = new short[maxSprites * 6];
public void addSprite(float x, float y, float width, float height) {
float[] positions = new float[] { x, y, x + width, y, x + width, y + height, x, y + height };
float[] texCoords = new float[] { 0, 0, 1, 0, 1, 1, 0, 1 };
short[] indexes = new short[] { 0, 1, 2, 0, 2, 3 };
for (int i = 0; i != indexes.length; i++)
indexes[i] += spriteIndex * 4;
System.arraycopy(positions, 0, this.positions, spriteIndex * positions.length, positions.length);
System.arraycopy(texCoords, 0, this.texCoords, spriteIndex * texCoords.length, texCoords.length);
System.arraycopy(indexes, 0, this.indexes, spriteIndex * indexes.length, indexes.length);
spriteIndex++;
}
public void updateBuffers() {
setBuffer(Type.Position, 2, positions);
setBuffer(Type.TexCoord, 2, texCoords);
setBuffer(Type.Index, 3, indexes);
updateCounts();
updateBound();
}
}
}
What is the appropriate solution to this?