Files
stk-code_catmod/src/graphics/shared_gpu_objects.cpp

249 lines
8.3 KiB
C++

// 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 <algorithm>
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