Added support for Instancing
Former-commit-id: 62f5f3186423b01f7a0ac2762969dca12bea1327
This commit is contained in:
parent
9b2eb8ce3f
commit
3b0751fb88
|
|
@ -28,8 +28,10 @@ enum nzOpenGLExtension
|
||||||
{
|
{
|
||||||
nzOpenGLExtension_AnisotropicFilter,
|
nzOpenGLExtension_AnisotropicFilter,
|
||||||
nzOpenGLExtension_DebugOutput,
|
nzOpenGLExtension_DebugOutput,
|
||||||
|
nzOpenGLExtension_DrawInstanced,
|
||||||
nzOpenGLExtension_FP64,
|
nzOpenGLExtension_FP64,
|
||||||
nzOpenGLExtension_FrameBufferObject,
|
nzOpenGLExtension_FrameBufferObject,
|
||||||
|
nzOpenGLExtension_InstancedArray,
|
||||||
nzOpenGLExtension_PixelBufferObject,
|
nzOpenGLExtension_PixelBufferObject,
|
||||||
nzOpenGLExtension_SamplerObjects,
|
nzOpenGLExtension_SamplerObjects,
|
||||||
nzOpenGLExtension_SeparateShaderObjects,
|
nzOpenGLExtension_SeparateShaderObjects,
|
||||||
|
|
@ -139,9 +141,11 @@ NAZARA_API extern PFNGLDEPTHMASKPROC glDepthMask;
|
||||||
NAZARA_API extern PFNGLDISABLEPROC glDisable;
|
NAZARA_API extern PFNGLDISABLEPROC glDisable;
|
||||||
NAZARA_API extern PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray;
|
NAZARA_API extern PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray;
|
||||||
NAZARA_API extern PFNGLDRAWARRAYSPROC glDrawArrays;
|
NAZARA_API extern PFNGLDRAWARRAYSPROC glDrawArrays;
|
||||||
|
NAZARA_API extern PFNGLDRAWARRAYSINSTANCEDPROC glDrawArraysInstanced;
|
||||||
NAZARA_API extern PFNGLDRAWBUFFERPROC glDrawBuffer;
|
NAZARA_API extern PFNGLDRAWBUFFERPROC glDrawBuffer;
|
||||||
NAZARA_API extern PFNGLDRAWBUFFERSPROC glDrawBuffers;
|
NAZARA_API extern PFNGLDRAWBUFFERSPROC glDrawBuffers;
|
||||||
NAZARA_API extern PFNGLDRAWELEMENTSPROC glDrawElements;
|
NAZARA_API extern PFNGLDRAWELEMENTSPROC glDrawElements;
|
||||||
|
NAZARA_API extern PFNGLDRAWELEMENTSINSTANCEDPROC glDrawElementsInstanced;
|
||||||
NAZARA_API extern PFNGLENABLEPROC glEnable;
|
NAZARA_API extern PFNGLENABLEPROC glEnable;
|
||||||
NAZARA_API extern PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray;
|
NAZARA_API extern PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray;
|
||||||
NAZARA_API extern PFNGLENDQUERYPROC glEndQuery;
|
NAZARA_API extern PFNGLENDQUERYPROC glEndQuery;
|
||||||
|
|
@ -234,6 +238,7 @@ NAZARA_API extern PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv;
|
||||||
NAZARA_API extern PFNGLUNMAPBUFFERPROC glUnmapBuffer;
|
NAZARA_API extern PFNGLUNMAPBUFFERPROC glUnmapBuffer;
|
||||||
NAZARA_API extern PFNGLUSEPROGRAMPROC glUseProgram;
|
NAZARA_API extern PFNGLUSEPROGRAMPROC glUseProgram;
|
||||||
NAZARA_API extern PFNGLVERTEXATTRIB4FPROC glVertexAttrib4f;
|
NAZARA_API extern PFNGLVERTEXATTRIB4FPROC glVertexAttrib4f;
|
||||||
|
NAZARA_API extern PFNGLVERTEXATTRIBDIVISORPROC glVertexAttribDivisor;
|
||||||
NAZARA_API extern PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer;
|
NAZARA_API extern PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer;
|
||||||
NAZARA_API extern PFNGLVIEWPORTPROC glViewport;
|
NAZARA_API extern PFNGLVIEWPORTPROC glViewport;
|
||||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||||
|
|
|
||||||
|
|
@ -27,16 +27,27 @@ class NzVertexDeclaration;
|
||||||
class NAZARA_API NzRenderer
|
class NAZARA_API NzRenderer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
struct InstancingData
|
||||||
|
{
|
||||||
|
NzMatrix4f worldMatrix;
|
||||||
|
};
|
||||||
|
|
||||||
NzRenderer() = delete;
|
NzRenderer() = delete;
|
||||||
~NzRenderer() = delete;
|
~NzRenderer() = delete;
|
||||||
|
|
||||||
static void Clear(unsigned long flags = nzRendererClear_Color | nzRendererClear_Depth);
|
static void Clear(unsigned long flags = nzRendererClear_Color | nzRendererClear_Depth);
|
||||||
|
|
||||||
static void DrawIndexedPrimitives(nzPrimitiveType primitive, unsigned int firstIndex, unsigned int indexCount);
|
static void DrawIndexedPrimitives(nzPrimitiveType primitive, unsigned int firstIndex, unsigned int indexCount);
|
||||||
|
static void DrawIndexedPrimitivesInstanced(unsigned int instanceCount, nzPrimitiveType primitive, unsigned int firstIndex, unsigned int indexCount);
|
||||||
static void DrawPrimitives(nzPrimitiveType primitive, unsigned int firstVertex, unsigned int vertexCount);
|
static void DrawPrimitives(nzPrimitiveType primitive, unsigned int firstVertex, unsigned int vertexCount);
|
||||||
|
static void DrawPrimitivesInstanced(unsigned int instanceCount, nzPrimitiveType primitive, unsigned int firstVertex, unsigned int vertexCount);
|
||||||
|
|
||||||
static void Enable(nzRendererParameter parameter, bool enable);
|
static void Enable(nzRendererParameter parameter, bool enable);
|
||||||
|
|
||||||
|
static void FillInstancingBuffer(const InstancingData* instancingData, unsigned int instanceCount);
|
||||||
|
|
||||||
|
static void Flush();
|
||||||
|
|
||||||
static float GetLineWidth();
|
static float GetLineWidth();
|
||||||
//static NzMatrix4f GetMatrix(nzMatrixCombination combination);
|
//static NzMatrix4f GetMatrix(nzMatrixCombination combination);
|
||||||
static NzMatrix4f GetMatrix(nzMatrixType type);
|
static NzMatrix4f GetMatrix(nzMatrixType type);
|
||||||
|
|
|
||||||
|
|
@ -111,24 +111,25 @@ bool NzGLSLShader::Create()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzElementUsage_TexCoord]+8, "InstanceMatrix");
|
||||||
|
|
||||||
glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzElementUsage_Position], "VertexPosition");
|
glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzElementUsage_Position], "VertexPosition");
|
||||||
glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzElementUsage_Normal], "VertexNormal");
|
glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzElementUsage_Normal], "VertexNormal");
|
||||||
glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzElementUsage_Diffuse], "VertexDiffuse");
|
glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzElementUsage_Diffuse], "VertexDiffuse");
|
||||||
glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzElementUsage_Tangent], "VertexTangent");
|
glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzElementUsage_Tangent], "VertexTangent");
|
||||||
|
|
||||||
NzString uniform;
|
char texCoordsUniform[] = "VertexTexCoord*";
|
||||||
uniform.Reserve(16); // 14 + 2
|
|
||||||
uniform = "VertexTexCoord";
|
|
||||||
|
|
||||||
unsigned int maxTexCoords = NzRenderer::GetMaxTextureUnits();
|
unsigned int maxTexCoords = std::min(8U, NzRenderer::GetMaxTextureUnits());
|
||||||
for (unsigned int i = 0; i < maxTexCoords; ++i)
|
for (unsigned int i = 0; i < maxTexCoords; ++i)
|
||||||
{
|
{
|
||||||
NzString uniformName = uniform + NzString::Number(i);
|
texCoordsUniform[14] = '0' + i;
|
||||||
glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzElementUsage_TexCoord]+i, uniformName.GetConstBuffer());
|
glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzElementUsage_TexCoord]+i, texCoordsUniform);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NzRenderer::HasCapability(nzRendererCap_MultipleRenderTargets))
|
if (NzRenderer::HasCapability(nzRendererCap_MultipleRenderTargets))
|
||||||
{
|
{
|
||||||
|
NzString uniform;
|
||||||
uniform.Reserve(14); // 12 + 2
|
uniform.Reserve(14); // 12 + 2
|
||||||
uniform = "RenderTarget";
|
uniform = "RenderTarget";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -413,6 +413,37 @@ bool NzOpenGL::Initialize()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DrawInstanced
|
||||||
|
if (s_openglVersion >= 330)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
glDrawArraysInstanced = reinterpret_cast<PFNGLDRAWARRAYSINSTANCEDPROC>(LoadEntry("glDrawArraysInstanced"));
|
||||||
|
glDrawElementsInstanced = reinterpret_cast<PFNGLDRAWELEMENTSINSTANCEDPROC>(LoadEntry("glDrawElementsInstanced"));
|
||||||
|
|
||||||
|
s_openGLextensions[nzOpenGLExtension_DrawInstanced] = true;
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
NazaraWarning("Failed to load GL_ARB_draw_instanced: " + NzString(e.what()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!s_openGLextensions[nzOpenGLExtension_DrawInstanced] && IsSupported("GL_ARB_draw_instanced"))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
glDrawArraysInstanced = reinterpret_cast<PFNGLDRAWARRAYSINSTANCEDARBPROC>(LoadEntry("glDrawArraysInstancedARB"));
|
||||||
|
glDrawElementsInstanced = reinterpret_cast<PFNGLDRAWELEMENTSINSTANCEDARBPROC>(LoadEntry("glDrawElementsInstancedARB"));
|
||||||
|
|
||||||
|
s_openGLextensions[nzOpenGLExtension_DrawInstanced] = true;
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
NazaraWarning("Failed to load GL_ARB_draw_instanced: " + NzString(e.what()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// FP64
|
// FP64
|
||||||
if (s_openglVersion >= 400 || IsSupported("GL_ARB_gpu_shader_fp64"))
|
if (s_openglVersion >= 400 || IsSupported("GL_ARB_gpu_shader_fp64"))
|
||||||
{
|
{
|
||||||
|
|
@ -460,6 +491,35 @@ bool NzOpenGL::Initialize()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// InstancedArray
|
||||||
|
if (s_openglVersion >= 330)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
glVertexAttribDivisor = reinterpret_cast<PFNGLVERTEXATTRIBDIVISORPROC>(LoadEntry("glVertexAttribDivisor"));
|
||||||
|
|
||||||
|
s_openGLextensions[nzOpenGLExtension_InstancedArray] = true;
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
NazaraWarning("Failed to load GL_ARB_instanced_arrays: " + NzString(e.what()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!s_openGLextensions[nzOpenGLExtension_InstancedArray] && IsSupported("GL_ARB_instanced_arrays"))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
glVertexAttribDivisor = reinterpret_cast<PFNGLVERTEXATTRIBDIVISORARBPROC>(LoadEntry("glVertexAttribDivisorARB"));
|
||||||
|
|
||||||
|
s_openGLextensions[nzOpenGLExtension_InstancedArray] = true;
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
NazaraWarning("Failed to load GL_ARB_instanced_arrays: " + NzString(e.what()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// PixelBufferObject
|
// PixelBufferObject
|
||||||
s_openGLextensions[nzOpenGLExtension_PixelBufferObject] = (s_openglVersion >= 210 || IsSupported("GL_ARB_pixel_buffer_object"));
|
s_openGLextensions[nzOpenGLExtension_PixelBufferObject] = (s_openglVersion >= 210 || IsSupported("GL_ARB_pixel_buffer_object"));
|
||||||
|
|
||||||
|
|
@ -980,9 +1040,11 @@ PFNGLDEPTHMASKPROC glDepthMask = nullptr;
|
||||||
PFNGLDISABLEPROC glDisable = nullptr;
|
PFNGLDISABLEPROC glDisable = nullptr;
|
||||||
PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray = nullptr;
|
PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray = nullptr;
|
||||||
PFNGLDRAWARRAYSPROC glDrawArrays = nullptr;
|
PFNGLDRAWARRAYSPROC glDrawArrays = nullptr;
|
||||||
|
PFNGLDRAWARRAYSINSTANCEDPROC glDrawArraysInstanced = nullptr;
|
||||||
PFNGLDRAWBUFFERPROC glDrawBuffer = nullptr;
|
PFNGLDRAWBUFFERPROC glDrawBuffer = nullptr;
|
||||||
PFNGLDRAWBUFFERSPROC glDrawBuffers = nullptr;
|
PFNGLDRAWBUFFERSPROC glDrawBuffers = nullptr;
|
||||||
PFNGLDRAWELEMENTSPROC glDrawElements = nullptr;
|
PFNGLDRAWELEMENTSPROC glDrawElements = nullptr;
|
||||||
|
PFNGLDRAWELEMENTSINSTANCEDPROC glDrawElementsInstanced = nullptr;
|
||||||
PFNGLENABLEPROC glEnable = nullptr;
|
PFNGLENABLEPROC glEnable = nullptr;
|
||||||
PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray = nullptr;
|
PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray = nullptr;
|
||||||
PFNGLENDQUERYPROC glEndQuery = nullptr;
|
PFNGLENDQUERYPROC glEndQuery = nullptr;
|
||||||
|
|
@ -1075,6 +1137,7 @@ PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv = nullptr;
|
||||||
PFNGLUNMAPBUFFERPROC glUnmapBuffer = nullptr;
|
PFNGLUNMAPBUFFERPROC glUnmapBuffer = nullptr;
|
||||||
PFNGLUSEPROGRAMPROC glUseProgram = nullptr;
|
PFNGLUSEPROGRAMPROC glUseProgram = nullptr;
|
||||||
PFNGLVERTEXATTRIB4FPROC glVertexAttrib4f = nullptr;
|
PFNGLVERTEXATTRIB4FPROC glVertexAttrib4f = nullptr;
|
||||||
|
PFNGLVERTEXATTRIBDIVISORPROC glVertexAttribDivisor = nullptr;
|
||||||
PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer = nullptr;
|
PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer = nullptr;
|
||||||
PFNGLVIEWPORTPROC glViewport = nullptr;
|
PFNGLVIEWPORTPROC glViewport = nullptr;
|
||||||
#if defined(NAZARA_PLATFORM_WINDOWS)
|
#if defined(NAZARA_PLATFORM_WINDOWS)
|
||||||
|
|
|
||||||
|
|
@ -60,9 +60,8 @@ namespace
|
||||||
|
|
||||||
std::map<VAO_Key, unsigned int> s_vaos;
|
std::map<VAO_Key, unsigned int> s_vaos;
|
||||||
std::vector<TextureUnit> s_textureUnits;
|
std::vector<TextureUnit> s_textureUnits;
|
||||||
|
NzBuffer* s_instancingBuffer = nullptr;
|
||||||
NzMatrix4f s_matrix[totalMatrixCount];
|
NzMatrix4f s_matrix[totalMatrixCount];
|
||||||
int s_matrixLocation[totalMatrixCount];
|
|
||||||
bool s_matrixUpdated[totalMatrixCount];
|
|
||||||
nzBlendFunc s_srcBlend;
|
nzBlendFunc s_srcBlend;
|
||||||
nzBlendFunc s_dstBlend;
|
nzBlendFunc s_dstBlend;
|
||||||
nzFaceCulling s_faceCulling;
|
nzFaceCulling s_faceCulling;
|
||||||
|
|
@ -79,12 +78,15 @@ namespace
|
||||||
const NzShader* s_shader;
|
const NzShader* s_shader;
|
||||||
const NzVertexBuffer* s_vertexBuffer;
|
const NzVertexBuffer* s_vertexBuffer;
|
||||||
const NzVertexDeclaration* s_vertexDeclaration;
|
const NzVertexDeclaration* s_vertexDeclaration;
|
||||||
bool s_vaoUpdated;
|
|
||||||
bool s_capabilities[nzRendererCap_Max+1];
|
bool s_capabilities[nzRendererCap_Max+1];
|
||||||
|
bool s_instancingEnabled;
|
||||||
|
bool s_matrixUpdated[totalMatrixCount];
|
||||||
bool s_stencilFuncUpdated;
|
bool s_stencilFuncUpdated;
|
||||||
bool s_stencilOpUpdated;
|
bool s_stencilOpUpdated;
|
||||||
bool s_useSamplerObjects;
|
bool s_useSamplerObjects;
|
||||||
bool s_useVertexArrayObjects;
|
bool s_useVertexArrayObjects;
|
||||||
|
bool s_vaoUpdated;
|
||||||
|
int s_matrixLocation[totalMatrixCount];
|
||||||
unsigned int s_maxRenderTarget;
|
unsigned int s_maxRenderTarget;
|
||||||
unsigned int s_maxTextureUnit;
|
unsigned int s_maxTextureUnit;
|
||||||
unsigned int s_stencilReference;
|
unsigned int s_stencilReference;
|
||||||
|
|
@ -147,6 +149,12 @@ void NzRenderer::DrawIndexedPrimitives(nzPrimitiveType primitive, unsigned int f
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (s_instancingEnabled)
|
||||||
|
{
|
||||||
|
glDisableVertexAttribArray(NzOpenGL::AttributeIndex[nzElementUsage_TexCoord]+8);
|
||||||
|
s_instancingEnabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (s_indexBuffer->IsSequential())
|
if (s_indexBuffer->IsSequential())
|
||||||
glDrawArrays(NzOpenGL::PrimitiveType[primitive], s_indexBuffer->GetStartIndex(), s_indexBuffer->GetIndexCount());
|
glDrawArrays(NzOpenGL::PrimitiveType[primitive], s_indexBuffer->GetStartIndex(), s_indexBuffer->GetIndexCount());
|
||||||
else
|
else
|
||||||
|
|
@ -168,6 +176,81 @@ void NzRenderer::DrawIndexedPrimitives(nzPrimitiveType primitive, unsigned int f
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NzRenderer::DrawIndexedPrimitivesInstanced(unsigned int instanceCount, nzPrimitiveType primitive, unsigned int firstIndex, unsigned int indexCount)
|
||||||
|
{
|
||||||
|
#ifdef NAZARA_DEBUG
|
||||||
|
if (NzContext::GetCurrent() == nullptr)
|
||||||
|
{
|
||||||
|
NazaraError("No active context");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (primitive > nzPrimitiveType_Max)
|
||||||
|
{
|
||||||
|
NazaraError("Primitive type out of enum");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if NAZARA_RENDERER_SAFE
|
||||||
|
if (!s_capabilities[nzRendererCap_Instancing])
|
||||||
|
{
|
||||||
|
NazaraError("Instancing not supported");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!s_indexBuffer)
|
||||||
|
{
|
||||||
|
NazaraError("No index buffer");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instanceCount == 0)
|
||||||
|
{
|
||||||
|
NazaraError("Instance count must be over 0");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instanceCount > NAZARA_RENDERER_INSTANCING_MAX)
|
||||||
|
{
|
||||||
|
NazaraError("Instance count is over maximum instance count (" + NzString::Number(instanceCount) + " >= " + NzString::Number(NAZARA_RENDERER_INSTANCING_MAX) + ')');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!EnsureStateUpdate())
|
||||||
|
{
|
||||||
|
NazaraError("Failed to update states");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!s_instancingEnabled)
|
||||||
|
{
|
||||||
|
glEnableVertexAttribArray(NzOpenGL::AttributeIndex[nzElementUsage_TexCoord]+8);
|
||||||
|
s_instancingEnabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s_indexBuffer->IsSequential())
|
||||||
|
glDrawArraysInstanced(NzOpenGL::PrimitiveType[primitive], s_indexBuffer->GetStartIndex(), s_indexBuffer->GetIndexCount(), instanceCount);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GLenum type;
|
||||||
|
const nzUInt8* ptr = reinterpret_cast<const nzUInt8*>(s_indexBuffer->GetPointer());
|
||||||
|
if (s_indexBuffer->HasLargeIndices())
|
||||||
|
{
|
||||||
|
ptr += firstIndex*sizeof(nzUInt32);
|
||||||
|
type = GL_UNSIGNED_INT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ptr += firstIndex*sizeof(nzUInt16);
|
||||||
|
type = GL_UNSIGNED_SHORT;
|
||||||
|
}
|
||||||
|
|
||||||
|
glDrawElementsInstanced(NzOpenGL::PrimitiveType[primitive], indexCount, type, ptr, instanceCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void NzRenderer::DrawPrimitives(nzPrimitiveType primitive, unsigned int firstVertex, unsigned int vertexCount)
|
void NzRenderer::DrawPrimitives(nzPrimitiveType primitive, unsigned int firstVertex, unsigned int vertexCount)
|
||||||
{
|
{
|
||||||
#ifdef NAZARA_DEBUG
|
#ifdef NAZARA_DEBUG
|
||||||
|
|
@ -190,9 +273,66 @@ void NzRenderer::DrawPrimitives(nzPrimitiveType primitive, unsigned int firstVer
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (s_instancingEnabled)
|
||||||
|
{
|
||||||
|
glDisableVertexAttribArray(NzOpenGL::AttributeIndex[nzElementUsage_TexCoord]+8);
|
||||||
|
s_instancingEnabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
glDrawArrays(NzOpenGL::PrimitiveType[primitive], firstVertex, vertexCount);
|
glDrawArrays(NzOpenGL::PrimitiveType[primitive], firstVertex, vertexCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NzRenderer::DrawPrimitivesInstanced(unsigned int instanceCount, nzPrimitiveType primitive, unsigned int firstVertex, unsigned int vertexCount)
|
||||||
|
{
|
||||||
|
#ifdef NAZARA_DEBUG
|
||||||
|
if (NzContext::GetCurrent() == nullptr)
|
||||||
|
{
|
||||||
|
NazaraError("No active context");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (primitive > nzPrimitiveType_Max)
|
||||||
|
{
|
||||||
|
NazaraError("Primitive type out of enum");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if NAZARA_RENDERER_SAFE
|
||||||
|
if (!s_capabilities[nzRendererCap_Instancing])
|
||||||
|
{
|
||||||
|
NazaraError("Instancing not supported");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instanceCount == 0)
|
||||||
|
{
|
||||||
|
NazaraError("Instance count must be over 0");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instanceCount > NAZARA_RENDERER_INSTANCING_MAX)
|
||||||
|
{
|
||||||
|
NazaraError("Instance count is over maximum instance count (" + NzString::Number(instanceCount) + " >= " + NzString::Number(NAZARA_RENDERER_INSTANCING_MAX) + ')');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!EnsureStateUpdate())
|
||||||
|
{
|
||||||
|
NazaraError("Failed to update states");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!s_instancingEnabled)
|
||||||
|
{
|
||||||
|
glEnableVertexAttribArray(NzOpenGL::AttributeIndex[nzElementUsage_TexCoord]+8);
|
||||||
|
s_instancingEnabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
glDrawArraysInstanced(NzOpenGL::PrimitiveType[primitive], firstVertex, vertexCount, instanceCount);
|
||||||
|
}
|
||||||
|
|
||||||
void NzRenderer::Enable(nzRendererParameter parameter, bool enable)
|
void NzRenderer::Enable(nzRendererParameter parameter, bool enable)
|
||||||
{
|
{
|
||||||
#ifdef NAZARA_DEBUG
|
#ifdef NAZARA_DEBUG
|
||||||
|
|
@ -229,6 +369,43 @@ void NzRenderer::Enable(nzRendererParameter parameter, bool enable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NzRenderer::FillInstancingBuffer(const NzRenderer::InstancingData* instancingData, unsigned int instanceCount)
|
||||||
|
{
|
||||||
|
#if NAZARA_RENDERER_SAFE
|
||||||
|
if (!s_capabilities[nzRendererCap_Instancing])
|
||||||
|
{
|
||||||
|
NazaraError("Instancing not supported");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!instancingData)
|
||||||
|
{
|
||||||
|
NazaraError("Instancing data must be valid");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instanceCount == 0)
|
||||||
|
{
|
||||||
|
NazaraError("Instance count must be over 0");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instanceCount > NAZARA_RENDERER_INSTANCING_MAX)
|
||||||
|
{
|
||||||
|
NazaraError("Instance count is over maximum instance count (" + NzString::Number(instanceCount) + " >= " + NzString::Number(NAZARA_RENDERER_INSTANCING_MAX) + ')');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!s_instancingBuffer->Fill(instancingData, 0, instanceCount))
|
||||||
|
NazaraError("Failed to fill instancing buffer");
|
||||||
|
}
|
||||||
|
|
||||||
|
void NzRenderer::Flush()
|
||||||
|
{
|
||||||
|
glFlush();
|
||||||
|
}
|
||||||
|
|
||||||
float NzRenderer::GetLineWidth()
|
float NzRenderer::GetLineWidth()
|
||||||
{
|
{
|
||||||
#ifdef NAZARA_DEBUG
|
#ifdef NAZARA_DEBUG
|
||||||
|
|
@ -387,6 +564,8 @@ bool NzRenderer::Initialize(bool initializeDebugDrawer)
|
||||||
|
|
||||||
NzContext::EnsureContext();
|
NzContext::EnsureContext();
|
||||||
|
|
||||||
|
NzBuffer::SetBufferFunction(nzBufferStorage_Hardware, HardwareBufferFunction);
|
||||||
|
|
||||||
for (unsigned int i = 0; i < totalMatrixCount; ++i)
|
for (unsigned int i = 0; i < totalMatrixCount; ++i)
|
||||||
{
|
{
|
||||||
s_matrix[i].MakeIdentity();
|
s_matrix[i].MakeIdentity();
|
||||||
|
|
@ -398,8 +577,8 @@ bool NzRenderer::Initialize(bool initializeDebugDrawer)
|
||||||
s_capabilities[nzRendererCap_AnisotropicFilter] = NzOpenGL::IsSupported(nzOpenGLExtension_AnisotropicFilter);
|
s_capabilities[nzRendererCap_AnisotropicFilter] = NzOpenGL::IsSupported(nzOpenGLExtension_AnisotropicFilter);
|
||||||
s_capabilities[nzRendererCap_FP64] = NzOpenGL::IsSupported(nzOpenGLExtension_FP64);
|
s_capabilities[nzRendererCap_FP64] = NzOpenGL::IsSupported(nzOpenGLExtension_FP64);
|
||||||
s_capabilities[nzRendererCap_HardwareBuffer] = true; // Natif depuis OpenGL 1.5
|
s_capabilities[nzRendererCap_HardwareBuffer] = true; // Natif depuis OpenGL 1.5
|
||||||
// MultipleRenderTargets (Techniquement natif depuis OpenGL 2.0 mais inutile sans glBindFragDataLocation)
|
s_capabilities[nzRendererCap_Instancing] = NzOpenGL::IsSupported(nzOpenGLExtension_DrawInstanced) && NzOpenGL::IsSupported(nzOpenGLExtension_InstancedArray);
|
||||||
s_capabilities[nzRendererCap_MultipleRenderTargets] = (glBindFragDataLocation != nullptr);
|
s_capabilities[nzRendererCap_MultipleRenderTargets] = (glBindFragDataLocation != nullptr); // Natif depuis OpenGL 2.0 mais inutile sans glBindFragDataLocation
|
||||||
s_capabilities[nzRendererCap_OcclusionQuery] = true; // Natif depuis OpenGL 1.5
|
s_capabilities[nzRendererCap_OcclusionQuery] = true; // Natif depuis OpenGL 1.5
|
||||||
s_capabilities[nzRendererCap_PixelBufferObject] = NzOpenGL::IsSupported(nzOpenGLExtension_PixelBufferObject);
|
s_capabilities[nzRendererCap_PixelBufferObject] = NzOpenGL::IsSupported(nzOpenGLExtension_PixelBufferObject);
|
||||||
s_capabilities[nzRendererCap_RenderTexture] = NzOpenGL::IsSupported(nzOpenGLExtension_FrameBufferObject);
|
s_capabilities[nzRendererCap_RenderTexture] = NzOpenGL::IsSupported(nzOpenGLExtension_FrameBufferObject);
|
||||||
|
|
@ -418,6 +597,35 @@ bool NzRenderer::Initialize(bool initializeDebugDrawer)
|
||||||
else
|
else
|
||||||
s_maxAnisotropyLevel = 1;
|
s_maxAnisotropyLevel = 1;
|
||||||
|
|
||||||
|
if (s_capabilities[nzRendererCap_Instancing])
|
||||||
|
{
|
||||||
|
s_instancingBuffer = new NzBuffer(nzBufferType_Vertex);
|
||||||
|
if (s_instancingBuffer->Create(NAZARA_RENDERER_INSTANCING_MAX, sizeof(InstancingData), nzBufferStorage_Hardware, nzBufferUsage_Dynamic))
|
||||||
|
{
|
||||||
|
static_cast<NzHardwareBuffer*>(s_instancingBuffer->GetImpl())->Bind();
|
||||||
|
|
||||||
|
unsigned int instanceMatrixIndex = NzOpenGL::AttributeIndex[nzElementUsage_TexCoord] + 8;
|
||||||
|
for (unsigned int i = 0; i < 4; ++i)
|
||||||
|
{
|
||||||
|
glVertexAttribPointer(instanceMatrixIndex, 4, GL_FLOAT, GL_FALSE, sizeof(InstancingData), reinterpret_cast<GLvoid*>(offsetof(InstancingData, worldMatrix) + sizeof(float)*4*i));
|
||||||
|
glVertexAttribDivisor(instanceMatrixIndex, 1);
|
||||||
|
|
||||||
|
instanceMatrixIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
s_instancingEnabled = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s_capabilities[nzRendererCap_Instancing] = false;
|
||||||
|
|
||||||
|
delete s_instancingBuffer;
|
||||||
|
s_instancingBuffer = nullptr;
|
||||||
|
|
||||||
|
NazaraWarning("Failed to create instancing buffer, disabled instancing.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (s_capabilities[nzRendererCap_MultipleRenderTargets])
|
if (s_capabilities[nzRendererCap_MultipleRenderTargets])
|
||||||
{
|
{
|
||||||
GLint maxDrawBuffers;
|
GLint maxDrawBuffers;
|
||||||
|
|
@ -467,8 +675,6 @@ bool NzRenderer::Initialize(bool initializeDebugDrawer)
|
||||||
s_vertexBuffer = nullptr;
|
s_vertexBuffer = nullptr;
|
||||||
s_vertexDeclaration = nullptr;
|
s_vertexDeclaration = nullptr;
|
||||||
|
|
||||||
NzBuffer::SetBufferFunction(nzBufferStorage_Hardware, HardwareBufferFunction);
|
|
||||||
|
|
||||||
if (initializeDebugDrawer && !NzDebugDrawer::Initialize())
|
if (initializeDebugDrawer && !NzDebugDrawer::Initialize())
|
||||||
NazaraWarning("Failed to initialize debug drawer"); // Non-critique
|
NazaraWarning("Failed to initialize debug drawer"); // Non-critique
|
||||||
|
|
||||||
|
|
@ -1040,6 +1246,13 @@ void NzRenderer::Uninitialize()
|
||||||
|
|
||||||
NzContext::EnsureContext();
|
NzContext::EnsureContext();
|
||||||
|
|
||||||
|
// Libération du buffer d'instancing
|
||||||
|
if (s_instancingBuffer)
|
||||||
|
{
|
||||||
|
delete s_instancingBuffer;
|
||||||
|
s_instancingBuffer = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
// Libération des VAOs
|
// Libération des VAOs
|
||||||
for (auto it = s_vaos.begin(); it != s_vaos.end(); ++it)
|
for (auto it = s_vaos.begin(); it != s_vaos.end(); ++it)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -303,14 +303,22 @@ namespace
|
||||||
sourceCode += '\n';
|
sourceCode += '\n';
|
||||||
|
|
||||||
/********************Uniformes********************/
|
/********************Uniformes********************/
|
||||||
if (flags & nzShaderBuilder_Lighting)
|
if (flags & nzShaderBuilder_Instancing)
|
||||||
sourceCode += "uniform mat4 WorldMatrix;\n";
|
sourceCode += "uniform mat4 ViewProjMatrix;\n";
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (flags & nzShaderBuilder_Lighting)
|
||||||
|
sourceCode += "uniform mat4 WorldMatrix;\n";
|
||||||
|
|
||||||
sourceCode += "uniform mat4 WorldViewProjMatrix;\n";
|
sourceCode += "uniform mat4 WorldViewProjMatrix;\n";
|
||||||
|
}
|
||||||
|
|
||||||
sourceCode += '\n';
|
sourceCode += '\n';
|
||||||
|
|
||||||
/********************Entrant********************/
|
/********************Entrant********************/
|
||||||
|
if (flags & nzShaderBuilder_Instancing)
|
||||||
|
sourceCode += inKW + " mat4 InstanceMatrix;\n";
|
||||||
|
|
||||||
sourceCode += inKW + " vec3 VertexPosition;\n";
|
sourceCode += inKW + " vec3 VertexPosition;\n";
|
||||||
|
|
||||||
if (flags & nzShaderBuilder_Lighting)
|
if (flags & nzShaderBuilder_Lighting)
|
||||||
|
|
@ -343,31 +351,43 @@ namespace
|
||||||
|
|
||||||
/********************Code********************/
|
/********************Code********************/
|
||||||
sourceCode += "void main()\n"
|
sourceCode += "void main()\n"
|
||||||
"{\n"
|
"{\n";
|
||||||
"gl_Position = WorldViewProjMatrix * vec4(VertexPosition, 1.0);\n";
|
|
||||||
|
if (flags & nzShaderBuilder_Instancing)
|
||||||
|
sourceCode += "gl_Position = InstanceMatrix * ViewProjMatrix * vec4(VertexPosition, 1.0);\n";
|
||||||
|
else
|
||||||
|
sourceCode += "gl_Position = WorldViewProjMatrix * vec4(VertexPosition, 1.0);\n";
|
||||||
|
|
||||||
if (flags & nzShaderBuilder_Lighting)
|
if (flags & nzShaderBuilder_Lighting)
|
||||||
{
|
{
|
||||||
sourceCode += "mat3 RotationMatrix = mat3(WorldMatrix);\n";
|
if (flags & nzShaderBuilder_Instancing)
|
||||||
|
sourceCode += "mat3 rotationMatrix = mat3(InstanceMatrix);\n";
|
||||||
|
else
|
||||||
|
sourceCode += "mat3 rotationMatrix = mat3(WorldMatrix);\n";
|
||||||
|
|
||||||
if (flags & nzShaderBuilder_NormalMapping)
|
if (flags & nzShaderBuilder_NormalMapping)
|
||||||
{
|
{
|
||||||
sourceCode += "\n"
|
sourceCode += "\n"
|
||||||
"vec3 binormal = cross(VertexNormal, VertexTangent);\n"
|
"vec3 binormal = cross(VertexNormal, VertexTangent);\n"
|
||||||
"vLightToWorld[0] = normalize(VertexTangent * RotationMatrix);\n"
|
"vLightToWorld[0] = normalize(VertexTangent * rotationMatrix);\n"
|
||||||
"vLightToWorld[1] = normalize(binormal * RotationMatrix);\n"
|
"vLightToWorld[1] = normalize(binormal * rotationMatrix);\n"
|
||||||
"vLightToWorld[2] = normalize(VertexNormal * RotationMatrix);\n"
|
"vLightToWorld[2] = normalize(VertexNormal * rotationMatrix);\n"
|
||||||
"\n";
|
"\n";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
sourceCode += "vNormal = normalize(RotationMatrix * VertexNormal);\n";
|
sourceCode += "vNormal = normalize(rotationMatrix * VertexNormal);\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & nzShaderBuilder_DiffuseMapping || flags & nzShaderBuilder_NormalMapping)
|
if (flags & nzShaderBuilder_DiffuseMapping || flags & nzShaderBuilder_NormalMapping)
|
||||||
sourceCode += "vTexCoord = VertexTexCoord0;\n";
|
sourceCode += "vTexCoord = VertexTexCoord0;\n";
|
||||||
|
|
||||||
if (flags & nzShaderBuilder_Lighting)
|
if (flags & nzShaderBuilder_Lighting)
|
||||||
sourceCode += "vWorldPos = vec3(WorldMatrix * vec4(VertexPosition, 1.0));\n";
|
{
|
||||||
|
if (flags & nzShaderBuilder_Instancing)
|
||||||
|
sourceCode += "vWorldPos = vec3(InstanceMatrix * vec4(VertexPosition, 1.0));\n";
|
||||||
|
else
|
||||||
|
sourceCode += "vWorldPos = vec3(WorldMatrix * vec4(VertexPosition, 1.0));\n";
|
||||||
|
}
|
||||||
|
|
||||||
sourceCode += "}\n";
|
sourceCode += "}\n";
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue