Add a ESM/PCF switch
This commit is contained in:
parent
883ab43e29
commit
3451d4e9a0
@ -1,6 +1,6 @@
|
|||||||
uniform sampler2D ntex;
|
uniform sampler2D ntex;
|
||||||
uniform sampler2D dtex;
|
uniform sampler2D dtex;
|
||||||
uniform sampler2DArray shadowtex;
|
uniform sampler2DArrayShadow shadowtex;
|
||||||
|
|
||||||
uniform float split0;
|
uniform float split0;
|
||||||
uniform float split1;
|
uniform float split1;
|
||||||
@ -22,10 +22,17 @@ float getShadowFactor(vec3 pos, int index)
|
|||||||
vec4 shadowcoord = (ShadowViewProjMatrixes[index] * InverseViewMatrix * vec4(pos, 1.0));
|
vec4 shadowcoord = (ShadowViewProjMatrixes[index] * InverseViewMatrix * vec4(pos, 1.0));
|
||||||
shadowcoord.xy /= shadowcoord.w;
|
shadowcoord.xy /= shadowcoord.w;
|
||||||
vec2 shadowtexcoord = shadowcoord.xy * 0.5 + 0.5;
|
vec2 shadowtexcoord = shadowcoord.xy * 0.5 + 0.5;
|
||||||
|
float d = .5 * shadowcoord.z + .5;
|
||||||
|
|
||||||
float z = texture(shadowtex, vec3(shadowtexcoord, float(index))).x;
|
float result = 0.;
|
||||||
float d = shadowcoord.z;
|
|
||||||
return min(pow(exp(-32. * d) * z, 8.), 1.);
|
for (float i = -1.; i <= 1.; i += 1.)
|
||||||
|
{
|
||||||
|
for (float j = -1.; j <= 1.; j += 1.)
|
||||||
|
result += texture(shadowtex, vec4(shadowtexcoord + vec2(i,j) / 1024., float(index), d));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result / 9.;
|
||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
61
data/shaders/sunlightshadowesm.frag
Normal file
61
data/shaders/sunlightshadowesm.frag
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
uniform sampler2D ntex;
|
||||||
|
uniform sampler2D dtex;
|
||||||
|
uniform sampler2DArray shadowtex;
|
||||||
|
|
||||||
|
uniform float split0;
|
||||||
|
uniform float split1;
|
||||||
|
uniform float split2;
|
||||||
|
uniform float splitmax;
|
||||||
|
|
||||||
|
in vec2 uv;
|
||||||
|
out vec4 Diff;
|
||||||
|
out vec4 Spec;
|
||||||
|
|
||||||
|
vec3 DecodeNormal(vec2 n);
|
||||||
|
vec3 SpecularBRDF(vec3 normal, vec3 eyedir, vec3 lightdir, vec3 color, float roughness);
|
||||||
|
vec3 DiffuseBRDF(vec3 normal, vec3 eyedir, vec3 lightdir, vec3 color, float roughness);
|
||||||
|
vec4 getPosFromUVDepth(vec3 uvDepth, mat4 InverseProjectionMatrix);
|
||||||
|
vec3 SunMRP(vec3 normal, vec3 eyedir);
|
||||||
|
|
||||||
|
float getShadowFactor(vec3 pos, int index)
|
||||||
|
{
|
||||||
|
vec4 shadowcoord = (ShadowViewProjMatrixes[index] * InverseViewMatrix * vec4(pos, 1.0));
|
||||||
|
shadowcoord.xy /= shadowcoord.w;
|
||||||
|
vec2 shadowtexcoord = shadowcoord.xy * 0.5 + 0.5;
|
||||||
|
|
||||||
|
float z = texture(shadowtex, vec3(shadowtexcoord, float(index))).x;
|
||||||
|
float d = shadowcoord.z;
|
||||||
|
return min(pow(exp(-32. * d) * z, 8.), 1.);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec2 uv = gl_FragCoord.xy / screen;
|
||||||
|
float z = texture(dtex, uv).x;
|
||||||
|
vec4 xpos = getPosFromUVDepth(vec3(uv, z), InverseProjectionMatrix);
|
||||||
|
|
||||||
|
vec3 norm = normalize(DecodeNormal(2. * texture(ntex, uv).xy - 1.));
|
||||||
|
float roughness =texture(ntex, uv).z;
|
||||||
|
vec3 eyedir = -normalize(xpos.xyz);
|
||||||
|
|
||||||
|
vec3 Lightdir = SunMRP(norm, eyedir);
|
||||||
|
float NdotL = clamp(dot(norm, Lightdir), 0., 1.);
|
||||||
|
|
||||||
|
vec3 Specular = SpecularBRDF(norm, eyedir, Lightdir, vec3(1.), roughness);
|
||||||
|
vec3 Diffuse = DiffuseBRDF(norm, eyedir, Lightdir, vec3(1.), roughness);
|
||||||
|
|
||||||
|
// Shadows
|
||||||
|
float factor;
|
||||||
|
if (xpos.z < split0)
|
||||||
|
factor = getShadowFactor(xpos.xyz, 0);
|
||||||
|
else if (xpos.z < split1)
|
||||||
|
factor = getShadowFactor(xpos.xyz, 1);
|
||||||
|
else if (xpos.z < split2)
|
||||||
|
factor = getShadowFactor(xpos.xyz, 2);
|
||||||
|
else if (xpos.z < splitmax)
|
||||||
|
factor = getShadowFactor(xpos.xyz, 3);
|
||||||
|
else
|
||||||
|
factor = 1.;
|
||||||
|
|
||||||
|
Diff = vec4(factor * NdotL * Diffuse * sun_col, 1.);
|
||||||
|
Spec = vec4(factor * NdotL * Specular * sun_col, 1.);
|
||||||
|
}
|
@ -470,6 +470,9 @@ namespace UserConfigParams
|
|||||||
PARAM_PREFIX BoolUserConfigParam m_sdsm
|
PARAM_PREFIX BoolUserConfigParam m_sdsm
|
||||||
PARAM_DEFAULT(BoolUserConfigParam(false, "enable_sdsm",
|
PARAM_DEFAULT(BoolUserConfigParam(false, "enable_sdsm",
|
||||||
&m_video_group, "Enable Sampled Distribued Shadow Map (buggy atm)"));
|
&m_video_group, "Enable Sampled Distribued Shadow Map (buggy atm)"));
|
||||||
|
PARAM_PREFIX BoolUserConfigParam m_esm
|
||||||
|
PARAM_DEFAULT(BoolUserConfigParam(false, "enable_esm",
|
||||||
|
&m_video_group, "Enable Exponential Shadow Map (better but slower)"));
|
||||||
|
|
||||||
// ---- Debug - not saved to config file
|
// ---- Debug - not saved to config file
|
||||||
/** If gamepad debugging is enabled. */
|
/** If gamepad debugging is enabled. */
|
||||||
|
@ -309,4 +309,10 @@ bool CentralVideoSettings::isSDSMEnabled() const
|
|||||||
bool CentralVideoSettings::isAZDOEnabled() const
|
bool CentralVideoSettings::isAZDOEnabled() const
|
||||||
{
|
{
|
||||||
return supportsIndirectInstancingRendering() && isARBBindlessTextureUsable() && isARBMultiDrawIndirectUsable() && UserConfigParams::m_azdo;
|
return supportsIndirectInstancingRendering() && isARBBindlessTextureUsable() && isARBMultiDrawIndirectUsable() && UserConfigParams::m_azdo;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Switch between Exponential Shadow Map (better but slower filtering) and Percentage Closer Filtering (faster but with some stability issue)
|
||||||
|
bool CentralVideoSettings::isESMEnabled() const
|
||||||
|
{
|
||||||
|
return UserConfigParams::m_esm;
|
||||||
}
|
}
|
@ -65,6 +65,7 @@ public:
|
|||||||
bool isTextureCompressionEnabled() const;
|
bool isTextureCompressionEnabled() const;
|
||||||
bool isSDSMEnabled() const;
|
bool isSDSMEnabled() const;
|
||||||
bool isAZDOEnabled() const;
|
bool isAZDOEnabled() const;
|
||||||
|
bool isESMEnabled() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern CentralVideoSettings* CVS;
|
extern CentralVideoSettings* CVS;
|
||||||
|
@ -271,19 +271,6 @@ void PostProcessing::renderSunlight(const core::vector3df &direction, const vide
|
|||||||
DrawFullScreenEffect<FullScreenShader::SunLightShader>(direction, col);
|
DrawFullScreenEffect<FullScreenShader::SunLightShader>(direction, col);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern float shadowSplit[5];
|
|
||||||
|
|
||||||
void PostProcessing::renderShadowedSunlight(const core::vector3df &direction, const video::SColorf &col, const std::vector<core::matrix4> &sun_ortho_matrix, GLuint depthtex)
|
|
||||||
{
|
|
||||||
glEnable(GL_BLEND);
|
|
||||||
glDisable(GL_DEPTH_TEST);
|
|
||||||
glBlendFunc(GL_ONE, GL_ONE);
|
|
||||||
glBlendEquation(GL_FUNC_ADD);
|
|
||||||
|
|
||||||
FullScreenShader::ShadowedSunLightShader::getInstance()->SetTextureUnits(irr_driver->getRenderTargetTexture(RTT_NORMAL_AND_DEPTH), irr_driver->getDepthStencilTexture(), depthtex);
|
|
||||||
DrawFullScreenEffect<FullScreenShader::ShadowedSunLightShader>(shadowSplit[1], shadowSplit[2], shadowSplit[3], shadowSplit[4], direction, col);
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
static
|
||||||
std::vector<float> getGaussianWeight(float sigma, size_t count)
|
std::vector<float> getGaussianWeight(float sigma, size_t count)
|
||||||
{
|
{
|
||||||
|
@ -75,7 +75,6 @@ public:
|
|||||||
|
|
||||||
/** Generate diffuse and specular map */
|
/** Generate diffuse and specular map */
|
||||||
void renderSunlight(const core::vector3df &direction, const video::SColorf &col);
|
void renderSunlight(const core::vector3df &direction, const video::SColorf &col);
|
||||||
void renderShadowedSunlight(const core::vector3df &direction, const video::SColorf &col, const std::vector<core::matrix4> &sun_ortho_matrix, unsigned depthtex);
|
|
||||||
|
|
||||||
void renderSSAO();
|
void renderSSAO();
|
||||||
void renderEnvMap(const float *bSHCoeff, const float *gSHCoeff, const float *rSHCoeff, unsigned skycubemap);
|
void renderEnvMap(const float *bSHCoeff, const float *gSHCoeff, const float *rSHCoeff, unsigned skycubemap);
|
||||||
|
@ -127,6 +127,8 @@ void IrrDriver::uploadLightingData()
|
|||||||
glBufferSubData(GL_UNIFORM_BUFFER, 0, 36 * sizeof(float), Lighting);
|
glBufferSubData(GL_UNIFORM_BUFFER, 0, 36 * sizeof(float), Lighting);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern float shadowSplit[5];
|
||||||
|
|
||||||
void IrrDriver::renderLights(unsigned pointlightcount, bool hasShadow)
|
void IrrDriver::renderLights(unsigned pointlightcount, bool hasShadow)
|
||||||
{
|
{
|
||||||
//RH
|
//RH
|
||||||
@ -184,7 +186,23 @@ void IrrDriver::renderLights(unsigned pointlightcount, bool hasShadow)
|
|||||||
{
|
{
|
||||||
ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_SUN));
|
ScopedGPUTimer timer(irr_driver->getGPUTimer(Q_SUN));
|
||||||
if (World::getWorld() && CVS->isShadowEnabled() && hasShadow)
|
if (World::getWorld() && CVS->isShadowEnabled() && hasShadow)
|
||||||
m_post_processing->renderShadowedSunlight(irr_driver->getSunDirection(), irr_driver->getSunColor(), sun_ortho_matrix, m_rtts->getShadowFBO().getRTT()[0]);
|
{
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
glBlendFunc(GL_ONE, GL_ONE);
|
||||||
|
glBlendEquation(GL_FUNC_ADD);
|
||||||
|
|
||||||
|
if (CVS->isESMEnabled())
|
||||||
|
{
|
||||||
|
FullScreenShader::ShadowedSunLightShaderESM::getInstance()->SetTextureUnits(irr_driver->getRenderTargetTexture(RTT_NORMAL_AND_DEPTH), irr_driver->getDepthStencilTexture(), m_rtts->getShadowFBO().getRTT()[0]);
|
||||||
|
DrawFullScreenEffect<FullScreenShader::ShadowedSunLightShaderESM>(shadowSplit[1], shadowSplit[2], shadowSplit[3], shadowSplit[4], irr_driver->getSunDirection(), irr_driver->getSunColor());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FullScreenShader::ShadowedSunLightShaderPCF::getInstance()->SetTextureUnits(irr_driver->getRenderTargetTexture(RTT_NORMAL_AND_DEPTH), irr_driver->getDepthStencilTexture(), m_rtts->getShadowFBO().getDepthTexture());
|
||||||
|
DrawFullScreenEffect<FullScreenShader::ShadowedSunLightShaderPCF>(shadowSplit[1], shadowSplit[2], shadowSplit[3], shadowSplit[4], irr_driver->getSunDirection(), irr_driver->getSunColor());
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
m_post_processing->renderSunlight(irr_driver->getSunDirection(), irr_driver->getSunColor());
|
m_post_processing->renderSunlight(irr_driver->getSunDirection(), irr_driver->getSunColor());
|
||||||
}
|
}
|
||||||
|
@ -863,10 +863,8 @@ GLuint createShadowSampler()
|
|||||||
glSamplerParameteri(id, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
glSamplerParameteri(id, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||||
glSamplerParameteri(id, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
glSamplerParameteri(id, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
glSamplerParameteri(id, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
glSamplerParameteri(id, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
glSamplerParameterf(id, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
|
||||||
int aniso = UserConfigParams::m_anisotropic;
|
glSamplerParameterf(id, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
|
||||||
if (aniso == 0) aniso = 1;
|
|
||||||
glSamplerParameterf(id, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)aniso);
|
|
||||||
return id;
|
return id;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -883,6 +881,38 @@ void BindTextureShadow(GLuint TU, GLuint tex)
|
|||||||
glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
|
glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GLuint createTrilinearClampedArray()
|
||||||
|
{
|
||||||
|
#ifdef GL_VERSION_3_3
|
||||||
|
unsigned id;
|
||||||
|
glGenSamplers(1, &id);
|
||||||
|
glSamplerParameteri(id, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glSamplerParameteri(id, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||||
|
glSamplerParameteri(id, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glSamplerParameteri(id, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
|
||||||
|
int aniso = UserConfigParams::m_anisotropic;
|
||||||
|
if (aniso == 0) aniso = 1;
|
||||||
|
glSamplerParameterf(id, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)aniso);
|
||||||
|
return id;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void BindTrilinearClampedArrayTexture(unsigned TU, unsigned tex)
|
||||||
|
{
|
||||||
|
glActiveTexture(GL_TEXTURE0 + TU);
|
||||||
|
glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
|
||||||
|
int aniso = UserConfigParams::m_anisotropic;
|
||||||
|
if (aniso == 0) aniso = 1;
|
||||||
|
glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)aniso);
|
||||||
|
}
|
||||||
|
|
||||||
void BindTextureVolume(GLuint TU, GLuint tex)
|
void BindTextureVolume(GLuint TU, GLuint tex)
|
||||||
{
|
{
|
||||||
glActiveTexture(GL_TEXTURE0 + TU);
|
glActiveTexture(GL_TEXTURE0 + TU);
|
||||||
@ -1659,7 +1689,7 @@ namespace FullScreenShader
|
|||||||
AssignSamplerNames(Program, 0, "ntex", 1, "dtex", 2, "probe");
|
AssignSamplerNames(Program, 0, "ntex", 1, "dtex", 2, "probe");
|
||||||
}
|
}
|
||||||
|
|
||||||
ShadowedSunLightShader::ShadowedSunLightShader()
|
ShadowedSunLightShaderPCF::ShadowedSunLightShaderPCF()
|
||||||
{
|
{
|
||||||
Program = LoadProgram(OBJECT,
|
Program = LoadProgram(OBJECT,
|
||||||
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
|
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
|
||||||
@ -1675,6 +1705,22 @@ namespace FullScreenShader
|
|||||||
AssignUniforms("split0", "split1", "split2", "splitmax", "direction", "col");
|
AssignUniforms("split0", "split1", "split2", "splitmax", "direction", "col");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ShadowedSunLightShaderESM::ShadowedSunLightShaderESM()
|
||||||
|
{
|
||||||
|
Program = LoadProgram(OBJECT,
|
||||||
|
GL_VERTEX_SHADER, file_manager->getAsset("shaders/screenquad.vert").c_str(),
|
||||||
|
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/decodeNormal.frag").c_str(),
|
||||||
|
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/SpecularBRDF.frag").c_str(),
|
||||||
|
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/DiffuseBRDF.frag").c_str(),
|
||||||
|
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/getPosFromUVDepth.frag").c_str(),
|
||||||
|
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/utils/SunMRP.frag").c_str(),
|
||||||
|
GL_FRAGMENT_SHADER, file_manager->getAsset("shaders/sunlightshadowesm.frag").c_str());
|
||||||
|
|
||||||
|
// Use 8 to circumvent a catalyst bug when binding sampler
|
||||||
|
AssignSamplerNames(Program, 0, "ntex", 1, "dtex", 8, "shadowtex");
|
||||||
|
AssignUniforms("split0", "split1", "split2", "splitmax", "direction", "col");
|
||||||
|
}
|
||||||
|
|
||||||
RadianceHintsConstructionShader::RadianceHintsConstructionShader()
|
RadianceHintsConstructionShader::RadianceHintsConstructionShader()
|
||||||
{
|
{
|
||||||
if (CVS->isAMDVertexShaderLayerUsable())
|
if (CVS->isAMDVertexShaderLayerUsable())
|
||||||
|
@ -426,10 +426,16 @@ public:
|
|||||||
IBLShader();
|
IBLShader();
|
||||||
};
|
};
|
||||||
|
|
||||||
class ShadowedSunLightShader : public ShaderHelperSingleton<ShadowedSunLightShader, float, float, float, float, core::vector3df, video::SColorf>, public TextureRead<Nearest_Filtered, Nearest_Filtered, Shadow_Sampler>
|
class ShadowedSunLightShaderPCF : public ShaderHelperSingleton<ShadowedSunLightShaderPCF, float, float, float, float, core::vector3df, video::SColorf>, public TextureRead<Nearest_Filtered, Nearest_Filtered, Shadow_Sampler>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ShadowedSunLightShader();
|
ShadowedSunLightShaderPCF();
|
||||||
|
};
|
||||||
|
|
||||||
|
class ShadowedSunLightShaderESM : public ShaderHelperSingleton<ShadowedSunLightShaderESM, float, float, float, float, core::vector3df, video::SColorf>, public TextureRead<Nearest_Filtered, Nearest_Filtered, Trilinear_Clamped_Array2D>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ShadowedSunLightShaderESM();
|
||||||
};
|
};
|
||||||
|
|
||||||
class RadianceHintsConstructionShader : public ShaderHelperSingleton<RadianceHintsConstructionShader, core::matrix4, core::matrix4, core::vector3df, video::SColorf>, public TextureRead<Bilinear_Filtered, Bilinear_Filtered, Bilinear_Filtered>
|
class RadianceHintsConstructionShader : public ShaderHelperSingleton<RadianceHintsConstructionShader, core::matrix4, core::matrix4, core::vector3df, video::SColorf>, public TextureRead<Bilinear_Filtered, Bilinear_Filtered, Bilinear_Filtered>
|
||||||
|
@ -221,6 +221,7 @@ enum SamplerType {
|
|||||||
Shadow_Sampler,
|
Shadow_Sampler,
|
||||||
Volume_Linear_Filtered,
|
Volume_Linear_Filtered,
|
||||||
Trilinear_cubemap,
|
Trilinear_cubemap,
|
||||||
|
Trilinear_Clamped_Array2D,
|
||||||
};
|
};
|
||||||
|
|
||||||
void setTextureSampler(GLenum, GLuint, GLuint, GLuint);
|
void setTextureSampler(GLenum, GLuint, GLuint, GLuint);
|
||||||
@ -486,6 +487,33 @@ struct BindTexture<Shadow_Sampler, tp...>
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
GLuint createTrilinearClampedArray();
|
||||||
|
|
||||||
|
template<SamplerType...tp>
|
||||||
|
struct CreateSamplers<Trilinear_Clamped_Array2D, tp...>
|
||||||
|
{
|
||||||
|
static void exec(std::vector<unsigned> &v, std::vector<GLenum> &e)
|
||||||
|
{
|
||||||
|
v.push_back(createTrilinearClampedArray());
|
||||||
|
e.push_back(GL_TEXTURE_2D_ARRAY);
|
||||||
|
CreateSamplers<tp...>::exec(v, e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void BindTrilinearClampedArrayTexture(unsigned TU, unsigned tex);
|
||||||
|
|
||||||
|
template<SamplerType...tp>
|
||||||
|
struct BindTexture<Trilinear_Clamped_Array2D, tp...>
|
||||||
|
{
|
||||||
|
template <int N, typename...Args>
|
||||||
|
static void exec(const std::vector<unsigned> &TU, GLuint TexId, Args... args)
|
||||||
|
{
|
||||||
|
BindTrilinearClampedArrayTexture(TU[N], TexId);
|
||||||
|
BindTexture<tp...>::template exec<N + 1>(TU, args...);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
template<SamplerType...tp>
|
template<SamplerType...tp>
|
||||||
class TextureRead
|
class TextureRead
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user