From f37afa88b8a4f6633c723521a44fd52a5b4c17af Mon Sep 17 00:00:00 2001 From: Marianne Gagnon Date: Wed, 25 Jun 2014 19:09:03 -0400 Subject: [PATCH 1/6] Only assign tangents for mesh buffers that actually use normal maps --- src/graphics/mesh_tools.cpp | 356 +++++++++++++++++++++++ src/graphics/mesh_tools.hpp | 8 +- src/tracks/track.cpp | 10 +- src/tracks/track_object_presentation.cpp | 7 +- 4 files changed, 370 insertions(+), 11 deletions(-) diff --git a/src/graphics/mesh_tools.cpp b/src/graphics/mesh_tools.cpp index 49c7814a0..9312af2ad 100644 --- a/src/graphics/mesh_tools.cpp +++ b/src/graphics/mesh_tools.cpp @@ -17,9 +17,11 @@ // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "graphics/mesh_tools.hpp" +#include #include #include #include "utils/log.hpp" +#include "graphics/irr_driver.hpp" void MeshTools::minMax3D(scene::IMesh* mesh, Vec3 *min, Vec3 *max) { @@ -80,3 +82,357 @@ void MeshTools::minMax3D(scene::IMesh* mesh, Vec3 *min, Vec3 *max) { } // for i +void recalculateTangentsT(scene::IMeshBuffer* buffer, bool recalculateNormals, bool smooth, bool angleWeighted) +{ + if (!buffer || (buffer->getVertexType() != video::EVT_TANGENTS)) + return; + + const u32 vtxCnt = buffer->getVertexCount(); + const u32 idxCnt = buffer->getIndexCount(); + + T* idx = reinterpret_cast(buffer->getIndices()); + video::S3DVertexTangents* v = + (video::S3DVertexTangents*)buffer->getVertices(); + + if (smooth) + { + u32 i; + + for (i = 0; i != vtxCnt; ++i) + { + if (recalculateNormals) + v[i].Normal.set(0.f, 0.f, 0.f); + v[i].Tangent.set(0.f, 0.f, 0.f); + v[i].Binormal.set(0.f, 0.f, 0.f); + } + + //Each vertex gets the sum of the tangents and binormals from the faces around it + for (i = 0; igetVertexType() == video::EVT_TANGENTS)) + { + if (buffer->getIndexType() == video::EIT_16BIT) + recalculateTangentsT(buffer, recalculateNormals, smooth, angleWeighted); + else + recalculateTangentsT(buffer, recalculateNormals, smooth, angleWeighted); + } +} + +// Copied from irrlicht +void recalculateTangents(scene::IMesh* mesh, bool recalculateNormals, bool smooth, bool angleWeighted) +{ + if (!mesh) + return; + + const u32 meshBufferCount = mesh->getMeshBufferCount(); + for (u32 b = 0; bgetMeshBuffer(b), recalculateNormals, smooth, angleWeighted); + } +} + +bool MeshTools::isNormalMap(scene::IMeshBuffer* mb) +{ + return (mb->getMaterial().MaterialType == irr_driver->getShader(ES_NORMAL_MAP)); +} + +// Copied from irrlicht +scene::IMesh* MeshTools::createMeshWithTangents(scene::IMesh* mesh, bool(*predicate)(scene::IMeshBuffer*), + bool recalculateNormals, bool smooth, bool angleWeighted, bool calculateTangents) +{ + if (!mesh) + return 0; + + // copy mesh and fill data into SMeshBufferTangents + + scene::SMesh* clone = new scene::SMesh(); + const u32 meshBufferCount = mesh->getMeshBufferCount(); + + bool needsNormalMap = false; + for (u32 b = 0; b < meshBufferCount; ++b) + { + scene::IMeshBuffer* original = mesh->getMeshBuffer(b); + if (predicate(original)) + { + needsNormalMap = true; + break; + } + } + + if (!needsNormalMap) + { + return mesh; + } + + for (u32 b = 0; bgetMeshBuffer(b); + const u32 idxCnt = original->getIndexCount(); + const u16* idx = original->getIndices(); + + if (!predicate(original)) + { + clone->addMeshBuffer(original); + continue; + } + + scene::SMeshBufferTangents* buffer = new scene::SMeshBufferTangents(); + + buffer->Material = original->getMaterial(); + buffer->Vertices.reallocate(idxCnt); + buffer->Indices.reallocate(idxCnt); + + core::map vertMap; + int vertLocation; + + // copy vertices + + const video::E_VERTEX_TYPE vType = original->getVertexType(); + video::S3DVertexTangents vNew; + for (u32 i = 0; igetVertices(); + vNew = video::S3DVertexTangents( + v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords); + } + break; + case video::EVT_2TCOORDS: + { + const video::S3DVertex2TCoords* v = + (const video::S3DVertex2TCoords*)original->getVertices(); + vNew = video::S3DVertexTangents( + v[idx[i]].Pos, v[idx[i]].Normal, v[idx[i]].Color, v[idx[i]].TCoords); + } + break; + case video::EVT_TANGENTS: + { + const video::S3DVertexTangents* v = + (const video::S3DVertexTangents*)original->getVertices(); + vNew = v[idx[i]]; + } + break; + } + core::map::Node* n = vertMap.find(vNew); + if (n) + { + vertLocation = n->getValue(); + } + else + { + vertLocation = buffer->Vertices.size(); + buffer->Vertices.push_back(vNew); + vertMap.insert(vNew, vertLocation); + } + + // create new indices + buffer->Indices.push_back(vertLocation); + } + buffer->recalculateBoundingBox(); + + // add new buffer + clone->addMeshBuffer(buffer); + buffer->drop(); + } + + clone->recalculateBoundingBox(); + if (calculateTangents) + recalculateTangents(clone, recalculateNormals, smooth, angleWeighted); + + return clone; +} + diff --git a/src/graphics/mesh_tools.hpp b/src/graphics/mesh_tools.hpp index 7d8d6337c..84bfa5555 100644 --- a/src/graphics/mesh_tools.hpp +++ b/src/graphics/mesh_tools.hpp @@ -21,7 +21,7 @@ namespace irr { - namespace scene { class IMesh; } + namespace scene { class IMesh; class IMeshBuffer; } } using namespace irr; @@ -33,6 +33,12 @@ using namespace irr; namespace MeshTools { void minMax3D(scene::IMesh* mesh, Vec3 *min, Vec3 *max); + + bool isNormalMap(scene::IMeshBuffer* mb); + + // Copied from irrlicht + scene::IMesh* createMeshWithTangents(scene::IMesh* mesh, bool(*predicate)(scene::IMeshBuffer*), + bool recalculateNormals = false, bool smooth = false, bool angleWeighted = false, bool calculateTangents = true); } // MeshTools #endif diff --git a/src/tracks/track.cpp b/src/tracks/track.cpp index a7d29b676..2fc317564 100644 --- a/src/tracks/track.cpp +++ b/src/tracks/track.cpp @@ -705,6 +705,8 @@ void Track::createPhysicsModel(unsigned int main_track_count) } // createPhysicsModel // ----------------------------------------------------------------------------- + + /** Convert the graohics track into its physics equivalents. * \param mesh The mesh to convert. * \param node The scene node. @@ -952,9 +954,7 @@ bool Track::loadMainTrack(const XMLNode &root) merged_mesh->addMesh(mesh); merged_mesh->finalize(); - scene::IMeshManipulator* manip = irr_driver->getVideoDriver()->getMeshManipulator(); - // TODO: memory leak? - scene::IMesh* tangent_mesh = manip->createMeshWithTangents(merged_mesh); + scene::IMesh* tangent_mesh = MeshTools::createMeshWithTangents(merged_mesh, &MeshTools::isNormalMap); adjustForFog(tangent_mesh, NULL); @@ -1163,8 +1163,6 @@ bool Track::loadMainTrack(const XMLNode &root) if (tangent) { - scene::IMeshManipulator* manip = irr_driver->getVideoDriver()->getMeshManipulator(); - scene::IMesh* original_mesh = irr_driver->getMesh(full_path); if (std::find(m_detached_cached_meshes.begin(), @@ -1186,7 +1184,7 @@ bool Track::loadMainTrack(const XMLNode &root) scene_node->remove(); irr_driver->grabAllTextures(original_mesh); - scene::IMesh* mesh = manip->createMeshWithTangents(original_mesh); + scene::IMesh* mesh = MeshTools::createMeshWithTangents(original_mesh, &MeshTools::isNormalMap); mesh->grab(); irr_driver->grabAllTextures(mesh); diff --git a/src/tracks/track_object_presentation.cpp b/src/tracks/track_object_presentation.cpp index 90bedf4f4..732e57224 100644 --- a/src/tracks/track_object_presentation.cpp +++ b/src/tracks/track_object_presentation.cpp @@ -24,6 +24,7 @@ #include "config/user_config.hpp" #include "graphics/irr_driver.hpp" #include "graphics/material_manager.hpp" +#include "graphics/mesh_tools.hpp" #include "graphics/particle_emitter.hpp" #include "graphics/particle_kind_manager.hpp" #include "graphics/stkinstancedscenenode.hpp" @@ -266,10 +267,8 @@ TrackObjectPresentationMesh::TrackObjectPresentationMesh(const XMLNode& xml_node if (tangent) { - scene::IMeshManipulator* manip = irr_driver->getVideoDriver()->getMeshManipulator(); - // TODO: perhaps the original mesh leaks here? - m_mesh = manip->createMeshWithTangents(m_mesh); - } + m_mesh = MeshTools::createMeshWithTangents(m_mesh, &MeshTools::isNormalMap); + } } if (!m_mesh) From 0a7e1312b55b570d3f32a9605ccc354af7d8ec6f Mon Sep 17 00:00:00 2001 From: Vincent Lejeune Date: Sun, 6 Jul 2014 17:56:02 +0200 Subject: [PATCH 2/6] Support for glDrawElements{Instanced}?BaseVertex --- src/graphics/glwrap.cpp | 4 ++++ src/graphics/glwrap.hpp | 2 ++ 2 files changed, 6 insertions(+) diff --git a/src/graphics/glwrap.cpp b/src/graphics/glwrap.cpp index bfb5a7e11..0f51896b9 100644 --- a/src/graphics/glwrap.cpp +++ b/src/graphics/glwrap.cpp @@ -47,7 +47,9 @@ PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation; PFNGLBLENDEQUATIONPROC glBlendEquation; PFNGLVERTEXATTRIBDIVISORPROC glVertexAttribDivisor; PFNGLDRAWARRAYSINSTANCEDPROC glDrawArraysInstanced; +PFNGLDRAWELEMENTSBASEVERTEXPROC glDrawElementsBaseVertex; PFNGLDRAWELEMENTSINSTANCEDPROC glDrawElementsInstanced; +PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC glDrawElementsInstancedBaseVertex; PFNGLDELETEBUFFERSPROC glDeleteBuffers; PFNGLGENVERTEXARRAYSPROC glGenVertexArrays; PFNGLBINDVERTEXARRAYPROC glBindVertexArray; @@ -201,7 +203,9 @@ void initGL() glBlendEquation = (PFNGLBLENDEQUATIONPROC)IRR_OGL_LOAD_EXTENSION("glBlendEquation"); glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISORPROC)IRR_OGL_LOAD_EXTENSION("glVertexAttribDivisor"); glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDPROC)IRR_OGL_LOAD_EXTENSION("glDrawArraysInstanced"); + glDrawElementsBaseVertex = (PFNGLDRAWELEMENTSBASEVERTEXPROC)IRR_OGL_LOAD_EXTENSION("glDrawElementsBaseVertex"); glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDPROC)IRR_OGL_LOAD_EXTENSION("glDrawElementsInstanced"); + glDrawElementsInstancedBaseVertex = (PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC)IRR_OGL_LOAD_EXTENSION("glDrawElementsInstancedBaseVertex"); glDeleteBuffers = (PFNGLDELETEBUFFERSPROC)IRR_OGL_LOAD_EXTENSION("glDeleteBuffers"); glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC)IRR_OGL_LOAD_EXTENSION("glGenVertexArrays"); glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC)IRR_OGL_LOAD_EXTENSION("glBindVertexArray"); diff --git a/src/graphics/glwrap.hpp b/src/graphics/glwrap.hpp index 186e0c9dc..11cf8474b 100644 --- a/src/graphics/glwrap.hpp +++ b/src/graphics/glwrap.hpp @@ -73,7 +73,9 @@ extern PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation; extern PFNGLBLENDEQUATIONPROC glBlendEquation; extern PFNGLVERTEXATTRIBDIVISORPROC glVertexAttribDivisor; extern PFNGLDRAWARRAYSINSTANCEDPROC glDrawArraysInstanced; +extern PFNGLDRAWELEMENTSBASEVERTEXPROC glDrawElementsBaseVertex; extern PFNGLDRAWELEMENTSINSTANCEDPROC glDrawElementsInstanced; +extern PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC glDrawElementsInstancedBaseVertex; extern PFNGLDELETEBUFFERSPROC glDeleteBuffers; extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays; extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray; From afd97345f7f79829c8c04f7ffea84f4d805aa3ad Mon Sep 17 00:00:00 2001 From: Vincent Lejeune Date: Sun, 6 Jul 2014 17:56:20 +0200 Subject: [PATCH 3/6] Add a global VAO manager --- src/graphics/glwrap.cpp | 229 ++++++++++++++++++++++++++++++++++++++++ src/graphics/glwrap.hpp | 5 + src/tracks/track.cpp | 1 + 3 files changed, 235 insertions(+) diff --git a/src/graphics/glwrap.cpp b/src/graphics/glwrap.cpp index 0f51896b9..302f36a98 100644 --- a/src/graphics/glwrap.cpp +++ b/src/graphics/glwrap.cpp @@ -508,6 +508,235 @@ void setTexture(unsigned TextureUnit, GLuint TextureId, GLenum MagFilter, GLenum glGetError(); } +class VBOGatherer +{ + enum VTXTYPE { VTXTYPE_STANDARD, VTXTYPE_TCOORD, VTXTYPE_TANGENT, VTXTYPE_COUNT }; + GLuint vbo[VTXTYPE_COUNT], ibo[VTXTYPE_COUNT], vao[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]; + + void regenerateBuffer(enum VTXTYPE); + void regenerateVAO(enum VTXTYPE); + size_t getVertexPitch(enum VTXTYPE) const; + VTXTYPE getVTXTYPE(video::E_VERTEX_TYPE type); + void append(scene::IMeshBuffer *, VBOGatherer::VTXTYPE tp); +public: + VBOGatherer(); + std::pair getBase(scene::IMeshBuffer *); + unsigned getVBO(video::E_VERTEX_TYPE type) { return vbo[getVTXTYPE(type)]; } + unsigned getVAO(video::E_VERTEX_TYPE type) { return vao[getVTXTYPE(type)]; } + ~VBOGatherer() + { + for (unsigned i = 0; i < VTXTYPE_COUNT; i++) + { + if (vbo[i]) + glDeleteBuffers(1, &vbo[i]); + if (ibo[i]) + glDeleteBuffers(1, &ibo[i]); + if (vao[i]) + glDeleteVertexArrays(1, &vao[i]); + } + } +}; + +VBOGatherer::VBOGatherer() +{ + 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; +} + +void VBOGatherer::regenerateBuffer(enum VTXTYPE tp) +{ + glBindVertexArray(0); + if (vbo[tp]) + glDeleteBuffers(1, &vbo[tp]); + glGenBuffers(1, &vbo[tp]); + glBindBuffer(GL_ARRAY_BUFFER, vbo[tp]); + glBufferData(GL_ARRAY_BUFFER, vtx_cnt[tp] * getVertexPitch(tp), vtx_mirror[tp], GL_STATIC_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_STATIC_DRAW); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); +} + +void VBOGatherer::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); +} + +size_t VBOGatherer::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; + } +} + +VBOGatherer::VTXTYPE VBOGatherer::getVTXTYPE(video::E_VERTEX_TYPE type) +{ + switch (type) + { + case video::EVT_STANDARD: + return VTXTYPE_STANDARD; + case video::EVT_2TCOORDS: + return VTXTYPE_TCOORD; + case video::EVT_TANGENTS: + return VTXTYPE_TANGENT; + default: + assert(0 && "Wrong vtxtype"); + } +}; + +void VBOGatherer::append(scene::IMeshBuffer *mb, VBOGatherer::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 VBOGatherer::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); + } + + 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); +} + +static VBOGatherer *gatherersingleton = 0; + +std::pair getVAOOffsetAndBase(scene::IMeshBuffer *mb) +{ + if (!gatherersingleton) + gatherersingleton = new VBOGatherer(); + return gatherersingleton->getBase(mb); +} + +unsigned getVBO(video::E_VERTEX_TYPE type) +{ + if (gatherersingleton) + return gatherersingleton->getVBO(type); + return 0; +} + +unsigned getVAO(video::E_VERTEX_TYPE type) +{ + if (gatherersingleton) + return gatherersingleton->getVAO(type); + return 0; +} + +void resetVAO() +{ + if (gatherersingleton) + delete gatherersingleton; + gatherersingleton = 0; +} + ScopedGPUTimer::ScopedGPUTimer(GPUTimer &timer) { if (!UserConfigParams::m_profiler_enabled) return; diff --git a/src/graphics/glwrap.hpp b/src/graphics/glwrap.hpp index 11cf8474b..90a3cf379 100644 --- a/src/graphics/glwrap.hpp +++ b/src/graphics/glwrap.hpp @@ -236,6 +236,11 @@ 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); +std::pair getVAOOffsetAndBase(scene::IMeshBuffer *mb); +unsigned getVAO(video::E_VERTEX_TYPE type); +unsigned getVBO(video::E_VERTEX_TYPE type); +void resetVAO(); + void draw3DLine(const core::vector3df& start, const core::vector3df& end, irr::video::SColor color); diff --git a/src/tracks/track.cpp b/src/tracks/track.cpp index 2fc317564..0b03e0bed 100644 --- a/src/tracks/track.cpp +++ b/src/tracks/track.cpp @@ -267,6 +267,7 @@ void Track::cleanup() { QuadGraph::destroy(); ItemManager::destroy(); + resetVAO(); ParticleKindManager::get()->cleanUpTrackSpecificGfx(); // Clear reminder of transformed textures From 6276cafba266569c3e86845c2208c3b4a6868244 Mon Sep 17 00:00:00 2001 From: vlj Date: Wed, 25 Jun 2014 14:53:49 +0200 Subject: [PATCH 4/6] Use global VAO for rendering --- data/shaders/transparent.frag | 9 +- data/shaders/transparentfog.frag | 29 +- src/graphics/render.cpp | 315 +++++++++++++++-- src/graphics/stkanimatedmesh.cpp | 47 ++- src/graphics/stkinstancedscenenode.cpp | 23 +- src/graphics/stkmesh.cpp | 456 ++++++++----------------- src/graphics/stkmesh.hpp | 28 +- src/graphics/stkmeshscenenode.cpp | 270 +++++++++++---- src/graphics/stkmeshscenenode.hpp | 3 +- 9 files changed, 703 insertions(+), 477 deletions(-) diff --git a/data/shaders/transparent.frag b/data/shaders/transparent.frag index cf94eed53..aaeba0601 100644 --- a/data/shaders/transparent.frag +++ b/data/shaders/transparent.frag @@ -1,18 +1,15 @@ uniform sampler2D tex; -#if __VERSION__ >= 130 in vec2 uv; in vec4 color; out vec4 FragColor; -#else -varying vec2 uv; -#define FragColor gl_FragColor -#endif void main() { - vec4 Color = texture(tex, uv) * pow(color, vec4(2.2)); + vec4 Color = texture(tex, uv); + Color.xyz *= pow(color.xyz, vec3(2.2)); + Color.a *= color.a; // Premultiply alpha FragColor = vec4(Color.rgb * Color.a, Color.a); } diff --git a/data/shaders/transparentfog.frag b/data/shaders/transparentfog.frag index 756901baf..76e315a0d 100644 --- a/data/shaders/transparentfog.frag +++ b/data/shaders/transparentfog.frag @@ -18,31 +18,28 @@ layout (std140) uniform MatrixesData vec2 screen; }; -#if __VERSION__ >= 130 in vec2 uv; in vec4 color; out vec4 FragColor; -#else -varying vec2 uv; -#define FragColor gl_FragColor -#endif void main() { - vec4 diffusecolor = texture(tex, uv) * pow(color, vec4(2.2)); - vec3 tmp = vec3(gl_FragCoord.xy / screen, gl_FragCoord.z); - tmp = 2. * tmp - 1.; + vec4 diffusecolor = texture(tex, uv); + diffusecolor.xyz *= pow(color.xyz, vec3(2.2)); + diffusecolor.a *= color.a; + vec3 tmp = vec3(gl_FragCoord.xy / screen, gl_FragCoord.z); + tmp = 2. * tmp - 1.; - vec4 xpos = vec4(tmp, 1.0); - xpos = InverseProjectionMatrix * xpos; - xpos.xyz /= xpos.w; + vec4 xpos = vec4(tmp, 1.0); + xpos = InverseProjectionMatrix * xpos; + xpos.xyz /= xpos.w; - float dist = length(xpos.xyz); - float fog = smoothstep(start, end, dist); + float dist = length(xpos.xyz); + float fog = smoothstep(start, end, dist); - fog = min(fog, fogmax); + fog = min(fog, fogmax); - vec4 color = vec4(vec4(col, 0.) * fog + diffusecolor *(1. - fog)); - FragColor = vec4(color.rgb * color.a, color.a); + vec4 finalcolor = vec4(col, 0.) * fog + diffusecolor *(1. - fog); + FragColor = vec4(finalcolor.rgb * finalcolor.a, finalcolor.a); } diff --git a/src/graphics/render.cpp b/src/graphics/render.cpp index 729d3992e..e7c2dbb6d 100644 --- a/src/graphics/render.cpp +++ b/src/graphics/render.cpp @@ -512,7 +512,8 @@ void IrrDriver::renderSolidFirstPass() glDisable(GL_BLEND); glEnable(GL_CULL_FACE); irr_driver->setPhase(SOLID_NORMAL_AND_DEPTH_PASS); - GroupedFPSM::reset(); + GroupedFPSM::reset(); + GroupedFPSM::reset(); GroupedFPSM::reset(); GroupedFPSM::reset(); m_scene_manager->drawAll(scene::ESNRP_SOLID); @@ -523,34 +524,58 @@ void IrrDriver::renderSolidFirstPass() { ScopedGPUTimer Timer(getGPUTimer(Q_SOLID_PASS1)); glUseProgram(MeshShader::ObjectPass1Shader::Program); - for (unsigned i = 0; i < GroupedFPSM::MeshSet.size(); ++i) + glBindVertexArray(getVAO(video::EVT_STANDARD)); + for (unsigned i = 0; i < GroupedFPSM::MeshSet.size(); ++i) { - GLMesh &mesh = *GroupedFPSM::MeshSet[i]; + GLMesh &mesh = *GroupedFPSM::MeshSet[i]; if (!mesh.textures[0]) mesh.textures[0] = getUnicolorTexture(video::SColor(255, 255, 255, 255)); compressTexture(mesh.textures[0], true); setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - draw(mesh, mesh.vao, GroupedFPSM::MVPSet[i], GroupedFPSM::TIMVSet[i], 0); + draw(mesh, GroupedFPSM::MVPSet[i], GroupedFPSM::TIMVSet[i], 0); + } + + glBindVertexArray(getVAO(video::EVT_2TCOORDS)); + for (unsigned i = 0; i < GroupedFPSM::MeshSet.size(); ++i) + { + GLMesh &mesh = *GroupedFPSM::MeshSet[i]; + if (!mesh.textures[0]) + mesh.textures[0] = getUnicolorTexture(video::SColor(255, 255, 255, 255)); + compressTexture(mesh.textures[0], true); + setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); + draw(mesh, GroupedFPSM::MVPSet[i], GroupedFPSM::TIMVSet[i], 0); } glUseProgram(MeshShader::ObjectRefPass1Shader::Program); + glBindVertexArray(getVAO(EVT_STANDARD)); for (unsigned i = 0; i < GroupedFPSM::MeshSet.size(); ++i) { const GLMesh &mesh = *GroupedFPSM::MeshSet[i]; + if (mesh.VAOType != video::EVT_STANDARD) + { +#ifdef DEBUG + Log::error("Materials", "Wrong vertex Type associed to alpha ref pass 1 (hint texture : %s)", mesh.textures[0]->getName().getPath().c_str()); +#endif + continue; + } compressTexture(mesh.textures[0], true); setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - draw(mesh, mesh.vao, GroupedFPSM::MVPSet[i], GroupedFPSM::TIMVSet[i], GroupedFPSM::MeshSet[i]->TextureMatrix, 0); + + draw(mesh, GroupedFPSM::MVPSet[i], GroupedFPSM::TIMVSet[i], GroupedFPSM::MeshSet[i]->TextureMatrix, 0); } glUseProgram(MeshShader::NormalMapShader::Program); + glBindVertexArray(getVAO(EVT_TANGENTS)); for (unsigned i = 0; i < GroupedFPSM::MeshSet.size(); ++i) { const GLMesh &mesh = *GroupedFPSM::MeshSet[i]; + assert(mesh.VAOType == video::EVT_TANGENTS); assert(mesh.textures[1]); compressTexture(mesh.textures[1], false); setTexture(0, getTextureGLuint(mesh.textures[1]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); compressTexture(mesh.textures[0], true); setTexture(1, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - draw(mesh, mesh.vao, GroupedFPSM::MVPSet[i], GroupedFPSM::TIMVSet[i], 0, 1); + + draw(mesh, GroupedFPSM::MVPSet[i], GroupedFPSM::TIMVSet[i], 0, 1); } } } @@ -577,7 +602,8 @@ void IrrDriver::renderSolidSecondPass() glEnable(GL_DEPTH_TEST); glDisable(GL_ALPHA_TEST); glDisable(GL_BLEND); - GroupedSM::reset(); + GroupedSM::reset(); + GroupedSM::reset(); GroupedSM::reset(); GroupedSM::reset(); GroupedSM::reset(); @@ -595,32 +621,177 @@ void IrrDriver::renderSolidSecondPass() m_scene_manager->drawAll(scene::ESNRP_SOLID); glUseProgram(MeshShader::ObjectPass2Shader::Program); - for (unsigned i = 0; i < GroupedSM::MeshSet.size(); i++) - drawObjectPass2(*GroupedSM::MeshSet[i], GroupedSM::MVPSet[i], GroupedSM::MeshSet[i]->TextureMatrix); + glBindVertexArray(getVAO(video::EVT_STANDARD)); + for (unsigned i = 0; i < GroupedSM::MeshSet.size(); i++) + { + const GLMesh &mesh = *GroupedSM::MeshSet[i]; + if (mesh.VAOType != video::EVT_STANDARD) + { +#ifdef DEBUG + Log::error("Materials", "Wrong vertex Type associed to pass 2 (hint texture : %s)", mesh.textures[0]->getName().getPath().c_str()); +#endif + continue; + } + compressTexture(mesh.textures[0], true); + setTexture(MeshShader::ObjectPass2Shader::TU_Albedo, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); + if (irr_driver->getLightViz()) + { + GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA }; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); + } + else + { + GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA }; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); + } + draw(mesh, GroupedSM::MVPSet[i], GroupedSM::MeshSet[i]->TextureMatrix); + } + + glBindVertexArray(getVAO(video::EVT_TANGENTS)); + for (unsigned i = 0; i < GroupedSM::MeshSet.size(); i++) + { + const GLMesh &mesh = *GroupedSM::MeshSet[i]; + assert(mesh.VAOType == video::EVT_TANGENTS); + compressTexture(mesh.textures[0], true); + setTexture(MeshShader::ObjectPass2Shader::TU_Albedo, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); + if (irr_driver->getLightViz()) + { + GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA }; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); + } + else + { + GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA }; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); + } + draw(mesh, GroupedSM::MVPSet[i], GroupedSM::MeshSet[i]->TextureMatrix); + } glUseProgram(MeshShader::ObjectRefPass2Shader::Program); + glBindVertexArray(getVAO(EVT_STANDARD)); for (unsigned i = 0; i < GroupedSM::MeshSet.size(); i++) - drawObjectRefPass2(*GroupedSM::MeshSet[i], GroupedSM::MVPSet[i], GroupedSM::MeshSet[i]->TextureMatrix); + { + const GLMesh &mesh = *GroupedSM::MeshSet[i]; + if (mesh.VAOType != video::EVT_STANDARD) + { +#ifdef DEBUG + Log::error("Materials", "Wrong vertex Type associed to alpha ref pass 2 (hint texture : %s)", mesh.textures[0]->getName().getPath().c_str()); +#endif + continue; + } + compressTexture(mesh.textures[0], true); + setTexture(MeshShader::ObjectRefPass2Shader::TU_Albedo, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); + if (irr_driver->getLightViz()) + { + GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA }; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); + } + else + { + GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA }; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); + } + + draw(mesh, GroupedSM::MVPSet[i], GroupedSM::MeshSet[i]->TextureMatrix); + } glUseProgram(MeshShader::ObjectRimLimitShader::Program); + glBindVertexArray(getVAO(EVT_STANDARD)); for (unsigned i = 0; i < GroupedSM::MeshSet.size(); i++) - drawObjectRimLimit(*GroupedSM::MeshSet[i], GroupedSM::MVPSet[i], GroupedSM::TIMVSet[i], GroupedSM::MeshSet[i]->TextureMatrix); + { + const GLMesh &mesh = *GroupedSM::MeshSet[i]; + assert(mesh.VAOType == EVT_STANDARD); + compressTexture(mesh.textures[0], true); + setTexture(MeshShader::ObjectRimLimitShader::TU_Albedo, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); + if (irr_driver->getLightViz()) + { + GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA }; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); + } + else + { + GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA }; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); + } + draw(mesh, GroupedSM::MVPSet[i], GroupedSM::TIMVSet[i], GroupedSM::MeshSet[i]->TextureMatrix); + } glUseProgram(MeshShader::SphereMapShader::Program); + glBindVertexArray(getVAO(EVT_STANDARD)); for (unsigned i = 0; i < GroupedSM::MeshSet.size(); i++) - drawSphereMap(*GroupedSM::MeshSet[i], GroupedSM::MVPSet[i], GroupedSM::TIMVSet[i]); + { + const GLMesh &mesh = *GroupedSM::MeshSet[i]; + assert(mesh.VAOType == EVT_STANDARD); + compressTexture(mesh.textures[0], true); + if (irr_driver->getLightViz()) + { + GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA }; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); + } + else + { + GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA }; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); + } + setTexture(MeshShader::SphereMapShader::TU_tex, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); + draw(mesh, GroupedSM::MVPSet[i], GroupedSM::TIMVSet[i], irr_driver->getSceneManager()->getAmbientLight()); + } glUseProgram(MeshShader::SplattingShader::Program); + glBindVertexArray(getVAO(EVT_2TCOORDS)); for (unsigned i = 0; i < GroupedSM::MeshSet.size(); i++) drawSplatting(*GroupedSM::MeshSet[i], GroupedSM::MVPSet[i]); glUseProgram(MeshShader::ObjectUnlitShader::Program); + glBindVertexArray(getVAO(EVT_STANDARD)); for (unsigned i = 0; i < GroupedSM::MeshSet.size(); i++) - drawObjectUnlit(*GroupedSM::MeshSet[i], GroupedSM::MVPSet[i]); + { + const GLMesh &mesh = *GroupedSM::MeshSet[i]; + assert(mesh.VAOType == EVT_STANDARD); + compressTexture(mesh.textures[0], true); + setTexture(MeshShader::ObjectUnlitShader::TU_tex, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); + if (irr_driver->getLightViz()) + { + GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA }; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); + } + else + { + GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA }; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); + } + draw(mesh, GroupedSM::MVPSet[i]); + } glUseProgram(MeshShader::DetailledObjectPass2Shader::Program); + glBindVertexArray(getVAO(EVT_2TCOORDS)); for (unsigned i = 0; i < GroupedSM::MeshSet.size(); i++) - drawDetailledObjectPass2(*GroupedSM::MeshSet[i], GroupedSM::MVPSet[i]); + { + GLMesh &mesh = *GroupedSM::MeshSet[i]; + assert(mesh.VAOType == EVT_2TCOORDS); + compressTexture(mesh.textures[0], true); + setTexture(MeshShader::DetailledObjectPass2Shader::TU_Albedo, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); + if (irr_driver->getLightViz()) + { + GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA }; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); + } + else + { + GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA }; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); + } + if (!mesh.textures[1]) + { +#ifdef DEBUG + Log::error("Materials", "No detail/lightmap texture provided for detail/lightmap material."); +#endif + mesh.textures[1] = getUnicolorTexture(video::SColor(255, 255, 255, 255)); + } + compressTexture(mesh.textures[1], true); + setTexture(MeshShader::DetailledObjectPass2Shader::TU_detail, getTextureGLuint(mesh.textures[1]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); + draw(mesh, GroupedSM::MVPSet[i]); + } } } @@ -637,25 +808,112 @@ void IrrDriver::renderTransparent() TransparentMeshes::reset(); m_scene_manager->drawAll(scene::ESNRP_TRANSPARENT); + glBindVertexArray(getVAO(EVT_STANDARD)); + if (World::getWorld() && World::getWorld()->isFogEnabled()) { + const Track * const track = World::getWorld()->getTrack(); + + // This function is only called once per frame - thus no need for setters. + 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(); + + core::vector3df col(tmpcol.getRed() / 255.0f, + tmpcol.getGreen() / 255.0f, + tmpcol.getBlue() / 255.0f); + glUseProgram(MeshShader::TransparentFogShader::Program); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); for (unsigned i = 0; i < TransparentMeshes::MeshSet.size(); i++) - drawTransparentFogObject(*TransparentMeshes::MeshSet[i], TransparentMeshes::MVPSet[i], TransparentMeshes::MeshSet[i]->TextureMatrix); + { + const GLMesh &mesh = *TransparentMeshes::MeshSet[i]; + if (mesh.VAOType != EVT_STANDARD) + { +#ifdef DEBUG + Log::error("Materials", "Wrong vertex Type associed to fog + transparent blend (hint texture : %s)", mesh.textures[0]->getName().getPath().c_str()); +#endif + glBindVertexArray(getVAO(mesh.VAOType)); + } + + + if (mesh.textures[0] != NULL) + { + compressTexture(mesh.textures[0], true); + setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); + } + + draw(mesh, TransparentMeshes::MVPSet[i], TransparentMeshes::MeshSet[i]->TextureMatrix, fogmax, startH, endH, start, end, col, Camera::getCamera(0)->getCameraSceneNode()->getAbsolutePosition(), 0); + if (mesh.VAOType != EVT_STANDARD) + glBindVertexArray(getVAO(EVT_STANDARD)); + } glBlendFunc(GL_ONE, GL_ONE); for (unsigned i = 0; i < TransparentMeshes::MeshSet.size(); i++) - drawTransparentFogObject(*TransparentMeshes::MeshSet[i], TransparentMeshes::MVPSet[i], TransparentMeshes::MeshSet[i]->TextureMatrix); + { + const GLMesh &mesh = *TransparentMeshes::MeshSet[i]; + if (mesh.VAOType != EVT_STANDARD) + { +#ifdef DEBUG + Log::error("Materials", "Wrong vertex Type associed to fog + transparent additive (hint texture : %s)", mesh.textures[0]->getName().getPath().c_str()); +#endif + glBindVertexArray(getVAO(mesh.VAOType)); + } + glBindVertexArray(getVAO(mesh.VAOType)); + + if (mesh.textures[0] != NULL) + { + compressTexture(mesh.textures[0], true); + setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); + } + + draw(mesh, TransparentMeshes::MVPSet[i], TransparentMeshes::MeshSet[i]->TextureMatrix, fogmax, startH, endH, start, end, col, Camera::getCamera(0)->getCameraSceneNode()->getAbsolutePosition(), 0); + if (mesh.VAOType != EVT_STANDARD) + glBindVertexArray(getVAO(EVT_STANDARD)); + } } else { glUseProgram(MeshShader::TransparentShader::Program); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); for (unsigned i = 0; i < TransparentMeshes::MeshSet.size(); i++) - drawTransparentObject(*TransparentMeshes::MeshSet[i], TransparentMeshes::MVPSet[i], TransparentMeshes::MeshSet[i]->TextureMatrix); + { + const GLMesh &mesh = *TransparentMeshes::MeshSet[i]; + if (mesh.VAOType != EVT_STANDARD) + { +#ifdef DEBUG + Log::error("Materials", "Wrong vertex Type associed to fog + transparent additive (hint texture : %s)", mesh.textures[0]->getName().getPath().c_str()); +#endif + glBindVertexArray(getVAO(mesh.VAOType)); + } + glBindVertexArray(getVAO(mesh.VAOType)); + compressTexture(mesh.textures[0], true); + setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); + draw(mesh, TransparentMeshes::MVPSet[i], TransparentMeshes::MeshSet[i]->TextureMatrix, 0); + if (mesh.VAOType != EVT_STANDARD) + glBindVertexArray(getVAO(EVT_STANDARD)); + } + glBlendFunc(GL_ONE, GL_ONE); for (unsigned i = 0; i < TransparentMeshes::MeshSet.size(); i++) - drawTransparentObject(*TransparentMeshes::MeshSet[i], TransparentMeshes::MVPSet[i], TransparentMeshes::MeshSet[i]->TextureMatrix); + { + const GLMesh &mesh = *TransparentMeshes::MeshSet[i]; + if (mesh.VAOType != EVT_STANDARD) + { +#ifdef DEBUG + Log::error("Materials", "Wrong vertex Type associed to fog + transparent additive (hint texture : %s)", mesh.textures[0]->getName().getPath().c_str()); +#endif + glBindVertexArray(getVAO(mesh.VAOType)); + } + glBindVertexArray(getVAO(mesh.VAOType)); + compressTexture(mesh.textures[0], true); + setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); + draw(mesh, TransparentMeshes::MVPSet[i], TransparentMeshes::MeshSet[i]->TextureMatrix, 0); + if (mesh.VAOType != EVT_STANDARD) + glBindVertexArray(getVAO(EVT_STANDARD)); + } } } @@ -857,9 +1115,6 @@ void IrrDriver::computeCameraMatrix(scene::ICameraSceneNode * const camnode, siz void IrrDriver::renderShadows() { - GroupedFPSM::reset(); - GroupedFPSM::reset(); - GroupedFPSM::reset(); irr_driver->setPhase(SHADOW_PASS); glDisable(GL_BLEND); glEnable(GL_POLYGON_OFFSET_FILL); @@ -873,12 +1128,18 @@ void IrrDriver::renderShadows() m_scene_manager->drawAll(scene::ESNRP_SOLID); glUseProgram(MeshShader::ShadowShader::Program); - for (unsigned i = 0; i < GroupedFPSM::MeshSet.size(); ++i) - drawShadow(*GroupedFPSM::MeshSet[i], GroupedFPSM::MVPSet[i]); + glBindVertexArray(getVAO(EVT_STANDARD)); + for (unsigned i = 0; i < GroupedFPSM::MeshSet.size(); ++i) + drawShadow(*GroupedFPSM::MeshSet[i], GroupedFPSM::MVPSet[i]); + glBindVertexArray(getVAO(EVT_2TCOORDS)); + for (unsigned i = 0; i < GroupedFPSM::MeshSet.size(); ++i) + drawShadow(*GroupedFPSM::MeshSet[i], GroupedFPSM::MVPSet[i]); + glBindVertexArray(getVAO(EVT_TANGENTS)); for (unsigned i = 0; i < GroupedFPSM::MeshSet.size(); ++i) drawShadow(*GroupedFPSM::MeshSet[i], GroupedFPSM::MVPSet[i]); glUseProgram(MeshShader::RefShadowShader::Program); + glBindVertexArray(getVAO(EVT_STANDARD)); for (unsigned i = 0; i < GroupedFPSM::MeshSet.size(); ++i) drawShadowRef(*GroupedFPSM::MeshSet[i], GroupedFPSM::MVPSet[i]); @@ -891,14 +1152,14 @@ void IrrDriver::renderShadows() glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glUseProgram(MeshShader::RSMShader::Program); - for (unsigned i = 0; i < GroupedFPSM::MeshSet.size(); ++i) + for (unsigned i = 0; i < GroupedFPSM::MeshSet.size(); ++i) { - const GLMesh mesh = *GroupedFPSM::MeshSet[i]; + const GLMesh mesh = *GroupedFPSM::MeshSet[i]; if (!mesh.textures[0]) continue; compressTexture(mesh.textures[0], true); setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - draw(mesh, mesh.vao, rsm_matrix, GroupedFPSM::MVPSet[i], 0); + draw(mesh, rsm_matrix, GroupedFPSM::MVPSet[i], 0); } } @@ -954,6 +1215,7 @@ void IrrDriver::renderGlow(std::vector& glows) glDepthMask(GL_FALSE); glDisable(GL_BLEND); + glBindVertexArray(getVAO(EVT_STANDARD)); for (u32 i = 0; i < glowcount; i++) { const GlowData &dat = glows[i]; @@ -1661,6 +1923,7 @@ void IrrDriver::renderDisplacement() glStencilFunc(GL_ALWAYS, 1, 0xFF); glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + glBindVertexArray(getVAO(EVT_2TCOORDS)); for (int i = 0; i < displacingcount; i++) { m_scene_manager->setCurrentRendertime(scene::ESNRP_TRANSPARENT); diff --git a/src/graphics/stkanimatedmesh.cpp b/src/graphics/stkanimatedmesh.cpp index 544574162..94ed2966a 100644 --- a/src/graphics/stkanimatedmesh.cpp +++ b/src/graphics/stkanimatedmesh.cpp @@ -93,17 +93,19 @@ void STKAnimatedMesh::render() if (rnd->isTransparent()) { TransparentMaterial TranspMat = MaterialTypeToTransparentMaterial(type, MaterialTypeParam); - initvaostate(mesh, TranspMat); TransparentMesh[TranspMat].push_back(&mesh); } else { - GeometricMaterial GeometricType = MaterialTypeToGeometricMaterial(type); - ShadedMaterial ShadedType = MaterialTypeToShadedMaterial(type, mesh.textures); - initvaostate(mesh, GeometricType, ShadedType); + GeometricMaterial GeometricType = MaterialTypeToGeometricMaterial(type, mb->getVertexType()); + ShadedMaterial ShadedType = MaterialTypeToShadedMaterial(type, mesh.textures, mb->getVertexType()); GeometricMesh[GeometricType].push_back(&mesh); ShadedMesh[ShadedType].push_back(&mesh); } + std::pair p = getVAOOffsetAndBase(mb); + mesh.vaoBaseVertex = p.first; + mesh.vaoOffset = p.second; + mesh.VAOType = mb->getVertexType(); } } firstTime = false; @@ -117,8 +119,9 @@ void STKAnimatedMesh::render() if (irr_driver->getPhase() == SOLID_NORMAL_AND_DEPTH_PASS) { glBindVertexArray(0); - glBindBuffer(GL_ARRAY_BUFFER, GLmeshes[i].vertex_buffer); - glBufferSubData(GL_ARRAY_BUFFER, 0, mb->getVertexCount() * GLmeshes[i].Stride, mb->getVertices()); + glBindBuffer(GL_ARRAY_BUFFER, getVBO(mb->getVertexType())); + glBufferSubData(GL_ARRAY_BUFFER, GLmeshes[i].vaoBaseVertex * GLmeshes[i].Stride, mb->getVertexCount() * GLmeshes[i].Stride, mb->getVertices()); + glBindBuffer(GL_ARRAY_BUFFER, 0); } } if (mb) @@ -133,7 +136,7 @@ void STKAnimatedMesh::render() continue; } - if (irr_driver->getPhase() == SOLID_NORMAL_AND_DEPTH_PASS || irr_driver->getPhase() == SHADOW_PASS) + if (irr_driver->getPhase() == SOLID_NORMAL_AND_DEPTH_PASS) { ModelViewProjectionMatrix = computeMVP(AbsoluteTransformation); TransposeInverseModelView = computeTIMV(AbsoluteTransformation); @@ -141,11 +144,18 @@ void STKAnimatedMesh::render() AbsoluteTransformation.getInverse(invmodel); GLMesh* mesh; - for_in(mesh, GeometricMesh[FPSM_DEFAULT]) + for_in(mesh, GeometricMesh[FPSM_DEFAULT_STANDARD]) { - GroupedFPSM::MeshSet.push_back(mesh); - GroupedFPSM::MVPSet.push_back(AbsoluteTransformation); - GroupedFPSM::TIMVSet.push_back(invmodel); + GroupedFPSM::MeshSet.push_back(mesh); + GroupedFPSM::MVPSet.push_back(AbsoluteTransformation); + GroupedFPSM::TIMVSet.push_back(invmodel); + } + + for_in(mesh, GeometricMesh[FPSM_DEFAULT_2TCOORD]) + { + GroupedFPSM::MeshSet.push_back(mesh); + GroupedFPSM::MVPSet.push_back(AbsoluteTransformation); + GroupedFPSM::TIMVSet.push_back(invmodel); } for_in(mesh, GeometricMesh[FPSM_ALPHA_REF_TEXTURE]) @@ -164,11 +174,18 @@ void STKAnimatedMesh::render() AbsoluteTransformation.getInverse(invmodel); GLMesh* mesh; - for_in(mesh, ShadedMesh[SM_DEFAULT]) + for_in(mesh, ShadedMesh[SM_DEFAULT_STANDARD]) { - GroupedSM::MeshSet.push_back(mesh); - GroupedSM::MVPSet.push_back(AbsoluteTransformation); - GroupedSM::TIMVSet.push_back(invmodel); + GroupedSM::MeshSet.push_back(mesh); + GroupedSM::MVPSet.push_back(AbsoluteTransformation); + GroupedSM::TIMVSet.push_back(invmodel); + } + + for_in(mesh, ShadedMesh[SM_DEFAULT_TANGENT]) + { + GroupedSM::MeshSet.push_back(mesh); + GroupedSM::MVPSet.push_back(AbsoluteTransformation); + GroupedSM::TIMVSet.push_back(invmodel); } for_in(mesh, ShadedMesh[SM_ALPHA_REF_TEXTURE]) diff --git a/src/graphics/stkinstancedscenenode.cpp b/src/graphics/stkinstancedscenenode.cpp index 4dc8ffb7e..95cbbbc19 100644 --- a/src/graphics/stkinstancedscenenode.cpp +++ b/src/graphics/stkinstancedscenenode.cpp @@ -50,6 +50,7 @@ void STKInstancedSceneNode::createGLMeshes() { scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i); GLmeshes.push_back(allocateMeshBuffer(mb)); + fillLocalBuffer(GLmeshes.back(), mb); } isMaterialInitialized = false; } @@ -98,8 +99,8 @@ void STKInstancedSceneNode::setFirstTimeMaterial() video::E_MATERIAL_TYPE type = mb->getMaterial().MaterialType; GLMesh &mesh = GLmeshes[i]; - GeometricMaterial GeometricType = MaterialTypeToGeometricMaterial(type); - ShadedMaterial ShadedType = MaterialTypeToShadedMaterial(type, mesh.textures); + GeometricMaterial GeometricType = MaterialTypeToGeometricMaterial(type, mb->getVertexType()); + ShadedMaterial ShadedType = MaterialTypeToShadedMaterial(type, mesh.textures, mb->getVertexType()); initinstancedvaostate(mesh, GeometricType, ShadedType); GeometricMesh[GeometricType].push_back(&mesh); ShadedMesh[ShadedType].push_back(&mesh); @@ -302,10 +303,10 @@ void STKInstancedSceneNode::render() ModelViewProjectionMatrix = irr_driver->getProjMatrix(); ModelViewProjectionMatrix *= irr_driver->getViewMatrix(); - if (!GeometricMesh[FPSM_DEFAULT].empty()) + if (!GeometricMesh[FPSM_DEFAULT_STANDARD].empty()) glUseProgram(MeshShader::InstancedObjectPass1Shader::Program); - for (unsigned i = 0; i < GeometricMesh[FPSM_DEFAULT].size(); i++) - drawFSPMDefault(*GeometricMesh[FPSM_DEFAULT][i], instance_pos.size() / 9); + for (unsigned i = 0; i < GeometricMesh[FPSM_DEFAULT_STANDARD].size(); i++) + drawFSPMDefault(*GeometricMesh[FPSM_DEFAULT_STANDARD][i], instance_pos.size() / 9); if (!GeometricMesh[FPSM_ALPHA_REF_TEXTURE].empty()) glUseProgram(MeshShader::InstancedObjectRefPass1Shader::Program); @@ -322,10 +323,10 @@ void STKInstancedSceneNode::render() if (irr_driver->getPhase() == SOLID_LIT_PASS) { - if (!ShadedMesh[SM_DEFAULT].empty()) + if (!ShadedMesh[SM_DEFAULT_STANDARD].empty()) glUseProgram(MeshShader::InstancedObjectPass2Shader::Program); - for (unsigned i = 0; i < ShadedMesh[FPSM_DEFAULT].size(); i++) - drawSMDefault(*ShadedMesh[FPSM_DEFAULT][i], ModelViewProjectionMatrix, instance_pos.size() / 9); + for (unsigned i = 0; i < ShadedMesh[SM_DEFAULT_STANDARD].size(); i++) + drawSMDefault(*ShadedMesh[SM_DEFAULT_STANDARD][i], ModelViewProjectionMatrix, instance_pos.size() / 9); if (!ShadedMesh[SM_ALPHA_REF_TEXTURE].empty()) glUseProgram(MeshShader::InstancedObjectRefPass2Shader::Program); @@ -341,10 +342,10 @@ void STKInstancedSceneNode::render() if (irr_driver->getPhase() == SHADOW_PASS) { - if (!GeometricMesh[FPSM_DEFAULT].empty()) + if (!GeometricMesh[FPSM_DEFAULT_STANDARD].empty()) glUseProgram(MeshShader::InstancedShadowShader::Program); - for (unsigned i = 0; i < GeometricMesh[FPSM_DEFAULT].size(); i++) - drawShadowDefault(*GeometricMesh[FPSM_DEFAULT][i], instance_pos.size() / 9); + for (unsigned i = 0; i < GeometricMesh[FPSM_DEFAULT_STANDARD].size(); i++) + drawShadowDefault(*GeometricMesh[FPSM_DEFAULT_STANDARD][i], instance_pos.size() / 9); if (!GeometricMesh[FPSM_ALPHA_REF_TEXTURE].empty()) glUseProgram(MeshShader::InstancedRefShadowShader::Program); diff --git a/src/graphics/stkmesh.cpp b/src/graphics/stkmesh.cpp index 12a740fcb..cc768a536 100644 --- a/src/graphics/stkmesh.cpp +++ b/src/graphics/stkmesh.cpp @@ -9,7 +9,7 @@ #include "graphics/camera.hpp" #include "modes/world.hpp" -GeometricMaterial MaterialTypeToGeometricMaterial(video::E_MATERIAL_TYPE MaterialType) +GeometricMaterial MaterialTypeToGeometricMaterial(video::E_MATERIAL_TYPE MaterialType, video::E_VERTEX_TYPE tp) { if (MaterialType == irr_driver->getShader(ES_NORMAL_MAP)) return FPSM_NORMAL_MAP; @@ -17,11 +17,13 @@ GeometricMaterial MaterialTypeToGeometricMaterial(video::E_MATERIAL_TYPE Materia return FPSM_ALPHA_REF_TEXTURE; else if (MaterialType == irr_driver->getShader(ES_GRASS) || MaterialType == irr_driver->getShader(ES_GRASS_REF)) return FPSM_GRASS; - else - return FPSM_DEFAULT; + else if (tp == video::EVT_2TCOORDS) + return FPSM_DEFAULT_2TCOORD; + assert(tp == video::EVT_STANDARD); + return FPSM_DEFAULT_STANDARD; } -ShadedMaterial MaterialTypeToShadedMaterial(video::E_MATERIAL_TYPE type, video::ITexture **textures) +ShadedMaterial MaterialTypeToShadedMaterial(video::E_MATERIAL_TYPE type, video::ITexture **textures, video::E_VERTEX_TYPE tp) { if (type == irr_driver->getShader(ES_SPHERE_MAP)) return SM_SPHEREMAP; @@ -35,10 +37,11 @@ ShadedMaterial MaterialTypeToShadedMaterial(video::E_MATERIAL_TYPE type, video:: return SM_GRASS; else if (type == irr_driver->getShader(ES_OBJECT_UNLIT)) return SM_UNLIT; - else if (textures[1] && type != irr_driver->getShader(ES_NORMAL_MAP)) + else if (tp == video::EVT_2TCOORDS) return SM_DETAILS; - else - return SM_DEFAULT; + else if (tp == video::EVT_TANGENTS) + return SM_DEFAULT_TANGENT; + return SM_DEFAULT_STANDARD; } TransparentMaterial MaterialTypeToTransparentMaterial(video::E_MATERIAL_TYPE type, f32 MaterialTypeParam) @@ -137,46 +140,28 @@ GLMesh allocateMeshBuffer(scene::IMeshBuffer* mb) GLMesh result = {}; if (!mb) return result; - glBindVertexArray(0); - glGenBuffers(1, &(result.vertex_buffer)); - glGenBuffers(1, &(result.index_buffer)); - glBindBuffer(GL_ARRAY_BUFFER, result.vertex_buffer); - const void* vertices = mb->getVertices(); - const u32 vertexCount = mb->getVertexCount(); - const irr::video::E_VERTEX_TYPE vType = mb->getVertexType(); - result.Stride = getVertexPitchFromType(vType); - const c8* vbuf = static_cast(vertices); - glBufferData(GL_ARRAY_BUFFER, vertexCount * result.Stride, vbuf, GL_STATIC_DRAW); - assert(vertexCount); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, result.index_buffer); - const void* indices = mb->getIndices(); - u32 indexCount = mb->getIndexCount(); - size_t indexSize = 0; + result.IndexCount = mb->getIndexCount(); switch (mb->getIndexType()) { - case irr::video::EIT_16BIT: - { - indexSize = sizeof(u16); - result.IndexType = GL_UNSIGNED_SHORT; - break; - } - case irr::video::EIT_32BIT: - { - indexSize = sizeof(u32); - result.IndexType = GL_UNSIGNED_INT; - break; - } - default: - { - assert(0 && "Wrong index size"); - } + case irr::video::EIT_16BIT: + { + result.IndexType = GL_UNSIGNED_SHORT; + break; } - glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount * indexSize, indices, GL_STATIC_DRAW); + case irr::video::EIT_32BIT: + { + result.IndexType = GL_UNSIGNED_INT; + break; + } + default: + { + assert(0 && "Wrong index size"); + } + } + result.VAOType = mb->getVertexType(); + result.Stride = getVertexPitchFromType(result.VAOType); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); result.IndexCount = mb->getIndexCount(); switch (mb->getPrimitiveType()) @@ -210,6 +195,44 @@ GLMesh allocateMeshBuffer(scene::IMeshBuffer* mb) return result; } +static +size_t getUnsignedSize(unsigned tp) +{ + switch (tp) + { + case GL_UNSIGNED_SHORT: + return sizeof(u16); + case GL_UNSIGNED_INT: + return sizeof(u32); + default: + assert(0 && "Unsupported index type"); + return 0; + } +} + +void fillLocalBuffer(GLMesh &mesh, scene::IMeshBuffer* mb) +{ + glBindVertexArray(0); + glGenBuffers(1, &(mesh.vertex_buffer)); + glGenBuffers(1, &(mesh.index_buffer)); + + glBindBuffer(GL_ARRAY_BUFFER, mesh.vertex_buffer); + const void* vertices = mb->getVertices(); + const u32 vertexCount = mb->getVertexCount(); + + const c8* vbuf = static_cast(vertices); + glBufferData(GL_ARRAY_BUFFER, vertexCount * mesh.Stride, vbuf, GL_STATIC_DRAW); + assert(vertexCount); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.index_buffer); + const void* indices = mb->getIndices(); + + glBufferData(GL_ELEMENT_ARRAY_BUFFER, mesh.IndexCount * getUnsignedSize(mesh.IndexType), indices, GL_STATIC_DRAW); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); +} + core::matrix4 computeMVP(const core::matrix4 &ModelMatrix) { @@ -243,149 +266,93 @@ void drawGrassPass1(const GLMesh &mesh, const core::matrix4 & ModelViewProjectio GLenum ptype = mesh.PrimitiveType; GLenum itype = mesh.IndexType; size_t count = mesh.IndexCount; + assert(mesh.VAOType == video::EVT_STANDARD); compressTexture(mesh.textures[0], true); setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); MeshShader::GrassPass1Shader::setUniforms(ModelViewProjectionMatrix, TransposeInverseModelView, windDir, 0); - - assert(mesh.vao); - glBindVertexArray(mesh.vao); - glDrawElements(ptype, count, itype, 0); + glDrawElementsBaseVertex(ptype, count, itype, (GLvoid *)mesh.vaoOffset, mesh.vaoBaseVertex); } -void drawSphereMap(const GLMesh &mesh, const core::matrix4 &ModelMatrix, const core::matrix4 &InverseModelMatrix) -{ - irr_driver->IncreaseObjectCount(); - GLenum ptype = mesh.PrimitiveType; - GLenum itype = mesh.IndexType; - size_t count = mesh.IndexCount; - - compressTexture(mesh.textures[0], true); - if (irr_driver->getLightViz()) - { - GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA }; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - } - else - { - GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA }; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - } - setTexture(MeshShader::SphereMapShader::TU_tex, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - - MeshShader::SphereMapShader::setUniforms(ModelMatrix, InverseModelMatrix, irr_driver->getSceneManager()->getAmbientLight()); - assert(mesh.vao); - glBindVertexArray(mesh.vao); - glDrawElements(ptype, count, itype, 0); -} void drawSplatting(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix) { irr_driver->IncreaseObjectCount(); - GLenum ptype = mesh.PrimitiveType; - GLenum itype = mesh.IndexType; - size_t count = mesh.IndexCount; + GLenum ptype = mesh.PrimitiveType; + GLenum itype = mesh.IndexType; + size_t count = mesh.IndexCount; - // Texlayout - compressTexture(mesh.textures[1], true); - setTexture(MeshShader::SplattingShader::TU_tex_layout, getTextureGLuint(mesh.textures[1]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - if (irr_driver->getLightViz()) - { - GLint swizzleMask[] = {GL_ONE, GL_ONE, GL_ONE, GL_ALPHA}; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - } - else - { - GLint swizzleMask[] = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA}; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - } - //Tex detail0 - compressTexture(mesh.textures[2], true); - setTexture(MeshShader::SplattingShader::TU_tex_detail0, getTextureGLuint(mesh.textures[2]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - if (irr_driver->getLightViz()) - { - GLint swizzleMask[] = {GL_ONE, GL_ONE, GL_ONE, GL_ALPHA}; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - } - else - { - GLint swizzleMask[] = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA}; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - } - //Tex detail1 - compressTexture(mesh.textures[3], true); - setTexture(MeshShader::SplattingShader::TU_tex_detail1, getTextureGLuint(mesh.textures[3]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - if (irr_driver->getLightViz()) - { - GLint swizzleMask[] = {GL_ONE, GL_ONE, GL_ONE, GL_ALPHA}; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - } - else - { - GLint swizzleMask[] = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA}; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - } - compressTexture(mesh.textures[4], true); - //Tex detail2 - setTexture(MeshShader::SplattingShader::TU_tex_detail2, getTextureGLuint(mesh.textures[4]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - if (irr_driver->getLightViz()) - { - GLint swizzleMask[] = {GL_ONE, GL_ONE, GL_ONE, GL_ALPHA}; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - } - else - { - GLint swizzleMask[] = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA}; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - } - //Tex detail3 - compressTexture(mesh.textures[5], true); - setTexture(MeshShader::SplattingShader::TU_tex_detail3, getTextureGLuint(mesh.textures[5]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - if (irr_driver->getLightViz()) - { - GLint swizzleMask[] = {GL_ONE, GL_ONE, GL_ONE, GL_ALPHA}; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - } - else - { - GLint swizzleMask[] = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA}; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - } + // Texlayout + compressTexture(mesh.textures[1], true); + setTexture(MeshShader::SplattingShader::TU_tex_layout, getTextureGLuint(mesh.textures[1]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); + if (irr_driver->getLightViz()) + { + GLint swizzleMask[] = {GL_ONE, GL_ONE, GL_ONE, GL_ALPHA}; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); + } + else + { + GLint swizzleMask[] = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA}; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); + } + //Tex detail0 + compressTexture(mesh.textures[2], true); + setTexture(MeshShader::SplattingShader::TU_tex_detail0, getTextureGLuint(mesh.textures[2]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); + if (irr_driver->getLightViz()) + { + GLint swizzleMask[] = {GL_ONE, GL_ONE, GL_ONE, GL_ALPHA}; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); + } + else + { + GLint swizzleMask[] = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA}; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); + } + //Tex detail1 + compressTexture(mesh.textures[3], true); + setTexture(MeshShader::SplattingShader::TU_tex_detail1, getTextureGLuint(mesh.textures[3]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); + if (irr_driver->getLightViz()) + { + GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA }; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); + } + else + { + GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA }; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); + } + compressTexture(mesh.textures[4], true); + //Tex detail2 + setTexture(MeshShader::SplattingShader::TU_tex_detail2, getTextureGLuint(mesh.textures[4]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); + if (irr_driver->getLightViz()) + { + GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA }; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); + } + else + { + GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA }; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); + } + //Tex detail3 + compressTexture(mesh.textures[5], true); + setTexture(MeshShader::SplattingShader::TU_tex_detail3, getTextureGLuint(mesh.textures[5]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); + if (irr_driver->getLightViz()) + { + GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA }; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); + } + else + { + GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA }; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); + } - MeshShader::SplattingShader::setUniforms(ModelViewProjectionMatrix); - - assert(mesh.vao); - glBindVertexArray(mesh.vao); - glDrawElements(ptype, count, itype, 0); + MeshShader::SplattingShader::setUniforms(ModelViewProjectionMatrix); + glDrawElementsBaseVertex(ptype, count, itype, (GLvoid *)mesh.vaoOffset, mesh.vaoBaseVertex); } -void drawObjectRefPass2(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TextureMatrix) -{ - irr_driver->IncreaseObjectCount(); - GLenum ptype = mesh.PrimitiveType; - GLenum itype = mesh.IndexType; - size_t count = mesh.IndexCount; - - compressTexture(mesh.textures[0], true); - setTexture(MeshShader::ObjectRefPass2Shader::TU_Albedo, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - if (irr_driver->getLightViz()) - { - GLint swizzleMask[] = {GL_ONE, GL_ONE, GL_ONE, GL_ALPHA}; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - } - else - { - GLint swizzleMask[] = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA}; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - } - - MeshShader::ObjectRefPass2Shader::setUniforms(ModelViewProjectionMatrix, TextureMatrix); - - assert(mesh.vao); - glBindVertexArray(mesh.vao); - glDrawElements(ptype, count, itype, 0); -} void drawGrassPass2(const GLMesh &mesh, const core::matrix4 & ModelViewProjectionMatrix, core::vector3df windDir) { @@ -393,7 +360,10 @@ void drawGrassPass2(const GLMesh &mesh, const core::matrix4 & ModelViewProjectio GLenum ptype = mesh.PrimitiveType; GLenum itype = mesh.IndexType; size_t count = mesh.IndexCount; + assert(mesh.VAOType == video::EVT_STANDARD); + if (!mesh.textures[0]) + const_cast(mesh).textures[0] = getUnicolorTexture(video::SColor(255, 255, 255, 255)); compressTexture(mesh.textures[0], true); setTexture(MeshShader::GrassPass2Shader::TU_Albedo, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); if (irr_driver->getLightViz()) @@ -408,136 +378,7 @@ void drawGrassPass2(const GLMesh &mesh, const core::matrix4 & ModelViewProjectio } MeshShader::GrassPass2Shader::setUniforms(ModelViewProjectionMatrix, windDir); - - assert(mesh.vao); - glBindVertexArray(mesh.vao); - glDrawElements(ptype, count, itype, 0); -} - -void drawUntexturedObject(const GLMesh &mesh, const core::matrix4 &ModelMatrix) -{ - irr_driver->IncreaseObjectCount(); - GLenum ptype = mesh.PrimitiveType; - GLenum itype = mesh.IndexType; - size_t count = mesh.IndexCount; - - MeshShader::UntexturedObjectShader::setUniforms(ModelMatrix); - - assert(mesh.vao); - glBindVertexArray(mesh.vao); - glDrawElements(ptype, count, itype, 0); -} - -void drawObjectRimLimit(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TransposeInverseModelView, const core::matrix4 &TextureMatrix) -{ - irr_driver->IncreaseObjectCount(); - GLenum ptype = mesh.PrimitiveType; - GLenum itype = mesh.IndexType; - size_t count = mesh.IndexCount; - - compressTexture(mesh.textures[0], true); - setTexture(MeshShader::ObjectRimLimitShader::TU_Albedo, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - if (irr_driver->getLightViz()) - { - GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA }; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - } - else - { - GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA }; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - } - - MeshShader::ObjectRimLimitShader::setUniforms(ModelViewProjectionMatrix, TransposeInverseModelView, TextureMatrix); - - assert(mesh.vao); - glBindVertexArray(mesh.vao); - glDrawElements(ptype, count, itype, 0); -} - -void drawObjectUnlit(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix) -{ - irr_driver->IncreaseObjectCount(); - GLenum ptype = mesh.PrimitiveType; - GLenum itype = mesh.IndexType; - size_t count = mesh.IndexCount; - - compressTexture(mesh.textures[0], true); - setTexture(MeshShader::ObjectUnlitShader::TU_tex, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - if (irr_driver->getLightViz()) - { - GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA }; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - } - else - { - GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA }; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - } - - MeshShader::ObjectUnlitShader::setUniforms(ModelViewProjectionMatrix); - - assert(mesh.vao); - glBindVertexArray(mesh.vao); - glDrawElements(ptype, count, itype, 0); -} - -void drawDetailledObjectPass2(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix) -{ - irr_driver->IncreaseObjectCount(); - GLenum ptype = mesh.PrimitiveType; - GLenum itype = mesh.IndexType; - size_t count = mesh.IndexCount; - - compressTexture(mesh.textures[0], true); - setTexture(MeshShader::DetailledObjectPass2Shader::TU_Albedo, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - if (irr_driver->getLightViz()) - { - GLint swizzleMask[] = {GL_ONE, GL_ONE, GL_ONE, GL_ALPHA}; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - } - else - { - GLint swizzleMask[] = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA}; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - } - compressTexture(mesh.textures[1], true); - setTexture(MeshShader::DetailledObjectPass2Shader::TU_detail, getTextureGLuint(mesh.textures[1]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - - MeshShader::DetailledObjectPass2Shader::setUniforms(ModelViewProjectionMatrix); - - assert(mesh.vao); - glBindVertexArray(mesh.vao); - glDrawElements(ptype, count, itype, 0); -} - -void drawObjectPass2(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TextureMatrix) -{ - irr_driver->IncreaseObjectCount(); - GLenum ptype = mesh.PrimitiveType; - GLenum itype = mesh.IndexType; - size_t count = mesh.IndexCount; - - if (!mesh.textures[0]) - const_cast(mesh).textures[0] = getUnicolorTexture(video::SColor(255, 255, 255, 255)); - compressTexture(mesh.textures[0], true); - setTexture(MeshShader::ObjectPass2Shader::TU_Albedo, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); - if (irr_driver->getLightViz()) - { - GLint swizzleMask[] = { GL_ONE, GL_ONE, GL_ONE, GL_ALPHA }; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - } - else - { - GLint swizzleMask[] = { GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA }; - glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask); - } - - MeshShader::ObjectPass2Shader::setUniforms(ModelViewProjectionMatrix, TextureMatrix); - - assert(mesh.vao); - glBindVertexArray(mesh.vao); - glDrawElements(ptype, count, itype, 0); + glDrawElementsBaseVertex(ptype, count, itype, (GLvoid *)mesh.vaoOffset, mesh.vaoBaseVertex); } void drawTransparentObject(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TextureMatrix) @@ -606,10 +447,7 @@ void drawBubble(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatr setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); MeshShader::BubbleShader::setUniforms(ModelViewProjectionMatrix, 0, time, transparency); - - assert(mesh.vao); - glBindVertexArray(mesh.vao); - glDrawElements(ptype, count, itype, 0); + glDrawElementsBaseVertex(ptype, count, itype, (GLvoid *)mesh.vaoOffset, mesh.vaoBaseVertex); } void drawShadowRef(const GLMesh &mesh, const core::matrix4 &ModelMatrix) @@ -622,10 +460,7 @@ void drawShadowRef(const GLMesh &mesh, const core::matrix4 &ModelMatrix) compressTexture(mesh.textures[0], true); setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); MeshShader::RefShadowShader::setUniforms(ModelMatrix, 0); - - assert(mesh.vao); - glBindVertexArray(mesh.vao); - glDrawElementsInstanced(ptype, count, itype, 0, 4); + glDrawElementsInstancedBaseVertex(ptype, count, itype, (GLvoid *)mesh.vaoOffset, 4, mesh.vaoBaseVertex); } void drawShadow(const GLMesh &mesh, const core::matrix4 &ModelMatrix) @@ -636,10 +471,7 @@ void drawShadow(const GLMesh &mesh, const core::matrix4 &ModelMatrix) size_t count = mesh.IndexCount; MeshShader::ShadowShader::setUniforms(ModelMatrix); - - assert(mesh.vao); - glBindVertexArray(mesh.vao); - glDrawElementsInstanced(ptype, count, itype, 0, 4); + glDrawElementsInstancedBaseVertex(ptype, count, itype, (GLvoid *) mesh.vaoOffset, 4, mesh.vaoBaseVertex); } bool isObject(video::E_MATERIAL_TYPE type) diff --git a/src/graphics/stkmesh.hpp b/src/graphics/stkmesh.hpp index bb983694d..86e6c83b6 100644 --- a/src/graphics/stkmesh.hpp +++ b/src/graphics/stkmesh.hpp @@ -12,7 +12,8 @@ enum GeometricMaterial { - FPSM_DEFAULT, + FPSM_DEFAULT_STANDARD, + FPSM_DEFAULT_2TCOORD, FPSM_ALPHA_REF_TEXTURE, FPSM_NORMAL_MAP, FPSM_GRASS, @@ -21,7 +22,8 @@ enum GeometricMaterial enum ShadedMaterial { - SM_DEFAULT, + SM_DEFAULT_STANDARD, + SM_DEFAULT_TANGENT, SM_ALPHA_REF_TEXTURE, SM_RIMLIT, SM_SPHEREMAP, @@ -51,9 +53,13 @@ struct GLMesh { size_t IndexCount; size_t Stride; core::matrix4 TextureMatrix; + size_t vaoBaseVertex; + size_t vaoOffset; + video::E_VERTEX_TYPE VAOType; }; GLMesh allocateMeshBuffer(scene::IMeshBuffer* mb); +void fillLocalBuffer(GLMesh &, scene::IMeshBuffer* mb); video::E_VERTEX_TYPE getVTXTYPEFromStride(size_t stride); GLuint createVAO(GLuint vbo, GLuint idx, video::E_VERTEX_TYPE type); void initvaostate(GLMesh &mesh, GeometricMaterial GeoMat, ShadedMaterial ShadedMat); @@ -89,7 +95,7 @@ std::vector GroupedFPSM::TIMVSet; template -void draw(const GLMesh &mesh, GLuint vao, uniforms... Args) +void draw(const GLMesh &mesh, uniforms... Args) { irr_driver->IncreaseObjectCount(); GLenum ptype = mesh.PrimitiveType; @@ -97,10 +103,7 @@ void draw(const GLMesh &mesh, GLuint vao, uniforms... Args) size_t count = mesh.IndexCount; Shader::setUniforms(Args...); - - assert(vao); - glBindVertexArray(vao); - glDrawElements(ptype, count, itype, 0); + glDrawElementsBaseVertex(ptype, count, itype, (GLvoid *)mesh.vaoOffset, mesh.vaoBaseVertex); } void drawGrassPass1(const GLMesh &mesh, const core::matrix4 & ModelViewProjectionMatrix, const core::matrix4 &TransposeInverseModelView, core::vector3df windDir); @@ -128,15 +131,8 @@ std::vector GroupedSM::MVPSet; template std::vector GroupedSM::TIMVSet; -void drawDetailledObjectPass2(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix); -void drawObjectPass2(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TextureMatrix); -void drawUntexturedObject(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix); -void drawObjectRefPass2(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TextureMatrix); -void drawSphereMap(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TransposeInverseModelView); void drawSplatting(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix); void drawGrassPass2(const GLMesh &mesh, const core::matrix4 & ModelViewProjectionMatrix, core::vector3df windDir); -void drawObjectRimLimit(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TransposeInverseModelView, const core::matrix4 &TextureMatrix); -void drawObjectUnlit(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix); // Shadow pass void drawShadowRef(const GLMesh &mesh, const core::matrix4 &ModelMatrix); @@ -166,8 +162,8 @@ void drawTransparentObject(const GLMesh &mesh, const core::matrix4 &ModelViewPro void drawTransparentFogObject(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix, const core::matrix4 &TextureMatrix); void drawBubble(const GLMesh &mesh, const core::matrix4 &ModelViewProjectionMatrix); -GeometricMaterial MaterialTypeToGeometricMaterial(video::E_MATERIAL_TYPE); -ShadedMaterial MaterialTypeToShadedMaterial(video::E_MATERIAL_TYPE, irr::video::ITexture **textures); +GeometricMaterial MaterialTypeToGeometricMaterial(video::E_MATERIAL_TYPE, video::E_VERTEX_TYPE); +ShadedMaterial MaterialTypeToShadedMaterial(video::E_MATERIAL_TYPE, irr::video::ITexture **textures, video::E_VERTEX_TYPE tp); TransparentMaterial MaterialTypeToTransparentMaterial(video::E_MATERIAL_TYPE, f32 MaterialTypeParam); #endif // STKMESH_H diff --git a/src/graphics/stkmeshscenenode.cpp b/src/graphics/stkmeshscenenode.cpp index 2e87a9a29..8835412b9 100644 --- a/src/graphics/stkmeshscenenode.cpp +++ b/src/graphics/stkmeshscenenode.cpp @@ -16,13 +16,16 @@ STKMeshSceneNode::STKMeshSceneNode(irr::scene::IMesh* mesh, ISceneNode* parent, const irr::core::vector3df& scale) : CMeshSceneNode(mesh, parent, mgr, id, position, rotation, scale) { - reload_each_frame = false; + immediate_draw = false; + update_each_frame = false; createGLMeshes(); } void STKMeshSceneNode::setReloadEachFrame(bool val) { - reload_each_frame = val; + update_each_frame = val; + if (val) + immediate_draw = true; } void STKMeshSceneNode::createGLMeshes() @@ -60,16 +63,38 @@ void STKMeshSceneNode::setFirstTimeMaterial() if (rnd->isTransparent()) { TransparentMaterial TranspMat = MaterialTypeToTransparentMaterial(type, MaterialTypeParam); - initvaostate(mesh, TranspMat); - TransparentMesh[TranspMat].push_back(&mesh); + if (immediate_draw) + { + fillLocalBuffer(mesh, mb); + initvaostate(mesh, TranspMat); + glBindVertexArray(0); + } + else + TransparentMesh[TranspMat].push_back(&mesh); } else { - GeometricMaterial GeometricType = MaterialTypeToGeometricMaterial(type); - ShadedMaterial ShadedType = MaterialTypeToShadedMaterial(type, mesh.textures); - initvaostate(mesh, GeometricType, ShadedType); - GeometricMesh[GeometricType].push_back(&mesh); - ShadedMesh[ShadedType].push_back(&mesh); + GeometricMaterial GeometricType = MaterialTypeToGeometricMaterial(type, mb->getVertexType()); + ShadedMaterial ShadedType = MaterialTypeToShadedMaterial(type, mesh.textures, mb->getVertexType()); + if (immediate_draw) + { + fillLocalBuffer(mesh, mb); + initvaostate(mesh, GeometricType, ShadedType); + glBindVertexArray(0); + } + else + { + GeometricMesh[GeometricType].push_back(&mesh); + ShadedMesh[ShadedType].push_back(&mesh); + } + } + + if (!immediate_draw) + { + std::pair p = getVAOOffsetAndBase(mb); + mesh.vaoBaseVertex = p.first; + mesh.vaoOffset = p.second; + mesh.VAOType = mb->getVertexType(); } } isMaterialInitialized = true; @@ -109,22 +134,26 @@ STKMeshSceneNode::~STKMeshSceneNode() void STKMeshSceneNode::drawGlow(const GLMesh &mesh) { ColorizeProvider * const cb = (ColorizeProvider *)irr_driver->getCallback(ES_COLORIZE); + assert(mesh.VAOType == video::EVT_STANDARD); GLenum ptype = mesh.PrimitiveType; GLenum itype = mesh.IndexType; size_t count = mesh.IndexCount; MeshShader::ColorizeShader::setUniforms(AbsoluteTransformation, cb->getRed(), cb->getGreen(), cb->getBlue()); - - assert(mesh.vao); - glBindVertexArray(mesh.vao); - glDrawElements(ptype, count, itype, 0); + glDrawElementsInstancedBaseVertex(ptype, count, itype, (GLvoid *)mesh.vaoOffset, 4, mesh.vaoBaseVertex); } static video::ITexture *displaceTex = 0; void STKMeshSceneNode::drawDisplace(const GLMesh &mesh) { + if (mesh.VAOType != video::EVT_2TCOORDS) + { + Log::error("Materials", "Displacement has wrong vertex type"); + return; + } + glBindVertexArray(getVAO(video::EVT_2TCOORDS)); DisplaceProvider * const cb = (DisplaceProvider *)irr_driver->getCallback(ES_DISPLACE); GLenum ptype = mesh.PrimitiveType; @@ -137,9 +166,7 @@ void STKMeshSceneNode::drawDisplace(const GLMesh &mesh) glUseProgram(MeshShader::DisplaceMaskShader::Program); MeshShader::DisplaceMaskShader::setUniforms(AbsoluteTransformation); - - glBindVertexArray(mesh.vao); - glDrawElements(ptype, count, itype, 0); + glDrawElementsInstancedBaseVertex(ptype, count, itype, (GLvoid *)mesh.vaoOffset, 4, mesh.vaoBaseVertex); // Render the effect if (!displaceTex) @@ -156,7 +183,7 @@ void STKMeshSceneNode::drawDisplace(const GLMesh &mesh) float(UserConfigParams::m_height)), 0, 1, 2); - glDrawElements(ptype, count, itype, 0); + glDrawElementsInstancedBaseVertex(ptype, count, itype, (GLvoid *)mesh.vaoOffset, 4, mesh.vaoBaseVertex); } void STKMeshSceneNode::drawTransparent(const GLMesh &mesh, video::E_MATERIAL_TYPE type) @@ -174,33 +201,6 @@ void STKMeshSceneNode::drawTransparent(const GLMesh &mesh, video::E_MATERIAL_TYP return; } -void STKMeshSceneNode::drawSolidPass1(const GLMesh &mesh, GeometricMaterial type) -{ - irr_driver->IncreaseObjectCount(); - windDir = getWind(); - switch (type) - { - case FPSM_GRASS: - drawGrassPass1(mesh, ModelViewProjectionMatrix, TransposeInverseModelView, windDir); - break; - default: - assert(0 && "wrong geometric material"); - } -} - -void STKMeshSceneNode::drawSolidPass2(const GLMesh &mesh, ShadedMaterial type) -{ - switch (type) - { - case SM_GRASS: - drawGrassPass2(mesh, ModelViewProjectionMatrix, windDir); - break; - default: - assert(0 && "Wrong shaded material"); - break; - } -} - void STKMeshSceneNode::updatevbo() { for (unsigned i = 0; i < Mesh->getMeshBufferCount(); ++i) @@ -243,8 +243,8 @@ void STKMeshSceneNode::render() if (!Mesh || !driver) return; - if (reload_each_frame) - updatevbo(); + bool isTransparentPass = + SceneManager->getSceneNodeRenderPass() == scene::ESNRP_TRANSPARENT; ++PassCount; @@ -260,20 +260,52 @@ void STKMeshSceneNode::render() GLmeshes[i].TextureMatrix = getMaterial(i).getTextureMatrix(0); } - if (irr_driver->getPhase() == SOLID_NORMAL_AND_DEPTH_PASS || irr_driver->getPhase() == SHADOW_PASS) + if (irr_driver->getPhase() == SOLID_NORMAL_AND_DEPTH_PASS) { - if (reload_each_frame) - glDisable(GL_CULL_FACE); ModelViewProjectionMatrix = computeMVP(AbsoluteTransformation); TransposeInverseModelView = computeTIMV(AbsoluteTransformation); core::matrix4 invmodel; AbsoluteTransformation.getInverse(invmodel); - GLMesh* mesh; - for_in(mesh, GeometricMesh[FPSM_DEFAULT]) + + if (immediate_draw) { - GroupedFPSM::MeshSet.push_back(mesh); - GroupedFPSM::MVPSet.push_back(AbsoluteTransformation); - GroupedFPSM::TIMVSet.push_back(invmodel); + glDisable(GL_CULL_FACE); + if (update_each_frame) + updatevbo(); + glUseProgram(MeshShader::ObjectPass1Shader::Program); + // Only untextured + for (unsigned i = 0; i < GLmeshes.size(); i++) + { + irr_driver->IncreaseObjectCount(); + GLMesh &mesh = GLmeshes[i]; + GLenum ptype = mesh.PrimitiveType; + GLenum itype = mesh.IndexType; + size_t count = mesh.IndexCount; + + MeshShader::ObjectPass1Shader::setUniforms(AbsoluteTransformation, invmodel, 0); + assert(mesh.vao); + glBindVertexArray(mesh.vao); + glDrawElements(ptype, count, itype, 0); + glBindVertexArray(0); + } + glEnable(GL_CULL_FACE); + return; + } + + + GLMesh* mesh; + for_in(mesh, GeometricMesh[FPSM_DEFAULT_STANDARD]) + { + GroupedFPSM::MeshSet.push_back(mesh); + GroupedFPSM::MVPSet.push_back(AbsoluteTransformation); + GroupedFPSM::TIMVSet.push_back(invmodel); + } + + for_in(mesh, GeometricMesh[FPSM_DEFAULT_2TCOORD]) + { + GroupedFPSM::MeshSet.push_back(mesh); + GroupedFPSM::MVPSet.push_back(AbsoluteTransformation); + GroupedFPSM::TIMVSet.push_back(invmodel); } for_in(mesh, GeometricMesh[FPSM_ALPHA_REF_TEXTURE]) @@ -290,33 +322,57 @@ void STKMeshSceneNode::render() GroupedFPSM::TIMVSet.push_back(invmodel); } - if (irr_driver->getPhase() == SOLID_NORMAL_AND_DEPTH_PASS) - { - if (!GeometricMesh[FPSM_GRASS].empty()) - glUseProgram(MeshShader::GrassPass1Shader::Program); - for_in(mesh, GeometricMesh[FPSM_GRASS]) - drawSolidPass1(*mesh, FPSM_GRASS); - } + if (!GeometricMesh[FPSM_GRASS].empty()) + glUseProgram(MeshShader::GrassPass1Shader::Program); + windDir = getWind(); + glBindVertexArray(getVAO(video::EVT_STANDARD)); + for_in(mesh, GeometricMesh[FPSM_GRASS]) + drawGrassPass1(*mesh, ModelViewProjectionMatrix, TransposeInverseModelView, windDir); - if (reload_each_frame) - glEnable(GL_CULL_FACE); return; } if (irr_driver->getPhase() == SOLID_LIT_PASS) { - if (reload_each_frame) - glDisable(GL_CULL_FACE); - core::matrix4 invmodel; AbsoluteTransformation.getInverse(invmodel); - GLMesh* mesh; - for_in(mesh, ShadedMesh[SM_DEFAULT]) + if (immediate_draw) { - GroupedSM::MeshSet.push_back(mesh); - GroupedSM::MVPSet.push_back(AbsoluteTransformation); - GroupedSM::TIMVSet.push_back(invmodel); + glDisable(GL_CULL_FACE); + glUseProgram(MeshShader::UntexturedObjectShader::Program); + // Only untextured + for (unsigned i = 0; i < GLmeshes.size(); i++) + { + irr_driver->IncreaseObjectCount(); + GLMesh &mesh = GLmeshes[i]; + GLenum ptype = mesh.PrimitiveType; + GLenum itype = mesh.IndexType; + size_t count = mesh.IndexCount; + + MeshShader::UntexturedObjectShader::setUniforms(AbsoluteTransformation); + assert(mesh.vao); + glBindVertexArray(mesh.vao); + glDrawElements(ptype, count, itype, 0); + glBindVertexArray(0); + } + glEnable(GL_CULL_FACE); + return; + } + + GLMesh* mesh; + for_in(mesh, ShadedMesh[SM_DEFAULT_STANDARD]) + { + GroupedSM::MeshSet.push_back(mesh); + GroupedSM::MVPSet.push_back(AbsoluteTransformation); + GroupedSM::TIMVSet.push_back(invmodel); + } + + for_in(mesh, ShadedMesh[SM_DEFAULT_TANGENT]) + { + GroupedSM::MeshSet.push_back(mesh); + GroupedSM::MVPSet.push_back(AbsoluteTransformation); + GroupedSM::TIMVSet.push_back(invmodel); } for_in(mesh, ShadedMesh[SM_ALPHA_REF_TEXTURE]) @@ -364,11 +420,10 @@ void STKMeshSceneNode::render() if (!ShadedMesh[SM_GRASS].empty()) glUseProgram(MeshShader::GrassPass2Shader::Program); + glBindVertexArray(getVAO(video::EVT_STANDARD)); for_in(mesh, ShadedMesh[SM_GRASS]) - drawSolidPass2(*mesh, SM_GRASS); + drawGrassPass2(*mesh, ModelViewProjectionMatrix, windDir); - if (reload_each_frame) - glEnable(GL_CULL_FACE); return; } @@ -380,6 +435,7 @@ void STKMeshSceneNode::render() scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i); if (!mb) continue; + glBindVertexArray(getVAO(video::EVT_STANDARD)); drawGlow(GLmeshes[i]); } } @@ -388,6 +444,71 @@ void STKMeshSceneNode::render() { ModelViewProjectionMatrix = computeMVP(AbsoluteTransformation); + if (immediate_draw) + { + if (update_each_frame) + updatevbo(); + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + + if (World::getWorld() && World::getWorld()->isFogEnabled()) + { + glUseProgram(MeshShader::TransparentFogShader::Program); + for (unsigned i = 0; i < GLmeshes.size(); i++) + { + GLMesh &mesh = GLmeshes[i]; + irr_driver->IncreaseObjectCount(); + GLenum ptype = mesh.PrimitiveType; + GLenum itype = mesh.IndexType; + size_t count = mesh.IndexCount; + + const Track * const track = World::getWorld()->getTrack(); + + // This function is only called once per frame - thus no need for setters. + 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(); + + core::vector3df col(tmpcol.getRed() / 255.0f, + tmpcol.getGreen() / 255.0f, + tmpcol.getBlue() / 255.0f); + + compressTexture(mesh.textures[0], true); + setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); + MeshShader::TransparentFogShader::setUniforms(AbsoluteTransformation, mesh.TextureMatrix, fogmax, startH, endH, start, end, col, Camera::getCamera(0)->getCameraSceneNode()->getAbsolutePosition(), 0); + + assert(mesh.vao); + glBindVertexArray(mesh.vao); + glDrawElements(ptype, count, itype, 0); + glBindVertexArray(0); + } + } + else + { + glUseProgram(MeshShader::TransparentShader::Program); + for (unsigned i = 0; i < GLmeshes.size(); i++) + { + irr_driver->IncreaseObjectCount(); + GLMesh &mesh = GLmeshes[i]; + GLenum ptype = mesh.PrimitiveType; + GLenum itype = mesh.IndexType; + size_t count = mesh.IndexCount; + + compressTexture(mesh.textures[0], true); + setTexture(0, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); + + MeshShader::TransparentShader::setUniforms(AbsoluteTransformation, mesh.TextureMatrix, 0); + assert(mesh.vao); + glBindVertexArray(mesh.vao); + glDrawElements(ptype, count, itype, 0); + glBindVertexArray(0); + } + } + return; + } + GLMesh* mesh; for_in(mesh, TransparentMesh[TM_DEFAULT]) @@ -404,6 +525,7 @@ void STKMeshSceneNode::render() if (!TransparentMesh[TM_BUBBLE].empty()) glUseProgram(MeshShader::BubbleShader::Program); + glBindVertexArray(getVAO(video::EVT_STANDARD)); for_in(mesh, TransparentMesh[TM_BUBBLE]) drawBubble(*mesh, ModelViewProjectionMatrix); return; diff --git a/src/graphics/stkmeshscenenode.hpp b/src/graphics/stkmeshscenenode.hpp index 35588e430..646935fe5 100644 --- a/src/graphics/stkmeshscenenode.hpp +++ b/src/graphics/stkmeshscenenode.hpp @@ -26,7 +26,8 @@ protected: void setFirstTimeMaterial(); void updatevbo(); bool isMaterialInitialized; - bool reload_each_frame; + bool immediate_draw; + bool update_each_frame; public: void setReloadEachFrame(bool); STKMeshSceneNode(irr::scene::IMesh* mesh, ISceneNode* parent, irr::scene::ISceneManager* mgr, irr::s32 id, From 6d7178aff5a9babe8f0d9fe2fdb82be9b203ce88 Mon Sep 17 00:00:00 2001 From: Vincent Lejeune Date: Wed, 9 Jul 2014 00:26:28 +0200 Subject: [PATCH 5/6] Fix for missing texture with non advanced pipeline --- src/graphics/render.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/graphics/render.cpp b/src/graphics/render.cpp index e7c2dbb6d..aa199e014 100644 --- a/src/graphics/render.cpp +++ b/src/graphics/render.cpp @@ -624,7 +624,7 @@ void IrrDriver::renderSolidSecondPass() glBindVertexArray(getVAO(video::EVT_STANDARD)); for (unsigned i = 0; i < GroupedSM::MeshSet.size(); i++) { - const GLMesh &mesh = *GroupedSM::MeshSet[i]; + GLMesh &mesh = *GroupedSM::MeshSet[i]; if (mesh.VAOType != video::EVT_STANDARD) { #ifdef DEBUG @@ -632,6 +632,8 @@ void IrrDriver::renderSolidSecondPass() #endif continue; } + if (!mesh.textures[0]) + mesh.textures[0] = getUnicolorTexture(video::SColor(255, 255, 255, 255)); compressTexture(mesh.textures[0], true); setTexture(MeshShader::ObjectPass2Shader::TU_Albedo, getTextureGLuint(mesh.textures[0]), GL_LINEAR, GL_LINEAR_MIPMAP_LINEAR, true); if (irr_driver->getLightViz()) From 7a0afd9321668ed3ae9263a0895dff2d8f55b71d Mon Sep 17 00:00:00 2001 From: Marianne Gagnon Date: Tue, 8 Jul 2014 20:10:54 -0400 Subject: [PATCH 6/6] Fix crash when changing kart from overworld --- src/modes/overworld.cpp | 4 ++-- src/modes/world.cpp | 9 ++++++++- src/modes/world.hpp | 6 ++++++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/modes/overworld.cpp b/src/modes/overworld.cpp index 667b54e28..0b98f69e7 100644 --- a/src/modes/overworld.cpp +++ b/src/modes/overworld.cpp @@ -149,12 +149,12 @@ void OverWorld::update(float dt) if (m_return_to_garage) { m_return_to_garage = false; - delayedSelfDestruct(); - race_manager->exitRace(false); + race_manager->exitRace(); KartSelectionScreen* s = OfflineKartSelectionScreen::getInstance(); s->setMultiplayer(false); s->setFromOverworld(true); StateManager::get()->resetAndGoToScreen(s); + throw AbortWorldUpdateException(); } } // update diff --git a/src/modes/world.cpp b/src/modes/world.cpp index af8ddb386..d80ae7b7d 100644 --- a/src/modes/world.cpp +++ b/src/modes/world.cpp @@ -793,7 +793,14 @@ void World::updateWorld(float dt) getPhase() == IN_GAME_MENU_PHASE ) return; - update(dt); + try + { + update(dt); + } + catch (AbortWorldUpdateException& e) + { + return; + } #ifdef DEBUG assert(m_magic_number == 0xB01D6543); diff --git a/src/modes/world.hpp b/src/modes/world.hpp index 1f88cf723..c4699facf 100644 --- a/src/modes/world.hpp +++ b/src/modes/world.hpp @@ -47,6 +47,12 @@ namespace irr namespace scene { class ISceneNode; } } +class AbortWorldUpdateException : public std::runtime_error +{ +public: + AbortWorldUpdateException() : std::runtime_error("race abort") { }; +}; + /** * \brief base class for all game modes * This class is responsible for running the actual race. A world is created