Moved AssignTextureUnit to new Shader base class.
This commit is contained in:
parent
118233fb24
commit
45d6c863b3
@ -28,6 +28,91 @@
|
||||
#include "../../lib/irrlicht/source/Irrlicht/os.h"
|
||||
#define COMPONENTCOUNT 8
|
||||
|
||||
|
||||
// ============================================================================
|
||||
/** Transform feedback shader that simulates the particles on GPU.
|
||||
*/
|
||||
class PointEmitterShader : public Shader
|
||||
< PointEmitterShader, core::matrix4, int, int, float >
|
||||
{
|
||||
public:
|
||||
PointEmitterShader()
|
||||
{
|
||||
const char *varyings[] = { "new_particle_position", "new_lifetime",
|
||||
"new_particle_velocity", "new_size" };
|
||||
loadTFBProgram("pointemitter.vert", varyings, 4);
|
||||
assignUniforms("sourcematrix", "dt", "level", "size_increase_factor");
|
||||
} // PointEmitterShader
|
||||
|
||||
}; // PointEmitterShader
|
||||
|
||||
// ============================================================================
|
||||
|
||||
/** A Shader to render particles.
|
||||
*/
|
||||
class SimpleParticleRender : public Shader<SimpleParticleRender, video::SColorf,
|
||||
video::SColorf>,
|
||||
public TextureRead<Trilinear_Anisotropic_Filtered,
|
||||
Nearest_Filtered>
|
||||
{
|
||||
public:
|
||||
SimpleParticleRender()
|
||||
{
|
||||
loadProgram(PARTICLES_RENDERING,
|
||||
GL_VERTEX_SHADER, "particle.vert",
|
||||
GL_FRAGMENT_SHADER, "utils/getPosFromUVDepth.frag",
|
||||
GL_FRAGMENT_SHADER, "particle.frag");
|
||||
|
||||
assignUniforms("color_from", "color_to");
|
||||
AssignSamplerNames(m_program, 0, "tex", 1, "dtex");
|
||||
} // SimpleParticleRender
|
||||
|
||||
}; // SimpleParticleRender
|
||||
|
||||
// ============================================================================
|
||||
|
||||
class FlipParticleRender : public Shader<FlipParticleRender>,
|
||||
public TextureRead < Trilinear_Anisotropic_Filtered,
|
||||
Nearest_Filtered >
|
||||
{
|
||||
public:
|
||||
FlipParticleRender()
|
||||
{
|
||||
loadProgram(PARTICLES_RENDERING,
|
||||
GL_VERTEX_SHADER, "flipparticle.vert",
|
||||
GL_FRAGMENT_SHADER, "utils/getPosFromUVDepth.frag",
|
||||
GL_FRAGMENT_SHADER, "particle.frag");
|
||||
assignUniforms();
|
||||
AssignSamplerNames(m_program, 0, "tex", 1, "dtex");
|
||||
}
|
||||
|
||||
}; // FlipParticleShader
|
||||
|
||||
// ============================================================================
|
||||
/** */
|
||||
class HeightmapSimulationShader : public Shader <HeightmapSimulationShader,
|
||||
core::matrix4, int, int,
|
||||
float,float,float,float,float>
|
||||
{
|
||||
public:
|
||||
GLuint m_TU_heightmap;
|
||||
|
||||
HeightmapSimulationShader()
|
||||
{
|
||||
const char *varyings[] = {"new_particle_position", "new_lifetime",
|
||||
"new_particle_velocity", "new_size" };
|
||||
loadTFBProgram("particlesimheightmap.vert", varyings, 4);
|
||||
assignUniforms("sourcematrix", "dt", "level", "size_increase_factor",
|
||||
"track_x", "track_x_len", "track_z", "track_z_len");
|
||||
m_TU_heightmap = 2;
|
||||
assignTextureUnit(TexUnit(m_TU_heightmap, "heightmap"));
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
|
||||
scene::IParticleSystemSceneNode *ParticleSystemProxy::addParticleNode(
|
||||
bool withDefaultEmitter, bool randomize_initial_y, ISceneNode* parent, s32 id,
|
||||
const core::vector3df& position,
|
||||
@ -388,7 +473,7 @@ void ParticleSystemProxy::simulate()
|
||||
if (has_height_map)
|
||||
{
|
||||
HeightmapSimulationShader::getInstance()->use();
|
||||
glActiveTexture(GL_TEXTURE0 + HeightmapSimulationShader::getInstance()->TU_heightmap);
|
||||
glActiveTexture(GL_TEXTURE0 + HeightmapSimulationShader::getInstance()->m_TU_heightmap);
|
||||
glBindTexture(GL_TEXTURE_BUFFER, heightmaptexture);
|
||||
HeightmapSimulationShader::getInstance()->setUniforms(matrix, timediff, active_count, size_increase_factor, track_x, track_x_len, track_z, track_z_len);
|
||||
}
|
||||
@ -535,101 +620,3 @@ void ParticleSystemProxy::render() {
|
||||
simulate();
|
||||
draw();
|
||||
}
|
||||
|
||||
|
||||
// ============================================================================
|
||||
|
||||
PointEmitterShader::PointEmitterShader()
|
||||
{
|
||||
const char *varyings[] = {
|
||||
"new_particle_position",
|
||||
"new_lifetime",
|
||||
"new_particle_velocity",
|
||||
"new_size",
|
||||
};
|
||||
loadTFBProgram("pointemitter.vert", varyings, 4);
|
||||
assignUniforms("sourcematrix", "dt", "level", "size_increase_factor");
|
||||
} // PointEmitterShader
|
||||
|
||||
// ============================================================================
|
||||
SimpleParticleRender::SimpleParticleRender()
|
||||
{
|
||||
loadProgram(PARTICLES_RENDERING,
|
||||
GL_VERTEX_SHADER, "particle.vert",
|
||||
GL_FRAGMENT_SHADER, "utils/getPosFromUVDepth.frag",
|
||||
GL_FRAGMENT_SHADER, "particle.frag");
|
||||
|
||||
assignUniforms("color_from", "color_to");
|
||||
|
||||
AssignSamplerNames(m_program, 0, "tex", 1, "dtex");
|
||||
} // SimpleParticleRender
|
||||
|
||||
// ============================================================================
|
||||
|
||||
|
||||
struct TexUnit
|
||||
{
|
||||
GLuint m_index;
|
||||
const char* m_uniform;
|
||||
|
||||
TexUnit(GLuint index, const char* uniform)
|
||||
{
|
||||
m_index = index;
|
||||
m_uniform = uniform;
|
||||
}
|
||||
};
|
||||
static void
|
||||
AssignTextureUnit(GLuint Program, TexUnit texUnit)
|
||||
{
|
||||
glUseProgram(Program);
|
||||
GLuint uniform = glGetUniformLocation(Program, texUnit.m_uniform);
|
||||
glUniform1i(uniform, texUnit.m_index);
|
||||
glUseProgram(0);
|
||||
}
|
||||
|
||||
template<typename... T>
|
||||
static void AssignTextureUnit(GLuint Program, TexUnit texUnit, T... rest)
|
||||
{
|
||||
glUseProgram(Program);
|
||||
GLuint uniform = glGetUniformLocation(Program, texUnit.m_uniform);
|
||||
glUniform1i(uniform, texUnit.m_index);
|
||||
AssignTextureUnit_Sub(Program, rest...);
|
||||
glUseProgram(0);
|
||||
}
|
||||
|
||||
static void AssignTextureUnit_Sub(GLuint Program) {}
|
||||
|
||||
template<typename... T>
|
||||
static void AssignTextureUnit_Sub(GLuint Program, TexUnit texUnit, T... rest)
|
||||
{
|
||||
GLuint uniform = glGetUniformLocation(Program, texUnit.m_uniform);
|
||||
glUniform1i(uniform, texUnit.m_index);
|
||||
AssignTextureUnit_Sub(Program, rest...);
|
||||
}
|
||||
|
||||
|
||||
|
||||
HeightmapSimulationShader::HeightmapSimulationShader()
|
||||
{
|
||||
const char *varyings[] = {
|
||||
"new_particle_position",
|
||||
"new_lifetime",
|
||||
"new_particle_velocity",
|
||||
"new_size",
|
||||
};
|
||||
loadTFBProgram("particlesimheightmap.vert", varyings, 4);
|
||||
TU_heightmap = 2;
|
||||
AssignTextureUnit(m_program, TexUnit(TU_heightmap, "heightmap"));
|
||||
assignUniforms("sourcematrix", "dt", "level", "size_increase_factor", "track_x", "track_x_len", "track_z", "track_z_len");
|
||||
}
|
||||
|
||||
FlipParticleRender::FlipParticleRender()
|
||||
{
|
||||
loadProgram(PARTICLES_RENDERING,
|
||||
GL_VERTEX_SHADER, "flipparticle.vert",
|
||||
GL_FRAGMENT_SHADER, "utils/getPosFromUVDepth.frag",
|
||||
GL_FRAGMENT_SHADER, "particle.frag");
|
||||
assignUniforms();
|
||||
|
||||
AssignSamplerNames(m_program, 0, "tex", 1, "dtex");
|
||||
}
|
||||
|
@ -19,48 +19,16 @@
|
||||
#define HEADER_GPU_PARTICLES_HPP
|
||||
|
||||
#include "graphics/shader.hpp"
|
||||
|
||||
#include "../lib/irrlicht/source/Irrlicht/CParticleSystemSceneNode.h"
|
||||
#include <ISceneManager.h>
|
||||
#include <IParticleSystemSceneNode.h>
|
||||
|
||||
|
||||
class PointEmitterShader : public Shader
|
||||
< PointEmitterShader, core::matrix4, int, int, float >
|
||||
{
|
||||
public:
|
||||
PointEmitterShader();
|
||||
}; // PointEmitterShader
|
||||
|
||||
// ============================================================================
|
||||
class SimpleParticleRender : public Shader<SimpleParticleRender, video::SColorf,
|
||||
video::SColorf>,
|
||||
public TextureRead<Trilinear_Anisotropic_Filtered,
|
||||
Nearest_Filtered>
|
||||
{
|
||||
public:
|
||||
SimpleParticleRender();
|
||||
}; // SimpleParticleRender
|
||||
|
||||
// ============================================================================
|
||||
|
||||
class HeightmapSimulationShader : public Shader<HeightmapSimulationShader, core::matrix4, int, int, float, float, float, float, float>
|
||||
{
|
||||
public:
|
||||
GLuint TU_heightmap;
|
||||
|
||||
HeightmapSimulationShader();
|
||||
};
|
||||
|
||||
|
||||
class FlipParticleRender : public Shader<FlipParticleRender>, public TextureRead<Trilinear_Anisotropic_Filtered, Nearest_Filtered>
|
||||
{
|
||||
public:
|
||||
FlipParticleRender();
|
||||
};
|
||||
|
||||
|
||||
namespace irr { namespace video{ class ITexture; } }
|
||||
|
||||
|
||||
|
||||
|
||||
class ParticleSystemProxy : public scene::CParticleSystemSceneNode
|
||||
{
|
||||
protected:
|
||||
|
@ -754,7 +754,7 @@ void IrrDriver::renderNormalsVisualisation()
|
||||
}
|
||||
|
||||
template<typename Shader, enum video::E_VERTEX_TYPE VertexType, int...List, typename... TupleType>
|
||||
void renderTransparenPass(const std::vector<TexUnit> &TexUnits, std::vector<STK::Tuple<TupleType...> > *meshes)
|
||||
void renderTransparenPass(const std::vector<RenderGeometry::TexUnit> &TexUnits, std::vector<STK::Tuple<TupleType...> > *meshes)
|
||||
{
|
||||
Shader::getInstance()->use();
|
||||
if (CVS->isARBBaseInstanceUsable())
|
||||
@ -802,19 +802,19 @@ void IrrDriver::renderTransparent()
|
||||
{
|
||||
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());
|
||||
RenderGeometry::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());
|
||||
RenderGeometry::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());
|
||||
RenderGeometry::TexUnit(0, true)), ListBlendTransparent::getInstance());
|
||||
glBlendFunc(GL_ONE, GL_ONE);
|
||||
renderTransparenPass<MeshShader::TransparentShader, video::EVT_STANDARD, 2, 1>(TexUnits(
|
||||
TexUnit(0, true)), ListAdditiveTransparent::getInstance());
|
||||
RenderGeometry::TexUnit(0, true)), ListAdditiveTransparent::getInstance());
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < BillBoardList::getInstance()->size(); i++)
|
||||
|
@ -238,6 +238,52 @@ private:
|
||||
Log::error("shader", filepath);
|
||||
printFileList(args...);
|
||||
} // printFileList
|
||||
protected:
|
||||
|
||||
/** Stores texture index and uniform. */
|
||||
class TexUnit
|
||||
{
|
||||
public:
|
||||
GLuint m_index;
|
||||
const char* m_uniform;
|
||||
|
||||
TexUnit(GLuint index, const char* uniform)
|
||||
{
|
||||
m_index = index;
|
||||
m_uniform = uniform;
|
||||
} // TexUnit
|
||||
}; // class TexUnit
|
||||
|
||||
// ========================================================================
|
||||
void assignTextureUnit(TexUnit tex_unit)
|
||||
{
|
||||
glUseProgram(m_program);
|
||||
GLuint uniform = glGetUniformLocation(m_program, tex_unit.m_uniform);
|
||||
glUniform1i(uniform, tex_unit.m_index);
|
||||
glUseProgram(0);
|
||||
} // assignTextureUnit
|
||||
// ------------------------------------------------------------------------
|
||||
template<typename... T>
|
||||
void assignTextureUnit(TexUnit tex_unit, T... rest)
|
||||
{
|
||||
glUseProgram(m_program);
|
||||
GLuint uniform = glGetUniformLocation(m_program, tex_unit.m_uniform);
|
||||
glUniform1i(uniform, tex_unit.m_index);
|
||||
assignTextureUnitNoUse(rest...);
|
||||
glUseProgram(0);
|
||||
} // assignTextureUnit
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
void assignTextureUnitNoUse() {}
|
||||
// ------------------------------------------------------------------------
|
||||
template<typename... T>
|
||||
void assignTextureUnitNoUse(TexUnit tex_unit, T... rest)
|
||||
{
|
||||
GLuint uniform = glGetUniformLocation(m_program, tex_unit.m_uniform);
|
||||
glUniform1i(uniform, tex_unit.m_index);
|
||||
assignTextureUnitNoUse(rest...);
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
@ -57,7 +57,7 @@
|
||||
\subsection shader_declaration_bind_texture_unit Bind texture unit and name
|
||||
|
||||
Texture are optional but if you have one, you must give them determined texture unit (up to 32).
|
||||
You can do this using the AssignTextureUnit function that takes pair of texture unit and sampler name
|
||||
You can do this using the assignTextureUnit function that takes pair of texture unit and sampler name
|
||||
as argument.
|
||||
|
||||
\section shader_usage
|
||||
@ -97,6 +97,7 @@
|
||||
#include "graphics/irr_driver.hpp"
|
||||
#include "graphics/gpuparticles.hpp"
|
||||
#include "graphics/shaders.hpp"
|
||||
#include "graphics/shaders_util.hpp"
|
||||
#include "io/file_manager.hpp"
|
||||
#include "utils/log.hpp"
|
||||
#include "graphics/glwrap.hpp"
|
||||
@ -515,20 +516,9 @@ namespace UtilShader
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
}
|
||||
|
||||
struct TexUnit
|
||||
{
|
||||
GLuint m_index;
|
||||
const char* m_uniform;
|
||||
|
||||
TexUnit(GLuint index, const char* uniform)
|
||||
{
|
||||
m_index = index;
|
||||
m_uniform = uniform;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
std::vector<TexUnit> TexUnits(T curr) // required on older clang versions
|
||||
std::vector<Shader::TexUnit> TexUnits(T curr) // required on older clang versions
|
||||
{
|
||||
std::vector<TexUnit> v;
|
||||
v.push_back(curr);
|
||||
@ -536,7 +526,7 @@ namespace UtilShader
|
||||
}
|
||||
|
||||
template <typename T, typename... R>
|
||||
std::vector<TexUnit> TexUnits(T curr, R... rest) // required on older clang versions
|
||||
std::vector<Shader::TexUnit> TexUnits(T curr, R... rest) // required on older clang versions
|
||||
{
|
||||
std::vector<TexUnit> v;
|
||||
v.push_back(curr);
|
||||
@ -545,46 +535,18 @@ namespace UtilShader
|
||||
}
|
||||
|
||||
template <typename T, typename... R>
|
||||
void VTexUnits(std::vector<TexUnit>& v, T curr, R... rest) // required on older clang versions
|
||||
void VTexUnits(std::vector<Shader::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)
|
||||
void VTexUnits(std::vector<Shader::TexUnit>& v, T curr)
|
||||
{
|
||||
v.push_back(curr);
|
||||
}
|
||||
|
||||
static void
|
||||
AssignTextureUnit(GLuint Program, TexUnit texUnit)
|
||||
{
|
||||
glUseProgram(Program);
|
||||
GLuint uniform = glGetUniformLocation(Program, texUnit.m_uniform);
|
||||
glUniform1i(uniform, texUnit.m_index);
|
||||
glUseProgram(0);
|
||||
}
|
||||
|
||||
template<typename... T>
|
||||
static void AssignTextureUnit(GLuint Program, TexUnit texUnit, T... rest)
|
||||
{
|
||||
glUseProgram(Program);
|
||||
GLuint uniform = glGetUniformLocation(Program, texUnit.m_uniform);
|
||||
glUniform1i(uniform, texUnit.m_index);
|
||||
AssignTextureUnit_Sub(Program, rest...);
|
||||
glUseProgram(0);
|
||||
}
|
||||
|
||||
static void AssignTextureUnit_Sub(GLuint Program) {}
|
||||
|
||||
template<typename... T>
|
||||
static void AssignTextureUnit_Sub(GLuint Program, TexUnit texUnit, T... rest)
|
||||
{
|
||||
GLuint uniform = glGetUniformLocation(Program, texUnit.m_uniform);
|
||||
glUniform1i(uniform, texUnit.m_index);
|
||||
AssignTextureUnit_Sub(Program, rest...);
|
||||
}
|
||||
}
|
||||
using namespace UtilShader;
|
||||
|
||||
@ -829,7 +791,7 @@ namespace UtilShader
|
||||
assignUniforms("PermutationMatrix", "ViewportSize");
|
||||
TU_Samples = 1;
|
||||
AssignSamplerNames(m_program, 0, "tex");
|
||||
AssignTextureUnit(m_program, TexUnit(TU_Samples, "samples"));
|
||||
assignTextureUnit(TexUnit(TU_Samples, "samples"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1614,7 +1576,7 @@ namespace FullScreenShader
|
||||
TU_SHR = 0;
|
||||
TU_SHG = 1;
|
||||
TU_SHB = 2;
|
||||
AssignTextureUnit(m_program, TexUnit(TU_SHR, "SHR"), TexUnit(TU_SHG, "SHG"), TexUnit(TU_SHB, "SHB"));
|
||||
assignTextureUnit(TexUnit(TU_SHR, "SHR"), TexUnit(TU_SHG, "SHG"), TexUnit(TU_SHB, "SHB"));
|
||||
}
|
||||
|
||||
GlobalIlluminationReconstructionShader::GlobalIlluminationReconstructionShader()
|
||||
@ -1644,7 +1606,7 @@ namespace FullScreenShader
|
||||
TU_dest = 2;
|
||||
assignUniforms("pixel");
|
||||
AssignSamplerNames(m_program, 0, "source", 1, "depth");
|
||||
AssignTextureUnit(m_program, TexUnit(TU_dest, "dest"));
|
||||
assignTextureUnit(TexUnit(TU_dest, "dest"));
|
||||
}
|
||||
|
||||
ComputeGaussian6HBlurShader::ComputeGaussian6HBlurShader()
|
||||
@ -1654,7 +1616,7 @@ namespace FullScreenShader
|
||||
TU_dest = 1;
|
||||
assignUniforms("pixel", "weights");
|
||||
AssignSamplerNames(m_program, 0, "source");
|
||||
AssignTextureUnit(m_program, TexUnit(TU_dest, "dest"));
|
||||
assignTextureUnit(TexUnit(TU_dest, "dest"));
|
||||
}
|
||||
|
||||
ComputeShadowBlurHShader::ComputeShadowBlurHShader()
|
||||
@ -1664,7 +1626,7 @@ namespace FullScreenShader
|
||||
TU_dest = 1;
|
||||
assignUniforms("pixel", "weights");
|
||||
AssignSamplerNames(m_program, 0, "source");
|
||||
AssignTextureUnit(m_program, TexUnit(TU_dest, "dest"));
|
||||
assignTextureUnit(TexUnit(TU_dest, "dest"));
|
||||
}
|
||||
|
||||
Gaussian6HBlurShader::Gaussian6HBlurShader()
|
||||
@ -1714,7 +1676,7 @@ namespace FullScreenShader
|
||||
TU_dest = 2;
|
||||
assignUniforms("pixel");
|
||||
AssignSamplerNames(m_program, 0, "source", 1, "depth");
|
||||
AssignTextureUnit(m_program, TexUnit(TU_dest, "dest"));
|
||||
assignTextureUnit(TexUnit(TU_dest, "dest"));
|
||||
}
|
||||
|
||||
ComputeGaussian6VBlurShader::ComputeGaussian6VBlurShader()
|
||||
@ -1724,7 +1686,7 @@ namespace FullScreenShader
|
||||
TU_dest = 1;
|
||||
assignUniforms("pixel", "weights");
|
||||
AssignSamplerNames(m_program, 0, "source");
|
||||
AssignTextureUnit(m_program, TexUnit(TU_dest, "dest"));
|
||||
assignTextureUnit(TexUnit(TU_dest, "dest"));
|
||||
}
|
||||
|
||||
ComputeShadowBlurVShader::ComputeShadowBlurVShader()
|
||||
@ -1734,7 +1696,7 @@ namespace FullScreenShader
|
||||
TU_dest = 1;
|
||||
assignUniforms("pixel", "weights");
|
||||
AssignSamplerNames(m_program, 0, "source");
|
||||
AssignTextureUnit(m_program, TexUnit(TU_dest, "dest"));
|
||||
assignTextureUnit(TexUnit(TU_dest, "dest"));
|
||||
}
|
||||
|
||||
Gaussian6VBlurShader::Gaussian6VBlurShader()
|
||||
@ -1774,7 +1736,7 @@ namespace FullScreenShader
|
||||
GL_FRAGMENT_SHADER, "layertexturequad.frag");
|
||||
TU_texture = 0;
|
||||
assignUniforms("layer");
|
||||
AssignTextureUnit(m_program, TexUnit(TU_texture, "tex"));
|
||||
assignTextureUnit(TexUnit(TU_texture, "tex"));
|
||||
vao = createVAO(m_program);
|
||||
}
|
||||
|
||||
|
@ -369,6 +369,7 @@ protected:
|
||||
std::vector<GLuint> TextureUnits;
|
||||
std::vector<GLenum> TextureType;
|
||||
std::vector<GLenum> TextureLocation;
|
||||
public:
|
||||
template<typename...Args>
|
||||
void AssignSamplerNames(GLuint Program, Args...args)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user