diff --git a/source/Irrlicht/CIrrDeviceSDL.cpp b/source/Irrlicht/CIrrDeviceSDL.cpp index 15d6043f5..9e45f415d 100644 --- a/source/Irrlicht/CIrrDeviceSDL.cpp +++ b/source/Irrlicht/CIrrDeviceSDL.cpp @@ -412,8 +412,8 @@ bool CIrrDeviceSDL::createWindow() break; case video::EDT_OPENGL3: SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); break; case video::EDT_OGLES1: SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1); diff --git a/source/Irrlicht/COpenGLCoreTexture.h b/source/Irrlicht/COpenGLCoreTexture.h index 984d2ecc8..386081be4 100644 --- a/source/Irrlicht/COpenGLCoreTexture.h +++ b/source/Irrlicht/COpenGLCoreTexture.h @@ -98,17 +98,19 @@ class COpenGLCoreTexture : public ITexture glTexParameteri(TextureType, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(TextureType, GL_TEXTURE_MAG_FILTER, GL_NEAREST); -#ifdef GL_GENERATE_MIPMAP_HINT - if (HasMipMaps) - { - if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED)) - glHint(GL_GENERATE_MIPMAP_HINT, GL_FASTEST); - else if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_QUALITY)) - glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST); - else - glHint(GL_GENERATE_MIPMAP_HINT, GL_DONT_CARE); - } -#endif + // TODO: The OpenGL core profile does not support GL_GENERATE_MIPMAP_HINT, is + // there a good replacement? + //#ifdef GL_GENERATE_MIPMAP + // if (HasMipMaps) + // { + // if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_SPEED)) + // glHint(GL_GENERATE_MIPMAP_HINT, GL_FASTEST); + // else if (Driver->getTextureCreationFlag(ETCF_OPTIMIZED_FOR_QUALITY)) + // glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST); + // else + // glHint(GL_GENERATE_MIPMAP_HINT, GL_DONT_CARE); + // } + //#endif #if !defined(IRR_OPENGL_HAS_glGenerateMipmap) && defined(GL_GENERATE_MIPMAP) if (HasMipMaps) diff --git a/source/Irrlicht/OpenGL/Driver.cpp b/source/Irrlicht/OpenGL/Driver.cpp index fdc091f8a..3426f4b97 100644 --- a/source/Irrlicht/OpenGL/Driver.cpp +++ b/source/Irrlicht/OpenGL/Driver.cpp @@ -134,13 +134,15 @@ void COpenGL3DriverBase::debugCb(GLenum source, GLenum type, GLuint id, GLenum s printf("%04x %04x %x %x %.*s\n", source, type, id, severity, length, message); } -COpenGL3DriverBase::COpenGL3DriverBase(const SIrrlichtCreationParameters& params, io::IFileSystem* io, IContextManager* contextManager) : - CNullDriver(io, params.WindowSize), COpenGL3ExtensionHandler(), CacheHandler(0), - Params(params), ResetRenderStates(true), LockRenderStateMode(false), AntiAlias(params.AntiAlias), - MaterialRenderer2DActive(0), MaterialRenderer2DTexture(0), MaterialRenderer2DNoTexture(0), - CurrentRenderMode(ERM_NONE), Transformation3DChanged(true), - OGLES2ShaderPath(params.OGLES2ShaderPath), - ColorFormat(ECF_R8G8B8), ContextManager(contextManager) +COpenGL3DriverBase::COpenGL3DriverBase(const SIrrlichtCreationParameters ¶ms, + io::IFileSystem *io, IContextManager *contextManager) : + CNullDriver(io, params.WindowSize), + COpenGL3ExtensionHandler(), CacheHandler(0), Params(params), + ResetRenderStates(true), LockRenderStateMode(false), AntiAlias(params.AntiAlias), + MaterialRenderer2DActive(0), MaterialRenderer2DTexture(0), + MaterialRenderer2DNoTexture(0), CurrentRenderMode(ERM_NONE), + Transformation3DChanged(true), OGLES2ShaderPath(params.OGLES2ShaderPath), + ColorFormat(ECF_R8G8B8), ContextManager(contextManager) { #ifdef _DEBUG setDebugName("Driver"); @@ -156,6 +158,12 @@ COpenGL3DriverBase::COpenGL3DriverBase(const SIrrlichtCreationParameters& params ContextManager->activateContext(ExposedData, false); GL.LoadAllProcedures(ContextManager); GL.DebugMessageCallback(debugCb, this); + + GL.GenVertexArrays(1, &GlobalVAO); + GL.BindVertexArray(GlobalVAO); + + GL.GenBuffers(1, &GlobalVBO); + initQuadsIndices(); } @@ -254,9 +262,12 @@ COpenGL3DriverBase::~COpenGL3DriverBase() setTransform(static_cast(i), core::IdentityMatrix); setAmbientLight(SColorf(0.0f, 0.0f, 0.0f, 0.0f)); - glClearDepthf(1.0f); + glClearDepthf(1.0); + + // TODO: The OpenGL core profile does not support GL_GENERATE_MIPMAP_HINT, is + // there a good replacement? + // glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST); - glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST); glFrontFace(GL_CW); // create material renderers @@ -576,19 +587,23 @@ COpenGL3DriverBase::~COpenGL3DriverBase() } } - if (HWBuffer->Mapped_Index != scene::EHM_NEVER) + // Should EHM_NEVER for index buffers just be ignored? Does this make sense? + + //if (HWBuffer->Mapped_Index != scene::EHM_NEVER) + //{ + + if (HWBuffer->ChangedID_Index != HWBuffer->MeshBuffer->getChangedID_Index() + || !static_cast(HWBuffer)->vbo_indicesID) { - if (HWBuffer->ChangedID_Index != HWBuffer->MeshBuffer->getChangedID_Index() - || !static_cast(HWBuffer)->vbo_indicesID) - { - HWBuffer->ChangedID_Index = HWBuffer->MeshBuffer->getChangedID_Index(); + HWBuffer->ChangedID_Index = HWBuffer->MeshBuffer->getChangedID_Index(); - if (!updateIndexHardwareBuffer((SHWBufferLink_opengl*)HWBuffer)) - return false; - } + if (!updateIndexHardwareBuffer((SHWBufferLink_opengl*)HWBuffer)) + return false; } + //} + return true; } @@ -596,7 +611,7 @@ COpenGL3DriverBase::~COpenGL3DriverBase() //! Create hardware buffer from meshbuffer COpenGL3DriverBase::SHWBufferLink *COpenGL3DriverBase::createHardwareBuffer(const scene::IMeshBuffer* mb) { - if (!mb || (mb->getHardwareMappingHint_Index() == scene::EHM_NEVER && mb->getHardwareMappingHint_Vertex() == scene::EHM_NEVER)) + if (!mb) return 0; SHWBufferLink_opengl *HWBuffer = new SHWBufferLink_opengl(mb); @@ -664,23 +679,34 @@ COpenGL3DriverBase::~COpenGL3DriverBase() vertices = 0; } - if (HWBuffer->Mapped_Index != scene::EHM_NEVER) - { - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, HWBuffer->vbo_indicesID); - indexList = 0; - } + // Should EHM_NEVER for index buffers just be ignored? Does this make sense? + //if (HWBuffer->Mapped_Index != scene::EHM_NEVER) + //{ + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, HWBuffer->vbo_indicesID); + indexList = 0; + //} - drawVertexPrimitiveList(vertices, mb->getVertexCount(), - indexList, mb->getPrimitiveCount(), - mb->getVertexType(), mb->getPrimitiveType(), - mb->getIndexType()); + if (HWBuffer->Mapped_Vertex == scene::EHM_NEVER) + { + drawVertexPrimitiveList(vertices, mb->getVertexCount(), indexList, + mb->getPrimitiveCount(), mb->getVertexType(), mb->getPrimitiveType(), + mb->getIndexType()); + } + else + { + drawVertexPrimitiveListWithBoundVBO(vertices, mb->getVertexCount(), indexList, + mb->getPrimitiveCount(), mb->getVertexType(), mb->getPrimitiveType(), + mb->getIndexType(), reinterpret_cast(vertices)); + } if (HWBuffer->Mapped_Vertex != scene::EHM_NEVER) glBindBuffer(GL_ARRAY_BUFFER, 0); - if (HWBuffer->Mapped_Index != scene::EHM_NEVER) - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + //if (HWBuffer->Mapped_Index != scene::EHM_NEVER) + //{ + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + //} } @@ -704,6 +730,21 @@ COpenGL3DriverBase::~COpenGL3DriverBase() void COpenGL3DriverBase::drawVertexPrimitiveList(const void* vertices, u32 vertexCount, const void* indexList, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType) + { + auto &vTypeDesc = getVertexTypeDescription(vType); + + // Use global vbo + glBindBuffer(GL_ARRAY_BUFFER, GlobalVBO); + glBufferData(GL_ARRAY_BUFFER, vTypeDesc.VertexSize * vertexCount, vertices, GL_DYNAMIC_DRAW); + + drawVertexPrimitiveListWithBoundVBO(vertices, vertexCount, indexList, primitiveCount, vType, pType, iType, 0); + } + + + void COpenGL3DriverBase::drawVertexPrimitiveListWithBoundVBO(const void *vertices, + u32 vertexCount, const void *indexList, u32 primitiveCount, + E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType, + uintptr_t offset) { if (!primitiveCount || !vertexCount) return; @@ -716,7 +757,6 @@ COpenGL3DriverBase::~COpenGL3DriverBase() setRenderStates3DMode(); auto &vTypeDesc = getVertexTypeDescription(vType); - beginDraw(vTypeDesc, reinterpret_cast(vertices)); GLenum indexSize = 0; switch (iType) @@ -741,6 +781,8 @@ COpenGL3DriverBase::~COpenGL3DriverBase() } } + beginDrawWithBoundVBO(vTypeDesc, offset); + switch (pType) { case scene::EPT_POINTS: @@ -1096,34 +1138,48 @@ COpenGL3DriverBase::~COpenGL3DriverBase() void COpenGL3DriverBase::drawArrays(GLenum primitiveType, const VertexType &vertexType, const void *vertices, int vertexCount) { - beginDraw(vertexType, reinterpret_cast(vertices)); + beginDraw(vertexType, vertexCount, vertices); glDrawArrays(primitiveType, 0, vertexCount); endDraw(vertexType); } void COpenGL3DriverBase::drawElements(GLenum primitiveType, const VertexType &vertexType, const void *vertices, int vertexCount, const u16 *indices, int indexCount) { - beginDraw(vertexType, reinterpret_cast(vertices)); + beginDraw(vertexType, vertexCount, vertices); glDrawRangeElements(primitiveType, 0, vertexCount - 1, indexCount, GL_UNSIGNED_SHORT, indices); endDraw(vertexType); } - void COpenGL3DriverBase::beginDraw(const VertexType &vertexType, uintptr_t verticesBase) + void COpenGL3DriverBase::beginDrawWithBoundVBO(const VertexType &vertexType, uintptr_t offset) { + void *openGLOffset; + for (auto attr: vertexType) { + openGLOffset = reinterpret_cast(attr.Offset + offset); + glEnableVertexAttribArray(attr.Index); switch (attr.mode) { - case VertexAttribute::Mode::Regular: glVertexAttribPointer(attr.Index, attr.ComponentCount, attr.ComponentType, GL_FALSE, vertexType.VertexSize, reinterpret_cast(verticesBase + attr.Offset)); break; - case VertexAttribute::Mode::Normalized: glVertexAttribPointer(attr.Index, attr.ComponentCount, attr.ComponentType, GL_TRUE, vertexType.VertexSize, reinterpret_cast(verticesBase + attr.Offset)); break; - case VertexAttribute::Mode::Integral: glVertexAttribIPointer(attr.Index, attr.ComponentCount, attr.ComponentType, vertexType.VertexSize, reinterpret_cast(verticesBase + attr.Offset)); break; + case VertexAttribute::Mode::Regular: glVertexAttribPointer(attr.Index, attr.ComponentCount, attr.ComponentType, GL_FALSE, vertexType.VertexSize, openGLOffset); break; + case VertexAttribute::Mode::Normalized: glVertexAttribPointer(attr.Index, attr.ComponentCount, attr.ComponentType, GL_TRUE, vertexType.VertexSize, openGLOffset); break; + case VertexAttribute::Mode::Integral: glVertexAttribIPointer(attr.Index, attr.ComponentCount, attr.ComponentType, vertexType.VertexSize, openGLOffset); break; } + } } + void COpenGL3DriverBase::beginDraw(const VertexType &vertexType, int vertexCount, const void *verticesBase) + { + glBindBuffer(GL_ARRAY_BUFFER, GlobalVBO); + glBufferData(GL_ARRAY_BUFFER, vertexType.VertexSize * vertexCount, verticesBase, GL_DYNAMIC_DRAW); + beginDrawWithBoundVBO(vertexType, 0); + } + void COpenGL3DriverBase::endDraw(const VertexType &vertexType) { for (auto attr: vertexType) glDisableVertexAttribArray(attr.Index); + // Unbind GL_ARRAY_BUFFER + glBindBuffer(GL_ARRAY_BUFFER, 0); } ITexture* COpenGL3DriverBase::createDeviceDependentTexture(const io::path& name, IImage* image) diff --git a/source/Irrlicht/OpenGL/Driver.h b/source/Irrlicht/OpenGL/Driver.h index 862c79d5e..83aea4b66 100644 --- a/source/Irrlicht/OpenGL/Driver.h +++ b/source/Irrlicht/OpenGL/Driver.h @@ -322,6 +322,13 @@ namespace video LockRenderStateMode = false; } + // This function is like drawVertexPrimitiveList, but it does not use GlobalVBO, + // allowing the user to draw with their own VBOs such as with the + // drawHardwareBuffer function. + void drawVertexPrimitiveListWithBoundVBO(const void *vertices, u32 vertexCount, + const void *indexList, u32 primitiveCount, E_VERTEX_TYPE vType, + scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType, uintptr_t offset); + void draw2D3DVertexPrimitiveList(const void* vertices, u32 vertexCount, const void* indexList, u32 primitiveCount, E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, @@ -341,7 +348,12 @@ namespace video void drawElements(GLenum primitiveType, const VertexType &vertexType, const void *vertices, int vertexCount, const u16 *indices, int indexCount); void drawElements(GLenum primitiveType, const VertexType &vertexType, uintptr_t vertices, uintptr_t indices, int indexCount); - void beginDraw(const VertexType &vertexType, uintptr_t verticesBase); + // This function is like beginDraw, but it does not use GlobalVBO, allowing the + // user to draw with their own VBOs such as with the + // drawHardwareBuffer function. + void beginDrawWithBoundVBO(const VertexType &vertexType, uintptr_t offset); + + void beginDraw(const VertexType &vertexType, int vertexCount, const void *verticesBase); void endDraw(const VertexType &vertexType); COpenGL3CacheHandler* CacheHandler; @@ -394,6 +406,10 @@ namespace video bool Transformation3DChanged; irr::io::path OGLES2ShaderPath; + // A nice global VAO and VBO to implement modern OpenGL as simply as possible + unsigned int GlobalVAO; + unsigned int GlobalVBO; + SMaterial Material, LastMaterial; //! Color buffer format diff --git a/source/Irrlicht/OpenGL3/Driver.cpp b/source/Irrlicht/OpenGL3/Driver.cpp index 70343a85a..515e768fa 100644 --- a/source/Irrlicht/OpenGL3/Driver.cpp +++ b/source/Irrlicht/OpenGL3/Driver.cpp @@ -29,8 +29,8 @@ namespace video { } void COpenGL3Driver::initFeatures() { - assert (Version.Spec == OpenGLSpec::Compat); - assert (isVersionAtLeast(3, 2)); + assert (Version.Spec == OpenGLSpec::Core); + assert (isVersionAtLeast(3, 3)); initExtensionsNew(); TextureFormats[ECF_A1R5G5B5] = {GL_RGB5_A1, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV}; // WARNING: may not be renderable