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);
private:
static void EnsureInitialization();
static void Initialize();
static char* TimeInfo();
static void Uninitialize();

View File

@ -39,7 +39,6 @@ template<typename T> class NzEulerAngles
template<typename U> void Set(const NzEulerAngles<U>& angles);
void SetZero();
//NzEulerAngles<T> ToEulerAngles() const;
//NzMatrix3<T> ToRotationMatrix() const;
NzQuaternion<T> ToQuaternion() 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);
void* GetBufferPtr();
const void* GetBufferPtr() const;
NzBufferImpl* GetImpl() const;
unsigned int GetLength() const;
unsigned int GetSize() 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);
bool Unlock();
static bool IsHardwareSupported();
static bool IsSupported(nzBufferStorage storage);
private:
nzBufferStorage m_storage;

View File

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

View File

@ -8,19 +8,26 @@
#define NAZARA_RENDERER_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()
enum nzPrimitiveType
{
nzPrimitiveType_LineList,
nzPrimitiveType_LineStrip,
nzPrimitiveType_PointList,
nzPrimitiveType_TriangleList,
nzPrimitiveType_TriangleStrip,
nzPrimitiveType_TriangleFan
};
enum nzRendererCap
{
nzRendererCap_AnisotropicFilter,
nzRendererCap_FP64,
nzRendererCap_HardwareBuffer,
nzRendererCap_MultipleRenderTargets,
nzRendererCap_SoftwareBuffer,
nzRendererCap_Texture3D,
nzRendererCap_TextureCubemap,
nzRendererCap_TextureMulti,
@ -36,6 +43,12 @@ enum nzRendererClear
nzRendererClear_Stencil = 0x04
};
class NzRenderTarget;
class NzIndexBuffer;
class NzShader;
class NzVertexBuffer;
class NzVertexDeclaration;
class NAZARA_API NzRenderer
{
public:
@ -44,6 +57,9 @@ class NAZARA_API NzRenderer
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;
NzRenderTarget* GetTarget() const;
@ -67,12 +83,15 @@ class NAZARA_API NzRenderer
static NzRenderer* Instance();
private:
bool UpdateVertexBuffer();
static NzRenderer* s_instance;
const NzIndexBuffer* m_indexBuffer;
NzRenderTarget* m_target;
NzShader* m_shader;
const NzVertexBuffer* m_vertexBuffer;
const NzVertexDeclaration* m_vertexDeclaration;
bool m_capabilities[nzRendererCap_Count];
bool m_vertexBufferUpdated;
};

View File

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

View File

@ -23,11 +23,11 @@ enum nzElementType
enum nzElementUsage
{
nzElementType_Diffuse,
nzElementType_Normal,
nzElementType_Position,
nzElementType_Tangent,
nzElementType_TexCoord
nzElementUsage_Diffuse,
nzElementUsage_Normal,
nzElementUsage_Position,
nzElementUsage_Tangent,
nzElementUsage_TexCoord
};
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)
{
EnsureInitialization();
if (!initialized)
Initialize();
Block* ptr = reinterpret_cast<Block*>(std::malloc(size+sizeof(Block)));
if (!ptr)
@ -121,21 +122,6 @@ void NzMemoryManager::NextFree(const char* file, unsigned int line)
nextFreeLine = line;
}
void NzMemoryManager::EnsureInitialization()
{
if (!initialized)
{
Initialize();
if (std::atexit(Uninitialize) != 0)
{
static NzMemoryManager manager;
}
initialized = true;
}
}
void NzMemoryManager::Initialize()
{
char* time = TimeInfo();
@ -147,6 +133,13 @@ void NzMemoryManager::Initialize()
std::fclose(file);
std::free(time);
if (std::atexit(Uninitialize) != 0)
{
static NzMemoryManager manager;
}
initialized = true;
}
char* NzMemoryManager::TimeInfo()

View File

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

View File

@ -17,14 +17,16 @@ class NzBufferImpl
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 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 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;
};

View File

@ -6,15 +6,53 @@
#include <Nazara/Renderer/GLSLShader.hpp>
#include <Nazara/Core/Error.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>
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_GEOMETRY_SHADER, // nzShaderType_Geometry
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) :
@ -80,15 +118,16 @@ bool NzGLSLShader::Create()
return false;
}
glBindAttribLocation(m_program, 0, "Position");
glBindAttribLocation(m_program, 1, "Normal");
//glBindAttribLocation(m_program, 2, "Diffuse");
glBindAttribLocation(m_program, 3, "Tangent");
glBindAttribLocation(m_program, attribIndex[nzElementUsage_Position], "Position");
glBindAttribLocation(m_program, attribIndex[nzElementUsage_Normal], "Normal");
glBindAttribLocation(m_program, attribIndex[nzElementUsage_Diffuse], "Diffuse");
glBindAttribLocation(m_program, attribIndex[nzElementUsage_Tangent], "Tangent");
NzString uniformName = "TexCoord0";
for (unsigned int i = 0; i < 8; ++i)
{
NzString uniformName = "TexCoord" + NzString::Number(i);
glBindAttribLocation(m_program, 4+i, uniformName.GetConstBuffer());
uniformName[8] = '0'+i;
glBindAttribLocation(m_program, attribIndex[nzElementUsage_TexCoord]+i, uniformName.GetConstBuffer());
}
for (int i = 0; i < nzShaderType_Count; ++i)
@ -252,3 +291,29 @@ void NzGLSLShader::Unbind()
{
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();
private:
bool UpdateVertexBuffer(const NzVertexBuffer* vertexBuffer, const NzVertexDeclaration* vertexDeclaration);
mutable std::map<NzString, GLint> m_idCache;
GLuint m_program;
GLuint m_shaders[nzShaderType_Count];

View File

@ -43,11 +43,11 @@ namespace
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)
{
@ -68,22 +68,24 @@ namespace
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)
lockBuffer = LockBufferRange;
else
lockBuffer = LockBuffer;
return lockBuffer(type, lock, offset, length);
return lockBuffer(type, lock, offset, size);
}
LockRoutine lockBuffer = LockBufferFirstRun;
}
NzHardwareBuffer::NzHardwareBuffer(NzBuffer* parent, nzBufferType type) :
@ -101,7 +103,7 @@ void NzHardwareBuffer::Bind()
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;
glGenBuffers(1, &m_buffer);
@ -116,7 +118,7 @@ bool NzHardwareBuffer::Create(unsigned int length, nzUInt8 typeSize, nzBufferUsa
glGetIntegerv(bufferTargetBinding[m_type], &previous);
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
if (previous != 0)
@ -130,7 +132,7 @@ void NzHardwareBuffer::Destroy()
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;
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);
// 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()]);
else
{
nzUInt8 typeSize = m_parent->GetTypeSize();
glBufferSubData(bufferTarget[m_type], offset*typeSize, length*typeSize, data);
}
glBufferSubData(bufferTarget[m_type], offset, size, data);
}
else
else*/
{
nzUInt8* ptr = lockBuffer(m_type, (length == m_parent->GetLength()) ? nzBufferLock_DiscardAndWrite : nzBufferLock_WriteOnly, offset, length);
if (ptr)
// La longueur que nous recevons est en fait la taille
nzUInt8* ptr = lockBuffer(m_type, (size == m_parent->GetSize()) ? nzBufferLock_DiscardAndWrite : nzBufferLock_WriteOnly, offset, size);
if (!ptr)
{
NazaraError("Failed to lock buffer");
return false;
}
std::memcpy(ptr, data, length*m_parent->GetTypeSize());
std::memcpy(ptr, data, size);
if (glUnmapBuffer(bufferTarget[m_type]) != GL_TRUE)
{
@ -178,6 +178,11 @@ bool NzHardwareBuffer::Fill(const void* data, unsigned int offset, unsigned int
return true;
}
void* NzHardwareBuffer::GetBufferPtr()
{
return nullptr;
}
bool NzHardwareBuffer::IsHardware() const
{
return true;

View File

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

View File

@ -13,7 +13,20 @@ m_indexCount(indexCount),
m_startIndex(startIndex)
{
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();
}
}
NzIndexBuffer::NzIndexBuffer(unsigned int length, nzUInt8 indexSize, nzBufferUsage usage) :
@ -21,6 +34,16 @@ m_ownsBuffer(true),
m_indexCount(length),
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->AddResourceReference();
m_buffer->SetPersistent(false);
@ -80,6 +103,32 @@ NzBuffer* NzIndexBuffer::GetBuffer() const
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
{
#if NAZARA_RENDERER_SAFE

View File

@ -6,14 +6,33 @@
#include <Nazara/Renderer/Renderer.hpp>
#include <Nazara/Core/Error.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/VertexBuffer.hpp>
#include <stdexcept>
#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() :
m_indexBuffer(nullptr),
m_target(nullptr),
m_shader(nullptr)
m_shader(nullptr),
m_vertexBuffer(nullptr),
m_vertexDeclaration(nullptr),
m_vertexBufferUpdated(false)
{
#if NAZARA_RENDERER_SAFE
if (s_instance)
@ -32,7 +51,7 @@ NzRenderer::~NzRenderer()
void NzRenderer::Clear(nzRendererClear flags)
{
#if NAZARA_DEBUG
#ifdef NAZARA_DEBUG
if (NzContext::GetCurrent() == nullptr)
{
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
{
return m_shader;
@ -80,6 +157,7 @@ bool NzRenderer::Initialize()
m_capabilities[nzRendererCap_FP64] = NzOpenGL::IsSupported(NzOpenGL::FP64);
m_capabilities[nzRendererCap_HardwareBuffer] = 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_TextureCubemap] = 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)
{
#if NAZARA_DEBUG
#ifdef NAZARA_DEBUG
if (NzContext::GetCurrent() == nullptr)
{
NazaraError("No active context");
@ -106,7 +184,7 @@ void NzRenderer::SetClearColor(nzUInt8 r, nzUInt8 g, nzUInt8 b, nzUInt8 a)
void NzRenderer::SetClearDepth(double depth)
{
#if NAZARA_DEBUG
#ifdef NAZARA_DEBUG
if (NzContext::GetCurrent() == nullptr)
{
NazaraError("No active context");
@ -119,7 +197,7 @@ void NzRenderer::SetClearDepth(double depth)
void NzRenderer::SetClearStencil(unsigned int value)
{
#if NAZARA_DEBUG
#ifdef NAZARA_DEBUG
if (NzContext::GetCurrent() == nullptr)
{
NazaraError("No active context");
@ -164,6 +242,7 @@ bool NzRenderer::SetShader(NzShader* shader)
}
m_shader = shader;
m_vertexBufferUpdated = false;
}
else if (m_shader)
{
@ -213,18 +292,20 @@ bool NzRenderer::SetVertexBuffer(const NzVertexBuffer* 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
if (!m_vertexBuffer->IsHardware() || !vertexBuffer->IsHardware())
m_vertexBufferUpdated = false;
}
m_vertexBuffer = vertexBuffer;
m_vertexBufferUpdated = false;
return true;
}
bool NzRenderer::SetVertexDeclaration(const NzVertexBuffer* vertexBuffer)
bool NzRenderer::SetVertexDeclaration(const NzVertexDeclaration* vertexDeclaration)
{
if (m_vertexBuffer == vertexBuffer)
return true;
m_vertexBuffer = vertexBuffer;
m_vertexDeclaration = vertexDeclaration;
m_vertexBufferUpdated = false;
return true;
@ -256,4 +337,34 @@ NzRenderer* NzRenderer::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;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -67,6 +67,16 @@ NzBuffer* NzVertexBuffer::GetBuffer() const
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
{
return m_startVertex;

View File

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

View File

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