I am making a voxel game in OpenGL and I currently render 8 x 8 chunks to the screen. The first thing I do is generate the map using Simplex Noise and this is done once when the chunk is created. I store each block in a 3D array contained in each chunk. After the chunk is created I then call a function that checks each block to see if it is next to an air block, if it is then it is added to a separate array of visibleBlocks as is, otherwise an empty air block is added to its place (There is probably a better way of doing this). Once I have an array of blocks of which are visible, I call a function that returns a mesh which holds all of the vertices, colour data, normals, etc into 3 big VBOs (one for each) rather than rendering each block to the screen with its own vbo (of which I couldn't even render one chunk properly).
public static Mesh genChunkMesh(Block[][][] visibleBlocks) { ArrayList<Float> vertexData = new ArrayList<Float>(); //Storage for the chunk vertices ArrayList<Float> colourData = new ArrayList<Float>(); //Storage for the colours ArrayList<Integer> indexData = new ArrayList<Integer>(); //Storage for the indices ArrayList<Float> normalData = new ArrayList<Float>(); //Storage for the normals int blockNum = 0; for(int x = 0; x < CHUNK_WIDTH; x++) { for(int y = 0; y < CHUNK_HEIGHT; y++) { for(int z = 0; z < CHUNK_WIDTH; z++) { //Grab the mesh for a given BlockType from some statically defined blocks Mesh blockMesh = Chunk.getBlockMesh(visibleBlocks[x][y][z]); if(blockMesh != null) { float[] vertices = blockMesh.getVertices(); float[] colours = blockMesh.getColours(); int[] indices = blockMesh.getIndices(); float[] normals = blockMesh.getNormals(); for(int i = 0; i < vertices.length; i += 3)//Add the next x, y, z position to the vertex data { vertexData.add(vertices[i] + visibleBlocks[x][y][z].getPosition().x); vertexData.add(vertices[i + 1] + visibleBlocks[x][y][z].getPosition().y); vertexData.add(vertices[i + 2] + visibleBlocks[x][y][z].getPosition().z); } for(int i = 0; i < colours.length; i++) { colourData.add(colours[i]); } for(int i = 0; i < indices.length; i++) { indexData.add(indices[i] + (blockNum * 24)); //Indices range from 0-23, so every block 24 is added to each index } for(int i = 0; i < normals.length; i++) { normalData.add(normals[i]); } blockNum++; } } } } return new Mesh(Util.toFloatArray(vertexData), Util.toIntArray(indexData), Util.toFloatArray(colourData), Util.toFloatArray(normalData), grassMaterial); } I have a world object which holds these 8 x 8 chunks (the reason for 8 x 8 is because if I do anymore it begins to lag and each chunk being 16 * 16 * 128 blocks. Also I am implementing infinite terrain but at the moment I want to make sure a finite terrain of 8 x 8 works first). Each chunk has its own mesh which itself has one vao and 3 vbos (vertex, colour, normal) which is only generated once when the chunks are created and eventually will be regenerated everytime the chunk is updated (haven't got to this yet). In my render method the chunk array is looped through and each mesh is rendered through:
//Bind the VAO glBindVertexArray(vaoID); glEnableVertexAttribArray(0); //Vertex Data glEnableVertexAttribArray(1); //Colour data glEnableVertexAttribArray(2); //Normal data glDrawElements(GL_TRIANGLES, numVertices, GL_UNSIGNED_INT, 0); //Restore state glDisableVertexAttribArray(0); glDisableVertexAttribArray(1); glDisableVertexAttribArray(2); glBindVertexArray(0); Now that you have some context, my question is, why do I get consistent 60 fps when I am outside of the world

However when I move inside a chunk below the terrain, I get stuttering frames that jump around 30 fps.
I am unsure of what I am doing wrong that is causing this to happen, I have been searching for similar problems online but I do not know how to word it as it is weird. Also as you can see in the first image, weird lines appear at far distances between the blocks. I have a directional light that is pointing straight down and I don't know if it is because I am rendering faces between two solid cubes and the top face is brighter than the side faces. Another thing I should mention is that glfwSwapBuffers(1) is called at the end of each render call and it is causing a considerable amount of time to finish (around 0.01 to 0.05 seconds per call).
tldr: As shown in the pictures, I get consistent 60 fps when outside/above the terrain, but when I am inside of the terrain, the fps stutters around 20-30 fps and I don't know why.
moi·re (/mwär/)and yes they're due to gaps between voxels which you can avoid by joining colocated vertices (suggest you write it alongside the existing approach, so you can revert to the older method for comparison / performance tests). Other than that, you should be getting a lot more than 60FPS at all times, though this doesn't explain the discrepancy. Also, have a look here for tools you can use to look into your performance drop. \$\endgroup\$glEnable(GL_CULL_FACE)? You should not be using double-sided faces. Your chunks should ideally consist of nothing but the outward facing surfaces of the entire chunk, and you should have absolutely no interstitial faces when they anyway can't be seen from outside. I also suggest trying something like OpenGL dev performance tools to see what is happening with draw calls etc. \$\endgroup\$