Use an instance manager
This commit is contained in:
parent
a0b376f04d
commit
4a62fd7968
@ -128,6 +128,7 @@ extern PFNGLDEBUGMESSAGECALLBACKARBPROC glDebugMessageCallbackARB;
|
||||
|
||||
#ifdef WIN32
|
||||
#define Bindless_Texture_Support
|
||||
#define Base_Instance_Support
|
||||
#endif
|
||||
|
||||
#endif
|
@ -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;
|
||||
|
@ -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();
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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()));
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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];
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user