Add new Renderer architecture (far from complete)
Former-commit-id: 52226793d7a087dfe0523315d3303934daffee49 [formerly 9de1c04df6b371f861a2eee8bba38902ee5041cd] [formerly ecd3099df5498722f6390447f40bd3907b8e40c4 [formerly 3076df585565fc9759ab3e718270f2e5ef620840]] Former-commit-id: 92d52f967d0b088d1271afef26069e08cacd6b0f [formerly 5fe27e2ead104278951c772c2121a7b677f88d4d] Former-commit-id: fb6c2456d8edd3ec022d5d953f79fecdd4f2b8f4
This commit is contained in:
@@ -1,393 +0,0 @@
|
||||
// Copyright (C) 2015 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - Renderer module"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/Renderer/TextureSampler.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Renderer/Config.hpp>
|
||||
#include <Nazara/Renderer/Context.hpp>
|
||||
#include <Nazara/Renderer/OpenGL.hpp>
|
||||
#include <Nazara/Renderer/Renderer.hpp>
|
||||
#include <Nazara/Renderer/Texture.hpp>
|
||||
#include <unordered_map>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
namespace Nz
|
||||
{
|
||||
namespace
|
||||
{
|
||||
std::unordered_map<UInt32, GLuint> s_samplers;
|
||||
UInt8 s_maxAnisotropyLevel;
|
||||
bool s_useAnisotropicFilter;
|
||||
}
|
||||
|
||||
TextureSampler::TextureSampler() :
|
||||
m_filterMode(SamplerFilter_Default),
|
||||
m_wrapMode(SamplerWrap_Default),
|
||||
m_anisotropicLevel(0),
|
||||
m_mipmaps(true),
|
||||
m_samplerId(0)
|
||||
{
|
||||
}
|
||||
|
||||
UInt8 TextureSampler::GetAnisotropicLevel() const
|
||||
{
|
||||
return m_anisotropicLevel;
|
||||
}
|
||||
|
||||
SamplerFilter TextureSampler::GetFilterMode() const
|
||||
{
|
||||
return m_filterMode;
|
||||
}
|
||||
|
||||
SamplerWrap TextureSampler::GetWrapMode() const
|
||||
{
|
||||
return m_wrapMode;
|
||||
}
|
||||
|
||||
void TextureSampler::SetAnisotropyLevel(UInt8 anisotropyLevel)
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (!Renderer::IsInitialized())
|
||||
{
|
||||
NazaraError("Renderer module must be initialized");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (m_anisotropicLevel != anisotropyLevel)
|
||||
{
|
||||
if (anisotropyLevel > s_maxAnisotropyLevel)
|
||||
{
|
||||
NazaraWarning("Anisotropy level is over maximum anisotropy level (" + String::Number(anisotropyLevel) + " > " + String::Number(s_maxAnisotropyLevel) + ')');
|
||||
anisotropyLevel = s_maxAnisotropyLevel;
|
||||
}
|
||||
|
||||
m_anisotropicLevel = anisotropyLevel;
|
||||
m_samplerId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void TextureSampler::SetFilterMode(SamplerFilter filterMode)
|
||||
{
|
||||
if (m_filterMode != filterMode)
|
||||
{
|
||||
m_filterMode = filterMode;
|
||||
m_samplerId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void TextureSampler::SetWrapMode(SamplerWrap wrapMode)
|
||||
{
|
||||
if (m_wrapMode != wrapMode)
|
||||
{
|
||||
m_wrapMode = wrapMode;
|
||||
m_samplerId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
UInt8 TextureSampler::GetDefaultAnisotropicLevel()
|
||||
{
|
||||
return s_defaultAnisotropyLevel;
|
||||
}
|
||||
|
||||
SamplerFilter TextureSampler::GetDefaultFilterMode()
|
||||
{
|
||||
return s_defaultFilterMode;
|
||||
}
|
||||
|
||||
SamplerWrap TextureSampler::GetDefaultWrapMode()
|
||||
{
|
||||
return s_defaultWrapMode;
|
||||
}
|
||||
|
||||
void TextureSampler::SetDefaultAnisotropyLevel(UInt8 anisotropyLevel)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (anisotropyLevel == 0)
|
||||
{
|
||||
NazaraError("Default anisotropy level mode cannot be set to default value (0)");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (!Renderer::IsInitialized())
|
||||
{
|
||||
NazaraError("Renderer module must be initialized");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (anisotropyLevel > s_maxAnisotropyLevel)
|
||||
{
|
||||
NazaraWarning("Anisotropy level is over maximum anisotropy level (" + String::Number(anisotropyLevel) + " > " + String::Number(s_maxAnisotropyLevel));
|
||||
anisotropyLevel = s_maxAnisotropyLevel;
|
||||
}
|
||||
|
||||
s_defaultAnisotropyLevel = anisotropyLevel;
|
||||
|
||||
if (s_useAnisotropicFilter)
|
||||
{
|
||||
for (const std::pair<UInt32, GLuint>& pair : s_samplers)
|
||||
{
|
||||
if (((pair.first >> 5) & 0xFF) == 0)
|
||||
glSamplerParameterf(pair.second, GL_TEXTURE_MAX_ANISOTROPY_EXT, static_cast<float>(anisotropyLevel));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TextureSampler::SetDefaultFilterMode(SamplerFilter filterMode)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (filterMode == SamplerFilter_Default)
|
||||
{
|
||||
NazaraError("Default filter mode cannot be set to default enum value (SamplerFilter_Default)");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
s_defaultFilterMode = filterMode;
|
||||
|
||||
for (const std::pair<UInt32, GLuint>& pair : s_samplers)
|
||||
{
|
||||
if (((pair.first >> 1) & 0x3) == SamplerFilter_Default)
|
||||
{
|
||||
bool mipmaps = pair.first & 0x1;
|
||||
switch (filterMode)
|
||||
{
|
||||
case SamplerFilter_Bilinear:
|
||||
if (mipmaps)
|
||||
glSamplerParameteri(pair.second, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
||||
else
|
||||
glSamplerParameteri(pair.second, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
|
||||
glSamplerParameteri(pair.second, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
break;
|
||||
|
||||
case SamplerFilter_Nearest:
|
||||
if (mipmaps)
|
||||
glSamplerParameteri(pair.second, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
|
||||
else
|
||||
glSamplerParameteri(pair.second, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
|
||||
glSamplerParameteri(pair.second, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
break;
|
||||
|
||||
case SamplerFilter_Trilinear:
|
||||
if (mipmaps)
|
||||
glSamplerParameteri(pair.second, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
else
|
||||
glSamplerParameteri(pair.second, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // Filtrage bilinéaire
|
||||
|
||||
glSamplerParameteri(pair.second, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
break;
|
||||
|
||||
default:
|
||||
NazaraError("Texture filter not handled (0x" + String::Number(filterMode, 16) + ')');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TextureSampler::SetDefaultWrapMode(SamplerWrap wrapMode)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (wrapMode == SamplerWrap_Default)
|
||||
{
|
||||
NazaraError("Default wrap mode cannot be set to default enum value (SamplerWrap_Default)");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
s_defaultWrapMode = wrapMode;
|
||||
|
||||
GLenum wrapEnum = OpenGL::SamplerWrapMode[wrapMode];
|
||||
for (const std::pair<UInt32, GLuint>& pair : s_samplers)
|
||||
{
|
||||
if (((pair.first >> 3) & 0x3) == SamplerWrap_Default)
|
||||
{
|
||||
glSamplerParameteri(pair.second, GL_TEXTURE_WRAP_R, wrapEnum);
|
||||
glSamplerParameteri(pair.second, GL_TEXTURE_WRAP_T, wrapEnum);
|
||||
glSamplerParameteri(pair.second, GL_TEXTURE_WRAP_S, wrapEnum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TextureSampler::Apply(const Texture* texture) const
|
||||
{
|
||||
ImageType type = texture->GetType();
|
||||
GLenum target = OpenGL::TextureTarget[type];
|
||||
|
||||
OpenGL::BindTexture(type, texture->GetOpenGLID());
|
||||
|
||||
if (s_useAnisotropicFilter)
|
||||
{
|
||||
UInt8 anisotropyLevel = (m_anisotropicLevel == 0) ? s_defaultAnisotropyLevel : m_anisotropicLevel;
|
||||
glTexParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, static_cast<float>(anisotropyLevel));
|
||||
}
|
||||
|
||||
SamplerFilter filterMode = (m_filterMode == SamplerFilter_Default) ? s_defaultFilterMode : m_filterMode;
|
||||
switch (filterMode)
|
||||
{
|
||||
case SamplerFilter_Bilinear:
|
||||
if (m_mipmaps)
|
||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
||||
else
|
||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
|
||||
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
break;
|
||||
|
||||
case SamplerFilter_Nearest:
|
||||
if (m_mipmaps)
|
||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
|
||||
else
|
||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
|
||||
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
break;
|
||||
|
||||
case SamplerFilter_Trilinear:
|
||||
if (m_mipmaps)
|
||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
else
|
||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // Filtrage bilinéaire
|
||||
|
||||
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
break;
|
||||
|
||||
default:
|
||||
NazaraError("Texture filter not handled (0x" + String::Number(filterMode, 16) + ')');
|
||||
break;
|
||||
}
|
||||
|
||||
GLenum wrapMode = OpenGL::SamplerWrapMode[(m_wrapMode == SamplerWrap_Default) ? s_defaultWrapMode : m_wrapMode];
|
||||
switch (type)
|
||||
{
|
||||
// Notez l'absence de "break" ici
|
||||
case ImageType_3D:
|
||||
glTexParameteri(target, GL_TEXTURE_WRAP_R, wrapMode);
|
||||
case ImageType_2D:
|
||||
case ImageType_2D_Array:
|
||||
case ImageType_Cubemap:
|
||||
glTexParameteri(target, GL_TEXTURE_WRAP_T, wrapMode);
|
||||
case ImageType_1D:
|
||||
case ImageType_1D_Array:
|
||||
glTexParameteri(target, GL_TEXTURE_WRAP_S, wrapMode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void TextureSampler::Bind(unsigned int unit) const
|
||||
{
|
||||
static_assert(SamplerFilter_Max < 0x4, "Maximum sampler filter mode takes more than 2 bits");
|
||||
static_assert(SamplerWrap_Max < 0x4, "Maximum sampler wrap mode takes more than 2 bits");
|
||||
|
||||
if (!m_samplerId)
|
||||
UpdateSamplerId();
|
||||
|
||||
OpenGL::BindSampler(unit, m_samplerId);
|
||||
}
|
||||
|
||||
unsigned int TextureSampler::GetOpenGLID() const
|
||||
{
|
||||
if (!m_samplerId)
|
||||
UpdateSamplerId();
|
||||
|
||||
return m_samplerId;
|
||||
}
|
||||
|
||||
void TextureSampler::UpdateSamplerId() const
|
||||
{
|
||||
UInt32 key = (((m_mipmaps) ? 1 : 0) << 0) | // 1 bit
|
||||
(m_filterMode << 1) | // 2 bits
|
||||
(m_wrapMode << 3) | // 2 bits
|
||||
(m_anisotropicLevel << 5); // 8 bits
|
||||
|
||||
auto it = s_samplers.find(key);
|
||||
if (it == s_samplers.end())
|
||||
{
|
||||
GLuint sampler;
|
||||
glGenSamplers(1, &sampler);
|
||||
|
||||
if (s_useAnisotropicFilter)
|
||||
{
|
||||
UInt8 anisotropyLevel = (m_anisotropicLevel == 0) ? s_defaultAnisotropyLevel : m_anisotropicLevel;
|
||||
glSamplerParameterf(sampler, GL_TEXTURE_MAX_ANISOTROPY_EXT, static_cast<float>(anisotropyLevel));
|
||||
}
|
||||
|
||||
SamplerFilter filterMode = (m_filterMode == SamplerFilter_Default) ? s_defaultFilterMode : m_filterMode;
|
||||
switch (filterMode)
|
||||
{
|
||||
case SamplerFilter_Bilinear:
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, (m_mipmaps) ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR);
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
break;
|
||||
|
||||
case SamplerFilter_Nearest:
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, (m_mipmaps) ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST);
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
break;
|
||||
|
||||
case SamplerFilter_Trilinear:
|
||||
// Équivalent au filtrage bilinéaire si les mipmaps sont absentes
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, (m_mipmaps) ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR);
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
break;
|
||||
|
||||
default:
|
||||
NazaraError("Texture filter not handled (0x" + String::Number(filterMode, 16) + ')');
|
||||
break;
|
||||
}
|
||||
|
||||
GLenum wrapMode = OpenGL::SamplerWrapMode[(m_wrapMode == SamplerWrap_Default) ? s_defaultWrapMode : m_wrapMode];
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_WRAP_R, wrapMode);
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, wrapMode);
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, wrapMode);
|
||||
|
||||
s_samplers[key] = sampler;
|
||||
m_samplerId = sampler;
|
||||
}
|
||||
else
|
||||
m_samplerId = it->second;
|
||||
}
|
||||
|
||||
bool TextureSampler::UseMipmaps(bool mipmaps)
|
||||
{
|
||||
if (m_mipmaps != mipmaps)
|
||||
{
|
||||
m_mipmaps = mipmaps;
|
||||
m_samplerId = 0;
|
||||
|
||||
return true; // Renvoie true si la valeur a été changée (Donc s'il faut réappliquer le sampler)
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TextureSampler::Initialize()
|
||||
{
|
||||
s_maxAnisotropyLevel = Renderer::GetMaxAnisotropyLevel();
|
||||
s_useAnisotropicFilter = OpenGL::IsSupported(OpenGLExtension_AnisotropicFilter);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void TextureSampler::Uninitialize()
|
||||
{
|
||||
if (!s_samplers.empty())
|
||||
{
|
||||
Context::EnsureContext();
|
||||
for (const std::pair<UInt32, GLuint>& pair : s_samplers)
|
||||
OpenGL::DeleteSampler(pair.second);
|
||||
|
||||
s_samplers.clear();
|
||||
}
|
||||
}
|
||||
|
||||
UInt8 TextureSampler::s_defaultAnisotropyLevel = 1;
|
||||
SamplerFilter TextureSampler::s_defaultFilterMode = SamplerFilter_Trilinear;
|
||||
SamplerWrap TextureSampler::s_defaultWrapMode = SamplerWrap_Repeat;
|
||||
}
|
||||
Reference in New Issue
Block a user