Use an instance manager

This commit is contained in:
vlj 2014-08-22 18:49:30 +02:00 committed by Vincent Lejeune
parent a0b376f04d
commit 4a62fd7968
9 changed files with 252 additions and 57 deletions

View File

@ -128,6 +128,7 @@ extern PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallbackARB;
#ifdef WIN32
#define Bindless_Texture_Support
#define Base_Instance_Support
#endif
#endif

View File

@ -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<const char*>(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<std::pair<video::E_VERTEX_TYPE, InstanceType>, GLuint> Map)
{
std::map<std::pair<video::E_VERTEX_TYPE, InstanceType>, 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<video::E_VERTEX_TYPE, InstanceType>(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<video::E_VERTEX_TYPE, InstanceType>(tp, (InstanceType)j)] = shadow_vao;
glBindVertexArray(0);
}
}
}
size_t VAOManager::getVertexPitch(enum VTXTYPE tp) const
{
switch (tp)
@ -756,6 +827,7 @@ std::pair<unsigned, unsigned> VAOManager::getBase(scene::IMeshBuffer *mb)
append(mb, tp);
regenerateBuffer(tp);
regenerateVAO(tp);
regenerateInstancedVAO();
}
std::map<scene::IMeshBuffer*, unsigned>::iterator It;
@ -767,6 +839,15 @@ std::pair<unsigned, unsigned> VAOManager::getBase(scene::IMeshBuffer *mb)
return std::pair<unsigned, unsigned>(vtx, It->second);
}
size_t VAOManager::appendInstance(enum InstanceType, const std::vector<InstanceData> &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;

View File

@ -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<VAOManager>
{
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<scene::IMeshBuffer *> storedCPUBuffer[VTXTYPE_COUNT];
void *vtx_mirror[VTXTYPE_COUNT], *idx_mirror[VTXTYPE_COUNT];
size_t vtx_cnt[VTXTYPE_COUNT], idx_cnt[VTXTYPE_COUNT];
std::map<scene::IMeshBuffer*, unsigned> mappedBaseVertex[VTXTYPE_COUNT], mappedBaseIndex[VTXTYPE_COUNT];
std::map<std::pair<video::E_VERTEX_TYPE, InstanceType>, 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<unsigned, unsigned> getBase(scene::IMeshBuffer *);
size_t appendInstance(enum InstanceType, const std::vector<InstanceData> &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<video::E_VERTEX_TYPE, InstanceType>(vt, it)]; }
unsigned getShadowInstanceVAO(video::E_VERTEX_TYPE vt, enum InstanceType it) { return ShadowInstanceVAO[std::pair<video::E_VERTEX_TYPE, InstanceType>(vt, it)]; }
~VAOManager();
};

View File

@ -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
}

View File

@ -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;

View File

@ -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<TexUnit> &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<MeshShader::ObjectPass1Shader, video::EVT_2TCOORDS, 2, 1>(TexUnits(TexUnit(0, true)), AnimatedListMatDetails::getInstance());
renderMeshes1stPass<MeshShader::ObjectRefPass1Shader, video::EVT_STANDARD, 3, 2, 1>(TexUnits(TexUnit(0, true)), AnimatedListMatUnlit::getInstance());
if (irr_driver->hasARB_base_instance())
glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(video::EVT_STANDARD, InstanceTypeDefault));
renderInstancedMeshes1stPass<MeshShader::InstancedObjectPass1Shader, video::EVT_STANDARD>(
TexUnits(TexUnit(0, true)),
ListInstancedMatDefault::getInstance());
if (irr_driver->hasARB_base_instance())
glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(video::EVT_STANDARD, InstanceTypeDefault));
renderInstancedMeshes1stPass<MeshShader::InstancedObjectRefPass1Shader, video::EVT_STANDARD>(
TexUnits(TexUnit(0, true)),
ListInstancedMatAlphaRef::getInstance());
if (irr_driver->hasARB_base_instance())
glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(video::EVT_STANDARD, InstanceTypeDefault));
renderInstancedMeshes1stPass<MeshShader::InstancedGrassPass1Shader, video::EVT_STANDARD, 2>(
TexUnits(TexUnit(0, true)),
ListInstancedMatGrass::getInstance());
if (irr_driver->hasARB_base_instance())
glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(video::EVT_TANGENTS, InstanceTypeDefault));
renderInstancedMeshes1stPass<MeshShader::InstancedNormalMapShader, video::EVT_TANGENTS>(
TexUnits(TexUnit(1, false), TexUnit(0, true)),
ListInstancedMatNormalMap::getInstance());
@ -385,7 +399,8 @@ void renderInstancedMeshes2ndPass(const std::vector<TexUnit> &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<GLuint> Textures(Prefilled_tex);
std::vector<uint64_t> Handles(Prefilled_Handles);
@ -529,15 +544,23 @@ void IrrDriver::renderSolidSecondPass()
TexUnit(0, true)
), ListMatNormalMap::getInstance(), createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle), DiffSpecSSAOTex);
if (irr_driver->hasARB_base_instance())
glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(video::EVT_STANDARD, InstanceTypeDefault));
renderInstancedMeshes2ndPass<MeshShader::InstancedObjectPass2Shader>(
TexUnits(TexUnit(0, true)),
ListInstancedMatDefault::getInstance(), createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle), DiffSpecSSAOTex);
if (irr_driver->hasARB_base_instance())
glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(video::EVT_TANGENTS, InstanceTypeDefault));
renderInstancedMeshes2ndPass<MeshShader::InstancedObjectPass2Shader>(
TexUnits(TexUnit(0, true)),
ListInstancedMatNormalMap::getInstance(), createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle), DiffSpecSSAOTex);
if (irr_driver->hasARB_base_instance())
glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(video::EVT_STANDARD, InstanceTypeDefault));
renderInstancedMeshes2ndPass<MeshShader::InstancedObjectRefPass2Shader>(
TexUnits(TexUnit(0, true)),
ListInstancedMatAlphaRef::getInstance(), createVector<uint64_t>(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<MeshShader::InstancedGrassPass2Shader, 3, 2>(
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<GLuint> TextureUnits, const std::ve
std::vector<uint64_t> Handles;
std::vector<GLuint> 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<MeshShader::RefShadowShader, EVT_STANDARD, 1>(std::vector<GLuint>{ 0 }, AnimatedListMatUnlit::getInstance());
renderShadow<MeshShader::ShadowShader, EVT_2TCOORDS, 1>(noTexUnits, AnimatedListMatDetails::getInstance());
if (irr_driver->hasARB_base_instance())
glBindVertexArray(VAOManager::getInstance()->getShadowInstanceVAO(video::EVT_STANDARD, InstanceTypeDefault));
renderInstancedShadow<MeshShader::InstancedShadowShader>(noTexUnits, ListInstancedMatDefault::getInstance());
if (irr_driver->hasARB_base_instance())
glBindVertexArray(VAOManager::getInstance()->getShadowInstanceVAO(video::EVT_STANDARD, InstanceTypeDefault));
renderInstancedShadow<MeshShader::InstancedRefShadowShader>(std::vector<GLuint>{ 0 }, ListInstancedMatAlphaRef::getInstance());
if (irr_driver->hasARB_base_instance())
glBindVertexArray(VAOManager::getInstance()->getShadowInstanceVAO(video::EVT_STANDARD, InstanceTypeDefault));
renderInstancedShadow<MeshShader::InstancedGrassShadowShader, 2>(std::vector<GLuint>{ 0 }, ListInstancedMatGrass::getInstance());
if (irr_driver->hasARB_base_instance())
glBindVertexArray(VAOManager::getInstance()->getShadowInstanceVAO(video::EVT_TANGENTS, InstanceTypeDefault));
renderInstancedShadow<MeshShader::InstancedShadowShader>(noTexUnits, ListInstancedMatNormalMap::getInstance());
glDisable(GL_POLYGON_OFFSET_FILL);

View File

@ -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<unsigned, unsigned> 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()));
}
}

View File

@ -22,7 +22,7 @@ protected:
int m_ref_count;
std::vector<GLMesh *> MeshSolidMaterial[MAT_COUNT];
std::vector<GLMesh> GLmeshes;
std::vector<float> instance_pos;
std::vector<InstanceData> 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);

View File

@ -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];
};