diff --git a/src/hexgame.cpp b/src/hexgame.cpp index 16c1ec0..83943fc 100644 --- a/src/hexgame.cpp +++ b/src/hexgame.cpp @@ -569,12 +569,14 @@ int main(int argc, char* argv[]) #endif // main loop + + const uint TARGET_FPS = 60; + const uint FRAME_DELAY = 1000 / TARGET_FPS; + uint frameStart, frameTime; + while (processSDLEvents()) { -#if defined(_WIN32) - // sort-of fixed in windows with platform_wait_for_vblank() -#else - SDL_Delay(16); // ~60hz -#endif + frameStart = SDL_GetTicks(); + game_state* g = g_game_state; render_state* r = g_render_state; @@ -591,7 +593,12 @@ int main(int argc, char* argv[]) SDL_GL_SwapWindow(handles.window); - platform_wait_for_vblank(VSYNC_ENABLED); + // TODO: test SDL_Delay on Win32 + //platform_wait_for_vblank(VSYNC_ENABLED); + frameTime = SDL_GetTicks() - frameStart; + + if (FRAME_DELAY > frameTime) + SDL_Delay(FRAME_DELAY - frameTime); } cleanUp(handles); diff --git a/src/render_group.cpp b/src/render_group.cpp index 72e1421..9ed6951 100644 --- a/src/render_group.cpp +++ b/src/render_group.cpp @@ -22,10 +22,6 @@ render_object * allocateRenderObject(uint buffer_len, uint index_len = 0); void freeRenderObject(render_object* ro); bool convertMeshInfo(meMeshInfo* mesh, render_object* ro, bool use_normals); void sendIndexBufferToGL(gl_index_buffer* index_buffer, GLenum usage, GLenum target); -void drawRenderObject(render_group* rg, render_object* ro, - glm::mat4 model_matrix, glm::mat4 view_matrix, glm::mat4 projection_matrix, - rg_point_light* lights, uint num_lights, - bool update_vertex_data, bool update_color_data); // interface @@ -158,10 +154,75 @@ rgDraw(render_group* rg, glm::mat4 model_matrix, bool update_vertex_data, bool update_color_data) { for (uint i = 0; i < rg->num_objects; i++) { - drawRenderObject(rg, rg->render_objects[i], - model_matrix, view_matrix, projection_matrix, - lights, num_lights, - update_vertex_data, update_color_data); + render_object* ro = rg->render_objects[i]; + + glUseProgram(rg->shader.program_id); + glUniformMatrix4fv(rg->shader.model_matrix_id, 1, GL_FALSE, &model_matrix[0][0]); + glUniformMatrix4fv(rg->shader.view_matrix_id, 1, GL_FALSE, &view_matrix[0][0]); + glUniformMatrix4fv(rg->shader.projection_matrix_id, 1, GL_FALSE, &projection_matrix[0][0]); + + // 1st attribute buffer : vertices + glEnableVertexAttribArray(0); + glBindBuffer(GL_ARRAY_BUFFER, ro->vertex_buffer.buffer_id); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0); + + if (update_vertex_data) + { + glBufferSubData(GL_ARRAY_BUFFER, 0, ro->vertex_buffer.buffer_len * sizeof(GLfloat), + ro->vertex_buffer.buffer); + } + + // 2nd attribute buffer : colors + if (ro->color_buffer.buffer) + { + glEnableVertexAttribArray(1); + glBindBuffer(GL_ARRAY_BUFFER, ro->color_buffer.buffer_id); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0); + + if (update_color_data) { + glBufferSubData(GL_ARRAY_BUFFER, 0, ro->color_buffer.buffer_len * sizeof(GLfloat), + ro->color_buffer.buffer); + } + } + + // 3rd attribute buffer: normals + if (rg->use_normals) { + glEnableVertexAttribArray(2); + glBindBuffer(GL_ARRAY_BUFFER, ro->normal_buffer.buffer_id); + glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0); + + glm::mat3 normal_matrix = glm::transpose(glm::inverse(glm::mat3(model_matrix))); + glUniformMatrix3fv(rg->shader.normal_matrix_id, 1, GL_FALSE, &normal_matrix[0][0]); + + // TODO: use Uniform Buffer Objects to update light data + // https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_uniform_buffer_object.txt + // https://www.khronos.org/opengl/wiki/Uniform_Buffer_Objects + + glUniform1ui(rg->shader.num_lights_id, num_lights); + + for (uint i = 0; i < num_lights; i++) { + // TODO: don't do this every frame * every render_group + std::stringstream ss; + ss << "lights[" << i << "].position"; + int light_pos_loc = glGetUniformLocation(rg->shader.program_id, ss.str().c_str()); + glUniform3fv(light_pos_loc, 1, &lights[i].position[0]); + } + } + + // draw + if (rg->draw_indexed) { + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ro->index_buffer.buffer_id); + glDrawElements(rg->draw_mode, ro->index_buffer.buffer_len, GL_UNSIGNED_INT, 0); + } else { + glDrawArrays(rg->draw_mode, 0, ro->vertex_buffer.buffer_len / 3); + } + + // cleanup + glDisableVertexAttribArray(0); + if (ro->color_buffer.buffer) + glDisableVertexAttribArray(1); + if (rg->use_normals) + glDisableVertexAttribArray(2); } } @@ -289,77 +350,3 @@ convertMeshInfo(meMeshInfo* mesh, render_object* ro, bool use_normals) return true; } -void -drawRenderObject(render_group* rg, render_object* ro, - glm::mat4 model_matrix, glm::mat4 view_matrix, glm::mat4 projection_matrix, - rg_point_light* lights, uint num_lights, - bool update_vertex_data, bool update_color_data) -{ - glUseProgram(rg->shader.program_id); - glUniformMatrix4fv(rg->shader.model_matrix_id, 1, GL_FALSE, &model_matrix[0][0]); - glUniformMatrix4fv(rg->shader.view_matrix_id, 1, GL_FALSE, &view_matrix[0][0]); - glUniformMatrix4fv(rg->shader.projection_matrix_id, 1, GL_FALSE, &projection_matrix[0][0]); - - // 1st attribute buffer : vertices - glEnableVertexAttribArray(0); - glBindBuffer(GL_ARRAY_BUFFER, ro->vertex_buffer.buffer_id); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0); - - if (update_vertex_data) - { - glBufferSubData(GL_ARRAY_BUFFER, 0, ro->vertex_buffer.buffer_len * sizeof(GLfloat), - ro->vertex_buffer.buffer); - } - - // 2nd attribute buffer : colors - if (ro->color_buffer.buffer) - { - glEnableVertexAttribArray(1); - glBindBuffer(GL_ARRAY_BUFFER, ro->color_buffer.buffer_id); - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0); - - if (update_color_data) { - glBufferSubData(GL_ARRAY_BUFFER, 0, ro->color_buffer.buffer_len * sizeof(GLfloat), - ro->color_buffer.buffer); - } - } - - // 3rd attribute buffer: normals - if (rg->use_normals) { - glEnableVertexAttribArray(2); - glBindBuffer(GL_ARRAY_BUFFER, ro->normal_buffer.buffer_id); - glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0); - - glm::mat3 normal_matrix = glm::transpose(glm::inverse(glm::mat3(model_matrix))); - glUniformMatrix3fv(rg->shader.normal_matrix_id, 1, GL_FALSE, &normal_matrix[0][0]); - - // TODO: use Uniform Buffer Objects to update light data - // https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_uniform_buffer_object.txt - // https://www.khronos.org/opengl/wiki/Uniform_Buffer_Objects - - glUniform1ui(rg->shader.num_lights_id, num_lights); - - for (uint i = 0; i < num_lights; i++) { - // TODO: don't do this every frame * every render_group - std::stringstream ss; - ss << "lights[" << i << "].position"; - int light_pos_loc = glGetUniformLocation(rg->shader.program_id, ss.str().c_str()); - glUniform3fv(light_pos_loc, 1, &lights[i].position[0]); - } - } - - // draw - if (rg->draw_indexed) { - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ro->index_buffer.buffer_id); - glDrawElements(rg->draw_mode, ro->index_buffer.buffer_len, GL_UNSIGNED_INT, 0); - } else { - glDrawArrays(rg->draw_mode, 0, ro->vertex_buffer.buffer_len / 3); - } - - // cleanup - glDisableVertexAttribArray(0); - if (ro->color_buffer.buffer) - glDisableVertexAttribArray(1); - if (rg->use_normals) - glDisableVertexAttribArray(2); -}