diff --git a/src/graphics/gl_headers.hpp b/src/graphics/gl_headers.hpp index 81789ddf2..91c314ef2 100644 --- a/src/graphics/gl_headers.hpp +++ b/src/graphics/gl_headers.hpp @@ -128,6 +128,7 @@ extern PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallbackARB; #ifdef WIN32 #define Bindless_Texture_Support +#define Base_Instance_Support #endif #endif \ No newline at end of file diff --git a/src/graphics/glwrap.cpp b/src/graphics/glwrap.cpp index c8b44bd5c..3baa27d22 100644 --- a/src/graphics/glwrap.cpp +++ b/src/graphics/glwrap.cpp @@ -4,6 +4,7 @@ #include "config/user_config.hpp" #include "utils/profiler.hpp" #include "utils/cpp2011.hpp" +#include "graphics/stkmesh.hpp" #ifdef _IRR_WINDOWS_API_ #define IRR_OGL_LOAD_EXTENSION(X) wglGetProcAddress(reinterpret_cast(X)) @@ -592,10 +593,33 @@ VAOManager::VAOManager() 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; + + glGenBuffers(1, &instance_vbo[0]); + glBindBuffer(GL_ARRAY_BUFFER, instance_vbo[0]); + glBufferData(GL_ARRAY_BUFFER, 10000 * sizeof(float)* 9, 0, GL_STATIC_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); + cleanVAOMap(ShadowInstanceVAO); + InstanceVAO.clear(); + ShadowInstanceVAO.clear(); } VAOManager::~VAOManager() { + cleanInstanceVAOs(); for (unsigned i = 0; i < 3; i++) { if (vtx_mirror[i]) @@ -609,7 +633,7 @@ VAOManager::~VAOManager() if (vao[i]) glDeleteVertexArrays(1, &vao[i]); } - + glDeleteBuffers(1, &instance_vbo[0]); } void VAOManager::regenerateBuffer(enum VTXTYPE tp) @@ -697,6 +721,53 @@ void VAOManager::regenerateVAO(enum VTXTYPE 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++) + { + for (unsigned j = 0; j < InstanceTypeCount; j++) + { + 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[j]); + + 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); + InstanceVAO[std::pair(tp, (InstanceType) j)] = vao; + + GLuint shadow_vao = createVAO(vbo[tp], ibo[tp], tp); + glBindBuffer(GL_ARRAY_BUFFER, instance_vbo[j]); + + glEnableVertexAttribArray(7); + glVertexAttribPointer(7, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), 0); + glVertexAttribDivisor(7, 4); + glEnableVertexAttribArray(8); + glVertexAttribPointer(8, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), (GLvoid*)(3 * sizeof(float))); + glVertexAttribDivisor(8, 4); + glEnableVertexAttribArray(9); + glVertexAttribPointer(9, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), (GLvoid*)(6 * sizeof(float))); + glVertexAttribDivisor(9, 4); + ShadowInstanceVAO[std::pair(tp, (InstanceType)j)] = shadow_vao; + glBindVertexArray(0); + } + } + + + +} + size_t VAOManager::getVertexPitch(enum VTXTYPE tp) const { switch (tp) @@ -756,6 +827,7 @@ std::pair VAOManager::getBase(scene::IMeshBuffer *mb) append(mb, tp); regenerateBuffer(tp); regenerateVAO(tp); + regenerateInstancedVAO(); } std::map::iterator It; @@ -767,6 +839,15 @@ std::pair VAOManager::getBase(scene::IMeshBuffer *mb) 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 &timer) { if (!UserConfigParams::m_profiler_enabled) return; diff --git a/src/graphics/glwrap.hpp b/src/graphics/glwrap.hpp index 034af4090..c775bcebe 100644 --- a/src/graphics/glwrap.hpp +++ b/src/graphics/glwrap.hpp @@ -139,25 +139,62 @@ 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, + InstanceTypeCount, +}; + +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; +}; + 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[1]; + size_t instance_count[1]; 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, ShadowInstanceVAO; + 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); unsigned getVBO(video::E_VERTEX_TYPE type) { return vbo[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)]; } + unsigned getShadowInstanceVAO(video::E_VERTEX_TYPE vt, enum InstanceType it) { return ShadowInstanceVAO[std::pair(vt, it)]; } ~VAOManager(); }; diff --git a/src/graphics/irr_driver.cpp b/src/graphics/irr_driver.cpp index 66eaabe21..b40d279d5 100644 --- a/src/graphics/irr_driver.cpp +++ b/src/graphics/irr_driver.cpp @@ -483,12 +483,20 @@ void IrrDriver::initDevice() // Parse extensions hasVSLayer = false; + hasBaseInstance = false; // Default false value for hasVSLayer if --no-graphics argument is used if (!ProfileWorld::isNoGraphics()) { if (hasGLExtension("GL_AMD_vertex_shader_layer")) { hasVSLayer = true; + Log::info("GLDriver", "AMD Vertex Shader Layer enabled"); } +#ifdef Base_Instance_Support + if (hasGLExtension("GL_ARB_base_instance")) { + hasBaseInstance = true; + Log::info("GLDriver", "ARB Instance enabled"); + } +#endif } diff --git a/src/graphics/irr_driver.hpp b/src/graphics/irr_driver.hpp index 86ca6490e..dec484903 100644 --- a/src/graphics/irr_driver.hpp +++ b/src/graphics/irr_driver.hpp @@ -199,6 +199,7 @@ class IrrDriver : public IEventReceiver, public NoCopy private: int GLMajorVersion, GLMinorVersion; bool hasVSLayer; + bool hasBaseInstance; bool m_need_ubo_workaround; bool m_need_rh_workaround; /** The irrlicht device. */ @@ -293,6 +294,11 @@ public: return m_need_rh_workaround; } + bool hasARB_base_instance() const + { + return hasBaseInstance; + } + bool hasVSLayerExtension() const { return hasVSLayer; diff --git a/src/graphics/render_geometry.cpp b/src/graphics/render_geometry.cpp index ae9d00c1d..1b3d01acb 100644 --- a/src/graphics/render_geometry.cpp +++ b/src/graphics/render_geometry.cpp @@ -176,7 +176,12 @@ struct instanced_custom_unroll_args<> size_t count = mesh->IndexCount; Shader->setUniforms(args...); - glDrawElementsInstanced(ptype, count, itype, 0, instance_count); +#ifdef Base_Instance_Support + if (irr_driver->hasARB_base_instance()) + glDrawElementsInstancedBaseVertexBaseInstance(ptype, count, itype, (const void*)mesh->vaoOffset, instance_count, mesh->vaoBaseVertex, mesh->vaoBaseInstance); + else +#endif + glDrawElementsInstanced(ptype, count, itype, 0, instance_count); } }; @@ -203,7 +208,8 @@ void renderInstancedMeshes1stPass(const std::vector &TexUnits, std::vec if (mesh.VAOType != VertexType) Log::error("RenderGeometry", "Wrong instanced vertex format"); #endif - glBindVertexArray(mesh.vao); + if (!irr_driver->hasARB_base_instance()) + glBindVertexArray(mesh.vao); for (unsigned j = 0; j < TexUnits.size(); j++) { if (!mesh.textures[TexUnits[j].m_id]) @@ -306,15 +312,23 @@ void IrrDriver::renderSolidFirstPass() renderMeshes1stPass(TexUnits(TexUnit(0, true)), AnimatedListMatDetails::getInstance()); renderMeshes1stPass(TexUnits(TexUnit(0, true)), AnimatedListMatUnlit::getInstance()); + if (irr_driver->hasARB_base_instance()) + glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(video::EVT_STANDARD, InstanceTypeDefault)); renderInstancedMeshes1stPass( TexUnits(TexUnit(0, true)), ListInstancedMatDefault::getInstance()); + if (irr_driver->hasARB_base_instance()) + glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(video::EVT_STANDARD, InstanceTypeDefault)); renderInstancedMeshes1stPass( TexUnits(TexUnit(0, true)), ListInstancedMatAlphaRef::getInstance()); + if (irr_driver->hasARB_base_instance()) + glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(video::EVT_STANDARD, InstanceTypeDefault)); renderInstancedMeshes1stPass( TexUnits(TexUnit(0, true)), ListInstancedMatGrass::getInstance()); + if (irr_driver->hasARB_base_instance()) + glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(video::EVT_TANGENTS, InstanceTypeDefault)); renderInstancedMeshes1stPass( TexUnits(TexUnit(1, false), TexUnit(0, true)), ListInstancedMatNormalMap::getInstance()); @@ -385,7 +399,8 @@ void renderInstancedMeshes2ndPass(const std::vector &TexUnits, std::vec for (unsigned i = 0; i < meshes->size(); i++) { GLMesh &mesh = *(STK::tuple_get<0>(meshes->at(i))); - glBindVertexArray(mesh.vao); + if (!irr_driver->hasARB_base_instance()) + glBindVertexArray(mesh.vao); std::vector Textures(Prefilled_tex); std::vector Handles(Prefilled_Handles); @@ -529,15 +544,23 @@ void IrrDriver::renderSolidSecondPass() TexUnit(0, true) ), ListMatNormalMap::getInstance(), createVector(DiffuseHandle, SpecularHandle, SSAOHandle), DiffSpecSSAOTex); + if (irr_driver->hasARB_base_instance()) + glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(video::EVT_STANDARD, InstanceTypeDefault)); renderInstancedMeshes2ndPass( TexUnits(TexUnit(0, true)), ListInstancedMatDefault::getInstance(), createVector(DiffuseHandle, SpecularHandle, SSAOHandle), DiffSpecSSAOTex); + if (irr_driver->hasARB_base_instance()) + glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(video::EVT_TANGENTS, InstanceTypeDefault)); renderInstancedMeshes2ndPass( TexUnits(TexUnit(0, true)), ListInstancedMatNormalMap::getInstance(), createVector(DiffuseHandle, SpecularHandle, SSAOHandle), DiffSpecSSAOTex); + if (irr_driver->hasARB_base_instance()) + glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(video::EVT_STANDARD, InstanceTypeDefault)); renderInstancedMeshes2ndPass( TexUnits(TexUnit(0, true)), ListInstancedMatAlphaRef::getInstance(), createVector(DiffuseHandle, SpecularHandle, SSAOHandle), DiffSpecSSAOTex); + if (irr_driver->hasARB_base_instance()) + glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(video::EVT_STANDARD, InstanceTypeDefault)); DiffSpecSSAOTex.push_back(irr_driver->getDepthStencilTexture()); renderInstancedMeshes2ndPass( TexUnits(TexUnit(0, true)), @@ -788,7 +811,12 @@ struct instanced_shadow_custom_unroll_args<> size_t count = mesh->IndexCount; Shader->setUniforms(args...); - glDrawElementsInstanced(ptype, count, itype, 0, 4 * instance_count); +#ifdef Base_Instance_Support + if (irr_driver->hasARB_base_instance()) + glDrawElementsInstancedBaseVertexBaseInstance(ptype, count, itype, (const void*) mesh->vaoOffset, 4 * instance_count, mesh->vaoBaseVertex, mesh->vaoBaseInstance); + else +#endif + glDrawElementsInstanced(ptype, count, itype, 0, 4 * instance_count); } }; @@ -811,7 +839,8 @@ void renderInstancedShadow(const std::vector TextureUnits, const std::ve std::vector Handles; std::vector Textures; GLMesh *mesh = STK::tuple_get<0>(t->at(i)); - glBindVertexArray(mesh->vao_shadow_pass); + if (!irr_driver->hasARB_base_instance()) + glBindVertexArray(mesh->vao_shadow_pass); for (unsigned j = 0; j < TextureUnits.size(); j++) { compressTexture(mesh->textures[TextureUnits[j]], true); @@ -883,9 +912,17 @@ void IrrDriver::renderShadows() renderShadow(std::vector{ 0 }, AnimatedListMatUnlit::getInstance()); renderShadow(noTexUnits, AnimatedListMatDetails::getInstance()); + if (irr_driver->hasARB_base_instance()) + glBindVertexArray(VAOManager::getInstance()->getShadowInstanceVAO(video::EVT_STANDARD, InstanceTypeDefault)); renderInstancedShadow(noTexUnits, ListInstancedMatDefault::getInstance()); + if (irr_driver->hasARB_base_instance()) + glBindVertexArray(VAOManager::getInstance()->getShadowInstanceVAO(video::EVT_STANDARD, InstanceTypeDefault)); renderInstancedShadow(std::vector{ 0 }, ListInstancedMatAlphaRef::getInstance()); + if (irr_driver->hasARB_base_instance()) + glBindVertexArray(VAOManager::getInstance()->getShadowInstanceVAO(video::EVT_STANDARD, InstanceTypeDefault)); renderInstancedShadow(std::vector{ 0 }, ListInstancedMatGrass::getInstance()); + if (irr_driver->hasARB_base_instance()) + glBindVertexArray(VAOManager::getInstance()->getShadowInstanceVAO(video::EVT_TANGENTS, InstanceTypeDefault)); renderInstancedShadow(noTexUnits, ListInstancedMatNormalMap::getInstance()); glDisable(GL_POLYGON_OFFSET_FILL); diff --git a/src/graphics/stkinstancedscenenode.cpp b/src/graphics/stkinstancedscenenode.cpp index 64c28206f..f12e27be7 100644 --- a/src/graphics/stkinstancedscenenode.cpp +++ b/src/graphics/stkinstancedscenenode.cpp @@ -50,41 +50,55 @@ void STKInstancedSceneNode::createGLMeshes() { scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i); GLmeshes.push_back(allocateMeshBuffer(mb)); - fillLocalBuffer(GLmeshes.back(), mb); + GLMesh &mesh = GLmeshes.back(); + if (irr_driver->hasARB_base_instance()) + { + std::pair p = VAOManager::getInstance()->getBase(mb); + mesh.vaoBaseVertex = p.first; + mesh.vaoOffset = p.second; + mesh.VAOType = mb->getVertexType(); + } + else + fillLocalBuffer(mesh, mb); } isMaterialInitialized = false; } void STKInstancedSceneNode::initinstancedvaostate(GLMesh &mesh) { - mesh.vao = createVAO(mesh.vertex_buffer, mesh.index_buffer, getVTXTYPEFromStride(mesh.Stride)); - glGenBuffers(1, &instances_vbo); - glBindBuffer(GL_ARRAY_BUFFER, instances_vbo); - glBufferData(GL_ARRAY_BUFFER, instance_pos.size() * sizeof(float), instance_pos.data(), GL_STATIC_DRAW); + if (irr_driver->hasARB_base_instance()) + mesh.vaoBaseInstance = VAOManager::getInstance()->appendInstance(InstanceTypeDefault, instanceData); + else + { + mesh.vao = createVAO(mesh.vertex_buffer, mesh.index_buffer, getVTXTYPEFromStride(mesh.Stride)); + glGenBuffers(1, &instances_vbo); + glBindBuffer(GL_ARRAY_BUFFER, instances_vbo); + glBufferData(GL_ARRAY_BUFFER, instanceData.size() * sizeof(InstanceData), instanceData.data(), GL_STATIC_DRAW); - glEnableVertexAttribArray(7); - glVertexAttribPointer(7, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), 0); - glVertexAttribDivisor(7, 1); - glEnableVertexAttribArray(8); - glVertexAttribPointer(8, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), (GLvoid*)(3 * sizeof(float))); - glVertexAttribDivisor(8, 1); - glEnableVertexAttribArray(9); - glVertexAttribPointer(9, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), (GLvoid*)(6 * sizeof(float))); - glVertexAttribDivisor(9, 1); + 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); - mesh.vao_shadow_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer, getVTXTYPEFromStride(mesh.Stride)); - glBindBuffer(GL_ARRAY_BUFFER, instances_vbo); - glEnableVertexAttribArray(7); - glVertexAttribPointer(7, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), 0); - glVertexAttribDivisor(7, 4); - glEnableVertexAttribArray(8); - glVertexAttribPointer(8, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), (GLvoid*)(3 * sizeof(float))); - glVertexAttribDivisor(8, 4); - glEnableVertexAttribArray(9); - glVertexAttribPointer(9, 3, GL_FLOAT, GL_FALSE, 9 * sizeof(float), (GLvoid*)(6 * sizeof(float))); - glVertexAttribDivisor(9, 4); + mesh.vao_shadow_pass = createVAO(mesh.vertex_buffer, mesh.index_buffer, getVTXTYPEFromStride(mesh.Stride)); + glBindBuffer(GL_ARRAY_BUFFER, instances_vbo); + glEnableVertexAttribArray(7); + glVertexAttribPointer(7, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), 0); + glVertexAttribDivisor(7, 4); + glEnableVertexAttribArray(8); + glVertexAttribPointer(8, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), (GLvoid*)(3 * sizeof(float))); + glVertexAttribDivisor(8, 4); + glEnableVertexAttribArray(9); + glVertexAttribPointer(9, 3, GL_FLOAT, GL_FALSE, sizeof(InstanceData), (GLvoid*)(6 * sizeof(float))); + glVertexAttribDivisor(9, 4); - glBindVertexArray(0); + glBindVertexArray(0); + } } void STKInstancedSceneNode::setFirstTimeMaterial() @@ -108,34 +122,44 @@ void STKInstancedSceneNode::setFirstTimeMaterial() void STKInstancedSceneNode::addInstance(const core::vector3df &origin, const core::vector3df &orientation, const core::vector3df &scale) { - instance_pos.push_back(origin.X); - instance_pos.push_back(origin.Y); - instance_pos.push_back(origin.Z); - instance_pos.push_back(orientation.X); - instance_pos.push_back(orientation.Y); - instance_pos.push_back(orientation.Z); - instance_pos.push_back(scale.X); - instance_pos.push_back(scale.Y); - instance_pos.push_back(scale.Z); + InstanceData instance = { + { + origin.X, + origin.Y, + origin.Z + }, + { + orientation.X, + orientation.Y, + orientation.Z + }, + { + scale.X, + scale.Y, + scale.Z + }, + 0 + }; + instanceData.push_back(instance); } core::matrix4 STKInstancedSceneNode::getInstanceTransform(int id) { core::matrix4 mat; - int offset = id * 9; + const InstanceData &instance = instanceData[id]; mat.setTranslation(core::vector3df( - instance_pos[offset], - instance_pos[offset + 1], - instance_pos[offset + 2])); + instance.Origin.X, + instance.Origin.Y, + instance.Origin.Z)); mat.setRotationDegrees(core::vector3df( - instance_pos[offset + 3], - instance_pos[offset + 4], - instance_pos[offset + 5])); + instance.Orientation.X, + instance.Orientation.Y, + instance.Orientation.Z)); mat.setScale(core::vector3df( - instance_pos[offset + 6], - instance_pos[offset + 7], - instance_pos[offset + 8])); + instance.Scale.X, + instance.Scale.Y, + instance.Scale.Z)); return mat; } @@ -154,13 +178,13 @@ void STKInstancedSceneNode::render() for(unsigned i = 0; i < MeshSolidMaterial[MAT_DEFAULT].size(); i++) { GLMesh *mesh = MeshSolidMaterial[MAT_DEFAULT][i]; - ListInstancedMatDefault::getInstance()->push_back(STK::make_tuple(mesh, instance_pos.size() / 9)); + ListInstancedMatDefault::getInstance()->push_back(STK::make_tuple(mesh, instanceData.size())); } for(unsigned i = 0; i < MeshSolidMaterial[MAT_ALPHA_REF].size(); i++) { GLMesh *mesh = MeshSolidMaterial[MAT_ALPHA_REF][i]; - ListInstancedMatAlphaRef::getInstance()->push_back(STK::make_tuple(mesh, instance_pos.size() / 9)); + ListInstancedMatAlphaRef::getInstance()->push_back(STK::make_tuple(mesh, instanceData.size())); } windDir = getWind(); @@ -168,12 +192,12 @@ void STKInstancedSceneNode::render() for(unsigned i = 0; i < MeshSolidMaterial[MAT_GRASS].size(); i++) { GLMesh *mesh = MeshSolidMaterial[MAT_GRASS][i]; - ListInstancedMatGrass::getInstance()->push_back(STK::make_tuple(mesh, instance_pos.size() / 9, windDir, cb->getPosition())); + ListInstancedMatGrass::getInstance()->push_back(STK::make_tuple(mesh, instanceData.size(), windDir, cb->getPosition())); } for(unsigned i = 0; i < MeshSolidMaterial[MAT_NORMAL_MAP].size(); i++) { GLMesh *mesh = MeshSolidMaterial[MAT_NORMAL_MAP][i]; - ListInstancedMatNormalMap::getInstance()->push_back(STK::make_tuple(mesh, instance_pos.size() / 9)); + ListInstancedMatNormalMap::getInstance()->push_back(STK::make_tuple(mesh, instanceData.size())); } } diff --git a/src/graphics/stkinstancedscenenode.hpp b/src/graphics/stkinstancedscenenode.hpp index d1063ca6d..35a38d8b1 100644 --- a/src/graphics/stkinstancedscenenode.hpp +++ b/src/graphics/stkinstancedscenenode.hpp @@ -22,7 +22,7 @@ protected: int m_ref_count; std::vector MeshSolidMaterial[MAT_COUNT]; std::vector GLmeshes; - std::vector instance_pos; + std::vector instanceData; core::matrix4 ModelViewProjectionMatrix, TransposeInverseModelView; GLuint instances_vbo; void createGLMeshes(); @@ -40,7 +40,7 @@ public: virtual void render(); void addInstance(const core::vector3df &origin, const core::vector3df &orientation, const core::vector3df &scale); - int getInstanceCount() const { return instance_pos.size() / 9; } + int getInstanceCount() const { return instanceData.size(); } core::matrix4 getInstanceTransform(int id); diff --git a/src/graphics/stkmesh.hpp b/src/graphics/stkmesh.hpp index dd21eb6c6..beaee62cb 100644 --- a/src/graphics/stkmesh.hpp +++ b/src/graphics/stkmesh.hpp @@ -46,6 +46,7 @@ struct GLMesh { core::matrix4 TextureMatrix; size_t vaoBaseVertex; size_t vaoOffset; + size_t vaoBaseInstance; video::E_VERTEX_TYPE VAOType; uint64_t TextureHandles[6]; };