Added texture samplers

I hate Git branchs


Former-commit-id: 6978f1489cdc841d36fbcd6f1a8e01a4adbfcb8a
This commit is contained in:
Lynix
2012-12-17 14:56:29 +01:00
parent dc30b918a1
commit 8b67d17e38
13 changed files with 669 additions and 341 deletions

View File

@@ -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)
{