// SuperTuxKart - a fun racing game with go-kart // Copyright (C) 2014-2015 SuperTuxKart-Team // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 3 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #ifndef SERVER_ONLY #include "graphics/shared_gpu_objects.hpp" #include "graphics/central_settings.hpp" #include "utils/log.hpp" #include "matrix4.h" #include GLuint SharedGPUObjects::m_billboard_vbo; GLuint SharedGPUObjects::m_sky_tri_vbo; GLuint SharedGPUObjects::m_frustrum_vbo; GLuint SharedGPUObjects::m_frustrum_indices; GLuint SharedGPUObjects::m_particle_quad_vbo; GLuint SharedGPUObjects::m_View_projection_matrices_ubo; GLuint SharedGPUObjects::m_lighting_data_ubo; GLuint SharedGPUObjects::m_full_screen_quad_vao; GLuint SharedGPUObjects::m_ui_vao; GLuint SharedGPUObjects::m_quad_buffer; GLuint SharedGPUObjects::m_quad_vbo; GLuint SharedGPUObjects::m_skinning_ubo; int SharedGPUObjects::m_max_mat4_size = 1024; bool SharedGPUObjects::m_has_been_initialised = false; /** Initialises m_full_screen_quad_vbo. */ void SharedGPUObjects::initQuadVBO() { const float QUAD_VERTEX[] = { -1., -1., 0., 0., // UpperLeft -1., 1., 0., 1., // LowerLeft 1., -1., 1., 0., // UpperRight 1., 1., 1., 1. // LowerRight }; glGenBuffers(1, &m_quad_vbo); glBindBuffer(GL_ARRAY_BUFFER, m_quad_vbo); glBufferData(GL_ARRAY_BUFFER, 16 * sizeof(float), QUAD_VERTEX, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); const float TRI_VERTEX[] = { -1., -1., -1., 3., 3., -1., }; GLuint tri_vbo; glGenBuffers(1, &tri_vbo); glBindBuffer(GL_ARRAY_BUFFER, tri_vbo); glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(float), TRI_VERTEX, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); glGenVertexArrays(1, &m_full_screen_quad_vao); glBindVertexArray(m_full_screen_quad_vao); glBindBuffer(GL_ARRAY_BUFFER, tri_vbo); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), 0); glBindVertexArray(0); } // initQuadVBO // ---------------------------------------------------------------------------- void SharedGPUObjects::initQuadBuffer() { const float QUAD_VERTEX[] = { -1., -1., -1., 1., // UpperLeft -1., 1., -1., -1., // LowerLeft 1., -1., 1., 1., // UpperRight 1., 1., 1., -1. // LowerRight }; glGenBuffers(1, &m_quad_buffer); glBindBuffer(GL_ARRAY_BUFFER, m_quad_buffer); glBufferData(GL_ARRAY_BUFFER, 16 * sizeof(float), QUAD_VERTEX, GL_STATIC_DRAW); glGenVertexArrays(1, &m_ui_vao); glBindVertexArray(m_ui_vao); glEnableVertexAttribArray(0); glEnableVertexAttribArray(3); glBindBuffer(GL_ARRAY_BUFFER, m_quad_buffer); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0); glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (GLvoid *)(2 * sizeof(float))); glBindVertexArray(0); } // initQuadBuffer // ---------------------------------------------------------------------------- void SharedGPUObjects::initBillboardVBO() { float QUAD[] = { -.5, -.5, 0., 1., -.5, .5, 0., 0., .5, -.5, 1., 1., .5, .5, 1., 0., }; glGenBuffers(1, &m_billboard_vbo); glBindBuffer(GL_ARRAY_BUFFER, m_billboard_vbo); glBufferData(GL_ARRAY_BUFFER, 16 * sizeof(float), QUAD, GL_STATIC_DRAW); } // initBillboardVBO // ---------------------------------------------------------------------------- void SharedGPUObjects::initSkyTriVBO() { const float TRI_VERTEX[] = { -1., -1., 1., -1., 3., 1., 3., -1., 1., }; glGenBuffers(1, &m_sky_tri_vbo); glBindBuffer(GL_ARRAY_BUFFER, m_sky_tri_vbo); glBufferData(GL_ARRAY_BUFFER, 3 * 3 * sizeof(float), TRI_VERTEX, GL_STATIC_DRAW); } // initSkyTriVBO // ---------------------------------------------------------------------------- void SharedGPUObjects::initFrustrumVBO() { glGenBuffers(1, &m_frustrum_vbo); glBindBuffer(GL_ARRAY_BUFFER, m_frustrum_vbo); glBufferData(GL_ARRAY_BUFFER, 8 * 3 * sizeof(float), 0, GL_DYNAMIC_DRAW); int INDICES[24] = { 0, 1, 1, 3, 3, 2, 2, 0, 4, 5, 5, 7, 7, 6, 6, 4, 0, 4, 1, 5, 2, 6, 3, 7, }; glGenBuffers(1, &m_frustrum_indices); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_frustrum_indices); glBufferData(GL_ELEMENT_ARRAY_BUFFER, 12 * 2 * sizeof(int), INDICES, GL_STATIC_DRAW); } // initFrustrumVBO // ---------------------------------------------------------------------------- void SharedGPUObjects::initShadowVPMUBO() { assert(CVS->isARBUniformBufferObjectUsable()); glGenBuffers(1, &m_View_projection_matrices_ubo); glBindBuffer(GL_UNIFORM_BUFFER, m_View_projection_matrices_ubo); glBufferData(GL_UNIFORM_BUFFER, (16 * 9 + 2) * sizeof(float), 0, GL_STREAM_DRAW); glBindBuffer(GL_UNIFORM_BUFFER, 0); } // initShadowVPMUBO // ---------------------------------------------------------------------------- void SharedGPUObjects::initLightingDataUBO() { assert(CVS->isARBUniformBufferObjectUsable()); glGenBuffers(1, &m_lighting_data_ubo); glBindBuffer(GL_UNIFORM_BUFFER, m_lighting_data_ubo); glBufferData(GL_UNIFORM_BUFFER, 36 * sizeof(float), 0, GL_STREAM_DRAW); glBindBuffer(GL_UNIFORM_BUFFER, 0); } // initLightingDataUBO // ---------------------------------------------------------------------------- void SharedGPUObjects::initSkinningUBO() { assert(CVS->isARBUniformBufferObjectUsable()); irr::core::matrix4 m; glGenBuffers(1, &m_skinning_ubo); glBindBuffer(GL_UNIFORM_BUFFER, m_skinning_ubo); int max_size = 0; glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &max_size); max_size = std::min(max_size, 65536); m_max_mat4_size = max_size / 16 / sizeof(float); Log::info("SharedGPUObjects", "Hardware skinning supported, max joints" " support: %d", m_max_mat4_size); glBufferData(GL_UNIFORM_BUFFER, max_size, 0, GL_STREAM_DRAW); // Reserve a identity matrix for non moving mesh in animated model used by // vertex shader calculation glBufferSubData(GL_UNIFORM_BUFFER, 0, 16 * sizeof(float), m.pointer()); glBindBuffer(GL_UNIFORM_BUFFER, 0); } // initSkinningUBO // ---------------------------------------------------------------------------- void SharedGPUObjects::initParticleQuadVBO() { static const GLfloat QUAD_VERTEX[] = { -.5, -.5, 0., 0., .5, -.5, 1., 0., -.5, .5, 0., 1., .5, .5, 1., 1., }; glGenBuffers(1, &m_particle_quad_vbo); glBindBuffer(GL_ARRAY_BUFFER, m_particle_quad_vbo); glBufferData(GL_ARRAY_BUFFER, sizeof(QUAD_VERTEX), QUAD_VERTEX, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); } // initParticleQuadVBO // ---------------------------------------------------------------------------- void SharedGPUObjects::init() { if (m_has_been_initialised) return; initQuadVBO(); initQuadBuffer(); initBillboardVBO(); initSkyTriVBO(); initFrustrumVBO(); initParticleQuadVBO(); if (CVS->isARBUniformBufferObjectUsable()) { initShadowVPMUBO(); initLightingDataUBO(); if (CVS->supportsHardwareSkinning()) initSkinningUBO(); } m_has_been_initialised = true; } // SharedGPUObjects // ---------------------------------------------------------------------------- /** A simple reset function. Atm it actually only resets the * m_has_been_initialised flag (all opengl data gets reset anyway when this * function is called). */ void SharedGPUObjects::reset() { m_has_been_initialised = false; } // reset #endif // !SERVER_ONLY