From 3bcfa99b5aa5a9c5b74da24b0089775a20fe141c Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Tue, 24 Nov 2015 16:14:30 -1000 Subject: [PATCH] Updates to support instanced rendering (OpenGL only) --- include/boo/graphicsdev/GL.hpp | 2 +- .../boo/graphicsdev/IGraphicsCommandQueue.hpp | 6 +++ .../boo/graphicsdev/IGraphicsDataFactory.hpp | 14 +++++-- lib/graphicsdev/GL.cpp | 41 ++++++++++++++++--- test/main.cpp | 2 +- 5 files changed, 54 insertions(+), 11 deletions(-) diff --git a/include/boo/graphicsdev/GL.hpp b/include/boo/graphicsdev/GL.hpp index a5a3203..5715867 100644 --- a/include/boo/graphicsdev/GL.hpp +++ b/include/boo/graphicsdev/GL.hpp @@ -48,7 +48,7 @@ public: IShaderDataBinding* newShaderDataBinding(IShaderPipeline* pipeline, IVertexFormat* vtxFormat, - IGraphicsBuffer* vbo, IGraphicsBuffer* ibo, + IGraphicsBuffer* vbo, IGraphicsBuffer* instVbo, IGraphicsBuffer* ibo, size_t ubufCount, IGraphicsBuffer** ubufs, size_t texCount, ITexture** texs); diff --git a/include/boo/graphicsdev/IGraphicsCommandQueue.hpp b/include/boo/graphicsdev/IGraphicsCommandQueue.hpp index 6f5a0f9..ae5fd6a 100644 --- a/include/boo/graphicsdev/IGraphicsCommandQueue.hpp +++ b/include/boo/graphicsdev/IGraphicsCommandQueue.hpp @@ -24,6 +24,12 @@ struct IGraphicsCommandQueue virtual void setRenderTarget(ITextureR* target)=0; virtual void setViewport(const SWindowRect& rect)=0; + /** + * @brief Which dynamic buffer slot is being populated for pending command list + * @return Index [0,2] indicating the buffer slot + */ + virtual int pendingDynamicSlot()=0; + virtual void resizeRenderTexture(ITextureR* tex, size_t width, size_t height)=0; virtual void flushBufferUpdates()=0; diff --git a/include/boo/graphicsdev/IGraphicsDataFactory.hpp b/include/boo/graphicsdev/IGraphicsDataFactory.hpp index 2483b00..4878cee 100644 --- a/include/boo/graphicsdev/IGraphicsDataFactory.hpp +++ b/include/boo/graphicsdev/IGraphicsDataFactory.hpp @@ -100,12 +100,18 @@ struct IVertexFormat {}; /** Types of vertex attributes */ enum class VertexSemantic { + None = 0, Position, Normal, Color, UV, - Weight + UV4, + Weight, + ModelView, + SemanticMask = 0xf, + Instanced = 0x10 }; +ENABLE_BITWISE_ENUM(VertexSemantic) /** Used to create IVertexFormat */ struct VertexElementDescriptor @@ -147,7 +153,9 @@ enum class BlendFactor SrcAlpha, InvSrcAlpha, DstAlpha, - InvDstAlpha + InvDstAlpha, + SrcColor1, + InvSrcColor1 }; /** Factory object for creating batches of resources as an IGraphicsData token */ @@ -196,7 +204,7 @@ struct IGraphicsDataFactory virtual IShaderDataBinding* newShaderDataBinding(IShaderPipeline* pipeline, IVertexFormat* vtxFormat, - IGraphicsBuffer* vbo, IGraphicsBuffer* ibo, + IGraphicsBuffer* vbo, IGraphicsBuffer* instVbo, IGraphicsBuffer* ibo, size_t ubufCount, IGraphicsBuffer** ubufs, size_t texCount, ITexture** texs)=0; diff --git a/lib/graphicsdev/GL.cpp b/lib/graphicsdev/GL.cpp index 067890e..b1374ed 100644 --- a/lib/graphicsdev/GL.cpp +++ b/lib/graphicsdev/GL.cpp @@ -346,7 +346,9 @@ static const GLenum BLEND_FACTOR_TABLE[] = GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_DST_ALPHA, - GL_ONE_MINUS_DST_ALPHA + GL_ONE_MINUS_DST_ALPHA, + GL_SRC1_COLOR, + GL_ONE_MINUS_SRC1_COLOR }; IShaderPipeline* GLDataFactory::newShaderPipeline @@ -503,7 +505,7 @@ struct GLShaderDataBinding : IShaderDataBinding IShaderDataBinding* GLDataFactory::newShaderDataBinding(IShaderPipeline* pipeline, IVertexFormat* vtxFormat, - IGraphicsBuffer*, IGraphicsBuffer*, + IGraphicsBuffer*, IGraphicsBuffer*, IGraphicsBuffer*, size_t ubufCount, IGraphicsBuffer** ubufs, size_t texCount, ITexture** texs) { @@ -550,28 +552,34 @@ void GLDataFactory::destroyAllData() static const GLint SEMANTIC_COUNT_TABLE[] = { + 0, 3, 3, 4, 2, + 4, 4 }; static const size_t SEMANTIC_SIZE_TABLE[] = { + 0, 12, 12, 4, 8, + 16, 16 }; static const GLenum SEMANTIC_TYPE_TABLE[] = { + GL_INVALID_ENUM, GL_FLOAT, GL_FLOAT, GL_UNSIGNED_BYTE, GL_FLOAT, + GL_FLOAT, GL_FLOAT }; @@ -647,13 +655,18 @@ struct GLCommandQueue : IGraphicsCommandQueue glGenVertexArrays(1, &fmt->m_vao); size_t stride = 0; + size_t instStride = 0; for (size_t i=0 ; im_elementCount ; ++i) { const VertexElementDescriptor* desc = &fmt->m_elements[i]; - stride += SEMANTIC_SIZE_TABLE[int(desc->semantic)]; + if ((desc->semantic & VertexSemantic::Instanced) != VertexSemantic::None) + instStride += SEMANTIC_SIZE_TABLE[int(desc->semantic & VertexSemantic::SemanticMask)]; + else + stride += SEMANTIC_SIZE_TABLE[int(desc->semantic & VertexSemantic::SemanticMask)]; } size_t offset = 0; + size_t instOffset = 0; glBindVertexArray(fmt->m_vao); const IGraphicsBuffer* lastVBO = nullptr; const IGraphicsBuffer* lastEBO = nullptr; @@ -677,9 +690,20 @@ struct GLCommandQueue : IGraphicsCommandQueue static_cast(lastEBO)->bindIndex(); } glEnableVertexAttribArray(i); - glVertexAttribPointer(i, SEMANTIC_COUNT_TABLE[int(desc->semantic)], - SEMANTIC_TYPE_TABLE[int(desc->semantic)], GL_TRUE, stride, (void*)offset); - offset += SEMANTIC_SIZE_TABLE[int(desc->semantic)]; + int maskedSem = int(desc->semantic & VertexSemantic::SemanticMask); + if ((desc->semantic & VertexSemantic::Instanced) != VertexSemantic::None) + { + glVertexAttribPointer(i, SEMANTIC_COUNT_TABLE[maskedSem], + SEMANTIC_TYPE_TABLE[maskedSem], GL_TRUE, instStride, (void*)instOffset); + glVertexAttribDivisor(i, 1); + instOffset += SEMANTIC_SIZE_TABLE[maskedSem]; + } + else + { + glVertexAttribPointer(i, SEMANTIC_COUNT_TABLE[maskedSem], + SEMANTIC_TYPE_TABLE[maskedSem], GL_TRUE, stride, (void*)offset); + offset += SEMANTIC_SIZE_TABLE[maskedSem]; + } } } @@ -845,6 +869,11 @@ struct GLCommandQueue : IGraphicsCommandQueue cmds.back().rect = rect; } + int pendingDynamicSlot() + { + return m_fillBuf; + } + void resizeRenderTexture(ITextureR* tex, size_t width, size_t height) { std::unique_lock lk(m_mt); diff --git a/test/main.cpp b/test/main.cpp index e696f8a..fd46f30 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -374,7 +374,7 @@ struct TestApplicationCallback : IApplicationCallback /* Make shader data binding */ self->m_binding = - factory->newShaderDataBinding(pipeline, vfmt, vbo, nullptr, 0, nullptr, 1, &texture); + factory->newShaderDataBinding(pipeline, vfmt, vbo, nullptr, nullptr, 0, nullptr, 1, &texture); /* Commit objects */ IGraphicsData* data = factory->commit();