Factorise material rendering code

This commit is contained in:
Vincent Lejeune
2014-09-20 17:44:28 +02:00
parent 88ebb46614
commit 54347458fd

View File

@@ -76,6 +76,90 @@ layout(location = 6) in vec3 Bitangent;
*/
struct DefaultMaterial
{
typedef MeshShader::InstancedObjectPass1Shader InstancedShader;
typedef ListInstancedMatDefault List;
static const enum E_VERTEX_TYPE VertexType = video::EVT_STANDARD;
static const enum MeshMaterial MaterialType = MAT_DEFAULT;
static const enum InstanceType Instance = InstanceTypeDualTex;
static const std::vector<size_t> FirstPassTextures;
};
const std::vector<size_t> DefaultMaterial::FirstPassTextures = { 0, 1 };
struct AlphaRef
{
typedef MeshShader::InstancedObjectRefPass1Shader InstancedShader;
typedef ListInstancedMatAlphaRef List;
static const enum E_VERTEX_TYPE VertexType = video::EVT_STANDARD;
static const enum MeshMaterial MaterialType = MAT_ALPHA_REF;
static const enum InstanceType Instance = InstanceTypeDualTex;
static const std::vector<size_t> FirstPassTextures;
};
const std::vector<size_t> AlphaRef::FirstPassTextures = { 0, 1 };
struct SphereMap
{
typedef MeshShader::InstancedObjectPass1Shader InstancedShader;
typedef ListInstancedMatSphereMap List;
static const enum E_VERTEX_TYPE VertexType = video::EVT_STANDARD;
static const enum MeshMaterial MaterialType = MAT_SPHEREMAP;
static const enum InstanceType Instance = InstanceTypeDualTex;
static const std::vector<size_t> FirstPassTextures;
};
const std::vector<size_t> SphereMap::FirstPassTextures = { 0, 1 };
struct UnlitMat
{
typedef MeshShader::InstancedObjectRefPass1Shader InstancedShader;
typedef ListInstancedMatUnlit List;
static const enum E_VERTEX_TYPE VertexType = video::EVT_STANDARD;
static const enum MeshMaterial MaterialType = MAT_UNLIT;
static const enum InstanceType Instance = InstanceTypeDualTex;
static const std::vector<size_t> FirstPassTextures;
};
const std::vector<size_t> UnlitMat::FirstPassTextures = { 0, 1 };
struct GrassMat
{
typedef MeshShader::InstancedGrassPass1Shader InstancedShader;
typedef ListInstancedMatGrass List;
static const enum E_VERTEX_TYPE VertexType = video::EVT_STANDARD;
static const enum MeshMaterial MaterialType = MAT_GRASS;
static const enum InstanceType Instance = InstanceTypeDualTex;
static const std::vector<size_t> FirstPassTextures;
};
const std::vector<size_t> GrassMat::FirstPassTextures = { 0 };
struct NormalMat
{
typedef MeshShader::InstancedNormalMapShader InstancedShader;
typedef ListInstancedMatNormalMap List;
static const enum E_VERTEX_TYPE VertexType = video::EVT_TANGENTS;
static const enum MeshMaterial MaterialType = MAT_NORMAL_MAP;
static const enum InstanceType Instance = InstanceTypeThreeTex;
static const std::vector<size_t> FirstPassTextures;
};
const std::vector<size_t> NormalMat::FirstPassTextures = { 2, 1 };
struct DetailMat
{
typedef MeshShader::InstancedNormalMapShader InstancedShader;
typedef ListInstancedMatDetails List;
static const enum E_VERTEX_TYPE VertexType = video::EVT_2TCOORDS;
static const enum MeshMaterial MaterialType = MAT_DETAIL;
static const enum InstanceType Instance = InstanceTypeThreeTex;
static const std::vector<size_t> FirstPassTextures;
};
const std::vector<size_t> DetailMat::FirstPassTextures = { 0, 1 };
namespace RenderGeometry
{
struct TexUnit
@@ -195,40 +279,42 @@ void renderMeshes1stPass(const std::vector<TexUnit> &TexUnits, std::vector<STK::
}
}
template<typename Shader, MeshMaterial Mat, video::E_VERTEX_TYPE VT, InstanceType IT, typename...Args>
void renderInstancedMeshes1stPass(const std::vector<TexUnit> &TexUnits, std::vector<GLMesh *> &meshes, Args...args)
template<typename T, typename...Args>
void renderInstancedMeshes1stPass(Args...args)
{
glUseProgram(Shader::getInstance()->Program);
glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(VT, IT));
const std::vector<size_t> &TexUnits = T::FirstPassTextures;
std::vector<GLMesh *> &meshes = T::List::getInstance()->SolidPass;
glUseProgram(T::InstancedShader::getInstance()->Program);
glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(T::VertexType, T::Instance));
for (unsigned i = 0; i < meshes.size(); i++)
{
std::vector<GLuint> Textures;
GLMesh *mesh = meshes[i];
#ifdef DEBUG
if (mesh->VAOType != VT)
if (mesh->VAOType != T::VertexType)
Log::error("RenderGeometry", "Wrong instanced vertex format (hint : %s)",
mesh->textures[0]->getName().getPath().c_str());
#endif
for (unsigned j = 0; j < TexUnits.size(); j++)
Textures.push_back(getTextureGLuint(mesh->textures[TexUnits[j].m_id]));
Shader::getInstance()->SetTextureUnits(Textures);
Textures.push_back(getTextureGLuint(mesh->textures[TexUnits[j]]));
T::InstancedShader::getInstance()->SetTextureUnits(Textures);
Shader::getInstance()->setUniforms(args...);
glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, (const void*)((SolidPassCmd::getInstance()->Offset[Mat] + i) * sizeof(DrawElementsIndirectCommand)));
T::InstancedShader::getInstance()->setUniforms(args...);
glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, (const void*)((SolidPassCmd::getInstance()->Offset[T::MaterialType] + i) * sizeof(DrawElementsIndirectCommand)));
}
}
template<typename Shader, MeshMaterial Mat, video::E_VERTEX_TYPE VT, InstanceType IT, typename...Args>
template<typename T, typename...Args>
void multidraw1stPass(Args...args)
{
glUseProgram(Shader::getInstance()->Program);
glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(VT, IT));
if (SolidPassCmd::getInstance()->Size[Mat])
glUseProgram(T::InstancedShader::getInstance()->Program);
glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(T::VertexType, T::Instance));
if (SolidPassCmd::getInstance()->Size[T::MaterialType])
{
Shader::getInstance()->setUniforms(args...);
T::InstancedShader::getInstance()->setUniforms(args...);
glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT,
(const void*)(SolidPassCmd::getInstance()->Offset[Mat] * sizeof(DrawElementsIndirectCommand)),
SolidPassCmd::getInstance()->Size[Mat],
(const void*)(SolidPassCmd::getInstance()->Offset[T::MaterialType] * sizeof(DrawElementsIndirectCommand)),
SolidPassCmd::getInstance()->Size[T::MaterialType],
sizeof(DrawElementsIndirectCommand));
}
}
@@ -264,41 +350,24 @@ void IrrDriver::renderSolidFirstPass()
if (UserConfigParams::m_azdo)
{
multidraw1stPass<MeshShader::InstancedObjectPass1Shader, MAT_DEFAULT, video::EVT_STANDARD, InstanceTypeDualTex>();
multidraw1stPass<MeshShader::InstancedObjectRefPass1Shader, MAT_ALPHA_REF, video::EVT_STANDARD, InstanceTypeDualTex>();
multidraw1stPass<MeshShader::InstancedObjectPass1Shader, MAT_SPHEREMAP, video::EVT_STANDARD, InstanceTypeDualTex>();
multidraw1stPass<MeshShader::InstancedObjectRefPass1Shader, MAT_UNLIT, video::EVT_STANDARD, InstanceTypeDualTex>();
multidraw1stPass<MeshShader::InstancedGrassPass1Shader, MAT_GRASS, video::EVT_STANDARD, InstanceTypeDualTex>(windDir);
multidraw1stPass<MeshShader::InstancedNormalMapShader, MAT_NORMAL_MAP, video::EVT_TANGENTS, InstanceTypeThreeTex>();
multidraw1stPass<MeshShader::InstancedObjectPass1Shader, MAT_DETAIL, video::EVT_2TCOORDS, InstanceTypeThreeTex>();
multidraw1stPass<DefaultMaterial>();
multidraw1stPass<AlphaRef>();
multidraw1stPass<SphereMap>();
multidraw1stPass<UnlitMat>();
multidraw1stPass<GrassMat>(windDir);
multidraw1stPass<NormalMat>();
multidraw1stPass<DetailMat>();
}
else if (irr_driver->hasARB_draw_indirect())
{
// Default
renderInstancedMeshes1stPass<MeshShader::InstancedObjectPass1Shader, MAT_DEFAULT, video::EVT_STANDARD, InstanceTypeDualTex>(
TexUnits(TexUnit(0, true), TexUnit(1, false)), ListInstancedMatDefault::getInstance()->SolidPass);
// Alpha ref
renderInstancedMeshes1stPass<MeshShader::InstancedObjectRefPass1Shader, MAT_ALPHA_REF, video::EVT_STANDARD, InstanceTypeDualTex>(
TexUnits(TexUnit(0, true), TexUnit(1, false)), ListInstancedMatAlphaRef::getInstance()->SolidPass);
// Unlit
renderInstancedMeshes1stPass<MeshShader::InstancedObjectPass1Shader, MAT_UNLIT, video::EVT_STANDARD, InstanceTypeDualTex>(
TexUnits(TexUnit(0, true), TexUnit(1, false)), ListInstancedMatUnlit::getInstance()->SolidPass);
// Spheremap
renderInstancedMeshes1stPass<MeshShader::InstancedObjectPass1Shader, MAT_SPHEREMAP, video::EVT_STANDARD, InstanceTypeDualTex>(
TexUnits(TexUnit(0, true), TexUnit(1, false)), ListInstancedMatSphereMap::getInstance()->SolidPass);
// Grass
renderInstancedMeshes1stPass<MeshShader::InstancedGrassPass1Shader, MAT_GRASS, video::EVT_STANDARD, InstanceTypeDualTex>(
TexUnits(TexUnit(0, true)), ListInstancedMatGrass::getInstance()->SolidPass, windDir);
// Detail
renderInstancedMeshes1stPass<MeshShader::InstancedObjectPass1Shader, MAT_DETAIL, video::EVT_2TCOORDS, InstanceTypeThreeTex>(
TexUnits(TexUnit(0, true), TexUnit(1, false)), ListInstancedMatDetails::getInstance()->SolidPass);
// Normal Map
renderInstancedMeshes1stPass<MeshShader::InstancedNormalMapShader, MAT_NORMAL_MAP, video::EVT_TANGENTS, InstanceTypeThreeTex>(
TexUnits(TexUnit(2, false), TexUnit(1, false)), ListInstancedMatNormalMap::getInstance()->SolidPass);
renderInstancedMeshes1stPass<DefaultMaterial>();
renderInstancedMeshes1stPass<AlphaRef>();
renderInstancedMeshes1stPass<UnlitMat>();
renderInstancedMeshes1stPass<SphereMap>();
renderInstancedMeshes1stPass<GrassMat>(windDir);
renderInstancedMeshes1stPass<DetailMat>();
renderInstancedMeshes1stPass<NormalMat>();
}
}
}