Skip to content
This repository was archived by the owner on May 13, 2024. It is now read-only.
4 changes: 2 additions & 2 deletions source/Irrlicht/CIrrDeviceSDL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
24 changes: 13 additions & 11 deletions source/Irrlicht/COpenGLCoreTexture.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
128 changes: 92 additions & 36 deletions source/Irrlicht/OpenGL/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 &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)
{
#ifdef _DEBUG
setDebugName("Driver");
Expand All @@ -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();
}

Expand Down Expand Up @@ -254,9 +262,12 @@ COpenGL3DriverBase::~COpenGL3DriverBase()
setTransform(static_cast<E_TRANSFORMATION_STATE>(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
Expand Down Expand Up @@ -576,27 +587,31 @@ 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<SHWBufferLink_opengl*>(HWBuffer)->vbo_indicesID)
{
if (HWBuffer->ChangedID_Index != HWBuffer->MeshBuffer->getChangedID_Index()
|| !static_cast<SHWBufferLink_opengl*>(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;
}


//! 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);
Expand Down Expand Up @@ -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<uintptr_t>(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);
//}
}


Expand All @@ -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;
Expand All @@ -716,7 +757,6 @@ COpenGL3DriverBase::~COpenGL3DriverBase()
setRenderStates3DMode();

auto &vTypeDesc = getVertexTypeDescription(vType);
beginDraw(vTypeDesc, reinterpret_cast<uintptr_t>(vertices));
GLenum indexSize = 0;

switch (iType)
Expand All @@ -741,6 +781,8 @@ COpenGL3DriverBase::~COpenGL3DriverBase()
}
}

beginDrawWithBoundVBO(vTypeDesc, offset);

switch (pType)
{
case scene::EPT_POINTS:
Expand Down Expand Up @@ -1096,34 +1138,48 @@ COpenGL3DriverBase::~COpenGL3DriverBase()

void COpenGL3DriverBase::drawArrays(GLenum primitiveType, const VertexType &vertexType, const void *vertices, int vertexCount)
{
beginDraw(vertexType, reinterpret_cast<uintptr_t>(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<uintptr_t>(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<void *>(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<void *>(verticesBase + attr.Offset)); break;
case VertexAttribute::Mode::Normalized: glVertexAttribPointer(attr.Index, attr.ComponentCount, attr.ComponentType, GL_TRUE, vertexType.VertexSize, reinterpret_cast<void *>(verticesBase + attr.Offset)); break;
case VertexAttribute::Mode::Integral: glVertexAttribIPointer(attr.Index, attr.ComponentCount, attr.ComponentType, vertexType.VertexSize, reinterpret_cast<void *>(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)
Expand Down
18 changes: 17 additions & 1 deletion source/Irrlicht/OpenGL/Driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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;
Expand Down Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions source/Irrlicht/OpenGL3/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down