stk-code_catmod/src/graphics/render_geometry.cpp
2014-09-09 16:39:28 +02:00

933 lines
44 KiB
C++

#include "graphics/irr_driver.hpp"
#include "config/user_config.hpp"
#include "graphics/callbacks.hpp"
#include "graphics/camera.hpp"
#include "graphics/glwrap.hpp"
#include "graphics/lens_flare.hpp"
#include "graphics/light.hpp"
#include "graphics/lod_node.hpp"
#include "graphics/material_manager.hpp"
#include "graphics/particle_kind_manager.hpp"
#include "graphics/per_camera_node.hpp"
#include "graphics/post_processing.hpp"
#include "graphics/referee.hpp"
#include "graphics/rtts.hpp"
#include "graphics/screenquad.hpp"
#include "graphics/shaders.hpp"
#include "graphics/stkmeshscenenode.hpp"
#include "graphics/wind.hpp"
#include "io/file_manager.hpp"
#include "items/item.hpp"
#include "items/item_manager.hpp"
#include "modes/world.hpp"
#include "physics/physics.hpp"
#include "tracks/track.hpp"
#include "utils/constants.hpp"
#include "utils/helpers.hpp"
#include "utils/log.hpp"
#include "utils/profiler.hpp"
#include "utils/tuple.hpp"
#include "stkscenemanager.hpp"
#include <algorithm>
namespace RenderGeometry
{
struct TexUnit
{
GLuint m_id;
bool m_premul_alpha;
TexUnit(GLuint id, bool premul_alpha)
{
m_id = id;
m_premul_alpha = premul_alpha;
}
};
template <typename T>
std::vector<TexUnit> TexUnits(T curr) // required on older clang versions
{
std::vector<TexUnit> v;
v.push_back(curr);
return v;
}
template <typename T, typename... R>
std::vector<TexUnit> TexUnits(T curr, R... rest) // required on older clang versions
{
std::vector<TexUnit> v;
v.push_back(curr);
VTexUnits(v, rest...);
return v;
}
template <typename T, typename... R>
void VTexUnits(std::vector<TexUnit>& v, T curr, R... rest) // required on older clang versions
{
v.push_back(curr);
VTexUnits(v, rest...);
}
template <typename T>
void VTexUnits(std::vector<TexUnit>& v, T curr)
{
v.push_back(curr);
}
}
using namespace RenderGeometry;
template<typename T, typename...uniforms>
void draw(const T *Shader, const GLMesh *mesh, uniforms... Args)
{
irr_driver->IncreaseObjectCount();
GLenum ptype = mesh->PrimitiveType;
GLenum itype = mesh->IndexType;
size_t count = mesh->IndexCount;
Shader->setUniforms(Args...);
glDrawElementsBaseVertex(ptype, count, itype, (GLvoid *)mesh->vaoOffset, mesh->vaoBaseVertex);
}
template<int...List>
struct custom_unroll_args;
template<>
struct custom_unroll_args<>
{
template<typename T, typename ...TupleTypes, typename ...Args>
static void exec(const T *Shader, const STK::Tuple<TupleTypes...> &t, Args... args)
{
draw<T>(Shader, STK::tuple_get<0>(t), args...);
}
};
template<int N, int...List>
struct custom_unroll_args<N, List...>
{
template<typename T, typename ...TupleTypes, typename ...Args>
static void exec(const T *Shader, const STK::Tuple<TupleTypes...> &t, Args... args)
{
custom_unroll_args<List...>::template exec<T>(Shader, t, STK::tuple_get<N>(t), args...);
}
};
template<typename Shader, enum E_VERTEX_TYPE VertexType, int ...List, typename... TupleType>
void renderMeshes1stPass(const std::vector<TexUnit> &TexUnits, std::vector<STK::Tuple<TupleType...> > &meshes)
{
glUseProgram(Shader::getInstance()->Program);
if (irr_driver->hasARB_base_instance())
glBindVertexArray(VAOManager::getInstance()->getVAO(VertexType));
for (unsigned i = 0; i < meshes.size(); i++)
{
std::vector<GLuint> Textures;
std::vector<uint64_t> Handles;
GLMesh &mesh = *(STK::tuple_get<0>(meshes.at(i)));
if (!irr_driver->hasARB_base_instance())
glBindVertexArray(mesh.vao);
for (unsigned j = 0; j < TexUnits.size(); j++)
{
if (UserConfigParams::m_azdo)
Handles.push_back(mesh.TextureHandles[TexUnits[j].m_id]);
else
Textures.push_back(getTextureGLuint(mesh.textures[TexUnits[j].m_id]));
}
if (mesh.VAOType != VertexType)
{
#ifdef DEBUG
Log::error("Materials", "Wrong vertex Type associed to pass 1 (hint texture : %s)", mesh.textures[0]->getName().getPath().c_str());
#endif
continue;
}
if (UserConfigParams::m_azdo)
Shader::getInstance()->SetTextureHandles(Handles);
else
Shader::getInstance()->SetTextureUnits(Textures);
custom_unroll_args<List...>::template exec(Shader::getInstance(), meshes.at(i));
}
}
template<typename Shader, MeshMaterial Mat, video::E_VERTEX_TYPE VT, typename...Args>
void renderInstancedMeshes1stPass(const std::vector<TexUnit> &TexUnits, std::vector<GLMesh *> &meshes, Args...args)
{
glUseProgram(Shader::getInstance()->Program);
glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(VT, InstanceTypeDefault));
for (unsigned i = 0; i < meshes.size(); i++)
{
std::vector<GLuint> Textures;
GLMesh *mesh = meshes[i];
#ifdef DEBUG
if (mesh->VAOType != VT)
Log::error("RenderGeometry", "Wrong instanced vertex format");
#endif
for (unsigned j = 0; j < TexUnits.size(); j++)
Textures.push_back(getTextureGLuint(mesh->textures[TexUnits[j].m_id]));
Shader::getInstance()->SetTextureUnits(Textures);
Shader::getInstance()->setUniforms(args...);
glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, (const void*)((SolidPassCmd::getInstance()->Offset[Mat] + i) * sizeof(DrawElementsIndirectCommand)));
}
}
template<typename Shader, MeshMaterial Mat, video::E_VERTEX_TYPE VT, typename...Args>
void multidraw1stPass(Args...args)
{
glUseProgram(Shader::getInstance()->Program);
glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(VT, InstanceTypeDefault));
if (SolidPassCmd::getInstance()->Size[Mat])
{
Shader::getInstance()->setUniforms(args...);
glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT,
(const void*)(SolidPassCmd::getInstance()->Offset[Mat] * sizeof(DrawElementsIndirectCommand)),
SolidPassCmd::getInstance()->Size[Mat],
sizeof(DrawElementsIndirectCommand));
}
}
static core::vector3df windDir;
void IrrDriver::renderSolidFirstPass()
{
windDir = getWindDir();
m_rtts->getFBO(FBO_NORMAL_AND_DEPTHS).Bind();
glClearColor(0., 0., 0., 0.);
glDepthMask(GL_TRUE);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);
glDisable(GL_ALPHA_TEST);
glDisable(GL_BLEND);
glEnable(GL_CULL_FACE);
if (irr_driver->hasARB_draw_indirect())
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, SolidPassCmd::getInstance()->drawindirectcmd);
if (!UserConfigParams::m_dynamic_lights)
return;
{
ScopedGPUTimer Timer(getGPUTimer(Q_SOLID_PASS1));
irr_driver->setPhase(SOLID_NORMAL_AND_DEPTH_PASS);
for (unsigned i = 0; i < ImmediateDrawList::getInstance()->size(); i++)
ImmediateDrawList::getInstance()->at(i)->render();
std::vector<TexUnit> object_pass1_texunits = TexUnits(TexUnit(0, true) );
renderMeshes1stPass<MeshShader::ObjectPass1Shader, video::EVT_STANDARD, 2, 1>(object_pass1_texunits, ListMatDefault::getInstance()->SolidPass);
renderMeshes1stPass<MeshShader::ObjectPass1Shader, video::EVT_2TCOORDS, 2, 1>(object_pass1_texunits, ListMatSplatting::getInstance()->SolidPass);
renderMeshes1stPass<MeshShader::ObjectRefPass1Shader, video::EVT_STANDARD, 3, 2, 1>(object_pass1_texunits, ListMatUnlit::getInstance()->SolidPass);
renderMeshes1stPass<MeshShader::ObjectRefPass1Shader, video::EVT_STANDARD, 3, 2, 1>(TexUnits(TexUnit(0, true)), ListMatAlphaRef::getInstance()->SolidPass);
renderMeshes1stPass<MeshShader::GrassPass1Shader, video::EVT_STANDARD, 3, 2, 1>(TexUnits(TexUnit(0, true)), ListMatGrass::getInstance()->SolidPass);
renderMeshes1stPass<MeshShader::NormalMapShader, video::EVT_TANGENTS, 2, 1>(TexUnits(
TexUnit(1, false),
TexUnit(0, true)
), ListMatNormalMap::getInstance()->SolidPass);
renderMeshes1stPass<MeshShader::ObjectPass1Shader, video::EVT_STANDARD, 2, 1>(object_pass1_texunits, ListMatSphereMap::getInstance()->SolidPass);
renderMeshes1stPass<MeshShader::ObjectPass1Shader, video::EVT_2TCOORDS, 2, 1>(object_pass1_texunits, ListMatDetails::getInstance()->SolidPass);
if (UserConfigParams::m_azdo)
{
multidraw1stPass<MeshShader::InstancedObjectPass1Shader, MAT_DEFAULT, video::EVT_STANDARD>();
multidraw1stPass<MeshShader::InstancedObjectRefPass1Shader, MAT_ALPHA_REF, video::EVT_STANDARD>();
multidraw1stPass<MeshShader::InstancedNormalMapShader, MAT_NORMAL_MAP, video::EVT_TANGENTS>();
multidraw1stPass<MeshShader::InstancedObjectPass1Shader, MAT_SPHEREMAP, video::EVT_STANDARD>();
multidraw1stPass<MeshShader::InstancedObjectPass1Shader, MAT_DETAIL, video::EVT_2TCOORDS>();
multidraw1stPass<MeshShader::InstancedObjectRefPass1Shader, MAT_UNLIT, video::EVT_STANDARD>();
multidraw1stPass<MeshShader::InstancedGrassPass1Shader, MAT_GRASS, video::EVT_STANDARD>(windDir);
}
else if (irr_driver->hasARB_draw_indirect())
{
// Default
renderInstancedMeshes1stPass<MeshShader::InstancedObjectPass1Shader, MAT_DEFAULT, video::EVT_STANDARD>(
TexUnits(TexUnit(0, true)), ListInstancedMatDefault::getInstance()->SolidPass);
// Alpha ref
renderInstancedMeshes1stPass<MeshShader::InstancedObjectRefPass1Shader, MAT_ALPHA_REF, video::EVT_STANDARD>(
TexUnits(TexUnit(0, true)), ListInstancedMatAlphaRef::getInstance()->SolidPass);
// Unlit
renderInstancedMeshes1stPass<MeshShader::InstancedObjectPass1Shader, MAT_UNLIT, video::EVT_STANDARD>(
TexUnits(TexUnit(0, true)), ListInstancedMatUnlit::getInstance()->SolidPass);
// Spheremap
renderInstancedMeshes1stPass<MeshShader::InstancedObjectPass1Shader, MAT_SPHEREMAP, video::EVT_STANDARD>(
TexUnits(TexUnit(0, true)), ListInstancedMatSphereMap::getInstance()->SolidPass);
// Grass
renderInstancedMeshes1stPass<MeshShader::InstancedGrassPass1Shader, MAT_GRASS, video::EVT_STANDARD>(
TexUnits(TexUnit(0, true)), ListInstancedMatGrass::getInstance()->SolidPass, windDir);
// Detail
renderInstancedMeshes1stPass<MeshShader::InstancedObjectPass1Shader, MAT_DETAIL, video::EVT_2TCOORDS>(
TexUnits(TexUnit(0, true)), ListInstancedMatDetails::getInstance()->SolidPass);
// Normal Map
renderInstancedMeshes1stPass<MeshShader::InstancedNormalMapShader, MAT_NORMAL_MAP, video::EVT_TANGENTS>(
TexUnits(TexUnit(1, false), TexUnit(0, true)), ListInstancedMatNormalMap::getInstance()->SolidPass);
}
}
}
template<typename Shader, enum E_VERTEX_TYPE VertexType, int...List, typename... TupleType>
void renderMeshes2ndPass(const std::vector<TexUnit> &TexUnits, std::vector<STK::Tuple<TupleType...> > &meshes, const std::vector<uint64_t> &Prefilled_Handle,
const std::vector<GLuint> &Prefilled_Tex)
{
glUseProgram(Shader::getInstance()->Program);
if (irr_driver->hasARB_base_instance())
glBindVertexArray(VAOManager::getInstance()->getVAO(VertexType));
for (unsigned i = 0; i < meshes.size(); i++)
{
std::vector<uint64_t> Handles(Prefilled_Handle);
std::vector<GLuint> Textures(Prefilled_Tex);
GLMesh &mesh = *(STK::tuple_get<0>(meshes.at(i)));
if (!irr_driver->hasARB_base_instance())
glBindVertexArray(mesh.vao);
for (unsigned j = 0; j < TexUnits.size(); j++)
{
if (UserConfigParams::m_azdo)
Handles.push_back(mesh.TextureHandles[TexUnits[j].m_id]);
else
Textures.push_back(getTextureGLuint(mesh.textures[TexUnits[j].m_id]));
}
if (mesh.VAOType != VertexType)
{
#ifdef DEBUG
Log::error("Materials", "Wrong vertex Type associed to pass 2 (hint texture : %s)", mesh.textures[0]->getName().getPath().c_str());
#endif
continue;
}
if (UserConfigParams::m_azdo)
Shader::getInstance()->SetTextureHandles(Handles);
else
Shader::getInstance()->SetTextureUnits(Textures);
custom_unroll_args<List...>::template exec(Shader::getInstance(), meshes.at(i));
}
}
template<typename Shader, MeshMaterial Mat, video::E_VERTEX_TYPE VT, typename...Args>
void renderInstancedMeshes2ndPass(const std::vector<TexUnit> &TexUnits, const std::vector<GLuint> &Prefilled_tex, std::vector<GLMesh *> &meshes, Args...args)
{
glUseProgram(Shader::getInstance()->Program);
glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(VT, InstanceTypeDefault));
for (unsigned i = 0; i < meshes.size(); i++)
{
GLMesh *mesh = meshes[i];
std::vector<GLuint> Textures(Prefilled_tex);
for (unsigned j = 0; j < TexUnits.size(); j++)
Textures.push_back(getTextureGLuint(mesh->textures[TexUnits[j].m_id]));
Shader::getInstance()->SetTextureUnits(Textures);
Shader::getInstance()->setUniforms(args...);
glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, (const void*)((SolidPassCmd::getInstance()->Offset[Mat] + i) * sizeof(DrawElementsIndirectCommand)));
}
}
template<typename Shader, MeshMaterial Mat, video::E_VERTEX_TYPE VT, typename...Args>
void multidraw2ndPass(const std::vector<uint64_t> &Handles, Args... args)
{
glUseProgram(Shader::getInstance()->Program);
glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(VT, InstanceTypeDefault));
if (SolidPassCmd::getInstance()->Size[Mat])
{
Shader::getInstance()->SetTextureHandles(Handles);
Shader::getInstance()->setUniforms(args...);
glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT,
(const void*)(SolidPassCmd::getInstance()->Offset[Mat] * sizeof(DrawElementsIndirectCommand)),
SolidPassCmd::getInstance()->Size[Mat],
sizeof(DrawElementsIndirectCommand));
}
}
void IrrDriver::renderSolidSecondPass()
{
SColor clearColor(0, 150, 150, 150);
if (World::getWorld() != NULL)
clearColor = World::getWorld()->getClearColor();
glClearColor(clearColor.getRed() / 255.f, clearColor.getGreen() / 255.f,
clearColor.getBlue() / 255.f, clearColor.getAlpha() / 255.f);
glClear(GL_COLOR_BUFFER_BIT);
if (UserConfigParams::m_dynamic_lights)
glDepthMask(GL_FALSE);
else
{
glDepthMask(GL_TRUE);
glClear(GL_DEPTH_BUFFER_BIT);
}
irr_driver->setPhase(SOLID_LIT_PASS);
glEnable(GL_DEPTH_TEST);
glDisable(GL_ALPHA_TEST);
glDisable(GL_BLEND);
uint64_t DiffuseHandle = 0, SpecularHandle = 0, SSAOHandle = 0, DepthHandle = 0;
if (UserConfigParams::m_azdo)
{
DiffuseHandle = glGetTextureSamplerHandleARB(m_rtts->getRenderTarget(RTT_DIFFUSE), MeshShader::ObjectPass2Shader::getInstance()->SamplersId[0]);
if (!glIsTextureHandleResidentARB(DiffuseHandle))
glMakeTextureHandleResidentARB(DiffuseHandle);
SpecularHandle = glGetTextureSamplerHandleARB(m_rtts->getRenderTarget(RTT_SPECULAR), MeshShader::ObjectPass2Shader::getInstance()->SamplersId[1]);
if (!glIsTextureHandleResidentARB(SpecularHandle))
glMakeTextureHandleResidentARB(SpecularHandle);
SSAOHandle = glGetTextureSamplerHandleARB(m_rtts->getRenderTarget(RTT_HALF1_R), MeshShader::ObjectPass2Shader::getInstance()->SamplersId[2]);
if (!glIsTextureHandleResidentARB(SSAOHandle))
glMakeTextureHandleResidentARB(SSAOHandle);
DepthHandle = glGetTextureSamplerHandleARB(getDepthStencilTexture(), MeshShader::ObjectPass2Shader::getInstance()->SamplersId[3]);
if (!glIsTextureHandleResidentARB(DepthHandle))
glMakeTextureHandleResidentARB(DepthHandle);
}
{
ScopedGPUTimer Timer(getGPUTimer(Q_SOLID_PASS2));
irr_driver->setPhase(SOLID_LIT_PASS);
for (unsigned i = 0; i < ImmediateDrawList::getInstance()->size(); i++)
ImmediateDrawList::getInstance()->at(i)->render();
std::vector<GLuint> DiffSpecSSAOTex = createVector<GLuint>(m_rtts->getRenderTarget(RTT_DIFFUSE), m_rtts->getRenderTarget(RTT_SPECULAR), m_rtts->getRenderTarget(RTT_HALF1_R));
renderMeshes2ndPass<MeshShader::ObjectPass2Shader, video::EVT_STANDARD, 3, 1>(TexUnits(
TexUnit(0, true)
), ListMatDefault::getInstance()->SolidPass,
createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle), DiffSpecSSAOTex);
renderMeshes2ndPass<MeshShader::ObjectRefPass2Shader, video::EVT_STANDARD, 3, 1 >(TexUnits(
TexUnit(0, true)
), ListMatAlphaRef::getInstance()->SolidPass, createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle), DiffSpecSSAOTex);
renderMeshes2ndPass<MeshShader::ObjectUnlitShader, video::EVT_STANDARD, 3, 1>(TexUnits(
TexUnit(0, true)
), ListMatUnlit::getInstance()->SolidPass, createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle), DiffSpecSSAOTex);
renderMeshes2ndPass<MeshShader::SplattingShader, video::EVT_2TCOORDS, 1>(TexUnits(
TexUnit(1, false),
TexUnit(2, true),
TexUnit(3, true),
TexUnit(4, true),
TexUnit(0, true)
), ListMatSplatting::getInstance()->SolidPass, createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle), DiffSpecSSAOTex);
renderMeshes2ndPass<MeshShader::SphereMapShader, video::EVT_STANDARD, 2, 1>(TexUnits(
TexUnit(0, true)
), ListMatSphereMap::getInstance()->SolidPass, createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle), DiffSpecSSAOTex);
renderMeshes2ndPass<MeshShader::DetailledObjectPass2Shader, video::EVT_2TCOORDS, 1>(TexUnits(
TexUnit(0, true),
TexUnit(1, true)
), ListMatDetails::getInstance()->SolidPass, createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle), DiffSpecSSAOTex);
renderMeshes2ndPass<MeshShader::GrassPass2Shader, video::EVT_STANDARD, 3, 1>(TexUnits(
TexUnit(0, true)
), ListMatGrass::getInstance()->SolidPass, createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle), DiffSpecSSAOTex);
renderMeshes2ndPass<MeshShader::ObjectPass2Shader, video::EVT_TANGENTS, 3, 1>(TexUnits(
TexUnit(0, true)
), ListMatNormalMap::getInstance()->SolidPass, createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle), DiffSpecSSAOTex);
if (UserConfigParams::m_azdo)
{
multidraw2ndPass<MeshShader::InstancedObjectPass2Shader, MAT_DEFAULT, video::EVT_STANDARD>(createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle, 0));
multidraw2ndPass<MeshShader::InstancedObjectPass2Shader, MAT_NORMAL_MAP, video::EVT_TANGENTS>(createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle, 0));
multidraw2ndPass<MeshShader::InstancedObjectRefPass2Shader, MAT_ALPHA_REF, video::EVT_STANDARD>(createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle, 0));
multidraw2ndPass<MeshShader::InstancedSphereMapShader, MAT_SPHEREMAP, video::EVT_STANDARD>(createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle, 0));
multidraw2ndPass<MeshShader::InstancedDetailledObjectPass2Shader, MAT_DETAIL, video::EVT_2TCOORDS>(createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle, 0, 0));
multidraw2ndPass<MeshShader::InstancedObjectUnlitShader, MAT_UNLIT, video::EVT_STANDARD>(createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle, 0));
SunLightProvider * const cb = (SunLightProvider *)irr_driver->getCallback(ES_SUNLIGHT);
multidraw2ndPass<MeshShader::InstancedGrassPass2Shader, MAT_GRASS, video::EVT_STANDARD>(createVector<uint64_t>(DiffuseHandle, SpecularHandle, SSAOHandle, DepthHandle, 0), windDir, cb->getPosition());
}
else if (irr_driver->hasARB_draw_indirect())
{
// Default
renderInstancedMeshes2ndPass<MeshShader::InstancedObjectPass2Shader, MAT_DEFAULT, video::EVT_STANDARD>(
TexUnits(TexUnit(0, true)), DiffSpecSSAOTex, ListInstancedMatDefault::getInstance()->SolidPass);
// Alpha ref
renderInstancedMeshes2ndPass<MeshShader::InstancedObjectRefPass2Shader, MAT_ALPHA_REF, video::EVT_STANDARD>(
TexUnits(TexUnit(0, true)), DiffSpecSSAOTex, ListInstancedMatAlphaRef::getInstance()->SolidPass);
// Unlit
renderInstancedMeshes2ndPass<MeshShader::InstancedObjectUnlitShader, MAT_UNLIT, video::EVT_STANDARD>(
TexUnits(TexUnit(0, true)), DiffSpecSSAOTex, ListInstancedMatUnlit::getInstance()->SolidPass);
// Spheremap
renderInstancedMeshes2ndPass<MeshShader::InstancedSphereMapShader, MAT_SPHEREMAP, video::EVT_STANDARD>(
TexUnits(TexUnit(0, true)), DiffSpecSSAOTex, ListInstancedMatSphereMap::getInstance()->SolidPass);
// Details
renderInstancedMeshes2ndPass<MeshShader::InstancedDetailledObjectPass2Shader, MAT_DETAIL, video::EVT_2TCOORDS>(
TexUnits(TexUnit(0, true), TexUnit(1, false)), DiffSpecSSAOTex, ListInstancedMatDetails::getInstance()->SolidPass);
// Normal map
renderInstancedMeshes2ndPass<MeshShader::InstancedObjectPass2Shader, MAT_NORMAL_MAP, video::EVT_TANGENTS>(
TexUnits(TexUnit(0, true)), DiffSpecSSAOTex, ListInstancedMatNormalMap::getInstance()->SolidPass);
// Grass
SunLightProvider * const cb = (SunLightProvider *)irr_driver->getCallback(ES_SUNLIGHT);
DiffSpecSSAOTex.push_back(irr_driver->getDepthStencilTexture());
renderInstancedMeshes2ndPass<MeshShader::InstancedGrassPass2Shader, MAT_GRASS, video::EVT_STANDARD>(
TexUnits(TexUnit(0, true)), DiffSpecSSAOTex, ListInstancedMatGrass::getInstance()->SolidPass, windDir, cb->getPosition());
}
}
}
template<enum E_VERTEX_TYPE VertexType, typename... TupleType>
static void renderMeshNormals(std::vector<STK::Tuple<TupleType...> > *meshes)
{
glUseProgram(MeshShader::NormalVisualizer::getInstance()->Program);
glBindVertexArray(VAOManager::getInstance()->getVAO(VertexType));
for (unsigned i = 0; i < meshes->size(); i++)
{
GLMesh &mesh = *(STK::tuple_get<0>(meshes->at(i)));
if (mesh.VAOType != VertexType)
{
#ifdef DEBUG
Log::error("Materials", "Wrong vertex Type associed to pass 2 (hint texture : %s)", mesh.textures[0]->getName().getPath().c_str());
#endif
continue;
}
draw(MeshShader::NormalVisualizer::getInstance(), STK::tuple_get<0>(meshes->at(i)), STK::tuple_get<1>(meshes->at(i)), STK::tuple_get<2>(meshes->at(i)), video::SColor(255, 0, 255, 0));
}
}
void IrrDriver::renderNormalsVisualisation()
{
// renderMeshNormals<video::EVT_STANDARD>(ListMatDefault::getInstance());
// renderMeshNormals<video::EVT_STANDARD>(ListMatAlphaRef::getInstance());
// renderMeshNormals<video::EVT_STANDARD>(ListMatSphereMap::getInstance());
// renderMeshNormals<video::EVT_STANDARD>(ListMatGrass::getInstance());
// renderMeshNormals<video::EVT_2TCOORDS>(ListMatDetails::getInstance());
// renderMeshNormals<video::EVT_STANDARD>(ListMatUnlit::getInstance());
// renderMeshNormals<video::EVT_2TCOORDS>(ListMatSplatting::getInstance());
// renderMeshNormals<video::EVT_TANGENTS>(ListMatNormalMap::getInstance());
}
template<typename Shader, enum E_VERTEX_TYPE VertexType, int...List, typename... TupleType>
void renderTransparenPass(const std::vector<TexUnit> &TexUnits, std::vector<STK::Tuple<TupleType...> > *meshes)
{
glUseProgram(Shader::getInstance()->Program);
if (irr_driver->hasARB_base_instance())
glBindVertexArray(VAOManager::getInstance()->getVAO(VertexType));
for (unsigned i = 0; i < meshes->size(); i++)
{
std::vector<uint64_t> Handles;
std::vector<GLuint> Textures;
GLMesh &mesh = *(STK::tuple_get<0>(meshes->at(i)));
if (!irr_driver->hasARB_base_instance())
glBindVertexArray(mesh.vao);
for (unsigned j = 0; j < TexUnits.size(); j++)
{
if (!mesh.textures[TexUnits[j].m_id])
mesh.textures[TexUnits[j].m_id] = getUnicolorTexture(video::SColor(255, 255, 255, 255));
compressTexture(mesh.textures[TexUnits[j].m_id], TexUnits[j].m_premul_alpha);
if (UserConfigParams::m_azdo)
{
if (!mesh.TextureHandles[TexUnits[j].m_id])
mesh.TextureHandles[TexUnits[j].m_id] = glGetTextureSamplerHandleARB(getTextureGLuint(mesh.textures[TexUnits[j].m_id]), Shader::getInstance()->SamplersId[Handles.size()]);
if (!glIsTextureHandleResidentARB(mesh.TextureHandles[TexUnits[j].m_id]))
glMakeTextureHandleResidentARB(mesh.TextureHandles[TexUnits[j].m_id]);
Handles.push_back(mesh.TextureHandles[TexUnits[j].m_id]);
}
else
Textures.push_back(getTextureGLuint(mesh.textures[TexUnits[j].m_id]));
}
if (mesh.VAOType != VertexType)
{
#ifdef DEBUG
Log::error("Materials", "Wrong vertex Type associed to pass 2 (hint texture : %s)", mesh.textures[0]->getName().getPath().c_str());
#endif
continue;
}
if (UserConfigParams::m_azdo)
Shader::getInstance()->SetTextureHandles(Handles);
else
Shader::getInstance()->SetTextureUnits(Textures);
custom_unroll_args<List...>::template exec(Shader::getInstance(), meshes->at(i));
}
}
static video::ITexture *displaceTex = 0;
void IrrDriver::renderTransparent()
{
glEnable(GL_DEPTH_TEST);
glDisable(GL_ALPHA_TEST);
glDepthMask(GL_FALSE);
glEnable(GL_BLEND);
glBlendEquation(GL_FUNC_ADD);
glDisable(GL_CULL_FACE);
irr_driver->setPhase(TRANSPARENT_PASS);
for (unsigned i = 0; i < ImmediateDrawList::getInstance()->size(); i++)
ImmediateDrawList::getInstance()->at(i)->render();
if (irr_driver->hasARB_base_instance())
glBindVertexArray(VAOManager::getInstance()->getVAO(EVT_STANDARD));
if (World::getWorld() && World::getWorld()->isFogEnabled())
{
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
renderTransparenPass<MeshShader::TransparentFogShader, video::EVT_STANDARD, 8, 7, 6, 5, 4, 3, 2, 1>(TexUnits(
TexUnit(0, true)), ListBlendTransparentFog::getInstance());
glBlendFunc(GL_ONE, GL_ONE);
renderTransparenPass<MeshShader::TransparentFogShader, video::EVT_STANDARD, 8, 7, 6, 5, 4, 3, 2, 1>(TexUnits(
TexUnit(0, true)), ListAdditiveTransparentFog::getInstance());
}
else
{
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
renderTransparenPass<MeshShader::TransparentShader, video::EVT_STANDARD, 2, 1>(TexUnits(
TexUnit(0, true)), ListBlendTransparent::getInstance());
glBlendFunc(GL_ONE, GL_ONE);
renderTransparenPass<MeshShader::TransparentShader, video::EVT_STANDARD, 2, 1>(TexUnits(
TexUnit(0, true)), ListAdditiveTransparent::getInstance());
}
if (!UserConfigParams::m_dynamic_lights)
return;
// Render displacement nodes
irr_driver->getFBO(FBO_TMP1_WITH_DS).Bind();
glClear(GL_COLOR_BUFFER_BIT);
irr_driver->getFBO(FBO_DISPLACE).Bind();
glClear(GL_COLOR_BUFFER_BIT);
DisplaceProvider * const cb = (DisplaceProvider *)irr_driver->getCallback(ES_DISPLACE);
cb->update();
glEnable(GL_DEPTH_TEST);
glDisable(GL_ALPHA_TEST);
glDepthMask(GL_FALSE);
glDisable(GL_BLEND);
glClear(GL_STENCIL_BUFFER_BIT);
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, 1, 0xFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
if (irr_driver->hasARB_base_instance())
glBindVertexArray(VAOManager::getInstance()->getVAO(EVT_2TCOORDS));
// Generate displace mask
// Use RTT_TMP4 as displace mask
irr_driver->getFBO(FBO_TMP1_WITH_DS).Bind();
for (unsigned i = 0; i < ListDisplacement::getInstance()->size(); i++)
{
const GLMesh &mesh = *(STK::tuple_get<0>(ListDisplacement::getInstance()->at(i)));
if (!irr_driver->hasARB_base_instance())
glBindVertexArray(mesh.vao);
const core::matrix4 &AbsoluteTransformation = STK::tuple_get<1>(ListDisplacement::getInstance()->at(i));
if (mesh.VAOType != video::EVT_2TCOORDS)
{
#ifdef DEBUG
Log::error("Materials", "Displacement has wrong vertex type");
#endif
continue;
}
GLenum ptype = mesh.PrimitiveType;
GLenum itype = mesh.IndexType;
size_t count = mesh.IndexCount;
glUseProgram(MeshShader::DisplaceMaskShader::getInstance()->Program);
MeshShader::DisplaceMaskShader::getInstance()->setUniforms(AbsoluteTransformation);
glDrawElementsBaseVertex(ptype, count, itype, (GLvoid *)mesh.vaoOffset, mesh.vaoBaseVertex);
}
irr_driver->getFBO(FBO_DISPLACE).Bind();
if (!displaceTex)
displaceTex = irr_driver->getTexture(FileManager::TEXTURE, "displace.png");
for (unsigned i = 0; i < ListDisplacement::getInstance()->size(); i++)
{
const GLMesh &mesh = *(STK::tuple_get<0>(ListDisplacement::getInstance()->at(i)));
if (!irr_driver->hasARB_base_instance())
glBindVertexArray(mesh.vao);
const core::matrix4 &AbsoluteTransformation = STK::tuple_get<1>(ListDisplacement::getInstance()->at(i));
if (mesh.VAOType != video::EVT_2TCOORDS)
continue;
GLenum ptype = mesh.PrimitiveType;
GLenum itype = mesh.IndexType;
size_t count = mesh.IndexCount;
// Render the effect
MeshShader::DisplaceShader::getInstance()->SetTextureUnits(
createVector<GLuint>(getTextureGLuint(displaceTex),
irr_driver->getRenderTargetTexture(RTT_COLOR),
irr_driver->getRenderTargetTexture(RTT_TMP1),
getTextureGLuint(mesh.textures[0])));
glUseProgram(MeshShader::DisplaceShader::getInstance()->Program);
MeshShader::DisplaceShader::getInstance()->setUniforms(AbsoluteTransformation,
core::vector2df(cb->getDirX(), cb->getDirY()),
core::vector2df(cb->getDir2X(), cb->getDir2Y()));
glDrawElementsBaseVertex(ptype, count, itype, (GLvoid *)mesh.vaoOffset, mesh.vaoBaseVertex);
}
irr_driver->getFBO(FBO_COLORS).Bind();
glStencilFunc(GL_EQUAL, 1, 0xFF);
m_post_processing->renderPassThrough(m_rtts->getRenderTarget(RTT_DISPLACE));
glDisable(GL_STENCIL_TEST);
}
template<typename T, typename...uniforms>
void drawShadow(const T *Shader, unsigned cascade, const GLMesh *mesh, uniforms... Args)
{
irr_driver->IncreaseObjectCount();
GLenum ptype = mesh->PrimitiveType;
GLenum itype = mesh->IndexType;
size_t count = mesh->IndexCount;
Shader->setUniforms(cascade, Args...);
glDrawElementsBaseVertex(ptype, count, itype, (GLvoid *)mesh->vaoOffset, mesh->vaoBaseVertex);
}
template<int...List>
struct shadow_custom_unroll_args;
template<>
struct shadow_custom_unroll_args<>
{
template<typename T, typename ...TupleTypes, typename ...Args>
static void exec(const T *Shader, unsigned cascade, const STK::Tuple<TupleTypes...> &t, Args... args)
{
drawShadow<T>(Shader, cascade, STK::tuple_get<0>(t), args...);
}
};
template<int N, int...List>
struct shadow_custom_unroll_args<N, List...>
{
template<typename T, typename ...TupleTypes, typename ...Args>
static void exec(const T *Shader, unsigned cascade, const STK::Tuple<TupleTypes...> &t, Args... args)
{
shadow_custom_unroll_args<List...>::template exec<T>(Shader, cascade, t, STK::tuple_get<N>(t), args...);
}
};
template<typename T, enum E_VERTEX_TYPE VertexType, int...List, typename... Args>
void renderShadow(const std::vector<GLuint> TextureUnits, unsigned cascade, const std::vector<STK::Tuple<Args...> > &t)
{
glUseProgram(T::getInstance()->Program);
if (irr_driver->hasARB_base_instance())
glBindVertexArray(VAOManager::getInstance()->getVAO(VertexType));
for (unsigned i = 0; i < t.size(); i++)
{
std::vector<uint64_t> Handles;
std::vector<GLuint> Textures;
GLMesh *mesh = STK::tuple_get<0>(t.at(i));
if (!irr_driver->hasARB_base_instance())
glBindVertexArray(mesh->vao);
for (unsigned j = 0; j < TextureUnits.size(); j++)
{
compressTexture(mesh->textures[TextureUnits[j]], true);
if (UserConfigParams::m_azdo)
Handles.push_back(mesh->TextureHandles[TextureUnits[j]]);
else
Textures.push_back(getTextureGLuint(mesh->textures[TextureUnits[j]]));
}
if (UserConfigParams::m_azdo)
T::getInstance()->SetTextureHandles(Handles);
else
T::getInstance()->SetTextureUnits(Textures);
shadow_custom_unroll_args<List...>::template exec<T>(T::getInstance(), cascade, t.at(i));
}
}
template<typename Shader, MeshMaterial Mat, video::E_VERTEX_TYPE VT, typename...Args>
void renderInstancedShadow(const std::vector<GLuint> TextureUnits, unsigned cascade, const std::vector<GLMesh *> &t, Args ...args)
{
glUseProgram(Shader::getInstance()->Program);
glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(VT, InstanceTypeShadow));
for (unsigned i = 0; i < t.size(); i++)
{
std::vector<uint64_t> Handles;
std::vector<GLuint> Textures;
GLMesh *mesh = t[i];
for (unsigned j = 0; j < TextureUnits.size(); j++)
Textures.push_back(getTextureGLuint(mesh->textures[TextureUnits[j]]));
Shader::getInstance()->SetTextureUnits(Textures);
Shader::getInstance()->setUniforms(cascade, args...);
size_t tmp = ShadowPassCmd::getInstance()->Offset[cascade][Mat] + i;
glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, (const void*)((tmp) * sizeof(DrawElementsIndirectCommand)));
}
}
template<typename Shader, MeshMaterial Mat, video::E_VERTEX_TYPE VT, typename...Args>
static void multidrawShadow(unsigned i, Args ...args)
{
glUseProgram(Shader::getInstance()->Program);
glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(VT, InstanceTypeShadow));
if (ShadowPassCmd::getInstance()->Size[i][Mat])
{
Shader::getInstance()->setUniforms(i, args...);
glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, (const void*)(ShadowPassCmd::getInstance()->Offset[i][Mat] * sizeof(DrawElementsIndirectCommand)), ShadowPassCmd::getInstance()->Size[i][Mat], sizeof(DrawElementsIndirectCommand));
}
}
void IrrDriver::renderShadows()
{
ScopedGPUTimer Timer(getGPUTimer(Q_SHADOWS));
glDepthFunc(GL_LEQUAL);
glDepthMask(GL_TRUE);
glEnable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
glDisable(GL_ALPHA_TEST);
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(1.5, 0.);
m_rtts->getShadowFBO().Bind();
glClear(GL_DEPTH_BUFFER_BIT);
glDrawBuffer(GL_NONE);
for (unsigned cascade = 0; cascade < 4; cascade++)
{
std::vector<GLuint> noTexUnits;
renderShadow<MeshShader::ShadowShader, EVT_STANDARD, 1>(noTexUnits, cascade, ListMatDefault::getInstance()->Shadows[cascade]);
renderShadow<MeshShader::ShadowShader, EVT_STANDARD, 1>(noTexUnits, cascade, ListMatSphereMap::getInstance()->Shadows[cascade]);
renderShadow<MeshShader::ShadowShader, EVT_2TCOORDS, 1>(noTexUnits, cascade, ListMatDetails::getInstance()->Shadows[cascade]);
renderShadow<MeshShader::ShadowShader, EVT_2TCOORDS, 1>(noTexUnits, cascade, ListMatSplatting::getInstance()->Shadows[cascade]);
renderShadow<MeshShader::ShadowShader, EVT_TANGENTS, 1>(noTexUnits, cascade, ListMatNormalMap::getInstance()->Shadows[cascade]);
renderShadow<MeshShader::RefShadowShader, EVT_STANDARD, 1>(std::vector<GLuint>{ 0 }, cascade, ListMatAlphaRef::getInstance()->Shadows[cascade]);
renderShadow<MeshShader::RefShadowShader, EVT_STANDARD, 1>(std::vector<GLuint>{ 0 }, cascade, ListMatUnlit::getInstance()->Shadows[cascade]);
renderShadow<MeshShader::GrassShadowShader, EVT_STANDARD, 3, 1>(std::vector<GLuint>{ 0 }, cascade, ListMatGrass::getInstance()->Shadows[cascade]);
if (irr_driver->hasARB_draw_indirect())
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, ShadowPassCmd::getInstance()->drawindirectcmd);
if (UserConfigParams::m_azdo)
{
multidrawShadow<MeshShader::InstancedShadowShader, MAT_DEFAULT, video::EVT_STANDARD>(cascade);
multidrawShadow<MeshShader::InstancedShadowShader, MAT_DETAIL, video::EVT_2TCOORDS>(cascade);
multidrawShadow<MeshShader::InstancedShadowShader, MAT_NORMAL_MAP, video::EVT_TANGENTS>(cascade);
multidrawShadow<MeshShader::InstancedRefShadowShader, MAT_ALPHA_REF, video::EVT_STANDARD>(cascade);
multidrawShadow<MeshShader::InstancedRefShadowShader, MAT_UNLIT, video::EVT_STANDARD>(cascade);
multidrawShadow<MeshShader::InstancedGrassShadowShader, MAT_GRASS, video::EVT_STANDARD>(cascade, windDir);
}
else if (irr_driver->hasARB_draw_indirect())
{
renderInstancedShadow<MeshShader::InstancedShadowShader, MAT_DEFAULT, video::EVT_STANDARD>(noTexUnits, cascade, ListInstancedMatDefault::getInstance()->Shadows[cascade]);
renderInstancedShadow<MeshShader::InstancedShadowShader, MAT_DETAIL, video::EVT_2TCOORDS>(noTexUnits, cascade, ListInstancedMatDetails::getInstance()->Shadows[cascade]);
renderInstancedShadow<MeshShader::InstancedRefShadowShader, MAT_ALPHA_REF, video::EVT_STANDARD>(std::vector < GLuint > { 0 }, cascade, ListInstancedMatAlphaRef::getInstance()->Shadows[cascade]);
renderInstancedShadow<MeshShader::InstancedRefShadowShader, MAT_UNLIT, video::EVT_STANDARD>(std::vector < GLuint > { 0 }, cascade, ListInstancedMatUnlit::getInstance()->Shadows[cascade]);
renderInstancedShadow<MeshShader::InstancedGrassShadowShader, MAT_GRASS, video::EVT_STANDARD>(std::vector < GLuint > { 0 }, cascade, ListInstancedMatGrass::getInstance()->Shadows[cascade], windDir);
renderInstancedShadow<MeshShader::InstancedShadowShader, MAT_NORMAL_MAP, video::EVT_TANGENTS>(noTexUnits, cascade, ListInstancedMatNormalMap::getInstance()->Shadows[cascade]);
}
}
glDisable(GL_POLYGON_OFFSET_FILL);
}
template<int...List>
struct rsm_custom_unroll_args;
template<>
struct rsm_custom_unroll_args<>
{
template<typename T, typename ...TupleTypes, typename ...Args>
static void exec(const core::matrix4 &rsm_matrix, const STK::Tuple<TupleTypes...> &t, Args... args)
{
draw<T>(T::getInstance(), STK::tuple_get<0>(t), rsm_matrix, args...);
}
};
template<int N, int...List>
struct rsm_custom_unroll_args<N, List...>
{
template<typename T, typename ...TupleTypes, typename ...Args>
static void exec(const core::matrix4 &rsm_matrix, const STK::Tuple<TupleTypes...> &t, Args... args)
{
rsm_custom_unroll_args<List...>::template exec<T>(rsm_matrix, t, STK::tuple_get<N>(t), args...);
}
};
template<typename T, enum E_VERTEX_TYPE VertexType, int... Selector, typename... Args>
void drawRSM(const core::matrix4 & rsm_matrix, const std::vector<GLuint> &TextureUnits, const std::vector<STK::Tuple<Args...> > &t)
{
glUseProgram(T::getInstance()->Program);
if (irr_driver->hasARB_base_instance())
glBindVertexArray(VAOManager::getInstance()->getVAO(VertexType));
for (unsigned i = 0; i < t.size(); i++)
{
std::vector<GLuint> Textures;
GLMesh *mesh = STK::tuple_get<0>(t.at(i));
if (!irr_driver->hasARB_base_instance())
glBindVertexArray(mesh->vao);
for (unsigned j = 0; j < TextureUnits.size(); j++)
Textures.push_back(getTextureGLuint(mesh->textures[TextureUnits[j]]));
T::getInstance()->SetTextureUnits(Textures);
rsm_custom_unroll_args<Selector...>::template exec<T>(rsm_matrix, t.at(i));
}
}
template<typename Shader, MeshMaterial Mat, video::E_VERTEX_TYPE VT, typename...Args>
void renderRSMShadow(const std::vector<GLuint> TextureUnits, const std::vector<GLMesh *> &t, Args ...args)
{
glUseProgram(Shader::getInstance()->Program);
glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(VT, InstanceTypeRSM));
for (unsigned i = 0; i < t.size(); i++)
{
std::vector<uint64_t> Handles;
std::vector<GLuint> Textures;
GLMesh *mesh = t[i];
for (unsigned j = 0; j < TextureUnits.size(); j++)
Textures.push_back(getTextureGLuint(mesh->textures[TextureUnits[j]]));
Shader::getInstance()->SetTextureUnits(Textures);
Shader::getInstance()->setUniforms(args...);
glDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, (const void*)((RSMPassCmd::getInstance()->Offset[Mat] + i)* sizeof(DrawElementsIndirectCommand)));
}
}
template<typename Shader, MeshMaterial Mat, enum E_VERTEX_TYPE VertexType, typename... Args>
void multidrawRSM(Args...args)
{
glUseProgram(Shader::getInstance()->Program);
glBindVertexArray(VAOManager::getInstance()->getInstanceVAO(VertexType, InstanceTypeRSM));
if (RSMPassCmd::getInstance()->Size[Mat])
{
Shader::getInstance()->setUniforms(args...);
glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, (const void*)(RSMPassCmd::getInstance()->Offset[Mat] * sizeof(DrawElementsIndirectCommand)), RSMPassCmd::getInstance()->Size[Mat], sizeof(DrawElementsIndirectCommand));
}
}
void IrrDriver::renderRSM()
{
ScopedGPUTimer Timer(getGPUTimer(Q_RSM));
m_rtts->getRSM().Bind();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
drawRSM<MeshShader::RSMShader, EVT_STANDARD, 3, 1>(rsm_matrix, std::vector<GLuint>{ 0 }, ListMatDefault::getInstance()->RSM);
drawRSM<MeshShader::RSMShader, EVT_STANDARD, 3, 1>(rsm_matrix, std::vector<GLuint>{ 0 }, ListMatAlphaRef::getInstance()->RSM);
drawRSM<MeshShader::RSMShader, EVT_TANGENTS, 3, 1>(rsm_matrix, std::vector<GLuint>{ 0 }, ListMatNormalMap::getInstance()->RSM);
drawRSM<MeshShader::RSMShader, EVT_STANDARD, 3, 1>(rsm_matrix, std::vector<GLuint>{ 0 }, ListMatUnlit::getInstance()->RSM);
drawRSM<MeshShader::RSMShader, EVT_2TCOORDS, 3, 1>(rsm_matrix, std::vector<GLuint>{ 0 }, ListMatDetails::getInstance()->RSM);
drawRSM<MeshShader::SplattingRSMShader, EVT_2TCOORDS, 1>(rsm_matrix, createVector<GLuint>(1, 2, 3, 4, 5), ListMatSplatting::getInstance()->RSM);
if (irr_driver->hasARB_draw_indirect())
glBindBuffer(GL_DRAW_INDIRECT_BUFFER, RSMPassCmd::getInstance()->drawindirectcmd);
if (UserConfigParams::m_azdo)
{
multidrawRSM<MeshShader::InstancedRSMShader, MAT_DEFAULT, video::EVT_STANDARD>(rsm_matrix);
multidrawRSM<MeshShader::InstancedRSMShader, MAT_NORMAL_MAP, video::EVT_TANGENTS>(rsm_matrix);
multidrawRSM<MeshShader::InstancedRSMShader, MAT_ALPHA_REF, video::EVT_STANDARD>(rsm_matrix);
multidrawRSM<MeshShader::InstancedRSMShader, MAT_UNLIT, video::EVT_STANDARD>(rsm_matrix);
multidrawRSM<MeshShader::InstancedRSMShader, MAT_DETAIL, video::EVT_2TCOORDS>(rsm_matrix);
}
else if (irr_driver->hasARB_draw_indirect())
{
renderRSMShadow<MeshShader::InstancedRSMShader, MAT_DEFAULT, video::EVT_STANDARD>(std::vector < GLuint > { 0 }, ListInstancedMatDefault::getInstance()->RSM, rsm_matrix);
renderRSMShadow<MeshShader::InstancedRSMShader, MAT_ALPHA_REF, video::EVT_STANDARD>(std::vector < GLuint > { 0 }, ListInstancedMatAlphaRef::getInstance()->RSM, rsm_matrix);
renderRSMShadow<MeshShader::InstancedRSMShader, MAT_UNLIT, video::EVT_STANDARD>(std::vector < GLuint > { 0 }, ListInstancedMatUnlit::getInstance()->RSM, rsm_matrix);
renderRSMShadow<MeshShader::InstancedRSMShader, MAT_NORMAL_MAP, video::EVT_TANGENTS>(std::vector < GLuint > { 0 }, ListInstancedMatNormalMap::getInstance()->RSM, rsm_matrix);
renderRSMShadow<MeshShader::InstancedRSMShader, MAT_DETAIL, video::EVT_2TCOORDS>(std::vector < GLuint > { 0 }, ListInstancedMatDetails::getInstance()->RSM, rsm_matrix);
}
}