Fixed rendering with OpenGL core profile

Added (automatic) support of Vertex Arrays Objects (VAO) to fix
rendering with an OpenGL core profile (OpenGL 3.2 require the use of
VAOs)
Added level check to NzImage::GetDepth/Height/Size/Width
Fixed occlussion query support not correctly setted
This commit is contained in:
Lynix 2012-05-31 18:18:28 +02:00
parent 3720967802
commit f4b194f6fe
9 changed files with 220 additions and 122 deletions

View File

@ -62,24 +62,18 @@
#if NAZARA_CORE_WINDOWS_VISTA #if NAZARA_CORE_WINDOWS_VISTA
// Version de Windows minimale : Vista // Version de Windows minimale : Vista
#if defined(_WIN32_WINNT) #define NAZARA_WINNT 0x0600
#if _WIN32_WINNT < 0x0600 #else
#undef _WIN32_WINNT #define NAZARA_WINNT 0x0501
#define _WIN32_WINNT 0x0600 #endif
#endif
#else #if defined(_WIN32_WINNT)
#define _WIN32_WINNT 0x0600 #if _WIN32_WINNT < NAZARA_WINNT
#undef _WIN32_WINNT
#define _WIN32_WINNT NAZARA_WINNT
#endif #endif
#else #else
// Version de Windows minimale : XP #define _WIN32_WINNT NAZARA_WINNT
#if defined(_WIN32_WINNT)
#if _WIN32_WINNT < 0x0501
#undef _WIN32_WINNT
#define _WIN32_WINNT 0x0501
#endif
#else
#define _WIN32_WINNT 0x0501
#endif
#endif #endif
#endif #endif
#elif defined(linux) || defined(__linux) #elif defined(linux) || defined(__linux)

View File

@ -35,8 +35,9 @@ class NAZARA_API NzOpenGL
{ {
AnisotropicFilter, AnisotropicFilter,
FP64, FP64,
Framebuffer_Object, FrameBufferObject,
Texture3D, Texture3D,
VertexArrayObject,
Count Count
}; };
@ -56,6 +57,7 @@ NAZARA_API extern PFNGLBINDBUFFERPROC glBindBuffer;
NAZARA_API extern PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer; NAZARA_API extern PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer;
NAZARA_API extern PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer; NAZARA_API extern PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer;
NAZARA_API extern PFNGLBINDTEXTUREPROC glBindTexture; NAZARA_API extern PFNGLBINDTEXTUREPROC glBindTexture;
NAZARA_API extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
NAZARA_API extern PFNGLBLENDFUNCPROC glBlendFunc; NAZARA_API extern PFNGLBLENDFUNCPROC glBlendFunc;
NAZARA_API extern PFNGLBUFFERDATAPROC glBufferData; NAZARA_API extern PFNGLBUFFERDATAPROC glBufferData;
NAZARA_API extern PFNGLBUFFERSUBDATAPROC glBufferSubData; NAZARA_API extern PFNGLBUFFERSUBDATAPROC glBufferSubData;
@ -76,6 +78,7 @@ NAZARA_API extern PFNGLDELETEQUERIESPROC glDeleteQueries;
NAZARA_API extern PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers; NAZARA_API extern PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers;
NAZARA_API extern PFNGLDELETESHADERPROC glDeleteShader; NAZARA_API extern PFNGLDELETESHADERPROC glDeleteShader;
NAZARA_API extern PFNGLDELETETEXTURESPROC glDeleteTextures; NAZARA_API extern PFNGLDELETETEXTURESPROC glDeleteTextures;
NAZARA_API extern PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays;
NAZARA_API extern PFNGLDEPTHFUNCPROC glDepthFunc; NAZARA_API extern PFNGLDEPTHFUNCPROC glDepthFunc;
NAZARA_API extern PFNGLDEPTHMASKPROC glDepthMask; NAZARA_API extern PFNGLDEPTHMASKPROC glDepthMask;
NAZARA_API extern PFNGLDISABLEPROC glDisable; NAZARA_API extern PFNGLDISABLEPROC glDisable;
@ -96,6 +99,7 @@ NAZARA_API extern PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers;
NAZARA_API extern PFNGLGENQUERIESPROC glGenQueries; NAZARA_API extern PFNGLGENQUERIESPROC glGenQueries;
NAZARA_API extern PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers; NAZARA_API extern PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers;
NAZARA_API extern PFNGLGENTEXTURESPROC glGenTextures; NAZARA_API extern PFNGLGENTEXTURESPROC glGenTextures;
NAZARA_API extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
NAZARA_API extern PFNGLGETBUFFERPARAMETERIVPROC glGetBufferParameteriv; NAZARA_API extern PFNGLGETBUFFERPARAMETERIVPROC glGetBufferParameteriv;
NAZARA_API extern PFNGLGETERRORPROC glGetError; NAZARA_API extern PFNGLGETERRORPROC glGetError;
NAZARA_API extern PFNGLGETINTEGERVPROC glGetIntegerv; NAZARA_API extern PFNGLGETINTEGERVPROC glGetIntegerv;

View File

@ -8,6 +8,8 @@
#define NAZARA_RENDERER_HPP #define NAZARA_RENDERER_HPP
#include <Nazara/Prerequesites.hpp> #include <Nazara/Prerequesites.hpp>
#include <map>
#include <tuple>
#define NazaraRenderer NzRenderer::Instance() #define NazaraRenderer NzRenderer::Instance()
@ -45,6 +47,7 @@ enum nzRendererClear
}; };
class NzColor; class NzColor;
class NzContext;
class NzIndexBuffer; class NzIndexBuffer;
class NzRenderTarget; class NzRenderTarget;
class NzShader; class NzShader;
@ -86,8 +89,11 @@ class NAZARA_API NzRenderer
static bool IsInitialized(); static bool IsInitialized();
private: private:
bool UpdateVertexBuffer(); bool UpdateStates();
typedef std::tuple<const NzContext*, const NzIndexBuffer*, const NzVertexBuffer*, const NzVertexDeclaration*> VAO_Key;
std::map<VAO_Key, unsigned int> m_vaos;
const NzIndexBuffer* m_indexBuffer; const NzIndexBuffer* m_indexBuffer;
NzRenderTarget* m_target; NzRenderTarget* m_target;
NzShader* m_shader; NzShader* m_shader;
@ -95,7 +101,7 @@ class NAZARA_API NzRenderer
const NzVertexBuffer* m_vertexBuffer; const NzVertexBuffer* m_vertexBuffer;
const NzVertexDeclaration* m_vertexDeclaration; const NzVertexDeclaration* m_vertexDeclaration;
bool m_capabilities[nzRendererCap_Count]; bool m_capabilities[nzRendererCap_Count];
bool m_vertexBufferUpdated; bool m_statesUpdated;
static NzRenderer* s_instance; static NzRenderer* s_instance;
static bool s_initialized; static bool s_initialized;

View File

@ -6,14 +6,13 @@
#include <Nazara/Renderer/GLSLShader.hpp> #include <Nazara/Renderer/GLSLShader.hpp>
#include <Nazara/Core/Error.hpp> #include <Nazara/Core/Error.hpp>
#include <Nazara/Core/String.hpp> #include <Nazara/Core/String.hpp>
#include <Nazara/Renderer/BufferImpl.hpp>
#include <Nazara/Renderer/VertexBuffer.hpp>
#include <Nazara/Renderer/VertexDeclaration.hpp> #include <Nazara/Renderer/VertexDeclaration.hpp>
#include <Nazara/Renderer/Debug.hpp> #include <Nazara/Renderer/Debug.hpp>
namespace namespace
{ {
nzUInt8 attribIndex[] = ///FIXME: Déclaré deux fois (ici et dans Renderer.cpp)
const nzUInt8 attribIndex[] =
{ {
2, // nzElementUsage_Diffuse 2, // nzElementUsage_Diffuse
1, // nzElementUsage_Normal 1, // nzElementUsage_Normal
@ -27,32 +26,6 @@ namespace
GL_GEOMETRY_SHADER, // nzShaderType_Geometry GL_GEOMETRY_SHADER, // nzShaderType_Geometry
GL_VERTEX_SHADER // nzShaderType_Vertex GL_VERTEX_SHADER // nzShaderType_Vertex
}; };
const nzUInt8 size[] =
{
4, // nzElementType_Color
1, // nzElementType_Double1
2, // nzElementType_Double2
3, // nzElementType_Double3
4, // nzElementType_Double4
1, // nzElementType_Float1
2, // nzElementType_Float2
3, // nzElementType_Float3
4 // nzElementType_Float4
};
const GLenum type[] =
{
GL_UNSIGNED_BYTE, // nzElementType_Color
GL_DOUBLE, // nzElementType_Double1
GL_DOUBLE, // nzElementType_Double2
GL_DOUBLE, // nzElementType_Double3
GL_DOUBLE, // nzElementType_Double4
GL_FLOAT, // nzElementType_Float1
GL_FLOAT, // nzElementType_Float2
GL_FLOAT, // nzElementType_Float3
GL_FLOAT // nzElementType_Float4
};
} }
NzGLSLShader::NzGLSLShader(NzShader* parent) : NzGLSLShader::NzGLSLShader(NzShader* parent) :
@ -331,29 +304,3 @@ void NzGLSLShader::Unlock() const
if (--m_lockedLevel == 0 && m_lockedPrevious != m_program) if (--m_lockedLevel == 0 && m_lockedPrevious != m_program)
glUseProgram(m_lockedPrevious); glUseProgram(m_lockedPrevious);
} }
bool NzGLSLShader::UpdateVertexBuffer(const NzVertexBuffer* vertexBuffer, const NzVertexDeclaration* vertexDeclaration)
{
vertexBuffer->GetBuffer()->GetImpl()->Bind();
const nzUInt8* buffer = reinterpret_cast<const nzUInt8*>(vertexBuffer->GetBufferPtr());
///FIXME: Améliorer les déclarations pour permettre de faire ça plus simplement
for (int i = 0; i < 12; ++i) // Solution temporaire, à virer
glDisableVertexAttribArray(i); // Chaque itération tue un chaton :(
unsigned int stride = vertexDeclaration->GetStride();
unsigned int elementCount = vertexDeclaration->GetElementCount();
for (unsigned int i = 0; i < elementCount; ++i)
{
const NzVertexDeclaration::Element* element = vertexDeclaration->GetElement(i);
glEnableVertexAttribArray(attribIndex[element->usage]+element->usageIndex);
glVertexAttribPointer(attribIndex[element->usage]+element->usageIndex,
size[element->type],
type[element->type],
(element->type == nzElementType_Color) ? GL_TRUE : GL_FALSE,
stride,
&buffer[element->offset]);
}
return true;
}

View File

@ -47,8 +47,6 @@ class NzGLSLShader : public NzShaderImpl
void Unlock() const; void Unlock() const;
private: private:
bool UpdateVertexBuffer(const NzVertexBuffer* vertexBuffer, const NzVertexDeclaration* vertexDeclaration);
mutable std::map<NzString, GLint> m_idCache; mutable std::map<NzString, GLint> m_idCache;
mutable GLuint m_lockedPrevious; mutable GLuint m_lockedPrevious;
GLuint m_program; GLuint m_program;

View File

@ -314,7 +314,7 @@ bool NzOpenGL::Initialize()
} }
} }
// Framebuffer_Object // FrameBufferObject
try try
{ {
glBindFramebuffer = reinterpret_cast<PFNGLBINDFRAMEBUFFERPROC>(LoadEntry("glBindFramebuffer")); glBindFramebuffer = reinterpret_cast<PFNGLBINDFRAMEBUFFERPROC>(LoadEntry("glBindFramebuffer"));
@ -329,7 +329,7 @@ bool NzOpenGL::Initialize()
glGenRenderbuffers = reinterpret_cast<PFNGLGENRENDERBUFFERSPROC>(LoadEntry("glGenRenderbuffers")); glGenRenderbuffers = reinterpret_cast<PFNGLGENRENDERBUFFERSPROC>(LoadEntry("glGenRenderbuffers"));
glRenderbufferStorage = reinterpret_cast<PFNGLRENDERBUFFERSTORAGEPROC>(LoadEntry("glRenderbufferStorage")); glRenderbufferStorage = reinterpret_cast<PFNGLRENDERBUFFERSTORAGEPROC>(LoadEntry("glRenderbufferStorage"));
openGLextensions[NzOpenGL::Framebuffer_Object] = true; openGLextensions[NzOpenGL::FrameBufferObject] = true;
} }
catch (const std::exception& e) catch (const std::exception& e)
{ {
@ -352,7 +352,7 @@ bool NzOpenGL::Initialize()
glGenRenderbuffers = reinterpret_cast<PFNGLGENRENDERBUFFERSEXTPROC>(LoadEntry("glGenRenderbuffersEXT")); glGenRenderbuffers = reinterpret_cast<PFNGLGENRENDERBUFFERSEXTPROC>(LoadEntry("glGenRenderbuffersEXT"));
glRenderbufferStorage = reinterpret_cast<PFNGLRENDERBUFFERSTORAGEEXTPROC>(LoadEntry("glRenderbufferStorageEXT")); glRenderbufferStorage = reinterpret_cast<PFNGLRENDERBUFFERSTORAGEEXTPROC>(LoadEntry("glRenderbufferStorageEXT"));
openGLextensions[NzOpenGL::Framebuffer_Object] = true; openGLextensions[NzOpenGL::FrameBufferObject] = true;
} }
catch (const std::exception& e) catch (const std::exception& e)
{ {
@ -377,8 +377,24 @@ bool NzOpenGL::Initialize()
} }
} }
/****************************************Contextes****************************************/ // VertexArrayObject
if (openGLversion >= 300 || IsSupported("GL_ARB_vertex_array_object"))
{
try
{
glBindVertexArray = reinterpret_cast<PFNGLBINDVERTEXARRAYPROC>(LoadEntry("glBindVertexArray", false));
glDeleteVertexArrays = reinterpret_cast<PFNGLDELETEVERTEXARRAYSPROC>(LoadEntry("glDeleteVertexArrays", false));
glGenVertexArrays = reinterpret_cast<PFNGLGENVERTEXARRAYSPROC>(LoadEntry("glGenVertexArrays", false));
openGLextensions[NzOpenGL::VertexArrayObject] = true;
}
catch (const std::exception& e)
{
NazaraError("Failed to load ARB_vertex_array_object: " + NzString(e.what()));
}
}
/****************************************Contextes****************************************/
NzContextParameters::defaultMajorVersion = openGLversion/100; NzContextParameters::defaultMajorVersion = openGLversion/100;
NzContextParameters::defaultMinorVersion = (openGLversion%100)/10; NzContextParameters::defaultMinorVersion = (openGLversion%100)/10;
@ -427,6 +443,7 @@ PFNGLBINDBUFFERPROC glBindBuffer = nullptr;
PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer = nullptr; PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer = nullptr;
PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer = nullptr; PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer = nullptr;
PFNGLBINDTEXTUREPROC glBindTexture = nullptr; PFNGLBINDTEXTUREPROC glBindTexture = nullptr;
PFNGLBINDVERTEXARRAYPROC glBindVertexArray = nullptr;
PFNGLBLENDFUNCPROC glBlendFunc = nullptr; PFNGLBLENDFUNCPROC glBlendFunc = nullptr;
PFNGLBUFFERDATAPROC glBufferData = nullptr; PFNGLBUFFERDATAPROC glBufferData = nullptr;
PFNGLBUFFERSUBDATAPROC glBufferSubData = nullptr; PFNGLBUFFERSUBDATAPROC glBufferSubData = nullptr;
@ -447,6 +464,7 @@ PFNGLDELETEQUERIESPROC glDeleteQueries = nullptr;
PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers = nullptr; PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers = nullptr;
PFNGLDELETESHADERPROC glDeleteShader = nullptr; PFNGLDELETESHADERPROC glDeleteShader = nullptr;
PFNGLDELETETEXTURESPROC glDeleteTextures = nullptr; PFNGLDELETETEXTURESPROC glDeleteTextures = nullptr;
PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays = nullptr;
PFNGLDEPTHFUNCPROC glDepthFunc = nullptr; PFNGLDEPTHFUNCPROC glDepthFunc = nullptr;
PFNGLDEPTHMASKPROC glDepthMask = nullptr; PFNGLDEPTHMASKPROC glDepthMask = nullptr;
PFNGLDISABLEPROC glDisable = nullptr; PFNGLDISABLEPROC glDisable = nullptr;
@ -467,6 +485,7 @@ PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers = nullptr;
PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers = nullptr; PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers = nullptr;
PFNGLGENQUERIESPROC glGenQueries = nullptr; PFNGLGENQUERIESPROC glGenQueries = nullptr;
PFNGLGENTEXTURESPROC glGenTextures = nullptr; PFNGLGENTEXTURESPROC glGenTextures = nullptr;
PFNGLGENVERTEXARRAYSPROC glGenVertexArrays = nullptr;
PFNGLGETBUFFERPARAMETERIVPROC glGetBufferParameteriv = nullptr; PFNGLGETBUFFERPARAMETERIVPROC glGetBufferParameteriv = nullptr;
PFNGLGETERRORPROC glGetError = nullptr; PFNGLGETERRORPROC glGetError = nullptr;
PFNGLGETINTEGERVPROC glGetIntegerv = nullptr; PFNGLGETINTEGERVPROC glGetIntegerv = nullptr;

View File

@ -14,13 +14,23 @@
#include <Nazara/Renderer/Shader.hpp> #include <Nazara/Renderer/Shader.hpp>
#include <Nazara/Renderer/ShaderImpl.hpp> #include <Nazara/Renderer/ShaderImpl.hpp>
#include <Nazara/Renderer/VertexBuffer.hpp> #include <Nazara/Renderer/VertexBuffer.hpp>
#include <Nazara/Renderer/VertexDeclaration.hpp>
#include <Nazara/Utility/Utility.hpp> #include <Nazara/Utility/Utility.hpp>
#include <stdexcept> #include <stdexcept>
#include <Nazara/Renderer/Debug.hpp> #include <Nazara/Renderer/Debug.hpp>
namespace namespace
{ {
GLenum openglPrimitive[] = { const nzUInt8 attribIndex[] =
{
2, // nzElementUsage_Diffuse
1, // nzElementUsage_Normal
0, // nzElementUsage_Position
3, // nzElementUsage_Tangent
4 // nzElementUsage_TexCoord
};
const GLenum openglPrimitive[] = {
GL_LINES, // nzPrimitiveType_LineList, GL_LINES, // nzPrimitiveType_LineList,
GL_LINE_STRIP, // nzPrimitiveType_LineStrip, GL_LINE_STRIP, // nzPrimitiveType_LineStrip,
GL_POINTS, // nzPrimitiveType_PointList, GL_POINTS, // nzPrimitiveType_PointList,
@ -28,6 +38,32 @@ namespace
GL_TRIANGLE_STRIP, // nzPrimitiveType_TriangleStrip, GL_TRIANGLE_STRIP, // nzPrimitiveType_TriangleStrip,
GL_TRIANGLE_FAN // nzPrimitiveType_TriangleFan GL_TRIANGLE_FAN // nzPrimitiveType_TriangleFan
}; };
const nzUInt8 openglSize[] =
{
4, // nzElementType_Color
1, // nzElementType_Double1
2, // nzElementType_Double2
3, // nzElementType_Double3
4, // nzElementType_Double4
1, // nzElementType_Float1
2, // nzElementType_Float2
3, // nzElementType_Float3
4 // nzElementType_Float4
};
const GLenum openglType[] =
{
GL_UNSIGNED_BYTE, // nzElementType_Color
GL_DOUBLE, // nzElementType_Double1
GL_DOUBLE, // nzElementType_Double2
GL_DOUBLE, // nzElementType_Double3
GL_DOUBLE, // nzElementType_Double4
GL_FLOAT, // nzElementType_Float1
GL_FLOAT, // nzElementType_Float2
GL_FLOAT, // nzElementType_Float3
GL_FLOAT // nzElementType_Float4
};
} }
NzRenderer::NzRenderer() : NzRenderer::NzRenderer() :
@ -36,7 +72,7 @@ m_target(nullptr),
m_shader(nullptr), m_shader(nullptr),
m_vertexBuffer(nullptr), m_vertexBuffer(nullptr),
m_vertexDeclaration(nullptr), m_vertexDeclaration(nullptr),
m_vertexBufferUpdated(false) m_statesUpdated(false)
{ {
#if NAZARA_RENDERER_SAFE #if NAZARA_RENDERER_SAFE
if (s_instance) if (s_instance)
@ -91,11 +127,11 @@ void NzRenderer::DrawIndexedPrimitives(nzPrimitiveType primitive, unsigned int f
} }
#endif #endif
if (!m_vertexBufferUpdated) if (!m_statesUpdated)
{ {
if (!UpdateVertexBuffer()) if (!UpdateStates())
{ {
NazaraError("Failed to update vertex buffer"); NazaraError("Failed to update states");
return; return;
} }
} }
@ -127,11 +163,11 @@ void NzRenderer::DrawIndexedPrimitives(nzPrimitiveType primitive, unsigned int f
void NzRenderer::DrawPrimitives(nzPrimitiveType primitive, unsigned int firstVertex, unsigned int vertexCount) void NzRenderer::DrawPrimitives(nzPrimitiveType primitive, unsigned int firstVertex, unsigned int vertexCount)
{ {
if (!m_vertexBufferUpdated) if (!m_statesUpdated)
{ {
if (!UpdateVertexBuffer()) if (!UpdateStates())
{ {
NazaraError("Failed to update vertex buffer"); NazaraError("Failed to update states");
return; return;
} }
} }
@ -191,7 +227,7 @@ bool NzRenderer::Initialize()
m_capabilities[nzRendererCap_FP64] = NzOpenGL::IsSupported(NzOpenGL::FP64); m_capabilities[nzRendererCap_FP64] = NzOpenGL::IsSupported(NzOpenGL::FP64);
m_capabilities[nzRendererCap_HardwareBuffer] = true; // Natif depuis OpenGL 1.5 m_capabilities[nzRendererCap_HardwareBuffer] = true; // Natif depuis OpenGL 1.5
m_capabilities[nzRendererCap_MultipleRenderTargets] = true; // Natif depuis OpenGL 2.0 m_capabilities[nzRendererCap_MultipleRenderTargets] = true; // Natif depuis OpenGL 2.0
m_capabilities[nzRendererCap_OcclusionQuery] = // Natif depuis OpenGL 1.5 m_capabilities[nzRendererCap_OcclusionQuery] = true; // Natif depuis OpenGL 1.5
m_capabilities[nzRendererCap_SoftwareBuffer] = NzOpenGL::GetVersion() <= 300; // Déprécié en OpenGL 3 m_capabilities[nzRendererCap_SoftwareBuffer] = NzOpenGL::GetVersion() <= 300; // Déprécié en OpenGL 3
m_capabilities[nzRendererCap_Texture3D] = NzOpenGL::IsSupported(NzOpenGL::Texture3D); m_capabilities[nzRendererCap_Texture3D] = NzOpenGL::IsSupported(NzOpenGL::Texture3D);
m_capabilities[nzRendererCap_TextureCubemap] = true; // Natif depuis OpenGL 1.3 m_capabilities[nzRendererCap_TextureCubemap] = true; // Natif depuis OpenGL 1.3
@ -260,12 +296,11 @@ void NzRenderer::SetClearStencil(unsigned int value)
bool NzRenderer::SetIndexBuffer(const NzIndexBuffer* indexBuffer) bool NzRenderer::SetIndexBuffer(const NzIndexBuffer* indexBuffer)
{ {
if (indexBuffer == m_indexBuffer) if (indexBuffer != m_indexBuffer)
return true; {
m_indexBuffer = indexBuffer;
// OpenGL ne nécessite pas de débinder un index buffer pour ne pas l'utiliser m_statesUpdated = false;
if (indexBuffer) }
indexBuffer->GetBuffer()->m_impl->Bind();
return true; return true;
} }
@ -292,7 +327,6 @@ bool NzRenderer::SetShader(NzShader* shader)
} }
m_shader = shader; m_shader = shader;
m_vertexBufferUpdated = false;
} }
else if (m_shader) else if (m_shader)
{ {
@ -339,24 +373,22 @@ bool NzRenderer::SetTarget(NzRenderTarget* target)
bool NzRenderer::SetVertexBuffer(const NzVertexBuffer* vertexBuffer) bool NzRenderer::SetVertexBuffer(const NzVertexBuffer* vertexBuffer)
{ {
if (m_vertexBuffer == vertexBuffer) if (m_vertexBuffer != vertexBuffer)
return true;
if (m_vertexBuffer && vertexBuffer)
{ {
// Si l'ancien buffer et le nouveau sont hardware, pas besoin de mettre à jour la déclaration m_vertexBuffer = vertexBuffer;
if (!m_vertexBuffer->IsHardware() || !vertexBuffer->IsHardware()) m_statesUpdated = false;
m_vertexBufferUpdated = false;
} }
m_vertexBuffer = vertexBuffer;
return true; return true;
} }
bool NzRenderer::SetVertexDeclaration(const NzVertexDeclaration* vertexDeclaration) bool NzRenderer::SetVertexDeclaration(const NzVertexDeclaration* vertexDeclaration)
{ {
m_vertexDeclaration = vertexDeclaration; if (m_vertexDeclaration != vertexDeclaration)
m_vertexBufferUpdated = false; {
m_vertexDeclaration = vertexDeclaration;
m_statesUpdated = false;
}
return true; return true;
} }
@ -371,10 +403,17 @@ void NzRenderer::Uninitialize()
} }
#endif #endif
NzOpenGL::Uninitialize();
s_initialized = false; s_initialized = false;
// Libération des VAOs
for (auto it = m_vaos.begin(); it != m_vaos.end(); ++it)
{
GLuint vao = it->second;
glDeleteVertexArrays(1, &vao);
}
NzOpenGL::Uninitialize();
if (m_utilityModule) if (m_utilityModule)
{ {
delete m_utilityModule; delete m_utilityModule;
@ -397,15 +436,9 @@ bool NzRenderer::IsInitialized()
return s_initialized; return s_initialized;
} }
bool NzRenderer::UpdateVertexBuffer() bool NzRenderer::UpdateStates()
{ {
#if NAZARA_RENDERER_SAFE #if NAZARA_RENDERER_SAFE
if (!m_shader)
{
NazaraError("No shader");
return false;
}
if (!m_vertexBuffer) if (!m_vertexBuffer)
{ {
NazaraError("No vertex buffer"); NazaraError("No vertex buffer");
@ -419,10 +452,78 @@ bool NzRenderer::UpdateVertexBuffer()
} }
#endif #endif
if (!m_shader->m_impl->UpdateVertexBuffer(m_vertexBuffer, m_vertexDeclaration)) static const bool vaoSupported = NzOpenGL::IsSupported(NzOpenGL::VertexArrayObject);
return false; bool update;
GLuint vao;
m_vertexBufferUpdated = true; // Si les VAOs sont supportés, on entoure nos appels par ceux-ci
if (vaoSupported)
{
// On recherche si un VAO existe déjà avec notre configuration
// Note: Les VAOs ne sont pas partagés entre les contextes, ils font donc partie de notre configuration
auto key = std::make_tuple(NzContext::GetCurrent(), m_indexBuffer, m_vertexBuffer, m_vertexDeclaration);
auto it = m_vaos.find(key);
if (it == m_vaos.end())
{
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
m_vaos.insert(std::make_pair(key, static_cast<unsigned int>(vao)));
update = true;
}
else
{
// Notre VAO existe déjà, il est donc inutile de le reprogrammer
vao = it->second;
update = false;
}
}
else
update = true; // Fallback si les VAOs ne sont pas supportés
if (update)
{
m_vertexBuffer->GetBuffer()->GetImpl()->Bind();
const nzUInt8* buffer = reinterpret_cast<const nzUInt8*>(m_vertexBuffer->GetBufferPtr());
///FIXME: Améliorer les déclarations pour permettre de faire ça plus simplement
for (int i = 0; i < 12; ++i) // Solution temporaire, à virer
glDisableVertexAttribArray(i); // Chaque itération tue un chaton :(
unsigned int stride = m_vertexDeclaration->GetStride();
unsigned int elementCount = m_vertexDeclaration->GetElementCount();
for (unsigned int i = 0; i < elementCount; ++i)
{
const NzVertexDeclaration::Element* element = m_vertexDeclaration->GetElement(i);
glEnableVertexAttribArray(attribIndex[element->usage]+element->usageIndex);
glVertexAttribPointer(attribIndex[element->usage]+element->usageIndex,
openglSize[element->type],
openglType[element->type],
(element->type == nzElementType_Color) ? GL_TRUE : GL_FALSE,
stride,
&buffer[element->offset]);
}
if (m_indexBuffer)
m_indexBuffer->GetBuffer()->GetImpl()->Bind();
}
if (vaoSupported)
{
// Si nous venons de définir notre VAO, nous devons le débinder pour indiquer la fin de sa construction
if (update)
glBindVertexArray(0);
// Nous (re)bindons le VAO pour définir les attributs de vertice
glBindVertexArray(vao);
}
m_statesUpdated = true;
return true; return true;
} }

View File

@ -47,9 +47,6 @@ class NzShaderImpl
virtual void Unbind() = 0; virtual void Unbind() = 0;
virtual void Unlock() const = 0; virtual void Unlock() const = 0;
protected:
virtual bool UpdateVertexBuffer(const NzVertexBuffer* vertexBuffer, const NzVertexDeclaration* vertexDeclaration) = 0;
}; };
#endif // NAZARA_SHADERIMPL_HPP #endif // NAZARA_SHADERIMPL_HPP

View File

@ -271,6 +271,14 @@ const nzUInt8* NzImage::GetConstPixels(nzUInt8 level) const
unsigned int NzImage::GetDepth(nzUInt8 level) const unsigned int NzImage::GetDepth(nzUInt8 level) const
{ {
#if NAZARA_UTILITY_SAFE
if (level >= m_sharedImage->levelCount)
{
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levelCount) + ')');
return 0;
}
#endif
return std::max(m_sharedImage->depth/(1 << level), 1U); return std::max(m_sharedImage->depth/(1 << level), 1U);
} }
@ -281,6 +289,14 @@ nzPixelFormat NzImage::GetFormat() const
unsigned int NzImage::GetHeight(nzUInt8 level) const unsigned int NzImage::GetHeight(nzUInt8 level) const
{ {
#if NAZARA_UTILITY_SAFE
if (level >= m_sharedImage->levelCount)
{
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levelCount) + ')');
return 0;
}
#endif
return std::max(m_sharedImage->height/(1 << level), 1U); return std::max(m_sharedImage->height/(1 << level), 1U);
} }
@ -422,6 +438,14 @@ unsigned int NzImage::GetSize() const
unsigned int NzImage::GetSize(nzUInt8 level) const unsigned int NzImage::GetSize(nzUInt8 level) const
{ {
#if NAZARA_UTILITY_SAFE
if (level >= m_sharedImage->levelCount)
{
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levelCount) + ')');
return 0;
}
#endif
return (std::max(m_sharedImage->width/(1 << level), 1U)) * return (std::max(m_sharedImage->width/(1 << level), 1U)) *
(std::max(m_sharedImage->height/(1 << level), 1U)) * (std::max(m_sharedImage->height/(1 << level), 1U)) *
((m_sharedImage->type == nzImageType_Cubemap) ? 6 : std::min(m_sharedImage->depth/(1 << level), 1U)) * ((m_sharedImage->type == nzImageType_Cubemap) ? 6 : std::min(m_sharedImage->depth/(1 << level), 1U)) *
@ -435,6 +459,14 @@ nzImageType NzImage::GetType() const
unsigned int NzImage::GetWidth(nzUInt8 level) const unsigned int NzImage::GetWidth(nzUInt8 level) const
{ {
#if NAZARA_UTILITY_SAFE
if (level >= m_sharedImage->levelCount)
{
NazaraError("Level out of bounds (" + NzString::Number(level) + " >= " + NzString::Number(m_sharedImage->levelCount) + ')');
return 0;
}
#endif
return std::max(m_sharedImage->width/(1 << level), 1U); return std::max(m_sharedImage->width/(1 << level), 1U);
} }
@ -905,4 +937,4 @@ void NzImage::ReleaseImage()
m_sharedImage = &emptyImage; m_sharedImage = &emptyImage;
} }
NzImage::SharedImage NzImage::emptyImage(0, nzImageType_2D, nzPixelFormat_Undefined, 0, nullptr, 0, 0, 0); NzImage::SharedImage NzImage::emptyImage(0, nzImageType_2D, nzPixelFormat_Undefined, 1, nullptr, 0, 0, 0);