The data points I've been able to get are 786,432 triangles at 60 fps and 55fps at 983,040 triangles. At 1,228,800 triangles it drops to 40 fps.
I'm rendering individual cubes, each with 12 triangles. The 12 triangles are in a single vertex buffer.
I'm fairly certain I'm using OpenGL 3.2.
Here's my drawing method. Chunk::CHUNK_SIZE is 16.
glViewport(0, 0, _windowWidth, _windowHeight); // Set the viewport size to fill the window
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // Clear required buffers
_modelMatrix = glm::mat4(); // Create our model matrix which will halve the size of our model
_lightPosition = glm::vec4(-10.0, 30.0, 16.0, 1.0);
_shader->bind(); // Bind our shader
int projectionMatrixLocation = glGetUniformLocation(_shader->id(), "projectionMatrix"); // Get the location of our projection matrix in the shader
int viewMatrixLocation = glGetUniformLocation(_shader->id(), "viewMatrix"); // Get the location of our view matrix in the shader
ChunkList chunks = _chunkManager.GetVisibleChunks();
_viewMatrix = _camera->GetViewMatrix();
glUniformMatrix4fv(projectionMatrixLocation, 1, GL_FALSE, &_projectionMatrix[0][0]); // Send our projection matrix to the shader
glUniformMatrix4fv(viewMatrixLocation, 1, GL_FALSE, &_viewMatrix[0][0]); // Send our view matrix to the shader
for (ChunkList::iterator it = chunks.begin(); it != chunks.end(); ++it)
{
Chunk *chunk = *it;
glm::mat4 world = glm::mat4();
world = glm::translate(world, glm::vec3(chunk->GetX() * Chunk::CHUNK_SIZE, chunk->GetY() * Chunk::CHUNK_SIZE, chunk->GetZ() * Chunk::CHUNK_SIZE));
for (float i = 0; i < Chunk::CHUNK_SIZE; ++i)
{
for (float j = 0; j < Chunk::CHUNK_SIZE; ++j)
{
for (float k = 0; k < Chunk::CHUNK_SIZE; ++k)
{
Block &block = *(chunk->GetBlock(i, j, k));
if (!block.IsActive())
{
continue;
}
//_modelMatrix = world;
_modelMatrix = glm::translate(world, glm::vec3(i, j, k));
int modelMatrixLocation = glGetUniformLocation(_shader->id(), "modelMatrix"); // Get the location of our model matrix in the shader
int pointLightPosition = glGetUniformLocation(_shader->id(), "pointLightPosition"); // Get the location of our model matrix in the shader
int material = glGetUniformLocation(_shader->id(), "color"); // Get the location of our model matrix in the shader
glUniformMatrix4fv(modelMatrixLocation, 1, GL_FALSE, &_modelMatrix[0][0]); // Send our model matrix to the shader
glm::vec4 colorArray;
switch (block.GetBlockType())
{
case BlockType::Dirt:
colorArray.r = 0.55;
colorArray.g = 0.27;
colorArray.b = 0.074;
colorArray.a = 1.0;
break;
case BlockType::Grass:
colorArray.r = 0.0;
colorArray.g = 1.0;
colorArray.b = 0.0;
colorArray.a = 1.0;
break;
case BlockType::Bedrock:
colorArray.r = 0.5;
colorArray.g = 0.5;
colorArray.b = 0.5;
colorArray.a = 1.0;
break;
}
glUniform4fv(pointLightPosition, 1, &_lightPosition[0]);
glUniform4fv(material, 1, &colorArray[0]);
glBindVertexArray(_vaoId[0]); // Bind our Vertex Array Object
glDrawArrays(GL_TRIANGLES, 0, 36); // Draw our square
}
}
}
}
glBindVertexArray(0);
_shader->unbind(); // Unbind our shader
Here's my initialization code:
_hwnd = hwnd; // Set the HWND for our window
_hdc = GetDC(hwnd); // Get the device context for our window
PIXELFORMATDESCRIPTOR pfd; // Create a new PIXELFORMATDESCRIPTOR (PFD)
memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR)); // Clear our PFD
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); // Set the size of the PFD to the size of the class
pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW; // Enable double buffering, opengl support and drawing to a window
pfd.iPixelType = PFD_TYPE_RGBA; // Set our application to use RGBA pixels
pfd.cColorBits = 32; // Give us 32 bits of color information (the higher, the more colors)
pfd.cDepthBits = 32; // Give us 32 bits of depth information (the higher, the more depth levels)
pfd.iLayerType = PFD_MAIN_PLANE; // Set the layer of the PFD
int nPixelFormat = ChoosePixelFormat(_hdc, &pfd); // Check if our PFD is valid and get a pixel format back
if (nPixelFormat == 0) // If it fails
return false;
bool bResult = SetPixelFormat(_hdc, nPixelFormat, &pfd); // Try and set the pixel format based on our PFD
if (!bResult) // If it fails
return false;
HGLRC tempOpenGLContext = wglCreateContext(_hdc); // Create an OpenGL 2.1 context for our device context
wglMakeCurrent(_hdc, tempOpenGLContext); // Make the OpenGL 2.1 context current and active
GLenum error = glewInit(); // Enable GLEW
if (error != GLEW_OK) // If GLEW fails
return false;
int attributes[] = {
WGL_CONTEXT_MAJOR_VERSION_ARB, 3, // Set the MAJOR version of OpenGL to 3
WGL_CONTEXT_MINOR_VERSION_ARB, 2, // Set the MINOR version of OpenGL to 2
WGL_CONTEXT_FLAGS_ARB, WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, // Set our OpenGL context to be forward compatible
0
};
if (wglewIsSupported("WGL_ARB_create_context") == 1) { // If the OpenGL 3.x context creation extension is available
_hrc = wglCreateContextAttribsARB(_hdc, NULL, attributes); // Create and OpenGL 3.x context based on the given attributes
wglMakeCurrent(NULL, NULL); // Remove the temporary context from being active
wglDeleteContext(tempOpenGLContext); // Delete the temporary OpenGL 2.1 context
wglMakeCurrent(_hdc, _hrc); // Make our OpenGL 3.0 context current
}
else {
_hrc = tempOpenGLContext; // If we didn't have support for OpenGL 3.x and up, use the OpenGL 2.1 context
}
The projection matrix is set to:
glm::perspective(60.0f, (float)_windowWidth / (float)_windowHeight, 0.1f, 100.f);