Added texture samplers
I hate Git branchs Former-commit-id: 6978f1489cdc841d36fbcd6f1a8e01a4adbfcb8a
This commit is contained in:
parent
dc30b918a1
commit
8b67d17e38
|
|
@ -2,6 +2,7 @@
|
|||
#include <Nazara/Core/Clock.hpp>
|
||||
#include <Nazara/Math.hpp>
|
||||
#include <Nazara/Renderer.hpp>
|
||||
#include <Nazara/Renderer/TextureSampler.hpp>
|
||||
#include <Nazara/Utility.hpp>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
|
|
@ -357,6 +358,18 @@ int main()
|
|||
drawHellknight = !drawHellknight;
|
||||
break;
|
||||
|
||||
case NzKeyboard::F5:
|
||||
{
|
||||
NzTextureSampler::SetDefaultFilterMode(nzSamplerFilter_Trilinear);
|
||||
break;
|
||||
}
|
||||
|
||||
case NzKeyboard::F6:
|
||||
{
|
||||
NzTextureSampler::SetDefaultFilterMode(nzSamplerFilter_Nearest);
|
||||
break;
|
||||
}
|
||||
|
||||
/*case NzKeyboard::F5:
|
||||
{
|
||||
NzString animationName;
|
||||
|
|
@ -574,9 +587,6 @@ bool CreateCheckerMaterial(NzMaterial* material)
|
|||
return false;
|
||||
}
|
||||
|
||||
texture->SetAnisotropyLevel(NzRenderer::GetMaxAnisotropyLevel()); // Un filtrage anisotropique pour la texture
|
||||
texture->SetWrapMode(nzTextureWrap_Repeat); // Si les coordonnées de texture dépassent 1.f, la texture sera répétée
|
||||
|
||||
material->SetDiffuseMap(texture);
|
||||
|
||||
texture->SetPersistent(false);
|
||||
|
|
|
|||
|
|
@ -117,6 +117,32 @@ enum nzRendererParameter
|
|||
nzRendererParameter_Max = nzRendererParameter_Stencil
|
||||
};
|
||||
|
||||
enum nzSamplerFilter
|
||||
{
|
||||
nzSamplerFilter_Unknown = -1,
|
||||
|
||||
nzSamplerFilter_Bilinear,
|
||||
nzSamplerFilter_Nearest,
|
||||
nzSamplerFilter_Trilinear,
|
||||
|
||||
nzSamplerFilter_Default,
|
||||
|
||||
nzSamplerFilter_Max = nzSamplerFilter_Default
|
||||
};
|
||||
|
||||
enum nzSamplerWrap
|
||||
{
|
||||
nzSamplerWrap_Unknown = -1,
|
||||
|
||||
nzSamplerWrap_Clamp,
|
||||
nzSamplerWrap_MirroredRepeat,
|
||||
nzSamplerWrap_Repeat,
|
||||
|
||||
nzSamplerWrap_Default,
|
||||
|
||||
nzSamplerWrap_Max = nzSamplerWrap_Repeat
|
||||
};
|
||||
|
||||
enum nzShaderLanguage
|
||||
{
|
||||
nzShaderLanguage_Unknown = -1,
|
||||
|
|
@ -150,27 +176,4 @@ enum nzStencilOperation
|
|||
nzStencilOperation_Max = nzStencilOperation_Zero
|
||||
};
|
||||
|
||||
enum nzTextureFilter
|
||||
{
|
||||
nzTextureFilter_Unknown = -1,
|
||||
|
||||
nzTextureFilter_Bilinear,
|
||||
nzTextureFilter_Nearest,
|
||||
nzTextureFilter_Trilinear,
|
||||
|
||||
nzTextureFilter_Default,
|
||||
|
||||
nzTextureFilter_Max = nzTextureFilter_Default
|
||||
};
|
||||
|
||||
enum nzTextureWrap
|
||||
{
|
||||
nzTextureWrap_Unknown = -1,
|
||||
|
||||
nzTextureWrap_Clamp,
|
||||
nzTextureWrap_Repeat,
|
||||
|
||||
nzTextureWrap_Max = nzTextureWrap_Repeat
|
||||
};
|
||||
|
||||
#endif // NAZARA_ENUMS_RENDERER_HPP
|
||||
|
|
|
|||
|
|
@ -43,11 +43,12 @@ class NAZARA_API NzMaterial : public NzResource
|
|||
nzBlendFunc GetDstBlend() const;
|
||||
nzFaceCulling GetFaceCulling() const;
|
||||
nzFaceFilling GetFaceFilling() const;
|
||||
nzSamplerFilter GetSamplerFilter() const;
|
||||
nzSamplerWrap GetSamplerWrap() const;
|
||||
float GetShininess() const;
|
||||
NzColor GetSpecularColor() const;
|
||||
const NzTexture* GetSpecularMap() const;
|
||||
nzBlendFunc GetSrcBlend() const;
|
||||
nzTextureFilter GetTextureFilter() const;
|
||||
nzRendererComparison GetZTestCompare() const;
|
||||
|
||||
bool IsAlphaBlendingEnabled() const;
|
||||
|
|
@ -66,12 +67,12 @@ class NAZARA_API NzMaterial : public NzResource
|
|||
void SetDstBlend(nzBlendFunc func);
|
||||
void SetFaceCulling(nzFaceCulling culling);
|
||||
void SetFaceFilling(nzFaceFilling filling);
|
||||
void SetSamplerFilter(nzSamplerFilter filter);
|
||||
void SetSamplerWrap(nzSamplerWrap wrapMode);
|
||||
void SetShininess(float shininess);
|
||||
void SetSpecularColor(const NzColor& specular);
|
||||
void SetSpecularMap(const NzTexture* map);
|
||||
void SetSrcBlend(nzBlendFunc func);
|
||||
void SetTextureFilter(nzTextureFilter filter);
|
||||
void SetTextureWrap(nzTextureWrap wrapMode);
|
||||
void SetZTestCompare(nzRendererComparison compareFunc);
|
||||
|
||||
static const NzMaterial* GetDefault();
|
||||
|
|
@ -82,8 +83,8 @@ class NAZARA_API NzMaterial : public NzResource
|
|||
nzFaceCulling m_faceCulling;
|
||||
nzFaceFilling m_faceFilling;
|
||||
nzRendererComparison m_zTestCompareFunc;
|
||||
nzTextureFilter m_textureFilter;
|
||||
nzTextureWrap m_textureWrap;
|
||||
nzSamplerFilter m_samplerFilter;
|
||||
nzSamplerWrap m_samplerWrap;
|
||||
NzColor m_ambientColor;
|
||||
NzColor m_diffuseColor;
|
||||
NzColor m_specularColor;
|
||||
|
|
|
|||
|
|
@ -86,12 +86,12 @@ class NAZARA_API NzOpenGL
|
|||
static GLenum PrimitiveType[nzPrimitiveType_Max+1];
|
||||
static GLenum RendererComparison[nzRendererComparison_Max+1];
|
||||
static GLenum RendererParameter[nzRendererParameter_Max+1];
|
||||
static GLenum SamplerWrapMode[nzSamplerWrap_Max+1];
|
||||
static GLenum ShaderType[nzShaderType_Max+1];
|
||||
static GLenum StencilOperation[nzStencilOperation_Max+1];
|
||||
static GLenum TextureTarget[nzImageType_Max+1];
|
||||
static GLenum TextureTargetBinding[nzImageType_Max+1];
|
||||
static GLenum TextureTargetProxy[nzImageType_Max+1];
|
||||
static GLenum TextureWrapMode[nzTextureWrap_Max+1];
|
||||
};
|
||||
|
||||
NAZARA_API extern PFNGLACTIVETEXTUREPROC glActiveTexture;
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@
|
|||
#include <Nazara/Math/Matrix4.hpp>
|
||||
#include <Nazara/Math/Rect.hpp>
|
||||
#include <Nazara/Renderer/Enums.hpp>
|
||||
#include <Nazara/Renderer/TextureSampler.hpp>
|
||||
#include <Nazara/Utility/Enums.hpp>
|
||||
#include <map>
|
||||
|
||||
class NzColor;
|
||||
class NzContext;
|
||||
|
|
@ -42,7 +42,7 @@ class NAZARA_API NzRenderer
|
|||
static float GetLineWidth();
|
||||
//static NzMatrix4f GetMatrix(nzMatrixCombination combination);
|
||||
static NzMatrix4f GetMatrix(nzMatrixType type);
|
||||
static unsigned int GetMaxAnisotropyLevel();
|
||||
static nzUInt8 GetMaxAnisotropyLevel();
|
||||
static unsigned int GetMaxRenderTargets();
|
||||
static unsigned int GetMaxTextureUnits();
|
||||
static float GetPointSize();
|
||||
|
|
@ -77,6 +77,8 @@ class NAZARA_API NzRenderer
|
|||
static void SetStencilReferenceValue(unsigned int refValue);
|
||||
static void SetStencilZFailOperation(nzStencilOperation zfailOperation);
|
||||
static bool SetTarget(NzRenderTarget* target);
|
||||
static void SetTexture(unsigned int unit, const NzTexture* texture);
|
||||
static void SetTextureSampling(unsigned int unit, const NzTextureSampler& sampler);
|
||||
static bool SetVertexBuffer(const NzVertexBuffer* vertexBuffer);
|
||||
static void SetViewport(const NzRectui& viewport);
|
||||
|
||||
|
|
|
|||
|
|
@ -33,15 +33,13 @@ class NAZARA_API NzTexture : public NzResource, NzNonCopyable
|
|||
|
||||
bool EnableMipmapping(bool enable);
|
||||
|
||||
unsigned int GetAnisotropyLevel() const;
|
||||
nzUInt8 GetBytesPerPixel() const;
|
||||
unsigned int GetDepth() const;
|
||||
nzTextureFilter GetFilterMode() const;
|
||||
nzSamplerFilter GetFilterMode() const;
|
||||
nzPixelFormat GetFormat() const;
|
||||
unsigned int GetHeight() const;
|
||||
nzImageType GetType() const;
|
||||
unsigned int GetWidth() const;
|
||||
nzTextureWrap GetWrapMode() const;
|
||||
|
||||
bool HasMipmaps() const;
|
||||
|
||||
|
|
@ -50,17 +48,14 @@ class NAZARA_API NzTexture : public NzResource, NzNonCopyable
|
|||
bool IsTarget() const;
|
||||
bool IsValid() const;
|
||||
|
||||
bool LoadFromFile(const NzString& filePath, const NzImageParams& params = NzImageParams());
|
||||
bool LoadFromImage(const NzImage& image);
|
||||
bool LoadFromMemory(const void* data, std::size_t size, const NzImageParams& params = NzImageParams());
|
||||
bool LoadFromStream(NzInputStream& stream, const NzImageParams& params = NzImageParams());
|
||||
bool LoadFromFile(const NzString& filePath, const NzImageParams& params = NzImageParams(), bool generateMipmaps = true);
|
||||
bool LoadFromImage(const NzImage& image, bool generateMipmaps = true);
|
||||
bool LoadFromMemory(const void* data, std::size_t size, const NzImageParams& params = NzImageParams(), bool generateMipmaps = true);
|
||||
bool LoadFromStream(NzInputStream& stream, const NzImageParams& params = NzImageParams(), bool generateMipmaps = true);
|
||||
|
||||
bool Lock();
|
||||
|
||||
bool SetAnisotropyLevel(unsigned int anistropyLevel);
|
||||
bool SetFilterMode(nzTextureFilter filter);
|
||||
bool SetMipmapRange(nzUInt8 minLevel, nzUInt8 maxLevel);
|
||||
bool SetWrapMode(nzTextureWrap wrap);
|
||||
|
||||
bool Update(const NzImage& image, nzUInt8 level = 0);
|
||||
bool Update(const NzImage& image, const NzRectui& rect, unsigned int z = 0, nzUInt8 level = 0);
|
||||
|
|
@ -76,8 +71,8 @@ class NAZARA_API NzTexture : public NzResource, NzNonCopyable
|
|||
void Unlock();
|
||||
|
||||
// Fonctions OpenGL
|
||||
bool Bind() const;
|
||||
unsigned int GetOpenGLID() const;
|
||||
bool Prepare() const;
|
||||
|
||||
static unsigned int GetValidSize(unsigned int size);
|
||||
static bool IsFormatSupported(nzPixelFormat format);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,60 @@
|
|||
// Copyright (C) 2012 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
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef NAZARA_TEXTURESAMPLER_HPP
|
||||
#define NAZARA_TEXTURESAMPLER_HPP
|
||||
|
||||
#include <Nazara/Prerequesites.hpp>
|
||||
#include <Nazara/Renderer/Enums.hpp>
|
||||
|
||||
class NzTexture;
|
||||
|
||||
class NAZARA_API NzTextureSampler
|
||||
{
|
||||
friend class NzRenderer;
|
||||
|
||||
public:
|
||||
NzTextureSampler();
|
||||
NzTextureSampler(const NzTextureSampler& sampler) = default;
|
||||
|
||||
nzUInt8 GetAnisotropicLevel() const;
|
||||
nzSamplerFilter GetFilterMode() const;
|
||||
nzSamplerWrap GetWrapMode() const;
|
||||
|
||||
void SetAnisotropyLevel(nzUInt8 anisotropyLevel);
|
||||
void SetFilterMode(nzSamplerFilter filterMode);
|
||||
void SetWrapMode(nzSamplerWrap wrapMode);
|
||||
|
||||
NzTextureSampler& operator=(const NzTextureSampler& sampler) = default;
|
||||
|
||||
static nzUInt8 GetDefaultAnisotropicLevel();
|
||||
static nzSamplerFilter GetDefaultFilterMode();
|
||||
static nzSamplerWrap GetDefaultWrapMode();
|
||||
|
||||
static void SetDefaultAnisotropyLevel(nzUInt8 anisotropyLevel);
|
||||
static void SetDefaultFilterMode(nzSamplerFilter filterMode);
|
||||
static void SetDefaultWrapMode(nzSamplerWrap wrapMode);
|
||||
|
||||
private:
|
||||
void Apply(const NzTexture* texture);
|
||||
void Bind(unsigned int unit);
|
||||
bool UseMipmaps(bool mipmaps);
|
||||
|
||||
static bool Initialize();
|
||||
static void Uninitialize();
|
||||
|
||||
nzSamplerFilter m_filterMode;
|
||||
nzSamplerWrap m_wrapMode;
|
||||
nzUInt8 m_anisotropicLevel;
|
||||
bool m_mipmaps;
|
||||
mutable unsigned int m_samplerId;
|
||||
|
||||
static nzSamplerFilter s_defaultFilterMode;
|
||||
static nzSamplerWrap s_defaultWrapMode;
|
||||
static nzUInt8 s_defaultAnisotropyLevel;
|
||||
};
|
||||
|
||||
#endif // NAZARA_TEXTURESAMPLER_HPP
|
||||
|
|
@ -51,14 +51,8 @@ bool NzGLSLShader::BindTextures()
|
|||
for (auto it = m_textures.begin(); it != m_textures.end(); ++it)
|
||||
{
|
||||
TextureSlot& slot = it->second;
|
||||
if (slot.enabled && !slot.updated)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0 + slot.unit);
|
||||
if (!slot.texture->Prepare())
|
||||
NazaraWarning("Failed to prepare texture");
|
||||
|
||||
slot.updated = true;
|
||||
}
|
||||
if (slot.enabled)
|
||||
NzRenderer::SetTexture(slot.unit, slot.texture);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -145,11 +145,11 @@ void NzMaterial::Reset()
|
|||
m_dstBlend = nzBlendFunc_Zero;
|
||||
m_faceCulling = nzFaceCulling_Back;
|
||||
m_faceFilling = nzFaceFilling_Fill;
|
||||
m_samplerFilter = nzSamplerFilter_Default;
|
||||
m_samplerWrap = nzSamplerWrap_Repeat;
|
||||
m_shininess = 0;
|
||||
m_specularColor = NzColor::White;
|
||||
m_srcBlend = nzBlendFunc_One;
|
||||
m_textureFilter = nzTextureFilter_Default;
|
||||
m_textureWrap = nzTextureWrap_Repeat;
|
||||
m_zTestCompareFunc = nzRendererComparison_LessOrEqual;
|
||||
m_zTestEnabled = true;
|
||||
m_zWriteEnabled = true;
|
||||
|
|
|
|||
|
|
@ -879,6 +879,13 @@ GLenum NzOpenGL::RendererParameter[nzRendererParameter_Max+1] =
|
|||
GL_STENCIL_TEST // nzRendererParameter_Stencil
|
||||
};
|
||||
|
||||
GLenum NzOpenGL::SamplerWrapMode[nzSamplerWrap_Max+1] =
|
||||
{
|
||||
GL_CLAMP_TO_EDGE, // nzTextureWrap_Clamp
|
||||
GL_MIRRORED_REPEAT, // nzSamplerWrap_MirroredRepeat
|
||||
GL_REPEAT // nzTextureWrap_Repeat
|
||||
};
|
||||
|
||||
GLenum NzOpenGL::ShaderType[nzShaderType_Max+1] =
|
||||
{
|
||||
GL_FRAGMENT_SHADER, // nzShaderType_Fragment
|
||||
|
|
@ -928,12 +935,6 @@ GLenum NzOpenGL::TextureTargetProxy[nzImageType_Max+1] =
|
|||
GL_PROXY_TEXTURE_CUBE_MAP // nzImageType_Cubemap
|
||||
};
|
||||
|
||||
GLenum NzOpenGL::TextureWrapMode[nzTextureWrap_Max+1] =
|
||||
{
|
||||
GL_CLAMP_TO_EDGE, // nzTextureWrap_Clamp
|
||||
GL_REPEAT // nzTextureWrap_Repeat
|
||||
};
|
||||
|
||||
PFNGLACTIVETEXTUREPROC glActiveTexture = nullptr;
|
||||
PFNGLATTACHSHADERPROC glAttachShader = nullptr;
|
||||
PFNGLBEGINQUERYPROC glBeginQuery = nullptr;
|
||||
|
|
|
|||
|
|
@ -21,8 +21,10 @@
|
|||
#include <Nazara/Utility/Utility.hpp>
|
||||
#include <Nazara/Utility/VertexBuffer.hpp>
|
||||
#include <Nazara/Utility/VertexDeclaration.hpp>
|
||||
#include <map>
|
||||
#include <stdexcept>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
namespace
|
||||
|
|
@ -37,6 +39,15 @@ namespace
|
|||
nzMatrixCombination_Max = nzMatrixCombination_WorldViewProj
|
||||
};
|
||||
|
||||
struct TextureUnit
|
||||
{
|
||||
NzTextureSampler sampler;
|
||||
const NzTexture* texture = nullptr;
|
||||
bool samplerUpdated = false;
|
||||
bool textureUpdated = true;
|
||||
bool updated = true;
|
||||
};
|
||||
|
||||
NzBufferImpl* HardwareBufferFunction(NzBuffer* parent, nzBufferType type)
|
||||
{
|
||||
return new NzHardwareBuffer(parent, type);
|
||||
|
|
@ -47,6 +58,7 @@ namespace
|
|||
using VAO_Key = std::tuple<const NzContext*, const NzIndexBuffer*, const NzVertexBuffer*, const NzVertexDeclaration*>;
|
||||
|
||||
std::map<VAO_Key, unsigned int> s_vaos;
|
||||
std::vector<TextureUnit> s_textureUnits;
|
||||
NzMatrix4f s_matrix[totalMatrixCount];
|
||||
int s_matrixLocation[totalMatrixCount];
|
||||
bool s_matrixUpdated[totalMatrixCount];
|
||||
|
|
@ -59,6 +71,7 @@ namespace
|
|||
nzStencilOperation s_stencilFail;
|
||||
nzStencilOperation s_stencilPass;
|
||||
nzStencilOperation s_stencilZFail;
|
||||
nzUInt8 s_maxAnisotropyLevel;
|
||||
nzUInt32 s_stencilMask;
|
||||
const NzIndexBuffer* s_indexBuffer;
|
||||
NzRenderTarget* s_target;
|
||||
|
|
@ -69,7 +82,6 @@ namespace
|
|||
bool s_capabilities[nzRendererCap_Max+1];
|
||||
bool s_stencilFuncUpdated;
|
||||
bool s_stencilOpUpdated;
|
||||
unsigned int s_maxAnisotropyLevel;
|
||||
unsigned int s_maxRenderTarget;
|
||||
unsigned int s_maxTextureUnit;
|
||||
unsigned int s_stencilReference;
|
||||
|
|
@ -327,7 +339,7 @@ NzMatrix4f NzRenderer::GetMatrix(nzMatrixType type)
|
|||
return s_matrix[type];
|
||||
}
|
||||
|
||||
unsigned int NzRenderer::GetMaxAnisotropyLevel()
|
||||
nzUInt8 NzRenderer::GetMaxAnisotropyLevel()
|
||||
{
|
||||
return s_maxAnisotropyLevel;
|
||||
}
|
||||
|
|
@ -425,25 +437,6 @@ bool NzRenderer::Initialize(bool initializeDebugDrawer)
|
|||
s_matrixUpdated[i] = false;
|
||||
}
|
||||
|
||||
s_dstBlend = nzBlendFunc_Zero;
|
||||
s_faceCulling = nzFaceCulling_Back;
|
||||
s_faceFilling = nzFaceFilling_Fill;
|
||||
s_indexBuffer = nullptr;
|
||||
s_shader = nullptr;
|
||||
s_srcBlend = nzBlendFunc_One;
|
||||
s_stencilCompare = nzRendererComparison_Always;
|
||||
s_stencilFail = nzStencilOperation_Keep;
|
||||
s_stencilFuncUpdated = true;
|
||||
s_stencilMask = 0xFFFFFFFF;
|
||||
s_stencilOpUpdated = true;
|
||||
s_stencilPass = nzStencilOperation_Keep;
|
||||
s_stencilReference = 0;
|
||||
s_stencilZFail = nzStencilOperation_Keep;
|
||||
s_target = nullptr;
|
||||
s_vaoUpdated = false;
|
||||
s_vertexBuffer = nullptr;
|
||||
s_vertexDeclaration = nullptr;
|
||||
|
||||
// Récupération des capacités d'OpenGL
|
||||
s_capabilities[nzRendererCap_AnisotropicFilter] = NzOpenGL::IsSupported(nzOpenGLExtension_AnisotropicFilter);
|
||||
s_capabilities[nzRendererCap_FP64] = NzOpenGL::IsSupported(nzOpenGLExtension_FP64);
|
||||
|
|
@ -460,10 +453,10 @@ bool NzRenderer::Initialize(bool initializeDebugDrawer)
|
|||
|
||||
if (s_capabilities[nzRendererCap_AnisotropicFilter])
|
||||
{
|
||||
GLint maxAnisotropy;
|
||||
glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropy);
|
||||
GLfloat maxAnisotropy;
|
||||
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropy);
|
||||
|
||||
s_maxAnisotropyLevel = static_cast<unsigned int>(maxAnisotropy);
|
||||
s_maxAnisotropyLevel = static_cast<nzUInt8>(maxAnisotropy);
|
||||
}
|
||||
else
|
||||
s_maxAnisotropyLevel = 1;
|
||||
|
|
@ -495,11 +488,33 @@ bool NzRenderer::Initialize(bool initializeDebugDrawer)
|
|||
else
|
||||
s_maxTextureUnit = 1;
|
||||
|
||||
s_dstBlend = nzBlendFunc_Zero;
|
||||
s_faceCulling = nzFaceCulling_Back;
|
||||
s_faceFilling = nzFaceFilling_Fill;
|
||||
s_indexBuffer = nullptr;
|
||||
s_shader = nullptr;
|
||||
s_srcBlend = nzBlendFunc_One;
|
||||
s_stencilCompare = nzRendererComparison_Always;
|
||||
s_stencilFail = nzStencilOperation_Keep;
|
||||
s_stencilFuncUpdated = true;
|
||||
s_stencilMask = 0xFFFFFFFF;
|
||||
s_stencilOpUpdated = true;
|
||||
s_stencilPass = nzStencilOperation_Keep;
|
||||
s_stencilReference = 0;
|
||||
s_stencilZFail = nzStencilOperation_Keep;
|
||||
s_target = nullptr;
|
||||
s_textureUnits.resize(s_maxTextureUnit);
|
||||
s_vaoUpdated = false;
|
||||
s_vertexBuffer = nullptr;
|
||||
s_vertexDeclaration = nullptr;
|
||||
|
||||
NzBuffer::SetBufferFunction(nzBufferStorage_Hardware, HardwareBufferFunction);
|
||||
|
||||
if (initializeDebugDrawer && !NzDebugDrawer::Initialize())
|
||||
NazaraWarning("Failed to initialize debug drawer"); // Non-critique
|
||||
|
||||
NzTextureSampler::Initialize();
|
||||
|
||||
// Loaders
|
||||
NzLoaders_Texture_Register();
|
||||
|
||||
|
|
@ -927,6 +942,47 @@ bool NzRenderer::SetTarget(NzRenderTarget* target)
|
|||
return true;
|
||||
}
|
||||
|
||||
void NzRenderer::SetTexture(unsigned int unit, const NzTexture* texture)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (unit >= s_textureUnits.size())
|
||||
{
|
||||
NazaraError("Texture unit out of range (" + NzString::Number(unit) + " >= " + NzString::Number(s_textureUnits.size()) + ')');
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!texture) // Pas besoin de mettre à jour s'il n'y a pas de texture
|
||||
return;
|
||||
|
||||
if (s_textureUnits[unit].texture != texture)
|
||||
{
|
||||
s_textureUnits[unit].texture = texture;
|
||||
s_textureUnits[unit].textureUpdated = false;
|
||||
|
||||
if (s_textureUnits[unit].sampler.UseMipmaps(texture->HasMipmaps()))
|
||||
s_textureUnits[unit].samplerUpdated = false;
|
||||
|
||||
s_textureUnits[unit].updated = false;
|
||||
}
|
||||
}
|
||||
|
||||
void NzRenderer::SetTextureSampling(unsigned int unit, const NzTextureSampler& sampler)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (unit >= s_textureUnits.size())
|
||||
{
|
||||
NazaraError("Texture unit out of range (" + NzString::Number(unit) + " >= " + NzString::Number(s_textureUnits.size()) + ')');
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
s_textureUnits[unit].sampler = sampler;
|
||||
s_textureUnits[unit].sampler.UseMipmaps(s_textureUnits[unit].texture->HasMipmaps());
|
||||
s_textureUnits[unit].samplerUpdated = false;
|
||||
s_textureUnits[unit].updated = false;
|
||||
}
|
||||
|
||||
bool NzRenderer::SetVertexBuffer(const NzVertexBuffer* vertexBuffer)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
|
|
@ -996,10 +1052,13 @@ void NzRenderer::Uninitialize()
|
|||
// Libération du module
|
||||
s_moduleReferenceCounter = 0;
|
||||
|
||||
s_textureUnits.clear();
|
||||
|
||||
// Loaders
|
||||
NzLoaders_Texture_Unregister();
|
||||
|
||||
NzDebugDrawer::Uninitialize();
|
||||
NzTextureSampler::Uninitialize();
|
||||
|
||||
NzContext::EnsureContext();
|
||||
|
||||
|
|
@ -1038,9 +1097,56 @@ bool NzRenderer::EnsureStateUpdate()
|
|||
|
||||
// Il est plus rapide d'opérer sur l'implémentation du shader directement
|
||||
NzShaderImpl* shaderImpl = s_shader->m_impl;
|
||||
shaderImpl->BindTextures();
|
||||
|
||||
if (!shaderImpl->BindTextures())
|
||||
NazaraWarning("Failed to bind textures");
|
||||
static const bool useSamplerObjects = NzOpenGL::IsSupported(nzOpenGLExtension_SamplerObjects);
|
||||
|
||||
if (useSamplerObjects)
|
||||
{
|
||||
for (unsigned int i = 0; i < s_textureUnits.size(); ++i)
|
||||
{
|
||||
TextureUnit& unit = s_textureUnits[i];
|
||||
|
||||
if (!unit.updated)
|
||||
{
|
||||
if (!unit.textureUpdated)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0 + i);
|
||||
unit.texture->Bind();
|
||||
|
||||
unit.textureUpdated = true;
|
||||
}
|
||||
|
||||
if (!unit.samplerUpdated)
|
||||
{
|
||||
unit.sampler.Bind(i);
|
||||
unit.samplerUpdated = true;
|
||||
}
|
||||
|
||||
unit.updated = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned int i = 0; i < s_textureUnits.size(); ++i)
|
||||
{
|
||||
TextureUnit& unit = s_textureUnits[i];
|
||||
|
||||
if (!unit.updated)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0 + i);
|
||||
|
||||
unit.texture->Bind();
|
||||
unit.textureUpdated = true;
|
||||
|
||||
unit.sampler.Apply(unit.texture);
|
||||
unit.samplerUpdated = true;
|
||||
|
||||
unit.updated = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i <= nzMatrixType_Max; ++i)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -347,11 +347,6 @@ bool NzTexture::Create(nzImageType type, nzPixelFormat format, unsigned int widt
|
|||
|
||||
m_impl = impl;
|
||||
|
||||
// Paramètres par défaut
|
||||
SetFilterMode(nzTextureFilter_Nearest);
|
||||
SetMipmapRange(0, m_impl->levelCount);
|
||||
SetWrapMode(nzTextureWrap_Repeat);
|
||||
|
||||
if (m_impl->levelCount > 1U)
|
||||
EnableMipmapping(true);
|
||||
|
||||
|
|
@ -445,15 +440,15 @@ bool NzTexture::EnableMipmapping(bool enable)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (m_impl->levelCount == 1)
|
||||
return true;
|
||||
|
||||
if (!IsMipmappingSupported())
|
||||
{
|
||||
NazaraError("Mipmapping not supported");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_impl->levelCount == 1) // Transformation d'une texture sans mipmaps vers une texture avec mipmaps
|
||||
m_impl->levelCount = NzImage::GetMaxLevel(m_impl->width, m_impl->height, m_impl->depth);
|
||||
|
||||
if (!m_impl->mipmapping && enable)
|
||||
m_impl->mipmapsUpdated = false;
|
||||
|
||||
|
|
@ -462,29 +457,6 @@ bool NzTexture::EnableMipmapping(bool enable)
|
|||
return true;
|
||||
}
|
||||
|
||||
unsigned int NzTexture::GetAnisotropyLevel() const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Texture must be valid");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!NzOpenGL::IsSupported(nzOpenGLExtension_AnisotropicFilter))
|
||||
return 1;
|
||||
|
||||
LockTexture(m_impl);
|
||||
|
||||
GLint anisotropyLevel;
|
||||
glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &anisotropyLevel);
|
||||
|
||||
UnlockTexture(m_impl);
|
||||
|
||||
return anisotropyLevel;
|
||||
}
|
||||
|
||||
nzUInt8 NzTexture::GetBytesPerPixel() const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
|
|
@ -511,43 +483,6 @@ unsigned int NzTexture::GetDepth() const
|
|||
return m_impl->depth;
|
||||
}
|
||||
|
||||
nzTextureFilter NzTexture::GetFilterMode() const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Texture must be valid");
|
||||
return nzTextureFilter_Unknown;
|
||||
}
|
||||
#endif
|
||||
|
||||
LockTexture(m_impl);
|
||||
|
||||
GLint value;
|
||||
glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, &value);
|
||||
|
||||
UnlockTexture(m_impl);
|
||||
|
||||
GLenum filterMode = static_cast<GLenum>(value);
|
||||
switch (filterMode)
|
||||
{
|
||||
case GL_LINEAR:
|
||||
case GL_LINEAR_MIPMAP_NEAREST:
|
||||
return nzTextureFilter_Bilinear;
|
||||
|
||||
case GL_NEAREST:
|
||||
case GL_NEAREST_MIPMAP_NEAREST:
|
||||
return nzTextureFilter_Nearest;
|
||||
|
||||
case GL_LINEAR_MIPMAP_LINEAR:
|
||||
return nzTextureFilter_Trilinear;
|
||||
|
||||
default:
|
||||
NazaraInternalError("OpenGL filter mode not handled (0x" + NzString::Number(filterMode, 16) + ')');
|
||||
return nzTextureFilter_Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
nzPixelFormat NzTexture::GetFormat() const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
|
|
@ -600,38 +535,6 @@ unsigned int NzTexture::GetWidth() const
|
|||
return m_impl->width;
|
||||
}
|
||||
|
||||
nzTextureWrap NzTexture::GetWrapMode() const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Texture must be valid");
|
||||
return nzTextureWrap_Unknown;
|
||||
}
|
||||
#endif
|
||||
|
||||
LockTexture(m_impl);
|
||||
|
||||
GLint value;
|
||||
glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, &value);
|
||||
|
||||
UnlockTexture(m_impl);
|
||||
|
||||
GLenum wrapMode = static_cast<GLenum>(value);
|
||||
switch (wrapMode)
|
||||
{
|
||||
case GL_CLAMP_TO_EDGE:
|
||||
return nzTextureWrap_Clamp;
|
||||
|
||||
case GL_REPEAT:
|
||||
return nzTextureWrap_Repeat;
|
||||
|
||||
default:
|
||||
NazaraInternalError("OpenGL wrap mode not handled (0x" + NzString::Number(wrapMode, 16) + ')');
|
||||
return nzTextureWrap_Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
bool NzTexture::HasMipmaps() const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
|
|
@ -689,7 +592,7 @@ bool NzTexture::IsValid() const
|
|||
return m_impl != nullptr;
|
||||
}
|
||||
|
||||
bool NzTexture::LoadFromFile(const NzString& filePath, const NzImageParams& params)
|
||||
bool NzTexture::LoadFromFile(const NzString& filePath, const NzImageParams& params, bool generateMipmaps)
|
||||
{
|
||||
NzImage image;
|
||||
if (!image.LoadFromFile(filePath, params))
|
||||
|
|
@ -698,10 +601,10 @@ bool NzTexture::LoadFromFile(const NzString& filePath, const NzImageParams& para
|
|||
return false;
|
||||
}
|
||||
|
||||
return LoadFromImage(image);
|
||||
return LoadFromImage(image, generateMipmaps);
|
||||
}
|
||||
|
||||
bool NzTexture::LoadFromImage(const NzImage& image)
|
||||
bool NzTexture::LoadFromImage(const NzImage& image, bool generateMipmaps)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!image.IsValid())
|
||||
|
|
@ -741,13 +644,14 @@ bool NzTexture::LoadFromImage(const NzImage& image)
|
|||
}
|
||||
|
||||
nzImageType type = newImage.GetType();
|
||||
if (!Create(type, format, newImage.GetWidth(), newImage.GetHeight(), newImage.GetDepth(), newImage.GetLevelCount(), true))
|
||||
nzUInt8 levelCount = newImage.GetLevelCount();
|
||||
if (!Create(type, format, newImage.GetWidth(), newImage.GetHeight(), newImage.GetDepth(), (generateMipmaps) ? 0xFF : levelCount, true))
|
||||
{
|
||||
NazaraError("Failed to create texture");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (nzUInt8 level = 0; level < m_impl->levelCount; ++level)
|
||||
for (nzUInt8 level = 0; level < levelCount; ++level)
|
||||
{
|
||||
if (!Update(newImage.GetConstPixels(level), level))
|
||||
{
|
||||
|
|
@ -763,7 +667,7 @@ bool NzTexture::LoadFromImage(const NzImage& image)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool NzTexture::LoadFromMemory(const void* data, std::size_t size, const NzImageParams& params)
|
||||
bool NzTexture::LoadFromMemory(const void* data, std::size_t size, const NzImageParams& params, bool generateMipmaps)
|
||||
{
|
||||
NzImage image;
|
||||
if (!image.LoadFromMemory(data, size, params))
|
||||
|
|
@ -772,10 +676,10 @@ bool NzTexture::LoadFromMemory(const void* data, std::size_t size, const NzImage
|
|||
return false;
|
||||
}
|
||||
|
||||
return LoadFromImage(image);
|
||||
return LoadFromImage(image, generateMipmaps);
|
||||
}
|
||||
|
||||
bool NzTexture::LoadFromStream(NzInputStream& stream, const NzImageParams& params)
|
||||
bool NzTexture::LoadFromStream(NzInputStream& stream, const NzImageParams& params, bool generateMipmaps)
|
||||
{
|
||||
NzImage image;
|
||||
if (!image.LoadFromStream(stream, params))
|
||||
|
|
@ -784,7 +688,7 @@ bool NzTexture::LoadFromStream(NzInputStream& stream, const NzImageParams& param
|
|||
return false;
|
||||
}
|
||||
|
||||
return LoadFromImage(image);
|
||||
return LoadFromImage(image, generateMipmaps);
|
||||
}
|
||||
|
||||
bool NzTexture::Lock()
|
||||
|
|
@ -802,84 +706,6 @@ bool NzTexture::Lock()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool NzTexture::SetAnisotropyLevel(unsigned int anistropyLevel)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Texture must be valid");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (anistropyLevel > 1 && !NzOpenGL::IsSupported(nzOpenGLExtension_AnisotropicFilter))
|
||||
{
|
||||
NazaraError("Anisotropic filter not supported");
|
||||
return false;
|
||||
}
|
||||
|
||||
LockTexture(m_impl);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anistropyLevel);
|
||||
|
||||
UnlockTexture(m_impl);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzTexture::SetFilterMode(nzTextureFilter filter)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Texture must be valid");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (filter == nzTextureFilter_Trilinear && m_impl->levelCount == 1)
|
||||
{
|
||||
NazaraError("Trilinear filter set wihout mipmaps");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
LockTexture(m_impl);
|
||||
|
||||
GLenum target = NzOpenGL::TextureTarget[m_impl->type];
|
||||
switch (filter)
|
||||
{
|
||||
case nzTextureFilter_Bilinear:
|
||||
if (m_impl->mipmapping > 1)
|
||||
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 nzTextureFilter_Nearest:
|
||||
if (m_impl->mipmapping > 1)
|
||||
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 nzTextureFilter_Trilinear:
|
||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
break;
|
||||
|
||||
default:
|
||||
NazaraError("Texture filter not handled (0x" + NzString::Number(filter, 16) + ')');
|
||||
}
|
||||
|
||||
UnlockTexture(m_impl);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzTexture::SetMipmapRange(nzUInt8 minLevel, nzUInt8 maxLevel)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
|
|
@ -904,59 +730,7 @@ bool NzTexture::SetMipmapRange(nzUInt8 minLevel, nzUInt8 maxLevel)
|
|||
|
||||
LockTexture(m_impl);
|
||||
glTexParameteri(NzOpenGL::TextureTarget[m_impl->type], GL_TEXTURE_BASE_LEVEL, minLevel);
|
||||
glTexParameteri(NzOpenGL::TextureTarget[m_impl->type], GL_TEXTURE_MAX_LEVEL, std::min(m_impl->levelCount, maxLevel));
|
||||
UnlockTexture(m_impl);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NzTexture::SetWrapMode(nzTextureWrap wrap)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Texture must be valid");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
GLenum wrapMode;
|
||||
switch (wrap)
|
||||
{
|
||||
case nzTextureWrap_Clamp:
|
||||
wrapMode = GL_CLAMP_TO_EDGE;
|
||||
break;
|
||||
|
||||
case nzTextureWrap_Repeat:
|
||||
wrapMode = GL_REPEAT;
|
||||
break;
|
||||
|
||||
default:
|
||||
NazaraError("Texture wrap mode not handled (0x" + NzString::Number(wrap, 16) + ')');
|
||||
return false;
|
||||
}
|
||||
|
||||
LockTexture(m_impl);
|
||||
|
||||
GLenum target = NzOpenGL::TextureTarget[m_impl->type];
|
||||
switch (m_impl->type)
|
||||
{
|
||||
// Notez l'absence de "break" ici
|
||||
case nzImageType_3D:
|
||||
glTexParameteri(target, GL_TEXTURE_WRAP_R, wrapMode);
|
||||
case nzImageType_2D:
|
||||
case nzImageType_2D_Array:
|
||||
case nzImageType_Cubemap:
|
||||
glTexParameteri(target, GL_TEXTURE_WRAP_T, wrapMode);
|
||||
case nzImageType_1D:
|
||||
case nzImageType_1D_Array:
|
||||
glTexParameteri(target, GL_TEXTURE_WRAP_S, wrapMode);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
glTexParameteri(NzOpenGL::TextureTarget[m_impl->type], GL_TEXTURE_MAX_LEVEL, maxLevel);
|
||||
UnlockTexture(m_impl);
|
||||
|
||||
return true;
|
||||
|
|
@ -1411,20 +1185,7 @@ void NzTexture::Unlock()
|
|||
UnlockTexture(m_impl);
|
||||
}
|
||||
|
||||
unsigned int NzTexture::GetOpenGLID() const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Texture must be valid");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->id;
|
||||
}
|
||||
|
||||
bool NzTexture::Prepare() const
|
||||
bool NzTexture::Bind() const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (lockedLevel[m_impl->type] > 0)
|
||||
|
|
@ -1445,6 +1206,19 @@ bool NzTexture::Prepare() const
|
|||
return true;
|
||||
}
|
||||
|
||||
unsigned int NzTexture::GetOpenGLID() const
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (!m_impl)
|
||||
{
|
||||
NazaraError("Texture must be valid");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return m_impl->id;
|
||||
}
|
||||
|
||||
unsigned int NzTexture::GetValidSize(unsigned int size)
|
||||
{
|
||||
if (NzRenderer::HasCapability(nzRendererCap_TextureNPOT))
|
||||
|
|
|
|||
|
|
@ -0,0 +1,382 @@
|
|||
// Copyright (C) 2012 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/OpenGL.hpp>
|
||||
#include <Nazara/Renderer/TextureSampler.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Renderer/Config.hpp>
|
||||
#include <Nazara/Renderer/Renderer.hpp>
|
||||
#include <Nazara/Renderer/Texture.hpp>
|
||||
#include <Nazara/Renderer/Debug.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
std::map<nzUInt32, GLuint> s_samplers;
|
||||
nzUInt8 s_maxAnisotropyLevel;
|
||||
bool s_useAnisotropicFilter;
|
||||
}
|
||||
|
||||
NzTextureSampler::NzTextureSampler() :
|
||||
m_filterMode(nzSamplerFilter_Default),
|
||||
m_wrapMode(nzSamplerWrap_Default),
|
||||
m_anisotropicLevel(0),
|
||||
m_mipmaps(true),
|
||||
m_samplerId(0)
|
||||
{
|
||||
}
|
||||
|
||||
nzUInt8 NzTextureSampler::GetAnisotropicLevel() const
|
||||
{
|
||||
return m_anisotropicLevel;
|
||||
}
|
||||
|
||||
nzSamplerFilter NzTextureSampler::GetFilterMode() const
|
||||
{
|
||||
return m_filterMode;
|
||||
}
|
||||
|
||||
nzSamplerWrap NzTextureSampler::GetWrapMode() const
|
||||
{
|
||||
return m_wrapMode;
|
||||
}
|
||||
|
||||
void NzTextureSampler::SetAnisotropyLevel(nzUInt8 anisotropyLevel)
|
||||
{
|
||||
#ifdef NAZARA_DEBUG
|
||||
if (!NzRenderer::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 (" + NzString::Number(anisotropyLevel) + " > " + NzString::Number(s_maxAnisotropyLevel));
|
||||
anisotropyLevel = s_maxAnisotropyLevel;
|
||||
}
|
||||
|
||||
m_anisotropicLevel = anisotropyLevel;
|
||||
m_samplerId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void NzTextureSampler::SetFilterMode(nzSamplerFilter filterMode)
|
||||
{
|
||||
if (m_filterMode != filterMode)
|
||||
{
|
||||
m_filterMode = filterMode;
|
||||
m_samplerId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void NzTextureSampler::SetWrapMode(nzSamplerWrap wrapMode)
|
||||
{
|
||||
if (m_wrapMode != wrapMode)
|
||||
{
|
||||
m_wrapMode = wrapMode;
|
||||
m_samplerId = 0;
|
||||
}
|
||||
}
|
||||
|
||||
nzUInt8 NzTextureSampler::GetDefaultAnisotropicLevel()
|
||||
{
|
||||
return s_defaultAnisotropyLevel;
|
||||
}
|
||||
|
||||
nzSamplerFilter NzTextureSampler::GetDefaultFilterMode()
|
||||
{
|
||||
return s_defaultFilterMode;
|
||||
}
|
||||
|
||||
nzSamplerWrap NzTextureSampler::GetDefaultWrapMode()
|
||||
{
|
||||
return s_defaultWrapMode;
|
||||
}
|
||||
|
||||
void NzTextureSampler::SetDefaultAnisotropyLevel(nzUInt8 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 (!NzRenderer::IsInitialized())
|
||||
{
|
||||
NazaraError("Renderer module must be initialized");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (anisotropyLevel > s_maxAnisotropyLevel)
|
||||
{
|
||||
NazaraWarning("Anisotropy level is over maximum anisotropy level (" + NzString::Number(anisotropyLevel) + " > " + NzString::Number(s_maxAnisotropyLevel));
|
||||
anisotropyLevel = s_maxAnisotropyLevel;
|
||||
}
|
||||
|
||||
s_defaultAnisotropyLevel = anisotropyLevel;
|
||||
|
||||
if (s_useAnisotropicFilter)
|
||||
{
|
||||
for (auto pair : s_samplers)
|
||||
{
|
||||
if (((pair.first >> 5) & 0xFF) == 0)
|
||||
glSamplerParameterf(pair.second, GL_TEXTURE_MAX_ANISOTROPY_EXT, static_cast<float>(anisotropyLevel));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NzTextureSampler::SetDefaultFilterMode(nzSamplerFilter filterMode)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (filterMode == nzSamplerFilter_Default)
|
||||
{
|
||||
NazaraError("Default filter mode cannot be set to default enum value (nzSamplerFilter_Default)");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
s_defaultFilterMode = filterMode;
|
||||
|
||||
for (auto pair : s_samplers)
|
||||
{
|
||||
if (((pair.first >> 1) & 0x3) == nzSamplerFilter_Default)
|
||||
{
|
||||
bool mipmaps = pair.first & 0x1;
|
||||
switch (filterMode)
|
||||
{
|
||||
case nzSamplerFilter_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 nzSamplerFilter_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 nzSamplerFilter_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" + NzString::Number(filterMode, 16) + ')');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NzTextureSampler::SetDefaultWrapMode(nzSamplerWrap wrapMode)
|
||||
{
|
||||
#if NAZARA_RENDERER_SAFE
|
||||
if (wrapMode == nzSamplerWrap_Default)
|
||||
{
|
||||
NazaraError("Default wrap mode cannot be set to default enum value (nzSamplerWrap_Default)");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
s_defaultWrapMode = wrapMode;
|
||||
|
||||
GLenum wrapEnum = NzOpenGL::SamplerWrapMode[wrapMode];
|
||||
for (auto pair : s_samplers)
|
||||
{
|
||||
if (((pair.first >> 3) & 0x3) == nzSamplerWrap_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 NzTextureSampler::Apply(const NzTexture* texture)
|
||||
{
|
||||
// On considère que la texture est déjà active lors de l'appel à cette fonction
|
||||
GLenum target = NzOpenGL::TextureTarget[texture->GetType()];
|
||||
|
||||
if (s_useAnisotropicFilter)
|
||||
{
|
||||
nzUInt8 anisotropyLevel = (m_anisotropicLevel == 0) ? s_defaultAnisotropyLevel : m_anisotropicLevel;
|
||||
glTexParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, static_cast<float>(anisotropyLevel));
|
||||
}
|
||||
|
||||
nzSamplerFilter filterMode = (m_filterMode == nzSamplerFilter_Default) ? s_defaultFilterMode : m_filterMode;
|
||||
switch (filterMode)
|
||||
{
|
||||
case nzSamplerFilter_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 nzSamplerFilter_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 nzSamplerFilter_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" + NzString::Number(filterMode, 16) + ')');
|
||||
break;
|
||||
}
|
||||
|
||||
GLenum wrapMode = NzOpenGL::SamplerWrapMode[(m_wrapMode == nzSamplerWrap_Default) ? s_defaultWrapMode : m_wrapMode];
|
||||
switch (texture->GetType())
|
||||
{
|
||||
// Notez l'absence de "break" ici
|
||||
case nzImageType_3D:
|
||||
glTexParameteri(target, GL_TEXTURE_WRAP_R, wrapMode);
|
||||
case nzImageType_2D:
|
||||
case nzImageType_2D_Array:
|
||||
case nzImageType_Cubemap:
|
||||
glTexParameteri(target, GL_TEXTURE_WRAP_T, wrapMode);
|
||||
case nzImageType_1D:
|
||||
case nzImageType_1D_Array:
|
||||
glTexParameteri(target, GL_TEXTURE_WRAP_S, wrapMode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void NzTextureSampler::Bind(unsigned int unit)
|
||||
{
|
||||
static_assert(nzSamplerFilter_Max < 0x4, "Maximum sampler filter mode takes more than 2 bits");
|
||||
static_assert(nzSamplerWrap_Max < 0x4, "Maximum sampler wrap mode takes more than 2 bits");
|
||||
|
||||
if (!m_samplerId)
|
||||
{
|
||||
nzUInt32 key = (m_mipmaps << 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)
|
||||
{
|
||||
nzUInt8 anisotropyLevel = (m_anisotropicLevel == 0) ? s_defaultAnisotropyLevel : m_anisotropicLevel;
|
||||
glSamplerParameterf(sampler, GL_TEXTURE_MAX_ANISOTROPY_EXT, static_cast<float>(anisotropyLevel));
|
||||
}
|
||||
|
||||
nzSamplerFilter filterMode = (m_filterMode == nzSamplerFilter_Default) ? s_defaultFilterMode : m_filterMode;
|
||||
switch (filterMode)
|
||||
{
|
||||
case nzSamplerFilter_Bilinear:
|
||||
if (m_mipmaps)
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
||||
else
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
break;
|
||||
|
||||
case nzSamplerFilter_Nearest:
|
||||
if (m_mipmaps)
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
|
||||
else
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
break;
|
||||
|
||||
case nzSamplerFilter_Trilinear:
|
||||
if (m_mipmaps)
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
else
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // Filtrage bilinéaire
|
||||
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
break;
|
||||
|
||||
default:
|
||||
NazaraError("Texture filter not handled (0x" + NzString::Number(filterMode, 16) + ')');
|
||||
break;
|
||||
}
|
||||
|
||||
GLenum wrapMode = NzOpenGL::SamplerWrapMode[(m_wrapMode == nzSamplerWrap_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;
|
||||
}
|
||||
|
||||
glBindSampler(unit, m_samplerId);
|
||||
}
|
||||
|
||||
bool NzTextureSampler::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 NzTextureSampler::Initialize()
|
||||
{
|
||||
s_maxAnisotropyLevel = NzRenderer::GetMaxAnisotropyLevel();
|
||||
s_useAnisotropicFilter = NzOpenGL::IsSupported(nzOpenGLExtension_AnisotropicFilter);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NzTextureSampler::Uninitialize()
|
||||
{
|
||||
for (auto it = s_samplers.begin(); it != s_samplers.end(); ++it)
|
||||
glDeleteSamplers(1, &it->second);
|
||||
|
||||
s_samplers.clear();
|
||||
}
|
||||
|
||||
nzUInt8 NzTextureSampler::s_defaultAnisotropyLevel = 1;
|
||||
nzSamplerFilter NzTextureSampler::s_defaultFilterMode = nzSamplerFilter_Trilinear;
|
||||
nzSamplerWrap NzTextureSampler::s_defaultWrapMode = nzSamplerWrap_Repeat;
|
||||
Loading…
Reference in New Issue