Laid the basis for rendering

This commit is contained in:
Lynix 2012-05-02 16:45:44 +02:00
parent e8ef4b59da
commit 7d117ce97c
25 changed files with 412 additions and 95 deletions

View File

@ -24,7 +24,6 @@ class NAZARA_API NzMemoryManager
static void NextFree(const char* file, unsigned int line); static void NextFree(const char* file, unsigned int line);
private: private:
static void EnsureInitialization();
static void Initialize(); static void Initialize();
static char* TimeInfo(); static char* TimeInfo();
static void Uninitialize(); static void Uninitialize();

View File

@ -39,7 +39,6 @@ template<typename T> class NzEulerAngles
template<typename U> void Set(const NzEulerAngles<U>& angles); template<typename U> void Set(const NzEulerAngles<U>& angles);
void SetZero(); void SetZero();
//NzEulerAngles<T> ToEulerAngles() const;
//NzMatrix3<T> ToRotationMatrix() const; //NzMatrix3<T> ToRotationMatrix() const;
NzQuaternion<T> ToQuaternion() const; NzQuaternion<T> ToQuaternion() const;
NzString ToString() const; NzString ToString() const;

View File

@ -55,6 +55,9 @@ class NAZARA_API NzBuffer : public NzResource
bool Fill(const void* data, unsigned int offset, unsigned int length); bool Fill(const void* data, unsigned int offset, unsigned int length);
void* GetBufferPtr();
const void* GetBufferPtr() const;
NzBufferImpl* GetImpl() const;
unsigned int GetLength() const; unsigned int GetLength() const;
unsigned int GetSize() const; unsigned int GetSize() const;
nzBufferStorage GetStorage() const; nzBufferStorage GetStorage() const;
@ -67,7 +70,7 @@ class NAZARA_API NzBuffer : public NzResource
void* Lock(nzBufferLock lock, unsigned int offset = 0, unsigned int length = 0); void* Lock(nzBufferLock lock, unsigned int offset = 0, unsigned int length = 0);
bool Unlock(); bool Unlock();
static bool IsHardwareSupported(); static bool IsSupported(nzBufferStorage storage);
private: private:
nzBufferStorage m_storage; nzBufferStorage m_storage;

View File

@ -21,6 +21,8 @@ class NAZARA_API NzIndexBuffer
bool Fill(const void* data, unsigned int offset, unsigned int length); bool Fill(const void* data, unsigned int offset, unsigned int length);
NzBuffer* GetBuffer() const; NzBuffer* GetBuffer() const;
void* GetBufferPtr();
const void* GetBufferPtr() const;
nzUInt8 GetIndexSize() const; nzUInt8 GetIndexSize() const;
unsigned int GetIndexCount() const; unsigned int GetIndexCount() const;
unsigned int GetStartIndex() const; unsigned int GetStartIndex() const;

View File

@ -8,19 +8,26 @@
#define NAZARA_RENDERER_HPP #define NAZARA_RENDERER_HPP
#include <Nazara/Prerequesites.hpp> #include <Nazara/Prerequesites.hpp>
#include <Nazara/Renderer/IndexBuffer.hpp>
#include <Nazara/Renderer/RenderTarget.hpp>
#include <Nazara/Renderer/Shader.hpp>
#include <Nazara/Renderer/VertexBuffer.hpp>
#define NazaraRenderer NzRenderer::Instance() #define NazaraRenderer NzRenderer::Instance()
enum nzPrimitiveType
{
nzPrimitiveType_LineList,
nzPrimitiveType_LineStrip,
nzPrimitiveType_PointList,
nzPrimitiveType_TriangleList,
nzPrimitiveType_TriangleStrip,
nzPrimitiveType_TriangleFan
};
enum nzRendererCap enum nzRendererCap
{ {
nzRendererCap_AnisotropicFilter, nzRendererCap_AnisotropicFilter,
nzRendererCap_FP64, nzRendererCap_FP64,
nzRendererCap_HardwareBuffer, nzRendererCap_HardwareBuffer,
nzRendererCap_MultipleRenderTargets, nzRendererCap_MultipleRenderTargets,
nzRendererCap_SoftwareBuffer,
nzRendererCap_Texture3D, nzRendererCap_Texture3D,
nzRendererCap_TextureCubemap, nzRendererCap_TextureCubemap,
nzRendererCap_TextureMulti, nzRendererCap_TextureMulti,
@ -36,6 +43,12 @@ enum nzRendererClear
nzRendererClear_Stencil = 0x04 nzRendererClear_Stencil = 0x04
}; };
class NzRenderTarget;
class NzIndexBuffer;
class NzShader;
class NzVertexBuffer;
class NzVertexDeclaration;
class NAZARA_API NzRenderer class NAZARA_API NzRenderer
{ {
public: public:
@ -44,6 +57,9 @@ class NAZARA_API NzRenderer
void Clear(nzRendererClear flags); void Clear(nzRendererClear flags);
void DrawIndexedPrimitives(nzPrimitiveType primitive, unsigned int firstIndex, unsigned int indexCount);
void DrawPrimitives(nzPrimitiveType primitive, unsigned int firstVertex, unsigned int vertexCount);
NzShader* GetShader() const; NzShader* GetShader() const;
NzRenderTarget* GetTarget() const; NzRenderTarget* GetTarget() const;
@ -67,12 +83,15 @@ class NAZARA_API NzRenderer
static NzRenderer* Instance(); static NzRenderer* Instance();
private: private:
bool UpdateVertexBuffer();
static NzRenderer* s_instance; static NzRenderer* s_instance;
const NzIndexBuffer* m_indexBuffer; const NzIndexBuffer* m_indexBuffer;
NzRenderTarget* m_target; NzRenderTarget* m_target;
NzShader* m_shader; NzShader* m_shader;
const NzVertexBuffer* m_vertexBuffer; const NzVertexBuffer* m_vertexBuffer;
const NzVertexDeclaration* m_vertexDeclaration;
bool m_capabilities[nzRendererCap_Count]; bool m_capabilities[nzRendererCap_Count];
bool m_vertexBufferUpdated; bool m_vertexBufferUpdated;
}; };

View File

@ -21,6 +21,8 @@ class NAZARA_API NzVertexBuffer
bool Fill(const void* data, unsigned int offset, unsigned int length); bool Fill(const void* data, unsigned int offset, unsigned int length);
NzBuffer* GetBuffer() const; NzBuffer* GetBuffer() const;
void* GetBufferPtr();
const void* GetBufferPtr() const;
unsigned int GetStartVertex() const; unsigned int GetStartVertex() const;
nzUInt8 GetTypeSize() const; nzUInt8 GetTypeSize() const;
unsigned int GetVertexCount() const; unsigned int GetVertexCount() const;

View File

@ -23,11 +23,11 @@ enum nzElementType
enum nzElementUsage enum nzElementUsage
{ {
nzElementType_Diffuse, nzElementUsage_Diffuse,
nzElementType_Normal, nzElementUsage_Normal,
nzElementType_Position, nzElementUsage_Position,
nzElementType_Tangent, nzElementUsage_Tangent,
nzElementType_TexCoord nzElementUsage_TexCoord
}; };
struct NzVertexElement struct NzVertexElement

View File

@ -50,7 +50,8 @@ NzMemoryManager::~NzMemoryManager()
void* NzMemoryManager::Allocate(std::size_t size, bool multi, const char* file, unsigned int line) void* NzMemoryManager::Allocate(std::size_t size, bool multi, const char* file, unsigned int line)
{ {
EnsureInitialization(); if (!initialized)
Initialize();
Block* ptr = reinterpret_cast<Block*>(std::malloc(size+sizeof(Block))); Block* ptr = reinterpret_cast<Block*>(std::malloc(size+sizeof(Block)));
if (!ptr) if (!ptr)
@ -121,21 +122,6 @@ void NzMemoryManager::NextFree(const char* file, unsigned int line)
nextFreeLine = line; nextFreeLine = line;
} }
void NzMemoryManager::EnsureInitialization()
{
if (!initialized)
{
Initialize();
if (std::atexit(Uninitialize) != 0)
{
static NzMemoryManager manager;
}
initialized = true;
}
}
void NzMemoryManager::Initialize() void NzMemoryManager::Initialize()
{ {
char* time = TimeInfo(); char* time = TimeInfo();
@ -147,6 +133,13 @@ void NzMemoryManager::Initialize()
std::fclose(file); std::fclose(file);
std::free(time); std::free(time);
if (std::atexit(Uninitialize) != 0)
{
static NzMemoryManager manager;
}
initialized = true;
} }
char* NzMemoryManager::TimeInfo() char* NzMemoryManager::TimeInfo()

View File

@ -11,6 +11,14 @@
#include <stdexcept> #include <stdexcept>
#include <Nazara/Renderer/Debug.hpp> #include <Nazara/Renderer/Debug.hpp>
namespace
{
nzRendererCap storageToCapability[] = {
nzRendererCap_HardwareBuffer, // nzBufferStorage_Hardware
nzRendererCap_SoftwareBuffer, // nzBufferStorage_Software
};
}
NzBuffer::NzBuffer(nzBufferType type) : NzBuffer::NzBuffer(nzBufferType type) :
m_type(type), m_type(type),
m_typeSize(0), m_typeSize(0),
@ -25,7 +33,7 @@ m_impl(nullptr)
{ {
Create(length, typeSize, usage); Create(length, typeSize, usage);
#if NAZARA_DEBUG #ifdef NAZARA_DEBUG
if (!m_impl) if (!m_impl)
{ {
NazaraError("Failed to create buffer"); NazaraError("Failed to create buffer");
@ -44,14 +52,14 @@ bool NzBuffer::CopyContent(NzBuffer& buffer)
void* ptr = buffer.Lock(nzBufferLock_ReadOnly); void* ptr = buffer.Lock(nzBufferLock_ReadOnly);
if (!ptr) if (!ptr)
{ {
NazaraError("Unable to lock buffer"); NazaraError("Unable to lock source buffer");
return false; return false;
} }
bool r = Fill(ptr, 0, m_length); bool r = Fill(ptr, 0, m_length);
if (!buffer.Unlock()) if (!buffer.Unlock())
NazaraWarning("Unable to unlock buffer"); NazaraWarning("Unable to unlock source buffer");
return r; return r;
} }
@ -64,7 +72,7 @@ bool NzBuffer::Create(unsigned int length, nzUInt8 typeSize, nzBufferUsage usage
if (NazaraRenderer->HasCapability(nzRendererCap_HardwareBuffer)) if (NazaraRenderer->HasCapability(nzRendererCap_HardwareBuffer))
{ {
m_impl = new NzHardwareBuffer(this, m_type); m_impl = new NzHardwareBuffer(this, m_type);
if (!m_impl->Create(length, typeSize, usage)) if (!m_impl->Create(length*typeSize, usage))
{ {
NazaraWarning("Failed to create hardware buffer, trying to create software buffer..."); NazaraWarning("Failed to create hardware buffer, trying to create software buffer...");
@ -76,7 +84,7 @@ bool NzBuffer::Create(unsigned int length, nzUInt8 typeSize, nzBufferUsage usage
if (!m_impl) if (!m_impl)
{ {
m_impl = new NzSoftwareBuffer(this, m_type); m_impl = new NzSoftwareBuffer(this, m_type);
if (!m_impl->Create(length, typeSize, usage)) if (!m_impl->Create(length*typeSize, usage))
{ {
NazaraError("Failed to create software buffer"); NazaraError("Failed to create software buffer");
delete m_impl; delete m_impl;
@ -120,7 +128,38 @@ bool NzBuffer::Fill(const void* data, unsigned int offset, unsigned int length)
} }
#endif #endif
return m_impl->Fill(data, offset, length); return m_impl->Fill(data, offset*m_typeSize, length*m_typeSize);
}
void* NzBuffer::GetBufferPtr()
{
#if NAZARA_RENDERER_SAFE
if (!m_impl)
{
NazaraError("Buffer not created");
return false;
}
#endif
return m_impl->GetBufferPtr();
}
const void* NzBuffer::GetBufferPtr() const
{
#if NAZARA_RENDERER_SAFE
if (!m_impl)
{
NazaraError("Buffer not created");
return false;
}
#endif
return m_impl->GetBufferPtr();
}
NzBufferImpl* NzBuffer::GetImpl() const
{
return m_impl;
} }
unsigned int NzBuffer::GetLength() const unsigned int NzBuffer::GetLength() const
@ -174,7 +213,7 @@ void* NzBuffer::Lock(nzBufferLock lock, unsigned int offset, unsigned int length
} }
#endif #endif
return m_impl->Lock(lock, offset, length); return m_impl->Lock(lock, offset*m_typeSize, length*m_typeSize);
} }
bool NzBuffer::Unlock() bool NzBuffer::Unlock()
@ -190,7 +229,7 @@ bool NzBuffer::Unlock()
return m_impl->Unlock(); return m_impl->Unlock();
} }
bool NzBuffer::IsHardwareSupported() bool NzBuffer::IsSupported(nzBufferStorage storage)
{ {
return NazaraRenderer->HasCapability(nzRendererCap_HardwareBuffer); return NazaraRenderer->HasCapability(storageToCapability[storage]);
} }

View File

@ -3,5 +3,6 @@
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Renderer/BufferImpl.hpp> #include <Nazara/Renderer/BufferImpl.hpp>
#include <Nazara/Renderer/Debug.hpp>
NzBufferImpl::~NzBufferImpl() = default; NzBufferImpl::~NzBufferImpl() = default;

View File

@ -17,14 +17,16 @@ class NzBufferImpl
virtual void Bind() = 0; virtual void Bind() = 0;
virtual bool Create(unsigned int length, nzUInt8 typeSize, nzBufferUsage usage = nzBufferUsage_Static) = 0; virtual bool Create(unsigned int size, nzBufferUsage usage = nzBufferUsage_Static) = 0;
virtual void Destroy() = 0; virtual void Destroy() = 0;
virtual bool Fill(const void* data, unsigned int offset, unsigned int length) = 0; virtual bool Fill(const void* data, unsigned int offset, unsigned int size) = 0;
virtual void* GetBufferPtr() = 0;
virtual bool IsHardware() const = 0; virtual bool IsHardware() const = 0;
virtual void* Lock(nzBufferLock lock, unsigned int offset = 0, unsigned int length = 0) = 0; virtual void* Lock(nzBufferLock lock, unsigned int offset = 0, unsigned int size = 0) = 0;
virtual bool Unlock() = 0; virtual bool Unlock() = 0;
}; };

View File

@ -6,15 +6,53 @@
#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/Debug.hpp> #include <Nazara/Renderer/Debug.hpp>
namespace namespace
{ {
GLenum shaderType[nzShaderType_Count] = { nzUInt8 attribIndex[] =
{
2, // nzElementUsage_Diffuse
1, // nzElementUsage_Normal
0, // nzElementUsage_Position
3, // nzElementUsage_Tangent
4 // nzElementUsage_TexCoord
};
const GLenum shaderType[nzShaderType_Count] = {
GL_FRAGMENT_SHADER, // nzShaderType_Fragment GL_FRAGMENT_SHADER, // nzShaderType_Fragment
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) :
@ -80,15 +118,16 @@ bool NzGLSLShader::Create()
return false; return false;
} }
glBindAttribLocation(m_program, 0, "Position"); glBindAttribLocation(m_program, attribIndex[nzElementUsage_Position], "Position");
glBindAttribLocation(m_program, 1, "Normal"); glBindAttribLocation(m_program, attribIndex[nzElementUsage_Normal], "Normal");
//glBindAttribLocation(m_program, 2, "Diffuse"); glBindAttribLocation(m_program, attribIndex[nzElementUsage_Diffuse], "Diffuse");
glBindAttribLocation(m_program, 3, "Tangent"); glBindAttribLocation(m_program, attribIndex[nzElementUsage_Tangent], "Tangent");
NzString uniformName = "TexCoord0";
for (unsigned int i = 0; i < 8; ++i) for (unsigned int i = 0; i < 8; ++i)
{ {
NzString uniformName = "TexCoord" + NzString::Number(i); uniformName[8] = '0'+i;
glBindAttribLocation(m_program, 4+i, uniformName.GetConstBuffer()); glBindAttribLocation(m_program, attribIndex[nzElementUsage_TexCoord]+i, uniformName.GetConstBuffer());
} }
for (int i = 0; i < nzShaderType_Count; ++i) for (int i = 0; i < nzShaderType_Count; ++i)
@ -252,3 +291,29 @@ void NzGLSLShader::Unbind()
{ {
glUseProgram(0); glUseProgram(0);
} }
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

@ -45,6 +45,8 @@ class NzGLSLShader : public NzShaderImpl
void Unbind(); void Unbind();
private: private:
bool UpdateVertexBuffer(const NzVertexBuffer* vertexBuffer, const NzVertexDeclaration* vertexDeclaration);
mutable std::map<NzString, GLint> m_idCache; mutable std::map<NzString, GLint> m_idCache;
GLuint m_program; GLuint m_program;
GLuint m_shaders[nzShaderType_Count]; GLuint m_shaders[nzShaderType_Count];

View File

@ -43,11 +43,11 @@ namespace
GL_STATIC_DRAW // nzBufferUsage_Static GL_STATIC_DRAW // nzBufferUsage_Static
}; };
typedef nzUInt8* (*LockRoutine)(nzBufferType type, nzBufferLock lock, unsigned int offset, unsigned int length); typedef nzUInt8* (*LockRoutine)(nzBufferType type, nzBufferLock lock, unsigned int offset, unsigned int size);
nzUInt8* LockBuffer(nzBufferType type, nzBufferLock lock, unsigned int offset, unsigned int length) nzUInt8* LockBuffer(nzBufferType type, nzBufferLock lock, unsigned int offset, unsigned int size)
{ {
NazaraUnused(length); NazaraUnused(size);
if (lock == nzBufferLock_DiscardAndWrite) if (lock == nzBufferLock_DiscardAndWrite)
{ {
@ -68,22 +68,24 @@ namespace
return nullptr; return nullptr;
} }
nzUInt8* LockBufferRange(nzBufferType type, nzBufferLock lock, unsigned int offset, unsigned int length) nzUInt8* LockBufferRange(nzBufferType type, nzBufferLock lock, unsigned int offset, unsigned int size)
{ {
return reinterpret_cast<nzUInt8*>(glMapBufferRange(bufferTarget[type], offset, length, bufferLockRange[lock])); return reinterpret_cast<nzUInt8*>(glMapBufferRange(bufferTarget[type], offset, size, bufferLockRange[lock]));
} }
nzUInt8* LockBufferFirstRun(nzBufferType type, nzBufferLock lock, unsigned int offset, unsigned int length) nzUInt8* LockBufferFirstRun(nzBufferType type, nzBufferLock lock, unsigned int offset, unsigned int size);
LockRoutine lockBuffer = LockBufferFirstRun;
nzUInt8* LockBufferFirstRun(nzBufferType type, nzBufferLock lock, unsigned int offset, unsigned int size)
{ {
if (glMapBufferRange) if (glMapBufferRange)
lockBuffer = LockBufferRange; lockBuffer = LockBufferRange;
else else
lockBuffer = LockBuffer; lockBuffer = LockBuffer;
return lockBuffer(type, lock, offset, length); return lockBuffer(type, lock, offset, size);
} }
LockRoutine lockBuffer = LockBufferFirstRun;
} }
NzHardwareBuffer::NzHardwareBuffer(NzBuffer* parent, nzBufferType type) : NzHardwareBuffer::NzHardwareBuffer(NzBuffer* parent, nzBufferType type) :
@ -101,7 +103,7 @@ void NzHardwareBuffer::Bind()
glBindBuffer(bufferTarget[m_type], m_buffer); glBindBuffer(bufferTarget[m_type], m_buffer);
} }
bool NzHardwareBuffer::Create(unsigned int length, nzUInt8 typeSize, nzBufferUsage usage) bool NzHardwareBuffer::Create(unsigned int size, nzBufferUsage usage)
{ {
m_buffer = 0; m_buffer = 0;
glGenBuffers(1, &m_buffer); glGenBuffers(1, &m_buffer);
@ -116,7 +118,7 @@ bool NzHardwareBuffer::Create(unsigned int length, nzUInt8 typeSize, nzBufferUsa
glGetIntegerv(bufferTargetBinding[m_type], &previous); glGetIntegerv(bufferTargetBinding[m_type], &previous);
glBindBuffer(bufferTarget[m_type], m_buffer); glBindBuffer(bufferTarget[m_type], m_buffer);
glBufferData(bufferTarget[m_type], length*typeSize, nullptr, bufferUsage[usage]); glBufferData(bufferTarget[m_type], size, nullptr, bufferUsage[usage]);
// Pour ne pas perturber le rendu, on interfère pas avec le binding déjà présent // Pour ne pas perturber le rendu, on interfère pas avec le binding déjà présent
if (previous != 0) if (previous != 0)
@ -130,7 +132,7 @@ void NzHardwareBuffer::Destroy()
glDeleteBuffers(1, &m_buffer); glDeleteBuffers(1, &m_buffer);
} }
bool NzHardwareBuffer::Fill(const void* data, unsigned int offset, unsigned int length) bool NzHardwareBuffer::Fill(const void* data, unsigned int offset, unsigned int size)
{ {
GLuint previous; GLuint previous;
glGetIntegerv(bufferTargetBinding[m_type], reinterpret_cast<GLint*>(&previous)); glGetIntegerv(bufferTargetBinding[m_type], reinterpret_cast<GLint*>(&previous));
@ -139,26 +141,24 @@ bool NzHardwareBuffer::Fill(const void* data, unsigned int offset, unsigned int
glBindBuffer(bufferTarget[m_type], m_buffer); glBindBuffer(bufferTarget[m_type], m_buffer);
// Il semblerait que glBufferSubData soit plus performant que glMapBuffer(Range) en dessous d'un certain seuil // Il semblerait que glBufferSubData soit plus performant que glMapBuffer(Range) en dessous d'un certain seuil
if (length < 32*1024) /*if (size < 32*1024)
{ {
if (length == m_parent->GetLength()) if (size == m_parent->GetLength())
glBufferData(bufferTarget[m_type], m_parent->GetSize(), data, bufferUsage[m_parent->GetStorage()]); glBufferData(bufferTarget[m_type], m_parent->GetSize(), data, bufferUsage[m_parent->GetStorage()]);
else else
{ glBufferSubData(bufferTarget[m_type], offset, size, data);
nzUInt8 typeSize = m_parent->GetTypeSize();
glBufferSubData(bufferTarget[m_type], offset*typeSize, length*typeSize, data);
}
} }
else else*/
{ {
nzUInt8* ptr = lockBuffer(m_type, (length == m_parent->GetLength()) ? nzBufferLock_DiscardAndWrite : nzBufferLock_WriteOnly, offset, length); // La longueur que nous recevons est en fait la taille
if (ptr) nzUInt8* ptr = lockBuffer(m_type, (size == m_parent->GetSize()) ? nzBufferLock_DiscardAndWrite : nzBufferLock_WriteOnly, offset, size);
if (!ptr)
{ {
NazaraError("Failed to lock buffer"); NazaraError("Failed to lock buffer");
return false; return false;
} }
std::memcpy(ptr, data, length*m_parent->GetTypeSize()); std::memcpy(ptr, data, size);
if (glUnmapBuffer(bufferTarget[m_type]) != GL_TRUE) if (glUnmapBuffer(bufferTarget[m_type]) != GL_TRUE)
{ {
@ -178,6 +178,11 @@ bool NzHardwareBuffer::Fill(const void* data, unsigned int offset, unsigned int
return true; return true;
} }
void* NzHardwareBuffer::GetBufferPtr()
{
return nullptr;
}
bool NzHardwareBuffer::IsHardware() const bool NzHardwareBuffer::IsHardware() const
{ {
return true; return true;

View File

@ -19,11 +19,13 @@ class NzHardwareBuffer : public NzBufferImpl
void Bind(); void Bind();
bool Create(unsigned int length, nzUInt8 typeSize, nzBufferUsage usage = nzBufferUsage_Static); bool Create(unsigned int size, nzBufferUsage usage = nzBufferUsage_Static);
void Destroy(); void Destroy();
bool Fill(const void* data, unsigned int offset, unsigned int length); bool Fill(const void* data, unsigned int offset, unsigned int length);
void* GetBufferPtr();
bool IsHardware() const; bool IsHardware() const;
void* Lock(nzBufferLock lock, unsigned int offset = 0, unsigned int length = 0); void* Lock(nzBufferLock lock, unsigned int offset = 0, unsigned int length = 0);

View File

@ -13,7 +13,20 @@ m_indexCount(indexCount),
m_startIndex(startIndex) m_startIndex(startIndex)
{ {
if (m_buffer) if (m_buffer)
{
#ifdef NAZARA_DEBUG
nzUInt8 indexSize = m_buffer->GetSize();
if (indexSize != 1 && indexSize != 2 && indexSize != 4)
{
NazaraError("Invalid index size (" + NzString::Number(indexSize) + ')');
m_buffer = nullptr;
throw std::runtime_error("Constructor failed");
}
#endif
m_buffer->AddResourceReference(); m_buffer->AddResourceReference();
}
} }
NzIndexBuffer::NzIndexBuffer(unsigned int length, nzUInt8 indexSize, nzBufferUsage usage) : NzIndexBuffer::NzIndexBuffer(unsigned int length, nzUInt8 indexSize, nzBufferUsage usage) :
@ -21,6 +34,16 @@ m_ownsBuffer(true),
m_indexCount(length), m_indexCount(length),
m_startIndex(0) m_startIndex(0)
{ {
#ifdef NAZARA_DEBUG
if (indexSize != 1 && indexSize != 2 && indexSize != 4)
{
NazaraError("Invalid index size");
m_buffer = nullptr;
throw std::runtime_error("Constructor failed");
}
#endif
m_buffer = new NzBuffer(nzBufferType_Index, length, indexSize, usage); m_buffer = new NzBuffer(nzBufferType_Index, length, indexSize, usage);
m_buffer->AddResourceReference(); m_buffer->AddResourceReference();
m_buffer->SetPersistent(false); m_buffer->SetPersistent(false);
@ -80,6 +103,32 @@ NzBuffer* NzIndexBuffer::GetBuffer() const
return m_buffer; return m_buffer;
} }
void* NzIndexBuffer::GetBufferPtr()
{
#if NAZARA_RENDERER_SAFE
if (!m_buffer)
{
NazaraError("Sequential index buffer: Buffer has no pointer");
return nullptr;
}
#endif
return reinterpret_cast<nzUInt8*>(m_buffer->GetBufferPtr()) + m_startIndex*m_buffer->GetTypeSize();
}
const void* NzIndexBuffer::GetBufferPtr() const
{
#if NAZARA_RENDERER_SAFE
if (!m_buffer)
{
NazaraError("Sequential index buffer: Buffer has no pointer");
return nullptr;
}
#endif
return reinterpret_cast<const nzUInt8*>(m_buffer->GetBufferPtr()) + m_startIndex*m_buffer->GetTypeSize();
}
nzUInt8 NzIndexBuffer::GetIndexSize() const nzUInt8 NzIndexBuffer::GetIndexSize() const
{ {
#if NAZARA_RENDERER_SAFE #if NAZARA_RENDERER_SAFE

View File

@ -6,14 +6,33 @@
#include <Nazara/Renderer/Renderer.hpp> #include <Nazara/Renderer/Renderer.hpp>
#include <Nazara/Core/Error.hpp> #include <Nazara/Core/Error.hpp>
#include <Nazara/Renderer/BufferImpl.hpp> #include <Nazara/Renderer/BufferImpl.hpp>
#include <Nazara/Renderer/IndexBuffer.hpp>
#include <Nazara/Renderer/RenderTarget.hpp>
#include <Nazara/Renderer/Shader.hpp>
#include <Nazara/Renderer/ShaderImpl.hpp> #include <Nazara/Renderer/ShaderImpl.hpp>
#include <Nazara/Renderer/VertexBuffer.hpp>
#include <stdexcept> #include <stdexcept>
#include <Nazara/Renderer/Debug.hpp> #include <Nazara/Renderer/Debug.hpp>
namespace
{
GLenum openglPrimitive[] = {
GL_LINES, // nzPrimitiveType_LineList,
GL_LINE_STRIP, // nzPrimitiveType_LineStrip,
GL_POINTS, // nzPrimitiveType_PointList,
GL_TRIANGLES, // nzPrimitiveType_TriangleList,
GL_TRIANGLE_STRIP, // nzPrimitiveType_TriangleStrip,
GL_TRIANGLE_FAN // nzPrimitiveType_TriangleFan
};
}
NzRenderer::NzRenderer() : NzRenderer::NzRenderer() :
m_indexBuffer(nullptr), m_indexBuffer(nullptr),
m_target(nullptr), m_target(nullptr),
m_shader(nullptr) m_shader(nullptr),
m_vertexBuffer(nullptr),
m_vertexDeclaration(nullptr),
m_vertexBufferUpdated(false)
{ {
#if NAZARA_RENDERER_SAFE #if NAZARA_RENDERER_SAFE
if (s_instance) if (s_instance)
@ -32,7 +51,7 @@ NzRenderer::~NzRenderer()
void NzRenderer::Clear(nzRendererClear flags) void NzRenderer::Clear(nzRendererClear flags)
{ {
#if NAZARA_DEBUG #ifdef NAZARA_DEBUG
if (NzContext::GetCurrent() == nullptr) if (NzContext::GetCurrent() == nullptr)
{ {
NazaraError("No active context"); NazaraError("No active context");
@ -57,6 +76,64 @@ void NzRenderer::Clear(nzRendererClear flags)
} }
} }
void NzRenderer::DrawIndexedPrimitives(nzPrimitiveType primitive, unsigned int firstIndex, unsigned int indexCount)
{
#ifdef NAZARA_DEBUG
if (!m_indexBuffer)
{
UngineError("No index buffer");
return;
}
#endif
if (!m_vertexBufferUpdated)
{
if (!UpdateVertexBuffer())
{
NazaraError("Failed to update vertex buffer");
return;
}
}
nzUInt8 indexSize = m_indexBuffer->GetIndexSize();
GLenum type;
switch (indexSize)
{
case 1:
type = GL_UNSIGNED_BYTE;
break;
case 2:
type = GL_UNSIGNED_SHORT;
break;
case 4:
type = GL_UNSIGNED_INT;
break;
default:
NazaraError("Invalid index size (" + NzString::Number(indexSize) + ')');
return;
}
glDrawElements(openglPrimitive[primitive], indexCount, type, reinterpret_cast<const nzUInt8*>(m_indexBuffer->GetBufferPtr()) + firstIndex*indexSize);
}
void NzRenderer::DrawPrimitives(nzPrimitiveType primitive, unsigned int firstVertex, unsigned int vertexCount)
{
if (!m_vertexBufferUpdated)
{
if (!UpdateVertexBuffer())
{
NazaraError("Failed to update vertex buffer");
return;
}
}
glDrawArrays(openglPrimitive[primitive], firstVertex, vertexCount);
}
NzShader* NzRenderer::GetShader() const NzShader* NzRenderer::GetShader() const
{ {
return m_shader; return m_shader;
@ -80,6 +157,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 2.0 m_capabilities[nzRendererCap_HardwareBuffer] = true; // Natif depuis OpenGL 2.0
m_capabilities[nzRendererCap_MultipleRenderTargets] = true; // Natif depuis OpenGL 2.0 m_capabilities[nzRendererCap_MultipleRenderTargets] = true; // Natif depuis OpenGL 2.0
m_capabilities[nzRendererCap_SoftwareBuffer] = NzOpenGL::GetVersion() <= 310; // Déprécié en OpenGL 3.1
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
m_capabilities[nzRendererCap_TextureMulti] = true; // Natif depuis OpenGL 1.3 m_capabilities[nzRendererCap_TextureMulti] = true; // Natif depuis OpenGL 1.3
@ -93,7 +171,7 @@ bool NzRenderer::Initialize()
void NzRenderer::SetClearColor(nzUInt8 r, nzUInt8 g, nzUInt8 b, nzUInt8 a) void NzRenderer::SetClearColor(nzUInt8 r, nzUInt8 g, nzUInt8 b, nzUInt8 a)
{ {
#if NAZARA_DEBUG #ifdef NAZARA_DEBUG
if (NzContext::GetCurrent() == nullptr) if (NzContext::GetCurrent() == nullptr)
{ {
NazaraError("No active context"); NazaraError("No active context");
@ -106,7 +184,7 @@ void NzRenderer::SetClearColor(nzUInt8 r, nzUInt8 g, nzUInt8 b, nzUInt8 a)
void NzRenderer::SetClearDepth(double depth) void NzRenderer::SetClearDepth(double depth)
{ {
#if NAZARA_DEBUG #ifdef NAZARA_DEBUG
if (NzContext::GetCurrent() == nullptr) if (NzContext::GetCurrent() == nullptr)
{ {
NazaraError("No active context"); NazaraError("No active context");
@ -119,7 +197,7 @@ void NzRenderer::SetClearDepth(double depth)
void NzRenderer::SetClearStencil(unsigned int value) void NzRenderer::SetClearStencil(unsigned int value)
{ {
#if NAZARA_DEBUG #ifdef NAZARA_DEBUG
if (NzContext::GetCurrent() == nullptr) if (NzContext::GetCurrent() == nullptr)
{ {
NazaraError("No active context"); NazaraError("No active context");
@ -164,6 +242,7 @@ bool NzRenderer::SetShader(NzShader* shader)
} }
m_shader = shader; m_shader = shader;
m_vertexBufferUpdated = false;
} }
else if (m_shader) else if (m_shader)
{ {
@ -213,18 +292,20 @@ bool NzRenderer::SetVertexBuffer(const NzVertexBuffer* vertexBuffer)
if (m_vertexBuffer == vertexBuffer) if (m_vertexBuffer == vertexBuffer)
return true; return true;
if (m_vertexBuffer && vertexBuffer)
{
// Si l'ancien buffer et le nouveau sont hardware, pas besoin de mettre à jour la déclaration
if (!m_vertexBuffer->IsHardware() || !vertexBuffer->IsHardware())
m_vertexBufferUpdated = false;
}
m_vertexBuffer = vertexBuffer; m_vertexBuffer = vertexBuffer;
m_vertexBufferUpdated = false;
return true; return true;
} }
bool NzRenderer::SetVertexDeclaration(const NzVertexBuffer* vertexBuffer) bool NzRenderer::SetVertexDeclaration(const NzVertexDeclaration* vertexDeclaration)
{ {
if (m_vertexBuffer == vertexBuffer) m_vertexDeclaration = vertexDeclaration;
return true;
m_vertexBuffer = vertexBuffer;
m_vertexBufferUpdated = false; m_vertexBufferUpdated = false;
return true; return true;
@ -256,4 +337,34 @@ NzRenderer* NzRenderer::Instance()
return s_instance; return s_instance;
} }
bool NzRenderer::UpdateVertexBuffer()
{
#if NAZARA_RENDERER_SAFE
if (!m_shader)
{
NazaraError("No shader");
return false;
}
if (!m_vertexBuffer)
{
NazaraError("No vertex buffer");
return false;
}
if (!m_vertexDeclaration)
{
NazaraError("No vertex declaration");
return false;
}
#endif
if (!m_shader->m_impl->UpdateVertexBuffer(m_vertexBuffer, m_vertexDeclaration))
return false;
m_vertexBufferUpdated = true;
return true;
}
NzRenderer* NzRenderer::s_instance = nullptr; NzRenderer* NzRenderer::s_instance = nullptr;

View File

@ -25,7 +25,7 @@ m_compiled(false)
{ {
Create(language); Create(language);
#if NAZARA_DEBUG #ifdef NAZARA_DEBUG
if (!m_impl) if (!m_impl)
{ {
NazaraError("Failed to create shader"); NazaraError("Failed to create shader");

View File

@ -3,5 +3,6 @@
// For conditions of distribution and use, see copyright notice in Config.hpp // For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Renderer/ShaderImpl.hpp> #include <Nazara/Renderer/ShaderImpl.hpp>
#include <Nazara/Renderer/Debug.hpp>
NzShaderImpl::~NzShaderImpl() = default; NzShaderImpl::~NzShaderImpl() = default;

View File

@ -9,8 +9,14 @@
#include <Nazara/Renderer/Shader.hpp> #include <Nazara/Renderer/Shader.hpp>
class NzRenderer;
class NzVertexBuffer;
class NzVertexDeclaration;
class NzShaderImpl class NzShaderImpl
{ {
friend class NzRenderer;
public: public:
NzShaderImpl() = default; NzShaderImpl() = default;
virtual ~NzShaderImpl(); virtual ~NzShaderImpl();
@ -38,6 +44,9 @@ class NzShaderImpl
virtual bool SendMatrix(const NzString& name, const NzMatrix4f& matrix) = 0; virtual bool SendMatrix(const NzString& name, const NzMatrix4f& matrix) = 0;
virtual void Unbind() = 0; virtual void Unbind() = 0;
protected:
virtual bool UpdateVertexBuffer(const NzVertexBuffer* vertexBuffer, const NzVertexDeclaration* vertexDeclaration) = 0;
}; };
#endif // NAZARA_SHADERIMPL_HPP #endif // NAZARA_SHADERIMPL_HPP

View File

@ -32,14 +32,14 @@ void NzSoftwareBuffer::Bind()
glBindBuffer(bufferTarget[m_type], 0); glBindBuffer(bufferTarget[m_type], 0);
} }
bool NzSoftwareBuffer::Create(unsigned int length, nzUInt8 typeSize, nzBufferUsage usage) bool NzSoftwareBuffer::Create(unsigned int size, nzBufferUsage usage)
{ {
NazaraUnused(usage); NazaraUnused(usage);
// Cette allocation est protégée car sa taille dépend directement de paramètres utilisateurs // Cette allocation est protégée car sa taille dépend directement de paramètres utilisateurs
try try
{ {
m_buffer = new nzUInt8[length*typeSize]; m_buffer = new nzUInt8[size];
} }
catch (const std::exception& e) catch (const std::exception& e)
{ {
@ -47,9 +47,7 @@ bool NzSoftwareBuffer::Create(unsigned int length, nzUInt8 typeSize, nzBufferUsa
return false; return false;
} }
m_length = length;
m_locked = false; m_locked = false;
m_typeSize = typeSize;
return true; return true;
} }
@ -59,7 +57,7 @@ void NzSoftwareBuffer::Destroy()
delete[] m_buffer; delete[] m_buffer;
} }
bool NzSoftwareBuffer::Fill(const void* data, unsigned int offset, unsigned int length) bool NzSoftwareBuffer::Fill(const void* data, unsigned int offset, unsigned int size)
{ {
#if NAZARA_RENDERER_SAFE #if NAZARA_RENDERER_SAFE
if (m_locked) if (m_locked)
@ -69,20 +67,25 @@ bool NzSoftwareBuffer::Fill(const void* data, unsigned int offset, unsigned int
} }
#endif #endif
std::memcpy(&m_buffer[offset*m_typeSize], data, length*m_typeSize); std::memcpy(&m_buffer[offset], data, size);
return true; return true;
} }
void* NzSoftwareBuffer::GetBufferPtr()
{
return m_buffer;
}
bool NzSoftwareBuffer::IsHardware() const bool NzSoftwareBuffer::IsHardware() const
{ {
return false; return false;
} }
void* NzSoftwareBuffer::Lock(nzBufferLock lock, unsigned int offset, unsigned int length) void* NzSoftwareBuffer::Lock(nzBufferLock lock, unsigned int offset, unsigned int size)
{ {
NazaraUnused(length);
NazaraUnused(lock); NazaraUnused(lock);
NazaraUnused(size);
#if NAZARA_RENDERER_SAFE #if NAZARA_RENDERER_SAFE
if (m_locked) if (m_locked)
@ -94,7 +97,7 @@ void* NzSoftwareBuffer::Lock(nzBufferLock lock, unsigned int offset, unsigned in
m_locked = true; m_locked = true;
return &m_buffer[offset*m_typeSize]; return &m_buffer[offset];
} }
bool NzSoftwareBuffer::Unlock() bool NzSoftwareBuffer::Unlock()

View File

@ -18,11 +18,13 @@ class NzSoftwareBuffer : public NzBufferImpl
void Bind(); void Bind();
bool Create(unsigned int length, nzUInt8 typeSize, nzBufferUsage usage = nzBufferUsage_Static); bool Create(unsigned int size, nzBufferUsage usage = nzBufferUsage_Static);
void Destroy(); void Destroy();
bool Fill(const void* data, unsigned int offset, unsigned int length); bool Fill(const void* data, unsigned int offset, unsigned int length);
void* GetBufferPtr();
bool IsHardware() const; bool IsHardware() const;
void* Lock(nzBufferLock lock, unsigned int offset = 0, unsigned int length = 0); void* Lock(nzBufferLock lock, unsigned int offset = 0, unsigned int length = 0);
@ -30,10 +32,8 @@ class NzSoftwareBuffer : public NzBufferImpl
private: private:
nzBufferType m_type; nzBufferType m_type;
nzUInt8 m_typeSize;
nzUInt8* m_buffer; nzUInt8* m_buffer;
bool m_locked; bool m_locked;
unsigned int m_length;
}; };
#endif // NAZARA_SOFTWAREBUFFER_HPP #endif // NAZARA_SOFTWAREBUFFER_HPP

View File

@ -67,6 +67,16 @@ NzBuffer* NzVertexBuffer::GetBuffer() const
return m_buffer; return m_buffer;
} }
void* NzVertexBuffer::GetBufferPtr()
{
return reinterpret_cast<nzUInt8*>(m_buffer->GetBufferPtr()) + m_startVertex*m_buffer->GetTypeSize();
}
const void* NzVertexBuffer::GetBufferPtr() const
{
return reinterpret_cast<const nzUInt8*>(m_buffer->GetBufferPtr()) + m_startVertex*m_buffer->GetTypeSize();
}
unsigned int NzVertexBuffer::GetStartVertex() const unsigned int NzVertexBuffer::GetStartVertex() const
{ {
return m_startVertex; return m_startVertex;

View File

@ -12,6 +12,7 @@
#include <Nazara/Renderer/Context.hpp> #include <Nazara/Renderer/Context.hpp>
#include <cstring> #include <cstring>
#include <iostream> #include <iostream>
#include <Nazara/Renderer/Debug.hpp>
NzContextImpl::NzContextImpl() NzContextImpl::NzContextImpl()
{ {

View File

@ -64,7 +64,7 @@ m_impl(nullptr)
{ {
Create(handle); Create(handle);
#if NAZARA_DEBUG #ifdef NAZARA_DEBUG
if (!m_impl) if (!m_impl)
{ {
NazaraError("Failed to create window"); NazaraError("Failed to create window");