diff --git a/src/graphics/gl_headers.hpp b/src/graphics/gl_headers.hpp index d553f4869..608f04ae7 100644 --- a/src/graphics/gl_headers.hpp +++ b/src/graphics/gl_headers.hpp @@ -49,4 +49,4 @@ struct DrawElementsIndirectCommand{ GLuint baseInstance; }; -#endif \ No newline at end of file +#endif diff --git a/src/graphics/glwrap.cpp b/src/graphics/glwrap.cpp index 7c7975fbd..f20d4eb5d 100644 --- a/src/graphics/glwrap.cpp +++ b/src/graphics/glwrap.cpp @@ -397,340 +397,6 @@ void setTexture(unsigned TextureUnit, GLuint TextureId, GLenum MagFilter, GLenum glGetError(); } -VAOManager::VAOManager() -{ - vao[0] = vao[1] = vao[2] = 0; - vbo[0] = vbo[1] = vbo[2] = 0; - ibo[0] = ibo[1] = ibo[2] = 0; - vtx_cnt[0] = vtx_cnt[1] = vtx_cnt[2] = 0; - idx_cnt[0] = idx_cnt[1] = idx_cnt[2] = 0; - vtx_mirror[0] = vtx_mirror[1] = vtx_mirror[2] = NULL; - idx_mirror[0] = idx_mirror[1] = idx_mirror[2] = NULL; - instance_count[0] = 0; - - for (unsigned i = 0; i < InstanceTypeCount; i++) - { - glGenBuffers(1, &instance_vbo[i]); - glBindBuffer(GL_ARRAY_BUFFER, instance_vbo[i]); -#ifdef Buffer_Storage - if (irr_driver->hasBufferStorageExtension()) - { - glBufferStorage(GL_ARRAY_BUFFER, 10000 * sizeof(InstanceData), 0, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT); - Ptr[i] = glMapBufferRange(GL_ARRAY_BUFFER, 0, 10000 * sizeof(InstanceData), GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT); - } - else -#endif - { - glBufferData(GL_ARRAY_BUFFER, 10000 * sizeof(InstanceData), 0, GL_STREAM_DRAW); - } - } -} - -static void cleanVAOMap(std::map, GLuint> Map) -{ - std::map, GLuint>::iterator It = Map.begin(), E = Map.end(); - for (; It != E; It++) - { - glDeleteVertexArrays(1, &(It->second)); - } -} - -void VAOManager::cleanInstanceVAOs() -{ - cleanVAOMap(InstanceVAO); - InstanceVAO.clear(); -} - -VAOManager::~VAOManager() -{ - cleanInstanceVAOs(); - for (unsigned i = 0; i < 3; i++) - { - if (vtx_mirror[i]) - free(vtx_mirror[i]); - if (idx_mirror[i]) - free(idx_mirror[i]); - if (vbo[i]) - glDeleteBuffers(1, &vbo[i]); - if (ibo[i]) - glDeleteBuffers(1, &ibo[i]); - if (vao[i]) - glDeleteVertexArrays(1, &vao[i]); - } - for (unsigned i = 0; i < InstanceTypeCount; i++) - { - glDeleteBuffers(1, &instance_vbo[i]); - } - -} - -void VAOManager::regenerateBuffer(enum VTXTYPE tp) -{ - glBindVertexArray(0); - if (vbo[tp]) - glDeleteBuffers(1, &vbo[tp]); - glGenBuffers(1, &vbo[tp]); - glBindBuffer(GL_ARRAY_BUFFER, vbo[tp]); -#ifdef Buffer_Storage - if (irr_driver->hasBufferStorageExtension()) - { - glBufferStorage(GL_ARRAY_BUFFER, vtx_cnt[tp] * getVertexPitch(tp), vtx_mirror[tp], GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT); - VBOPtr[tp] = glMapBufferRange(GL_ARRAY_BUFFER, 0, vtx_cnt[tp] * getVertexPitch(tp), GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT); - } - else -#endif - glBufferData(GL_ARRAY_BUFFER, vtx_cnt[tp] * getVertexPitch(tp), vtx_mirror[tp], GL_DYNAMIC_DRAW); - - - if (ibo[tp]) - glDeleteBuffers(1, &ibo[tp]); - glGenBuffers(1, &ibo[tp]); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo[tp]); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(u16)* idx_cnt[tp], idx_mirror[tp], GL_DYNAMIC_DRAW); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); -} - -void VAOManager::regenerateVAO(enum VTXTYPE tp) -{ - if (vao[tp]) - glDeleteVertexArrays(1, &vao[tp]); - glGenVertexArrays(1, &vao[tp]); - glBindVertexArray(vao[tp]); - glBindBuffer(GL_ARRAY_BUFFER, vbo[tp]); - switch (tp) - { - case VTXTYPE_STANDARD: - // Position - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), 0); - // Normal - glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)12); - // Color - glEnableVertexAttribArray(2); - glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitch(tp), (GLvoid*)24); - // Texcoord - glEnableVertexAttribArray(3); - glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)28); - break; - case VTXTYPE_TCOORD: - // Position - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), 0); - // Normal - glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)12); - // Color - glEnableVertexAttribArray(2); - glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitch(tp), (GLvoid*)24); - // Texcoord - glEnableVertexAttribArray(3); - glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)28); - // SecondTexcoord - glEnableVertexAttribArray(4); - glVertexAttribPointer(4, 2, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)36); - break; - case VTXTYPE_TANGENT: - // Position - glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), 0); - // Normal - glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)12); - // Color - glEnableVertexAttribArray(2); - glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitch(tp), (GLvoid*)24); - // Texcoord - glEnableVertexAttribArray(3); - glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)28); - // Tangent - glEnableVertexAttribArray(5); - glVertexAttribPointer(5, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)36); - // Bitangent - glEnableVertexAttribArray(6); - glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)48); - break; - } - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo[tp]); - glBindVertexArray(0); -} - -void VAOManager::regenerateInstancedVAO() -{ - cleanInstanceVAOs(); - - enum video::E_VERTEX_TYPE IrrVT[] = { video::EVT_STANDARD, video::EVT_2TCOORDS, video::EVT_TANGENTS }; - for (unsigned i = 0; i < VTXTYPE_COUNT; i++) - { - video::E_VERTEX_TYPE tp = IrrVT[i]; - if (!vbo[tp] || !ibo[tp]) - continue; - GLuint vao = createVAO(vbo[tp], ibo[tp], tp); - glBindBuffer(GL_ARRAY_BUFFER, instance_vbo[InstanceTypeDefault]); - - glEnableVertexAttribArray(7); - glVertexAttribPointer(7, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), 0); - glVertexAttribDivisor(7, 1); - glEnableVertexAttribArray(8); - glVertexAttribPointer(8, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), (GLvoid*)(3 * sizeof(float))); - glVertexAttribDivisor(8, 1); - glEnableVertexAttribArray(9); - glVertexAttribPointer(9, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), (GLvoid*)(6 * sizeof(float))); - glVertexAttribDivisor(9, 1); - glEnableVertexAttribArray(10); - glVertexAttribIPointer(10, 2, GL_UNSIGNED_INT, sizeof(InstanceData), (GLvoid*)(9 * sizeof(float))); - glVertexAttribDivisor(10, 1); - glEnableVertexAttribArray(11); - glVertexAttribIPointer(11, 2, GL_UNSIGNED_INT, sizeof(InstanceData), (GLvoid*)(9 * sizeof(float) + 2 * sizeof(unsigned))); - glVertexAttribDivisor(11, 1); - InstanceVAO[std::pair(tp, InstanceTypeDefault)] = vao; - - vao = createVAO(vbo[tp], ibo[tp], tp); - glBindBuffer(GL_ARRAY_BUFFER, instance_vbo[InstanceTypeShadow]); - - glEnableVertexAttribArray(7); - glVertexAttribPointer(7, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), 0); - glVertexAttribDivisor(7, 1); - glEnableVertexAttribArray(8); - glVertexAttribPointer(8, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), (GLvoid*)(3 * sizeof(float))); - glVertexAttribDivisor(8, 1); - glEnableVertexAttribArray(9); - glVertexAttribPointer(9, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), (GLvoid*)(6 * sizeof(float))); - glVertexAttribDivisor(9, 1); - glEnableVertexAttribArray(10); - glVertexAttribIPointer(10, 2, GL_UNSIGNED_INT, sizeof(InstanceData), (GLvoid*)(9 * sizeof(float))); - glVertexAttribDivisor(10, 1); - glEnableVertexAttribArray(11); - glVertexAttribIPointer(11, 2, GL_UNSIGNED_INT, sizeof(InstanceData), (GLvoid*)(9 * sizeof(float) + 2 * sizeof(unsigned))); - glVertexAttribDivisor(11, 1); - InstanceVAO[std::pair(tp, InstanceTypeShadow)] = vao; - - vao = createVAO(vbo[tp], ibo[tp], tp); - glBindBuffer(GL_ARRAY_BUFFER, instance_vbo[InstanceTypeRSM]); - - glEnableVertexAttribArray(7); - glVertexAttribPointer(7, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), 0); - glVertexAttribDivisor(7, 1); - glEnableVertexAttribArray(8); - glVertexAttribPointer(8, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), (GLvoid*)(3 * sizeof(float))); - glVertexAttribDivisor(8, 1); - glEnableVertexAttribArray(9); - glVertexAttribPointer(9, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), (GLvoid*)(6 * sizeof(float))); - glVertexAttribDivisor(9, 1); - glEnableVertexAttribArray(10); - glVertexAttribIPointer(10, 2, GL_UNSIGNED_INT, sizeof(InstanceData), (GLvoid*)(9 * sizeof(float))); - glVertexAttribDivisor(10, 1); - glEnableVertexAttribArray(11); - glVertexAttribIPointer(11, 2, GL_UNSIGNED_INT, sizeof(InstanceData), (GLvoid*)(9 * sizeof(float) + 2 * sizeof(unsigned))); - glVertexAttribDivisor(11, 1); - InstanceVAO[std::pair(tp, InstanceTypeRSM)] = vao; - - vao = createVAO(vbo[tp], ibo[tp], tp); - glBindBuffer(GL_ARRAY_BUFFER, instance_vbo[InstanceTypeGlow]); - - glEnableVertexAttribArray(7); - glVertexAttribPointer(7, 3, GL_FLOAT, GL_FALSE, sizeof(GlowInstanceData), 0); - glVertexAttribDivisor(7, 1); - glEnableVertexAttribArray(8); - glVertexAttribPointer(8, 3, GL_FLOAT, GL_FALSE, sizeof(GlowInstanceData), (GLvoid*)(3 * sizeof(float))); - glVertexAttribDivisor(8, 1); - glEnableVertexAttribArray(9); - glVertexAttribPointer(9, 3, GL_FLOAT, GL_FALSE, sizeof(GlowInstanceData), (GLvoid*)(6 * sizeof(float))); - glVertexAttribDivisor(9, 1); - glEnableVertexAttribArray(12); - glVertexAttribPointer(12, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(GlowInstanceData), (GLvoid*)(9 * sizeof(float))); - glVertexAttribDivisor(12, 1); - InstanceVAO[std::pair(tp, InstanceTypeGlow)] = vao; - glBindVertexArray(0); - } - - - -} - -size_t VAOManager::getVertexPitch(enum VTXTYPE tp) const -{ - switch (tp) - { - case VTXTYPE_STANDARD: - return getVertexPitchFromType(video::EVT_STANDARD); - case VTXTYPE_TCOORD: - return getVertexPitchFromType(video::EVT_2TCOORDS); - case VTXTYPE_TANGENT: - return getVertexPitchFromType(video::EVT_TANGENTS); - default: - assert(0 && "Wrong vtxtype"); - return -1; - } -} - -VAOManager::VTXTYPE VAOManager::getVTXTYPE(video::E_VERTEX_TYPE type) -{ - switch (type) - { - default: - assert(0 && "Wrong vtxtype"); - case video::EVT_STANDARD: - return VTXTYPE_STANDARD; - case video::EVT_2TCOORDS: - return VTXTYPE_TCOORD; - case video::EVT_TANGENTS: - return VTXTYPE_TANGENT; - } -}; - -void VAOManager::append(scene::IMeshBuffer *mb, VTXTYPE tp) -{ - size_t old_vtx_cnt = vtx_cnt[tp]; - vtx_cnt[tp] += mb->getVertexCount(); - vtx_mirror[tp] = realloc(vtx_mirror[tp], vtx_cnt[tp] * getVertexPitch(tp)); - intptr_t dstptr = (intptr_t)vtx_mirror[tp] + (old_vtx_cnt * getVertexPitch(tp)); - memcpy((void *)dstptr, mb->getVertices(), mb->getVertexCount() * getVertexPitch(tp)); - mappedBaseVertex[tp][mb] = old_vtx_cnt; - - size_t old_idx_cnt = idx_cnt[tp]; - idx_cnt[tp] += mb->getIndexCount(); - idx_mirror[tp] = realloc(idx_mirror[tp], idx_cnt[tp] * sizeof(u16)); - - dstptr = (intptr_t)idx_mirror[tp] + (old_idx_cnt * sizeof(u16)); - memcpy((void *)dstptr, mb->getIndices(), mb->getIndexCount() * sizeof(u16)); - mappedBaseIndex[tp][mb] = old_idx_cnt * sizeof(u16); -} - -std::pair VAOManager::getBase(scene::IMeshBuffer *mb) -{ - VTXTYPE tp = getVTXTYPE(mb->getVertexType()); - if (mappedBaseVertex[tp].find(mb) == mappedBaseVertex[tp].end()) - { - assert(mappedBaseIndex[tp].find(mb) == mappedBaseIndex[tp].end()); - storedCPUBuffer[tp].push_back(mb); - append(mb, tp); - regenerateBuffer(tp); - regenerateVAO(tp); - regenerateInstancedVAO(); - } - - std::map::iterator It; - It = mappedBaseVertex[tp].find(mb); - assert(It != mappedBaseVertex[tp].end()); - unsigned vtx = It->second; - It = mappedBaseIndex[tp].find(mb); - assert(It != mappedBaseIndex[tp].end()); - return std::pair(vtx, It->second); -} - -size_t VAOManager::appendInstance(enum InstanceType, const std::vector &instance_data) -{ - glBindBuffer(GL_ARRAY_BUFFER, instance_vbo[0]); - glBufferSubData(GL_ARRAY_BUFFER, instance_count[0] * sizeof(InstanceData), instance_data.size() * sizeof(InstanceData), instance_data.data()); - size_t result = instance_count[0]; - instance_count[0] += instance_data.size(); - return result; -} - ScopedGPUTimer::ScopedGPUTimer(GPUTimer &t) : timer(t) { if (!UserConfigParams::m_profiler_enabled) return; diff --git a/src/graphics/glwrap.hpp b/src/graphics/glwrap.hpp index cd4da2a20..8c2949430 100644 --- a/src/graphics/glwrap.hpp +++ b/src/graphics/glwrap.hpp @@ -6,7 +6,7 @@ #include #include "irr_driver.hpp" #include "utils/log.hpp" - +#include "vaomanager.hpp" void initGL(); GLuint LoadTFBProgram(const char * vertex_file_path, const char **varyings, unsigned varyingscount); @@ -139,110 +139,6 @@ void compressTexture(irr::video::ITexture *tex, bool srgb, bool premul_alpha = f bool loadCompressedTexture(const std::string& compressed_tex); void saveCompressedTexture(const std::string& compressed_tex); -enum InstanceType -{ - InstanceTypeDefault, - InstanceTypeShadow, - InstanceTypeRSM, - InstanceTypeGlow, - InstanceTypeCount, -}; - -#ifdef WIN32 -#pragma pack(push, 1) -#endif -struct InstanceData -{ - struct - { - float X; - float Y; - float Z; - } Origin; - struct - { - float X; - float Y; - float Z; - } Orientation; - struct - { - float X; - float Y; - float Z; - } Scale; - uint64_t Texture; - uint64_t SecondTexture; -#ifdef WIN32 -}; -#else -} __attribute__((packed)); -#endif - -struct GlowInstanceData -{ - struct - { - float X; - float Y; - float Z; - } Origin; - struct - { - float X; - float Y; - float Z; - } Orientation; - struct - { - float X; - float Y; - float Z; - } Scale; - unsigned Color; -#ifdef WIN32 -}; -#else -} __attribute__((packed)); -#endif -#ifdef WIN32 -#pragma pack(pop) -#endif - -class VAOManager : public Singleton -{ - enum VTXTYPE { VTXTYPE_STANDARD, VTXTYPE_TCOORD, VTXTYPE_TANGENT, VTXTYPE_COUNT }; - GLuint vbo[VTXTYPE_COUNT], ibo[VTXTYPE_COUNT], vao[VTXTYPE_COUNT]; - GLuint instance_vbo[InstanceTypeCount]; - size_t instance_count[InstanceTypeCount]; - void *Ptr[InstanceTypeCount]; - void *VBOPtr[VTXTYPE_COUNT]; - std::vector storedCPUBuffer[VTXTYPE_COUNT]; - void *vtx_mirror[VTXTYPE_COUNT], *idx_mirror[VTXTYPE_COUNT]; - size_t vtx_cnt[VTXTYPE_COUNT], idx_cnt[VTXTYPE_COUNT]; - std::map mappedBaseVertex[VTXTYPE_COUNT], mappedBaseIndex[VTXTYPE_COUNT]; - std::map, GLuint> InstanceVAO; - - void cleanInstanceVAOs(); - void regenerateBuffer(enum VTXTYPE); - void regenerateVAO(enum VTXTYPE); - void regenerateInstancedVAO(); - size_t getVertexPitch(enum VTXTYPE) const; - VTXTYPE getVTXTYPE(video::E_VERTEX_TYPE type); - void append(scene::IMeshBuffer *, VTXTYPE tp); -public: - VAOManager(); - std::pair getBase(scene::IMeshBuffer *); - size_t appendInstance(enum InstanceType, const std::vector &instance_data); - GLuint getInstanceBuffer(InstanceType it) { return instance_vbo[it]; } - void *getInstanceBufferPtr(InstanceType it) { return Ptr[it]; } - unsigned getVBO(video::E_VERTEX_TYPE type) { return vbo[getVTXTYPE(type)]; } - void *getVBOPtr(video::E_VERTEX_TYPE type) { return VBOPtr[getVTXTYPE(type)]; } - unsigned getVAO(video::E_VERTEX_TYPE type) { return vao[getVTXTYPE(type)]; } - unsigned getInstanceVAO(video::E_VERTEX_TYPE vt, enum InstanceType it) { return InstanceVAO[std::pair(vt, it)]; } - ~VAOManager(); -}; - void draw3DLine(const core::vector3df& start, const core::vector3df& end, irr::video::SColor color); diff --git a/src/graphics/irr_driver.cpp b/src/graphics/irr_driver.cpp index 15d911208..53a30e58d 100644 --- a/src/graphics/irr_driver.cpp +++ b/src/graphics/irr_driver.cpp @@ -506,27 +506,27 @@ void IrrDriver::initDevice() // Default false value for hasVSLayer if --no-graphics argument is used if (!ProfileWorld::isNoGraphics()) { - if (GLEW_AMD_vertex_shader_layer) { + if (hasGLExtension("GL_AMD_vertex_shader_layer")) { hasVSLayer = true; Log::info("GLDriver", "AMD Vertex Shader Layer enabled"); } - if (GLEW_ARB_buffer_storage) { + if (hasGLExtension("GL_ARB_buffer_storage")) { hasBuffserStorage = true; Log::info("GLDriver", "ARB Buffer Storage enabled"); } - if (GLEW_ARB_base_instance) { + if (hasGLExtension("GL_ARB_base_instance")) { hasBaseInstance = true; Log::info("GLDriver", "ARB Base Instance enabled"); } - if (GLEW_ARB_draw_indirect) { + if (hasGLExtension("GL_ARB_draw_indirect")) { hasDrawIndirect = true; Log::info("GLDriver", "ARB Draw Indirect enabled"); } - if (GLEW_ARB_compute_shader) { + if (hasGLExtension("GL_ARB_compute_shader")) { hasComputeShaders = true; Log::info("GLDriver", "ARB Compute Shader enabled"); } - if (GLEW_ARB_texture_storage) { + if (hasGLExtension("GL_ARB_texture_storage")) { hasTextureStorage = true; Log::info("GLDriver", "ARB Texture Storage enabled"); } @@ -1742,17 +1742,23 @@ void IrrDriver::displayFPS() if (low > kilotris) low = kilotris; if (high < kilotris) high = kilotris; - static char buffer[128]; + core::stringw fpsString; if (UserConfigParams::m_artist_debug_mode) { - sprintf( - buffer, "FPS: %i/%i/%i - PolyCount (Solid:%d Shadows:%d) - LightDst : ~%d", - min, fps, max, - poly_count[SOLID_NORMAL_AND_DEPTH_PASS], - poly_count[SHADOW_PASS], - m_last_light_bucket_distance - ); + fpsString += _("FPS: "); + fpsString += core::stringw(min); + fpsString += _("/"); + fpsString += core::stringw(fps); + fpsString += _("/"); + fpsString += core::stringw(max); + fpsString += _(" PolyCount: "); + fpsString += _(" (Solid) "); + fpsString += core::stringw(poly_count[SOLID_NORMAL_AND_DEPTH_PASS]); + fpsString += _(" (Shadows) "); + fpsString += core::stringw(poly_count[SHADOW_PASS]); + fpsString += _(" LightDist: "); + fpsString += core::stringw(m_last_light_bucket_distance); poly_count[SOLID_NORMAL_AND_DEPTH_PASS] = 0; poly_count[SHADOW_PASS] = 0; object_count[SOLID_NORMAL_AND_DEPTH_PASS] = 0; @@ -1761,12 +1767,17 @@ void IrrDriver::displayFPS() } else { - sprintf(buffer, "FPS: %i/%i/%i - %i KTris", min, fps, max, - (int)roundf(kilotris)); + fpsString += _("FPS: "); + fpsString += core::stringw(min); + fpsString += _("/"); + fpsString += core::stringw(fps); + fpsString += _("/"); + fpsString += core::stringw(max); + fpsString += _(" - "); + fpsString += core::stringw((int)roundf(kilotris)); + fpsString += _("KTris"); } - core::stringw fpsString = buffer; - static video::SColor fpsColor = video::SColor(255, 0, 0, 0); font->draw( fpsString.c_str(), core::rect< s32 >(100,0,400,50), fpsColor, false ); diff --git a/src/graphics/irr_driver.hpp b/src/graphics/irr_driver.hpp index f324b1dcd..95da8891b 100644 --- a/src/graphics/irr_driver.hpp +++ b/src/graphics/irr_driver.hpp @@ -419,7 +419,7 @@ private: void renderRSM(); void renderGlow(std::vector& glows); void renderSSAO(); - void renderLights(unsigned pointlightCount); + void renderLights(unsigned pointlightCount, bool hasShadow); void renderShadowsDebug(); void doScreenShot(); void PrepareDrawCalls(scene::ICameraSceneNode *camnode); diff --git a/src/graphics/render.cpp b/src/graphics/render.cpp index ee510d776..aa383cd20 100644 --- a/src/graphics/render.cpp +++ b/src/graphics/render.cpp @@ -311,7 +311,7 @@ void IrrDriver::renderScene(scene::ICameraSceneNode * const camnode, unsigned po // Lights { PROFILER_PUSH_CPU_MARKER("- Light", 0x00, 0xFF, 0x00); - renderLights(pointlightcount); + renderLights(pointlightcount, hasShadow); PROFILER_POP_CPU_MARKER(); } diff --git a/src/graphics/render_lighting.cpp b/src/graphics/render_lighting.cpp index d69c7a843..ee033432b 100644 --- a/src/graphics/render_lighting.cpp +++ b/src/graphics/render_lighting.cpp @@ -126,10 +126,10 @@ unsigned IrrDriver::UpdateLightsInfo(scene::ICameraSceneNode * const camnode, fl return lightnum; } -void IrrDriver::renderLights(unsigned pointlightcount) +void IrrDriver::renderLights(unsigned pointlightcount, bool hasShadow) { //RH - if (UserConfigParams::m_gi) + if (UserConfigParams::m_gi && UserConfigParams::m_shadows && hasShadow) { ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_RH)); glDisable(GL_BLEND); @@ -171,7 +171,7 @@ void IrrDriver::renderLights(unsigned pointlightcount) return; m_rtts->getFBO(FBO_DIFFUSE).Bind(); - if (UserConfigParams::m_gi) + if (UserConfigParams::m_gi && UserConfigParams::m_shadows && hasShadow) { ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_GI)); m_post_processing->renderGI(rh_matrix, rh_extend, m_rtts->getRH().getRTT()[0], m_rtts->getRH().getRTT()[1], m_rtts->getRH().getRTT()[2]); diff --git a/src/graphics/render_skybox.cpp b/src/graphics/render_skybox.cpp index 8fcd5c9a6..94d28fb2e 100644 --- a/src/graphics/render_skybox.cpp +++ b/src/graphics/render_skybox.cpp @@ -439,7 +439,7 @@ GLuint generateCubeMapFromTextures(const std::vector &texture swapPixels(tmp, rgba[i], size, x, y, (size - y - 1), x); } } - free(tmp); + delete[] tmp; } glBindTexture(GL_TEXTURE_CUBE_MAP, result); @@ -574,4 +574,4 @@ void IrrDriver::renderSkybox(const scene::ICameraSceneNode *camera) glDrawElements(GL_TRIANGLES, 6 * 6, GL_UNSIGNED_INT, 0); glBindVertexArray(0); -} \ No newline at end of file +} diff --git a/src/graphics/stkanimatedmesh.cpp b/src/graphics/stkanimatedmesh.cpp index a5c44b289..ed732a22e 100644 --- a/src/graphics/stkanimatedmesh.cpp +++ b/src/graphics/stkanimatedmesh.cpp @@ -20,7 +20,8 @@ const core::vector3df& rotation, const core::vector3df& scale) : CAnimatedMeshSceneNode(mesh, parent, mgr, id, position, rotation, scale) { - firstTime = true; + isGLInitialized = false; + isMaterialInitialized = false; } void STKAnimatedMesh::cleanGLMeshes() @@ -34,8 +35,6 @@ void STKAnimatedMesh::cleanGLMeshes() glDeleteVertexArrays(1, &(mesh.vao)); glDeleteBuffers(1, &(mesh.vertex_buffer)); glDeleteBuffers(1, &(mesh.index_buffer)); - if (mesh.instance_buffer) - glDeleteBuffers(1, &(mesh.instance_buffer)); #ifdef Bindless_Texture_Support for (unsigned j = 0; j < 6; j++) { @@ -48,16 +47,16 @@ void STKAnimatedMesh::cleanGLMeshes() void STKAnimatedMesh::setMesh(scene::IAnimatedMesh* mesh) { - firstTime = true; + isGLInitialized = false; + isMaterialInitialized = false; GLmeshes.clear(); for (unsigned i = 0; i < MAT_COUNT; i++) MeshSolidMaterial[i].clearWithoutDeleting(); CAnimatedMeshSceneNode::setMesh(mesh); } -void STKAnimatedMesh::update() +void STKAnimatedMesh::updateNoGL() { - video::IVideoDriver* driver = SceneManager->getVideoDriver(); scene::IMesh* m = getMeshForCurrentFrame(); if (m) @@ -68,8 +67,9 @@ void STKAnimatedMesh::update() return; } - if (firstTime) + if (!isMaterialInitialized) { + video::IVideoDriver* driver = SceneManager->getVideoDriver(); for (u32 i = 0; i < m->getMeshBufferCount(); ++i) { scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i); @@ -101,6 +101,32 @@ void STKAnimatedMesh::update() { MeshMaterial MatType = MaterialTypeToMeshMaterial(type, mb->getVertexType()); MeshSolidMaterial[MatType].push_back(&mesh); + } + } + isMaterialInitialized = true; + } +} + +void STKAnimatedMesh::updateGL() +{ + + scene::IMesh* m = getMeshForCurrentFrame(); + + if (!isGLInitialized) + { + for (u32 i = 0; i < m->getMeshBufferCount(); ++i) + { + scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i); + if (!mb) + continue; + video::IVideoDriver* driver = SceneManager->getVideoDriver(); + video::E_MATERIAL_TYPE type = mb->getMaterial().MaterialType; + video::IMaterialRenderer* rnd = driver->getMaterialRenderer(type); + GLMesh &mesh = GLmeshes[i]; + + if (!rnd->isTransparent()) + { + MeshMaterial MatType = MaterialTypeToMeshMaterial(type, mb->getVertexType()); InitTextures(mesh, MatType); } @@ -117,8 +143,8 @@ void STKAnimatedMesh::update() glBindVertexArray(0); } } + isGLInitialized = true; } - firstTime = false; for (u32 i = 0; igetMeshBufferCount(); ++i) { @@ -164,71 +190,6 @@ void STKAnimatedMesh::render() ++PassCount; - update(); - -/* if (irr_driver->getPhase() == SOLID_NORMAL_AND_DEPTH_PASS || irr_driver->getPhase() == SHADOW_PASS) - { - ModelViewProjectionMatrix = computeMVP(AbsoluteTransformation); - core::matrix4 invmodel; - AbsoluteTransformation.getInverse(invmodel); - - GLMesh* mesh; - for_in(mesh, MeshSolidMaterial[MAT_DEFAULT]) - pushVector(ListMatDefault::getInstance(), mesh, AbsoluteTransformation, invmodel, mesh->TextureMatrix); - - for_in(mesh, MeshSolidMaterial[MAT_ALPHA_REF]) - pushVector(ListMatAlphaRef::getInstance(), mesh, AbsoluteTransformation, invmodel, mesh->TextureMatrix); - - for_in(mesh, MeshSolidMaterial[MAT_DETAIL]) - pushVector(ListMatDetails::getInstance(), mesh, AbsoluteTransformation, invmodel, mesh->TextureMatrix); - - for_in(mesh, MeshSolidMaterial[MAT_UNLIT]) - pushVector(ListMatUnlit::getInstance(), mesh, AbsoluteTransformation, core::matrix4::EM4CONST_IDENTITY, mesh->TextureMatrix); - - return; - }*/ - - if (irr_driver->getPhase() == TRANSPARENT_PASS) - { - ModelViewProjectionMatrix = computeMVP(AbsoluteTransformation); - - if (!TransparentMesh[TM_BUBBLE].empty()) - glUseProgram(MeshShader::BubbleShader::Program); - - GLMesh* mesh; - if (World::getWorld() && World::getWorld()->isFogEnabled()) - { - const Track * const track = World::getWorld()->getTrack(); - - // Todo : put everything in a ubo - const float fogmax = track->getFogMax(); - const float startH = track->getFogStartHeight(); - const float endH = track->getFogEndHeight(); - const float start = track->getFogStart(); - const float end = track->getFogEnd(); - const video::SColor tmpcol = track->getFogColor(); - - video::SColorf col(tmpcol.getRed() / 255.0f, - tmpcol.getGreen() / 255.0f, - tmpcol.getBlue() / 255.0f); - - for_in(mesh, TransparentMesh[TM_DEFAULT]) - ListBlendTransparentFog::getInstance()->push_back( - STK::make_tuple(mesh, AbsoluteTransformation, mesh->TextureMatrix, - fogmax, startH, endH, start, end, col)); - for_in(mesh, TransparentMesh[TM_ADDITIVE]) - ListAdditiveTransparentFog::getInstance()->push_back( - STK::make_tuple(mesh, AbsoluteTransformation, mesh->TextureMatrix, - fogmax, startH, endH, start, end, col)); - } - else - { - for_in(mesh, TransparentMesh[TM_DEFAULT]) - pushVector(ListBlendTransparent::getInstance(), mesh, AbsoluteTransformation, mesh->TextureMatrix); - - for_in(mesh, TransparentMesh[TM_ADDITIVE]) - pushVector(ListAdditiveTransparent::getInstance(), mesh, AbsoluteTransformation, mesh->TextureMatrix); - } - return; - } + updateNoGL(); + updateGL(); } diff --git a/src/graphics/stkanimatedmesh.hpp b/src/graphics/stkanimatedmesh.hpp index bfcd3f571..aaa669c28 100644 --- a/src/graphics/stkanimatedmesh.hpp +++ b/src/graphics/stkanimatedmesh.hpp @@ -10,12 +10,14 @@ class STKAnimatedMesh : public irr::scene::CAnimatedMeshSceneNode, public STKMeshCommon { protected: - bool firstTime; + bool isMaterialInitialized; + bool isGLInitialized; std::vector GLmeshes; core::matrix4 ModelViewProjectionMatrix; void cleanGLMeshes(); public: - virtual void update(); + virtual void updateNoGL(); + virtual void updateGL(); STKAnimatedMesh(irr::scene::IAnimatedMesh* mesh, irr::scene::ISceneNode* parent, irr::scene::ISceneManager* mgr, irr::s32 id, const irr::core::vector3df& position = irr::core::vector3df(0,0,0), diff --git a/src/graphics/stkmesh.hpp b/src/graphics/stkmesh.hpp index f4e9d8cf0..dadeae82f 100644 --- a/src/graphics/stkmesh.hpp +++ b/src/graphics/stkmesh.hpp @@ -36,7 +36,6 @@ struct GLMesh { GLuint vao; GLuint vertex_buffer; GLuint index_buffer; - GLuint instance_buffer; video::ITexture *textures[6]; GLenum PrimitiveType; GLenum IndexType; @@ -69,7 +68,8 @@ protected: public: PtrVector MeshSolidMaterial[MAT_COUNT]; PtrVector TransparentMesh[TM_COUNT]; - virtual void update() = 0; + virtual void updateNoGL() = 0; + virtual void updateGL() = 0; virtual bool glow() const = 0; virtual bool isImmediateDraw() const { return false; } bool isCulledForPlayerCam() const { return m_culledForPlayerCam; } diff --git a/src/graphics/stkmeshscenenode.cpp b/src/graphics/stkmeshscenenode.cpp index a1026a2da..109a94f4e 100644 --- a/src/graphics/stkmeshscenenode.cpp +++ b/src/graphics/stkmeshscenenode.cpp @@ -43,63 +43,7 @@ void STKMeshSceneNode::createGLMeshes() GLmeshes.push_back(allocateMeshBuffer(mb)); } isMaterialInitialized = false; -} - -void STKMeshSceneNode::setFirstTimeMaterial() -{ - if (isMaterialInitialized) - return; - irr::video::IVideoDriver* driver = irr_driver->getVideoDriver(); - for (u32 i = 0; igetMeshBufferCount(); ++i) - { - scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i); - if (!mb) - continue; - - video::E_MATERIAL_TYPE type = mb->getMaterial().MaterialType; - f32 MaterialTypeParam = mb->getMaterial().MaterialTypeParam; - video::IMaterialRenderer* rnd = driver->getMaterialRenderer(type); - if (!isObject(type)) - { -#ifdef DEBUG - Log::warn("material", "Unhandled (static) material type : %d", type); -#endif - continue; - } - - - GLMesh &mesh = GLmeshes[i]; - if (rnd->isTransparent()) - { - TransparentMaterial TranspMat = MaterialTypeToTransparentMaterial(type, MaterialTypeParam); - if (!immediate_draw) - TransparentMesh[TranspMat].push_back(&mesh); - } - else - { - assert(!isDisplacement); - MeshMaterial MatType = MaterialTypeToMeshMaterial(type, mb->getVertexType()); - if (!immediate_draw) - { - InitTextures(mesh, MatType); - MeshSolidMaterial[MatType].push_back(&mesh); - } - } - - if (!immediate_draw && irr_driver->hasARB_base_instance()) - { - std::pair p = VAOManager::getInstance()->getBase(mb); - mesh.vaoBaseVertex = p.first; - mesh.vaoOffset = p.second; - } - else - { - fillLocalBuffer(mesh, mb); - mesh.vao = createVAO(mesh.vertex_buffer, mesh.index_buffer, mb->getVertexType()); - glBindVertexArray(0); - } - } - isMaterialInitialized = true; + isGLInitialized = false; } void STKMeshSceneNode::cleanGLMeshes() @@ -115,8 +59,6 @@ void STKMeshSceneNode::cleanGLMeshes() glDeleteBuffers(1, &(mesh.vertex_buffer)); if (mesh.index_buffer) glDeleteBuffers(1, &(mesh.index_buffer)); - if (mesh.instance_buffer) - glDeleteBuffers(1, &(mesh.instance_buffer)); #ifdef Bindless_Texture_Support for (unsigned j = 0; j < 6; j++) { @@ -170,11 +112,47 @@ void STKMeshSceneNode::updatevbo() } } -void STKMeshSceneNode::update() +void STKMeshSceneNode::updateNoGL() { Box = Mesh->getBoundingBox(); - setFirstTimeMaterial(); + if (!isMaterialInitialized) + { + irr::video::IVideoDriver* driver = irr_driver->getVideoDriver(); + for (u32 i = 0; i < Mesh->getMeshBufferCount(); ++i) + { + scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i); + if (!mb) + continue; + + video::E_MATERIAL_TYPE type = mb->getMaterial().MaterialType; + f32 MaterialTypeParam = mb->getMaterial().MaterialTypeParam; + video::IMaterialRenderer* rnd = driver->getMaterialRenderer(type); + if (!isObject(type)) + { +#ifdef DEBUG + Log::warn("material", "Unhandled (static) material type : %d", type); +#endif + continue; + } + + GLMesh &mesh = GLmeshes[i]; + if (rnd->isTransparent()) + { + TransparentMaterial TranspMat = MaterialTypeToTransparentMaterial(type, MaterialTypeParam); + if (!immediate_draw) + TransparentMesh[TranspMat].push_back(&mesh); + } + else + { + assert(!isDisplacement); + MeshMaterial MatType = MaterialTypeToMeshMaterial(type, mb->getVertexType()); + if (!immediate_draw) + MeshSolidMaterial[MatType].push_back(&mesh); + } + } + isMaterialInitialized = true; + } for (u32 i = 0; i < Mesh->getMeshBufferCount(); ++i) { @@ -185,6 +163,45 @@ void STKMeshSceneNode::update() } } +void STKMeshSceneNode::updateGL() +{ + if (isGLInitialized) + return; + for (u32 i = 0; i < Mesh->getMeshBufferCount(); ++i) + { + scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i); + if (!mb) + continue; + GLMesh &mesh = GLmeshes[i]; + + irr::video::IVideoDriver* driver = irr_driver->getVideoDriver(); + video::E_MATERIAL_TYPE type = mb->getMaterial().MaterialType; + f32 MaterialTypeParam = mb->getMaterial().MaterialTypeParam; + video::IMaterialRenderer* rnd = driver->getMaterialRenderer(type); + + + if (!rnd->isTransparent()) + { + MeshMaterial MatType = MaterialTypeToMeshMaterial(type, mb->getVertexType()); + if (!immediate_draw) + InitTextures(mesh, MatType); + } + + if (!immediate_draw && irr_driver->hasARB_base_instance()) + { + std::pair p = VAOManager::getInstance()->getBase(mb); + mesh.vaoBaseVertex = p.first; + mesh.vaoOffset = p.second; + } + else + { + fillLocalBuffer(mesh, mb); + mesh.vao = createVAO(mesh.vertex_buffer, mesh.index_buffer, mb->getVertexType()); + glBindVertexArray(0); + } + } + isGLInitialized = true; +} void STKMeshSceneNode::OnRegisterSceneNode() { @@ -205,7 +222,8 @@ void STKMeshSceneNode::render() ++PassCount; - update(); + updateNoGL(); + updateGL(); bool isTransparent; diff --git a/src/graphics/stkmeshscenenode.hpp b/src/graphics/stkmeshscenenode.hpp index a8e8724ed..fae8103ec 100644 --- a/src/graphics/stkmeshscenenode.hpp +++ b/src/graphics/stkmeshscenenode.hpp @@ -19,13 +19,15 @@ protected: void setFirstTimeMaterial(); void updatevbo(); bool isMaterialInitialized; + bool isGLInitialized; bool immediate_draw; bool update_each_frame; bool isDisplacement; bool isGlow; video::SColor glowcolor; public: - virtual void update(); + virtual void updateNoGL(); + virtual void updateGL(); void setReloadEachFrame(bool); STKMeshSceneNode(irr::scene::IMesh* mesh, ISceneNode* parent, irr::scene::ISceneManager* mgr, irr::s32 id, const irr::core::vector3df& position = irr::core::vector3df(0, 0, 0), diff --git a/src/graphics/stkscenemanager.cpp b/src/graphics/stkscenemanager.cpp index 97942d799..1c7ebe8fb 100644 --- a/src/graphics/stkscenemanager.cpp +++ b/src/graphics/stkscenemanager.cpp @@ -9,7 +9,6 @@ #include #include "callbacks.hpp" #include "utils/cpp2011.hpp" -#include #include "modes/world.hpp" #include "tracks/track.hpp" #include "lod_node.hpp" @@ -179,6 +178,7 @@ handleSTKCommon(scene::ISceneNode *Node, std::vector *Immed STKMeshCommon *node = dynamic_cast(Node); if (!node) return; + node->updateNoGL(); DeferredUpdate.push_back(node); if (node->isImmediateDraw()) @@ -507,7 +507,7 @@ void IrrDriver::PrepareDrawCalls(scene::ICameraSceneNode *camnode) break; }*/ for (unsigned i = 0; i < DeferredUpdate.size(); i++) - DeferredUpdate[i]->update(); + DeferredUpdate[i]->updateGL(); if (!irr_driver->hasARB_draw_indirect()) return; diff --git a/src/graphics/vaomanager.cpp b/src/graphics/vaomanager.cpp new file mode 100644 index 000000000..70e49bf3f --- /dev/null +++ b/src/graphics/vaomanager.cpp @@ -0,0 +1,320 @@ +#include "vaomanager.hpp" +#include "stkmesh.hpp" + +VAOManager::VAOManager() +{ + vao[0] = vao[1] = vao[2] = 0; + vbo[0] = vbo[1] = vbo[2] = 0; + ibo[0] = ibo[1] = ibo[2] = 0; + vtx_cnt[0] = vtx_cnt[1] = vtx_cnt[2] = 0; + idx_cnt[0] = idx_cnt[1] = idx_cnt[2] = 0; + vtx_mirror[0] = vtx_mirror[1] = vtx_mirror[2] = NULL; + idx_mirror[0] = idx_mirror[1] = idx_mirror[2] = NULL; + instance_count[0] = 0; + + for (unsigned i = 0; i < InstanceTypeCount; i++) + { + glGenBuffers(1, &instance_vbo[i]); + glBindBuffer(GL_ARRAY_BUFFER, instance_vbo[i]); +#ifdef Buffer_Storage + if (irr_driver->hasBufferStorageExtension()) + { + glBufferStorage(GL_ARRAY_BUFFER, 10000 * sizeof(InstanceData), 0, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT); + Ptr[i] = glMapBufferRange(GL_ARRAY_BUFFER, 0, 10000 * sizeof(InstanceData), GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT); + } + else +#endif + { + glBufferData(GL_ARRAY_BUFFER, 10000 * sizeof(InstanceData), 0, GL_STREAM_DRAW); + } + } +} + +void VAOManager::cleanInstanceVAOs() +{ + std::map, GLuint>::iterator It = InstanceVAO.begin(), E = InstanceVAO.end(); + for (; It != E; It++) + glDeleteVertexArrays(1, &(It->second)); + InstanceVAO.clear(); +} + +VAOManager::~VAOManager() +{ + cleanInstanceVAOs(); + for (unsigned i = 0; i < 3; i++) + { + if (vtx_mirror[i]) + free(vtx_mirror[i]); + if (idx_mirror[i]) + free(idx_mirror[i]); + if (vbo[i]) + glDeleteBuffers(1, &vbo[i]); + if (ibo[i]) + glDeleteBuffers(1, &ibo[i]); + if (vao[i]) + glDeleteVertexArrays(1, &vao[i]); + } + for (unsigned i = 0; i < InstanceTypeCount; i++) + { + glDeleteBuffers(1, &instance_vbo[i]); + } + +} + +void VAOManager::regenerateBuffer(enum VTXTYPE tp) +{ + glBindVertexArray(0); + if (vbo[tp]) + glDeleteBuffers(1, &vbo[tp]); + glGenBuffers(1, &vbo[tp]); + glBindBuffer(GL_ARRAY_BUFFER, vbo[tp]); +#ifdef Buffer_Storage + if (irr_driver->hasBufferStorageExtension()) + { + glBufferStorage(GL_ARRAY_BUFFER, vtx_cnt[tp] * getVertexPitch(tp), vtx_mirror[tp], GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT); + VBOPtr[tp] = glMapBufferRange(GL_ARRAY_BUFFER, 0, vtx_cnt[tp] * getVertexPitch(tp), GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT); + } + else +#endif + glBufferData(GL_ARRAY_BUFFER, vtx_cnt[tp] * getVertexPitch(tp), vtx_mirror[tp], GL_DYNAMIC_DRAW); + + + if (ibo[tp]) + glDeleteBuffers(1, &ibo[tp]); + glGenBuffers(1, &ibo[tp]); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo[tp]); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(u16)* idx_cnt[tp], idx_mirror[tp], GL_DYNAMIC_DRAW); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); +} + +void VAOManager::regenerateVAO(enum VTXTYPE tp) +{ + if (vao[tp]) + glDeleteVertexArrays(1, &vao[tp]); + glGenVertexArrays(1, &vao[tp]); + glBindVertexArray(vao[tp]); + glBindBuffer(GL_ARRAY_BUFFER, vbo[tp]); + switch (tp) + { + case VTXTYPE_STANDARD: + // Position + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), 0); + // Normal + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)12); + // Color + glEnableVertexAttribArray(2); + glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitch(tp), (GLvoid*)24); + // Texcoord + glEnableVertexAttribArray(3); + glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)28); + break; + case VTXTYPE_TCOORD: + // Position + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), 0); + // Normal + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)12); + // Color + glEnableVertexAttribArray(2); + glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitch(tp), (GLvoid*)24); + // Texcoord + glEnableVertexAttribArray(3); + glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)28); + // SecondTexcoord + glEnableVertexAttribArray(4); + glVertexAttribPointer(4, 2, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)36); + break; + case VTXTYPE_TANGENT: + // Position + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), 0); + // Normal + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)12); + // Color + glEnableVertexAttribArray(2); + glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, getVertexPitch(tp), (GLvoid*)24); + // Texcoord + glEnableVertexAttribArray(3); + glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)28); + // Tangent + glEnableVertexAttribArray(5); + glVertexAttribPointer(5, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)36); + // Bitangent + glEnableVertexAttribArray(6); + glVertexAttribPointer(6, 3, GL_FLOAT, GL_FALSE, getVertexPitch(tp), (GLvoid*)48); + break; + } + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo[tp]); + glBindVertexArray(0); +} + +void VAOManager::regenerateInstancedVAO() +{ + cleanInstanceVAOs(); + + enum video::E_VERTEX_TYPE IrrVT[] = { video::EVT_STANDARD, video::EVT_2TCOORDS, video::EVT_TANGENTS }; + for (unsigned i = 0; i < VTXTYPE_COUNT; i++) + { + video::E_VERTEX_TYPE tp = IrrVT[i]; + if (!vbo[tp] || !ibo[tp]) + continue; + GLuint vao = createVAO(vbo[tp], ibo[tp], tp); + glBindBuffer(GL_ARRAY_BUFFER, instance_vbo[InstanceTypeDefault]); + + glEnableVertexAttribArray(7); + glVertexAttribPointer(7, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), 0); + glVertexAttribDivisor(7, 1); + glEnableVertexAttribArray(8); + glVertexAttribPointer(8, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), (GLvoid*)(3 * sizeof(float))); + glVertexAttribDivisor(8, 1); + glEnableVertexAttribArray(9); + glVertexAttribPointer(9, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), (GLvoid*)(6 * sizeof(float))); + glVertexAttribDivisor(9, 1); + glEnableVertexAttribArray(10); + glVertexAttribIPointer(10, 2, GL_UNSIGNED_INT, sizeof(InstanceData), (GLvoid*)(9 * sizeof(float))); + glVertexAttribDivisor(10, 1); + glEnableVertexAttribArray(11); + glVertexAttribIPointer(11, 2, GL_UNSIGNED_INT, sizeof(InstanceData), (GLvoid*)(9 * sizeof(float) + 2 * sizeof(unsigned))); + glVertexAttribDivisor(11, 1); + InstanceVAO[std::pair(tp, InstanceTypeDefault)] = vao; + + vao = createVAO(vbo[tp], ibo[tp], tp); + glBindBuffer(GL_ARRAY_BUFFER, instance_vbo[InstanceTypeShadow]); + + glEnableVertexAttribArray(7); + glVertexAttribPointer(7, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), 0); + glVertexAttribDivisor(7, 1); + glEnableVertexAttribArray(8); + glVertexAttribPointer(8, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), (GLvoid*)(3 * sizeof(float))); + glVertexAttribDivisor(8, 1); + glEnableVertexAttribArray(9); + glVertexAttribPointer(9, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), (GLvoid*)(6 * sizeof(float))); + glVertexAttribDivisor(9, 1); + glEnableVertexAttribArray(10); + glVertexAttribIPointer(10, 2, GL_UNSIGNED_INT, sizeof(InstanceData), (GLvoid*)(9 * sizeof(float))); + glVertexAttribDivisor(10, 1); + glEnableVertexAttribArray(11); + glVertexAttribIPointer(11, 2, GL_UNSIGNED_INT, sizeof(InstanceData), (GLvoid*)(9 * sizeof(float) + 2 * sizeof(unsigned))); + glVertexAttribDivisor(11, 1); + InstanceVAO[std::pair(tp, InstanceTypeShadow)] = vao; + + vao = createVAO(vbo[tp], ibo[tp], tp); + glBindBuffer(GL_ARRAY_BUFFER, instance_vbo[InstanceTypeRSM]); + + glEnableVertexAttribArray(7); + glVertexAttribPointer(7, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), 0); + glVertexAttribDivisor(7, 1); + glEnableVertexAttribArray(8); + glVertexAttribPointer(8, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), (GLvoid*)(3 * sizeof(float))); + glVertexAttribDivisor(8, 1); + glEnableVertexAttribArray(9); + glVertexAttribPointer(9, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), (GLvoid*)(6 * sizeof(float))); + glVertexAttribDivisor(9, 1); + glEnableVertexAttribArray(10); + glVertexAttribIPointer(10, 2, GL_UNSIGNED_INT, sizeof(InstanceData), (GLvoid*)(9 * sizeof(float))); + glVertexAttribDivisor(10, 1); + glEnableVertexAttribArray(11); + glVertexAttribIPointer(11, 2, GL_UNSIGNED_INT, sizeof(InstanceData), (GLvoid*)(9 * sizeof(float) + 2 * sizeof(unsigned))); + glVertexAttribDivisor(11, 1); + InstanceVAO[std::pair(tp, InstanceTypeRSM)] = vao; + + vao = createVAO(vbo[tp], ibo[tp], tp); + glBindBuffer(GL_ARRAY_BUFFER, instance_vbo[InstanceTypeGlow]); + + glEnableVertexAttribArray(7); + glVertexAttribPointer(7, 3, GL_FLOAT, GL_FALSE, sizeof(GlowInstanceData), 0); + glVertexAttribDivisor(7, 1); + glEnableVertexAttribArray(8); + glVertexAttribPointer(8, 3, GL_FLOAT, GL_FALSE, sizeof(GlowInstanceData), (GLvoid*)(3 * sizeof(float))); + glVertexAttribDivisor(8, 1); + glEnableVertexAttribArray(9); + glVertexAttribPointer(9, 3, GL_FLOAT, GL_FALSE, sizeof(GlowInstanceData), (GLvoid*)(6 * sizeof(float))); + glVertexAttribDivisor(9, 1); + glEnableVertexAttribArray(12); + glVertexAttribPointer(12, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(GlowInstanceData), (GLvoid*)(9 * sizeof(float))); + glVertexAttribDivisor(12, 1); + InstanceVAO[std::pair(tp, InstanceTypeGlow)] = vao; + glBindVertexArray(0); + } + + + +} + +size_t VAOManager::getVertexPitch(enum VTXTYPE tp) const +{ + switch (tp) + { + case VTXTYPE_STANDARD: + return getVertexPitchFromType(video::EVT_STANDARD); + case VTXTYPE_TCOORD: + return getVertexPitchFromType(video::EVT_2TCOORDS); + case VTXTYPE_TANGENT: + return getVertexPitchFromType(video::EVT_TANGENTS); + default: + assert(0 && "Wrong vtxtype"); + return -1; + } +} + +VAOManager::VTXTYPE VAOManager::getVTXTYPE(video::E_VERTEX_TYPE type) +{ + switch (type) + { + default: + assert(0 && "Wrong vtxtype"); + case video::EVT_STANDARD: + return VTXTYPE_STANDARD; + case video::EVT_2TCOORDS: + return VTXTYPE_TCOORD; + case video::EVT_TANGENTS: + return VTXTYPE_TANGENT; + } +}; + +void VAOManager::append(scene::IMeshBuffer *mb, VTXTYPE tp) +{ + size_t old_vtx_cnt = vtx_cnt[tp]; + vtx_cnt[tp] += mb->getVertexCount(); + vtx_mirror[tp] = realloc(vtx_mirror[tp], vtx_cnt[tp] * getVertexPitch(tp)); + intptr_t dstptr = (intptr_t)vtx_mirror[tp] + (old_vtx_cnt * getVertexPitch(tp)); + memcpy((void *)dstptr, mb->getVertices(), mb->getVertexCount() * getVertexPitch(tp)); + mappedBaseVertex[tp][mb] = old_vtx_cnt; + + size_t old_idx_cnt = idx_cnt[tp]; + idx_cnt[tp] += mb->getIndexCount(); + idx_mirror[tp] = realloc(idx_mirror[tp], idx_cnt[tp] * sizeof(u16)); + + dstptr = (intptr_t)idx_mirror[tp] + (old_idx_cnt * sizeof(u16)); + memcpy((void *)dstptr, mb->getIndices(), mb->getIndexCount() * sizeof(u16)); + mappedBaseIndex[tp][mb] = old_idx_cnt * sizeof(u16); +} + +std::pair VAOManager::getBase(scene::IMeshBuffer *mb) +{ + VTXTYPE tp = getVTXTYPE(mb->getVertexType()); + if (mappedBaseVertex[tp].find(mb) == mappedBaseVertex[tp].end()) + { + assert(mappedBaseIndex[tp].find(mb) == mappedBaseIndex[tp].end()); + storedCPUBuffer[tp].push_back(mb); + append(mb, tp); + regenerateBuffer(tp); + regenerateVAO(tp); + regenerateInstancedVAO(); + } + + std::unordered_map::iterator It; + It = mappedBaseVertex[tp].find(mb); + assert(It != mappedBaseVertex[tp].end()); + unsigned vtx = It->second; + It = mappedBaseIndex[tp].find(mb); + assert(It != mappedBaseIndex[tp].end()); + return std::pair(vtx, It->second); +} diff --git a/src/graphics/vaomanager.hpp b/src/graphics/vaomanager.hpp new file mode 100644 index 000000000..39056c0aa --- /dev/null +++ b/src/graphics/vaomanager.hpp @@ -0,0 +1,114 @@ +#ifndef VAOMANAGER_HPP +#define VAOMANAGER_HPP + +#include "gl_headers.hpp" +#include "utils/singleton.hpp" +#include "irr_driver.hpp" +#include +#include +#include + +enum InstanceType +{ + InstanceTypeDefault, + InstanceTypeShadow, + InstanceTypeRSM, + InstanceTypeGlow, + InstanceTypeCount, +}; + +#ifdef WIN32 +#pragma pack(push, 1) +#endif +struct InstanceData +{ + struct + { + float X; + float Y; + float Z; + } Origin; + struct + { + float X; + float Y; + float Z; + } Orientation; + struct + { + float X; + float Y; + float Z; + } Scale; + uint64_t Texture; + uint64_t SecondTexture; +#ifdef WIN32 +}; +#else +} __attribute__((packed)); +#endif + +struct GlowInstanceData +{ + struct + { + float X; + float Y; + float Z; + } Origin; + struct + { + float X; + float Y; + float Z; + } Orientation; + struct + { + float X; + float Y; + float Z; + } Scale; + unsigned Color; +#ifdef WIN32 +}; +#else +} __attribute__((packed)); +#endif +#ifdef WIN32 +#pragma pack(pop) +#endif + +class VAOManager : public Singleton +{ + enum VTXTYPE { VTXTYPE_STANDARD, VTXTYPE_TCOORD, VTXTYPE_TANGENT, VTXTYPE_COUNT }; + GLuint vbo[VTXTYPE_COUNT], ibo[VTXTYPE_COUNT], vao[VTXTYPE_COUNT]; + GLuint instance_vbo[InstanceTypeCount]; + size_t instance_count[InstanceTypeCount]; + void *Ptr[InstanceTypeCount]; + void *VBOPtr[VTXTYPE_COUNT]; + std::vector storedCPUBuffer[VTXTYPE_COUNT]; + void *vtx_mirror[VTXTYPE_COUNT], *idx_mirror[VTXTYPE_COUNT]; + size_t vtx_cnt[VTXTYPE_COUNT], idx_cnt[VTXTYPE_COUNT]; + std::unordered_map mappedBaseVertex[VTXTYPE_COUNT], mappedBaseIndex[VTXTYPE_COUNT]; + std::map, GLuint> InstanceVAO; + + void cleanInstanceVAOs(); + void regenerateBuffer(enum VTXTYPE); + void regenerateVAO(enum VTXTYPE); + void regenerateInstancedVAO(); + size_t getVertexPitch(enum VTXTYPE) const; + VTXTYPE getVTXTYPE(video::E_VERTEX_TYPE type); + void append(scene::IMeshBuffer *, VTXTYPE tp); +public: + VAOManager(); + std::pair getBase(scene::IMeshBuffer *); + GLuint getInstanceBuffer(InstanceType it) { return instance_vbo[it]; } + void *getInstanceBufferPtr(InstanceType it) { return Ptr[it]; } + unsigned getVBO(video::E_VERTEX_TYPE type) { return vbo[getVTXTYPE(type)]; } + void *getVBOPtr(video::E_VERTEX_TYPE type) { return VBOPtr[getVTXTYPE(type)]; } + unsigned getVAO(video::E_VERTEX_TYPE type) { return vao[getVTXTYPE(type)]; } + unsigned getInstanceVAO(video::E_VERTEX_TYPE vt, enum InstanceType it) { return InstanceVAO[std::pair(vt, it)]; } + ~VAOManager(); +}; + +#endif \ No newline at end of file diff --git a/src/io/file_manager.cpp b/src/io/file_manager.cpp index 71e9ab6ee..f429c44c9 100644 --- a/src/io/file_manager.cpp +++ b/src/io/file_manager.cpp @@ -422,7 +422,7 @@ XMLNode *FileManager::createXMLTreeFromString(const std::string & content) { char *b = new char[content.size()]; memcpy(b, content.c_str(), content.size()); - io::IReadFile * ireadfile = m_file_system->createMemoryReadFile(b, strlen(b), "tempfile", true); + io::IReadFile * ireadfile = m_file_system->createMemoryReadFile(b, content.size(), "tempfile", true); io::IXMLReader * reader = m_file_system->createXMLReader(ireadfile); XMLNode* node = new XMLNode(reader); reader->drop(); @@ -791,7 +791,7 @@ void FileManager::checkAndCreateConfigDir() { m_user_config_dir = getenv("HOME"); checkAndCreateDirectory(m_user_config_dir); - + m_user_config_dir += "/.config"; if(!checkAndCreateDirectory(m_user_config_dir)) { diff --git a/src/states_screens/track_info_screen.cpp b/src/states_screens/track_info_screen.cpp index 0e8914283..de3852755 100644 --- a/src/states_screens/track_info_screen.cpp +++ b/src/states_screens/track_info_screen.cpp @@ -193,6 +193,9 @@ void TrackInfoScreen::init() getWidget("highscore2")->setVisible(false); getWidget("highscore3")->setVisible(false); } + + RibbonWidget* bt_start = getWidget("buttons"); + bt_start->setFocusForPlayer(PLAYER_ID_GAME_MASTER); } // init @@ -325,3 +328,37 @@ void TrackInfoScreen::eventCallback(Widget* widget, const std::string& name, } // eventCallback // ---------------------------------------------------------------------------- +GUIEngine::EventPropagation TrackInfoScreen::filterActions(PlayerAction action, + int deviceID, + const unsigned int value, + Input::InputType type, + int playerId) +{ + GUIEngine::EventPropagation result = EVENT_LET; + RibbonWidget* bt_start = getWidget("buttons"); + + switch (action) + { + case PA_MENU_LEFT: + case PA_MENU_RIGHT: + { + if (bt_start->isFocusedForPlayer(playerId)) + { + result = EVENT_BLOCK; + } + + break; + } + case PA_MENU_UP: + case PA_MENU_DOWN: + case PA_MENU_SELECT: + case PA_MENU_CANCEL: + break; + default: + break; + } + + return result; +} // filterActions + +// ----------------------------------------------------------------------------- diff --git a/src/states_screens/track_info_screen.hpp b/src/states_screens/track_info_screen.hpp index 00387bc60..ee2668ad8 100644 --- a/src/states_screens/track_info_screen.hpp +++ b/src/states_screens/track_info_screen.hpp @@ -74,6 +74,14 @@ public: virtual void loadedFromFile(); virtual void eventCallback(GUIEngine::Widget *,const std::string &name , const int player_id); + + /** \brief implement callback from parent class GUIEngine::Screen */ + virtual GUIEngine::EventPropagation filterActions( PlayerAction action, + int deviceID, + const unsigned int value, + Input::InputType type, + int playerId) OVERRIDE; + void onEnterPressedInternal(); void setTrack(Track *track); };