I wrote a simple instancing demo for a member here. The demo just creates a cube composed of 512 instances of a cube and the view rotates around this by updating the MVP matrix with glm::rotate. I noticed that the framerate was fluctuating in an almost sinusoidal fashion and this led me to the rotate function. The frame rate goes from a high of around .75 ms/frame to a low of around 1.5 ms/frame. This isn't too bad, but what I find curious, and my main question is, why is this not constant? I tested it and it seems that the frame rate spikes when the angle is 180° and drops to the low point at 0°.
Is this normal? I took a look at the source for glm::rotate, but couldn't find anything wrong. This leads me to believe that I am doing something wrong.
Here is the source:
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
MSG msg;
BOOL done;
gl_win_app app_instance;
RECT bounds;
float angle;
float aspect;
float fov;
GLuint mvp_matrix_loc;
GLuint texture_loc;
GLuint instance_matrix_loc;
GLuint loc_1,loc_2,loc_3,loc_4;
glm::mat4 projection;
glm::mat4 view;
glm::mat4 mvp;
fov = 60.0f;
SetupConsole();
app_instance.InitializeApp("GL Instance Test");
app_instance.RegisterAppClass(hInstance);
app_instance.CreateAppWindow("GL Instance Test",WS_EX_APPWINDOW,WS_CAPTION | WS_SYSMENU | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,10,10,1000,1000,false);
app_instance.ShowAppWindow(true);
app_instance.SetAppWindowForeground();
app_instance.SetAppWindowFocus();
glClearColor(1.0f,1.0f,1.0f,1.0f);
glEnable(GL_TEXTURE_2D);
glEnable(GL_DEPTH_TEST);
done = false;
GetClientRect(app_instance.h_wnd,&bounds);
bounds.bottom += GetSystemMetrics(SM_CYCAPTION) + (GetSystemMetrics(SM_CYFRAME) * 3) + (GetSystemMetrics(SM_CYBORDER) * 3);
bounds.right += (GetSystemMetrics(SM_CXFRAME) * 3) + (GetSystemMetrics(SM_CXBORDER) * 3);
aspect = float(bounds.right) / float(bounds.bottom);
projection = glm::perspective(fov,aspect,0.1f,1000.0f);
view = glm::lookAt(glm::vec3(0.0,0.0,25.0),glm::vec3(0.0,0.0,-25.0),glm::vec3(0,1,0));
shader = LoadShaders("data/instance.vs","data/instance.fs");
limestone.LoadTexture("data/limestone.tga");
CreateInstanceMatrices();
LoadCube();
glBindTexture(GL_TEXTURE_2D,limestone.GetTextureID());
glActiveTexture(GL_TEXTURE0);
glUniform1i(limestone.GetTextureID(),0);
mvp_matrix_loc = glGetUniformLocation(shader,"MVP");
texture_loc = glGetUniformLocation(shader,"texture_sampler");
instance_matrix_loc = glGetAttribLocation(shader,"instance_matrix");
loc_1 = instance_matrix_loc + 0;
loc_2 = instance_matrix_loc + 1;
loc_3 = instance_matrix_loc + 2;
loc_4 = instance_matrix_loc + 3;
glUseProgram(shader);
angle = 0.0f;
while(!done)
{
if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
if(msg.message == WM_QUIT){
done = true;
}else{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}else{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
mvp = projection * view * glm::rotate(glm::mat4(),angle,glm::vec3(0.0,1.0,1.0));
angle += 0.025f;
if(angle > 360.0f)
angle = 0.0f;
glBindBuffer(GL_ARRAY_BUFFER,matrix_vbo);
glEnableVertexAttribArray(loc_1);
glEnableVertexAttribArray(loc_2);
glEnableVertexAttribArray(loc_3);
glEnableVertexAttribArray(loc_4);
glVertexAttribPointer(loc_1,4,GL_FLOAT,GL_FALSE,sizeof(GLfloat) * 4 * 4,(void*)(0));
glVertexAttribPointer(loc_2,4,GL_FLOAT,GL_FALSE,sizeof(GLfloat) * 4 * 4,(void*)(sizeof(float) * 4));
glVertexAttribPointer(loc_3,4,GL_FLOAT,GL_FALSE,sizeof(GLfloat) * 4 * 4,(void*)(sizeof(float) * 8));
glVertexAttribPointer(loc_4,4,GL_FLOAT,GL_FALSE,sizeof(GLfloat) * 4 * 4,(void*)(sizeof(float) * 12));
glVertexAttribDivisor(loc_1,1);
glVertexAttribDivisor(loc_2,1);
glVertexAttribDivisor(loc_3,1);
glVertexAttribDivisor(loc_4,1);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER,vertexbuffer);
glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,20,BUFFER_OFFSET(0));
glVertexAttribPointer(1,2,GL_FLOAT,GL_FALSE,20,BUFFER_OFFSET(12));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,elementbuffer);
glUniformMatrix4fv(mvp_matrix_loc,1,GL_FALSE,glm::value_ptr(mvp));
glDrawElementsInstanced(GL_TRIANGLES,index_array.size(),GL_UNSIGNED_INT,BUFFER_OFFSET(0),matrices.size());
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
app_instance.gl_context.SwapBuffers();
}
}
glUseProgram(0);
// Cleanup VBO and shader
glDeleteBuffers(1,&vertexbuffer);
glDeleteBuffers(1,&matrix_vbo);
glDeleteBuffers(1,&elementbuffer);
glDeleteProgram(shader);
FreeConsole();
app_instance.ReleaseApp();
return(msg.wParam);
}