Universal OpenGL object RAII wrapper classOpenGL object wrapped in a Qt WidgetArray-like container for uints shorter than 8 bits (Rev 1)Simple CubeMap opengl wrapper classPrimitive Type Wrapper in C++C++ OpenGLBuffer class, wrapper around the raw OpenGL apiOpenGL 4.5 Core Buffer wrapperModern OpenGL shader wrapper v2Copy-and-Move Concept Using Smart PointerDesigning the constructor interface for a reflection object (any class)C++ std::array wrapper
What is the command to reset a PC without deleting any files
How to answer pointed "are you quitting" questioning when I don't want them to suspect
Extreme, but not acceptable situation and I can't start the work tomorrow morning
OA final episode explanation
What do you call something that goes against the spirit of the law, but is legal when interpreting the law to the letter?
Does the average primeness of natural numbers tend to zero?
Pristine Bit Checking
Latin words with no plurals in English
Add an angle to a sphere
Can I legally use front facing blue light in the UK?
Weird behaviour when using querySelector
Is repealing the EU Withdrawal Act a precondition of revoking Article 50?
Finding files for which a command fails
Why do UK politicians seemingly ignore opinion polls on Brexit?
Eliminate empty elements from a list with a specifict pattern
Denied boarding due to overcrowding, Sparpreis ticket. What are my rights?
Is Social Media Science Fiction?
Is it legal to have the "// (c) 2019 John Smith" header in all files when there are hundreds of contributors?
Does a dangling wire really electrocute me if I'm standing in water?
How is it possible for user's password to be changed after storage was encrypted? (on OS X, Android)
Why is making salt water prohibited on Shabbat?
How would photo IDs work for shapeshifters?
Why was the "bread communication" in the arena of Catching Fire left out in the movie?
How do you conduct xenoanthropology after first contact?
Universal OpenGL object RAII wrapper class
OpenGL object wrapped in a Qt WidgetArray-like container for uints shorter than 8 bits (Rev 1)Simple CubeMap opengl wrapper classPrimitive Type Wrapper in C++C++ OpenGLBuffer class, wrapper around the raw OpenGL apiOpenGL 4.5 Core Buffer wrapperModern OpenGL shader wrapper v2Copy-and-Move Concept Using Smart PointerDesigning the constructor interface for a reflection object (any class)C++ std::array wrapper
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;
$begingroup$
I created a universal OpenGL object RAII wrapper class, that only takes care of object creation and destruction. Here's my code and reasoning behind it:
I first wrote a class that would take glCreate/Delete*() function pointers as constructor arguments, but I quickly realized that's not the right way to go. I'd have to store the glDelete*() function pointer in each object (waste of memory + dereference overhead). Additionally, OpenGL functions have three different forms (see specializations section, further in my code), so that would require 3 different pointer types - ugly. I decided to change my approach.
So, here I am with this template code. As far as I'm concerned, there should be no unnecessary OpenGL call overhead. The class is standard layout, only contains the object ID and there's no virtual stuff involved, so that seems pretty nice. Also, classes wrapping different OpenGL object types cannot be assigned to each other, because template arguments differ.
I'd like to hear your remarks according my code, the class design and the reasoning behind it. Improvement ideas are also welcome. Thanks in advance.
This is the main code:
/**
brief Serves as a RAII wrapper for OpenGL objects
note This class provides no OpenGL error checking - this is up to derived classes.
template T is object type as in glObjectLabel
*/
template <GLenum T>
class gl_object
public:
//! Object type used for labeling
const static GLenum object_type = T;
inline gl_object( );
inline explicit gl_object( GLenum target );
inline ~gl_object( );
// Deleted copy constructor and copy assignment operator
gl_object( const gl_object &src ) = delete;
gl_object &operator=( const gl_object &rhs ) = delete;
// Move semantics with source invalidation
gl_object( gl_object &&src );
gl_object &operator=( gl_object &&rhs );
//! Allows casting to object's ID (GLuint)
inline operator GLuint( ) const noexcept;
//! Returns object's ID
inline GLuint id( ) const noexcept;
protected:
//! The object ID
GLuint m_id;
;
//! Move constructor with source invalidation
template <GLenum T>
gl_object<T>::gl_object( gl_object<T> &&src ) :
m_id( src.m_id )
src.m_id = 0;
//! Move assignment operator with source invalidation
template <GLenum T>
gl_object<T> &gl_object<T>::operator=( gl_object<T> &&rhs )
// Prevent self-move
if ( this != &rhs )
m_id = rhs.m_id;
rhs.m_id = 0;
return *this;
// Allows cast to GLuint
template <GLenum T>
gl_object<T>::operator GLuint( ) const noexcept
return m_id;
// Used for acquiring object's ID
template <GLenum T>
GLuint gl_object<T>::id( ) const noexcept
return m_id;
Then, there are many very similar template specializations. Here are the most interesting ones:
// Specializations for GL_BUFFER
template <>
gl_object<GL_BUFFER>::gl_object( )
glCreateBuffers( 1, &m_id );
template <>
gl_object<GL_BUFFER>::~gl_object( )
glDeleteBuffers( 1, &m_id );
// Specializations for GL_TEXTURE
template <>
gl_object<GL_TEXTURE>::gl_object( GLenum target )
glCreateTextures( target, 1, &m_id );
template <>
gl_object<GL_TEXTURE>::~gl_object( )
glDeleteTextures( 1, &m_id );
// Specializations for GL_SHADER
template <>
gl_object<GL_SHADER>::gl_object( GLenum type )
m_id = glCreateShader( type );
template <>
gl_object<GL_SHADER>::~gl_object( )
glDeleteShader( m_id );
// Specializations for GL_PROGRAM
template <>
gl_object<GL_PROGRAM>::gl_object( )
m_id = glCreateProgram( );
template <>
gl_object<GL_PROGRAM>::~gl_object( )
glDeleteProgram( m_id );
c++ opengl wrapper
$endgroup$
add a comment |
$begingroup$
I created a universal OpenGL object RAII wrapper class, that only takes care of object creation and destruction. Here's my code and reasoning behind it:
I first wrote a class that would take glCreate/Delete*() function pointers as constructor arguments, but I quickly realized that's not the right way to go. I'd have to store the glDelete*() function pointer in each object (waste of memory + dereference overhead). Additionally, OpenGL functions have three different forms (see specializations section, further in my code), so that would require 3 different pointer types - ugly. I decided to change my approach.
So, here I am with this template code. As far as I'm concerned, there should be no unnecessary OpenGL call overhead. The class is standard layout, only contains the object ID and there's no virtual stuff involved, so that seems pretty nice. Also, classes wrapping different OpenGL object types cannot be assigned to each other, because template arguments differ.
I'd like to hear your remarks according my code, the class design and the reasoning behind it. Improvement ideas are also welcome. Thanks in advance.
This is the main code:
/**
brief Serves as a RAII wrapper for OpenGL objects
note This class provides no OpenGL error checking - this is up to derived classes.
template T is object type as in glObjectLabel
*/
template <GLenum T>
class gl_object
public:
//! Object type used for labeling
const static GLenum object_type = T;
inline gl_object( );
inline explicit gl_object( GLenum target );
inline ~gl_object( );
// Deleted copy constructor and copy assignment operator
gl_object( const gl_object &src ) = delete;
gl_object &operator=( const gl_object &rhs ) = delete;
// Move semantics with source invalidation
gl_object( gl_object &&src );
gl_object &operator=( gl_object &&rhs );
//! Allows casting to object's ID (GLuint)
inline operator GLuint( ) const noexcept;
//! Returns object's ID
inline GLuint id( ) const noexcept;
protected:
//! The object ID
GLuint m_id;
;
//! Move constructor with source invalidation
template <GLenum T>
gl_object<T>::gl_object( gl_object<T> &&src ) :
m_id( src.m_id )
src.m_id = 0;
//! Move assignment operator with source invalidation
template <GLenum T>
gl_object<T> &gl_object<T>::operator=( gl_object<T> &&rhs )
// Prevent self-move
if ( this != &rhs )
m_id = rhs.m_id;
rhs.m_id = 0;
return *this;
// Allows cast to GLuint
template <GLenum T>
gl_object<T>::operator GLuint( ) const noexcept
return m_id;
// Used for acquiring object's ID
template <GLenum T>
GLuint gl_object<T>::id( ) const noexcept
return m_id;
Then, there are many very similar template specializations. Here are the most interesting ones:
// Specializations for GL_BUFFER
template <>
gl_object<GL_BUFFER>::gl_object( )
glCreateBuffers( 1, &m_id );
template <>
gl_object<GL_BUFFER>::~gl_object( )
glDeleteBuffers( 1, &m_id );
// Specializations for GL_TEXTURE
template <>
gl_object<GL_TEXTURE>::gl_object( GLenum target )
glCreateTextures( target, 1, &m_id );
template <>
gl_object<GL_TEXTURE>::~gl_object( )
glDeleteTextures( 1, &m_id );
// Specializations for GL_SHADER
template <>
gl_object<GL_SHADER>::gl_object( GLenum type )
m_id = glCreateShader( type );
template <>
gl_object<GL_SHADER>::~gl_object( )
glDeleteShader( m_id );
// Specializations for GL_PROGRAM
template <>
gl_object<GL_PROGRAM>::gl_object( )
m_id = glCreateProgram( );
template <>
gl_object<GL_PROGRAM>::~gl_object( )
glDeleteProgram( m_id );
c++ opengl wrapper
$endgroup$
add a comment |
$begingroup$
I created a universal OpenGL object RAII wrapper class, that only takes care of object creation and destruction. Here's my code and reasoning behind it:
I first wrote a class that would take glCreate/Delete*() function pointers as constructor arguments, but I quickly realized that's not the right way to go. I'd have to store the glDelete*() function pointer in each object (waste of memory + dereference overhead). Additionally, OpenGL functions have three different forms (see specializations section, further in my code), so that would require 3 different pointer types - ugly. I decided to change my approach.
So, here I am with this template code. As far as I'm concerned, there should be no unnecessary OpenGL call overhead. The class is standard layout, only contains the object ID and there's no virtual stuff involved, so that seems pretty nice. Also, classes wrapping different OpenGL object types cannot be assigned to each other, because template arguments differ.
I'd like to hear your remarks according my code, the class design and the reasoning behind it. Improvement ideas are also welcome. Thanks in advance.
This is the main code:
/**
brief Serves as a RAII wrapper for OpenGL objects
note This class provides no OpenGL error checking - this is up to derived classes.
template T is object type as in glObjectLabel
*/
template <GLenum T>
class gl_object
public:
//! Object type used for labeling
const static GLenum object_type = T;
inline gl_object( );
inline explicit gl_object( GLenum target );
inline ~gl_object( );
// Deleted copy constructor and copy assignment operator
gl_object( const gl_object &src ) = delete;
gl_object &operator=( const gl_object &rhs ) = delete;
// Move semantics with source invalidation
gl_object( gl_object &&src );
gl_object &operator=( gl_object &&rhs );
//! Allows casting to object's ID (GLuint)
inline operator GLuint( ) const noexcept;
//! Returns object's ID
inline GLuint id( ) const noexcept;
protected:
//! The object ID
GLuint m_id;
;
//! Move constructor with source invalidation
template <GLenum T>
gl_object<T>::gl_object( gl_object<T> &&src ) :
m_id( src.m_id )
src.m_id = 0;
//! Move assignment operator with source invalidation
template <GLenum T>
gl_object<T> &gl_object<T>::operator=( gl_object<T> &&rhs )
// Prevent self-move
if ( this != &rhs )
m_id = rhs.m_id;
rhs.m_id = 0;
return *this;
// Allows cast to GLuint
template <GLenum T>
gl_object<T>::operator GLuint( ) const noexcept
return m_id;
// Used for acquiring object's ID
template <GLenum T>
GLuint gl_object<T>::id( ) const noexcept
return m_id;
Then, there are many very similar template specializations. Here are the most interesting ones:
// Specializations for GL_BUFFER
template <>
gl_object<GL_BUFFER>::gl_object( )
glCreateBuffers( 1, &m_id );
template <>
gl_object<GL_BUFFER>::~gl_object( )
glDeleteBuffers( 1, &m_id );
// Specializations for GL_TEXTURE
template <>
gl_object<GL_TEXTURE>::gl_object( GLenum target )
glCreateTextures( target, 1, &m_id );
template <>
gl_object<GL_TEXTURE>::~gl_object( )
glDeleteTextures( 1, &m_id );
// Specializations for GL_SHADER
template <>
gl_object<GL_SHADER>::gl_object( GLenum type )
m_id = glCreateShader( type );
template <>
gl_object<GL_SHADER>::~gl_object( )
glDeleteShader( m_id );
// Specializations for GL_PROGRAM
template <>
gl_object<GL_PROGRAM>::gl_object( )
m_id = glCreateProgram( );
template <>
gl_object<GL_PROGRAM>::~gl_object( )
glDeleteProgram( m_id );
c++ opengl wrapper
$endgroup$
I created a universal OpenGL object RAII wrapper class, that only takes care of object creation and destruction. Here's my code and reasoning behind it:
I first wrote a class that would take glCreate/Delete*() function pointers as constructor arguments, but I quickly realized that's not the right way to go. I'd have to store the glDelete*() function pointer in each object (waste of memory + dereference overhead). Additionally, OpenGL functions have three different forms (see specializations section, further in my code), so that would require 3 different pointer types - ugly. I decided to change my approach.
So, here I am with this template code. As far as I'm concerned, there should be no unnecessary OpenGL call overhead. The class is standard layout, only contains the object ID and there's no virtual stuff involved, so that seems pretty nice. Also, classes wrapping different OpenGL object types cannot be assigned to each other, because template arguments differ.
I'd like to hear your remarks according my code, the class design and the reasoning behind it. Improvement ideas are also welcome. Thanks in advance.
This is the main code:
/**
brief Serves as a RAII wrapper for OpenGL objects
note This class provides no OpenGL error checking - this is up to derived classes.
template T is object type as in glObjectLabel
*/
template <GLenum T>
class gl_object
public:
//! Object type used for labeling
const static GLenum object_type = T;
inline gl_object( );
inline explicit gl_object( GLenum target );
inline ~gl_object( );
// Deleted copy constructor and copy assignment operator
gl_object( const gl_object &src ) = delete;
gl_object &operator=( const gl_object &rhs ) = delete;
// Move semantics with source invalidation
gl_object( gl_object &&src );
gl_object &operator=( gl_object &&rhs );
//! Allows casting to object's ID (GLuint)
inline operator GLuint( ) const noexcept;
//! Returns object's ID
inline GLuint id( ) const noexcept;
protected:
//! The object ID
GLuint m_id;
;
//! Move constructor with source invalidation
template <GLenum T>
gl_object<T>::gl_object( gl_object<T> &&src ) :
m_id( src.m_id )
src.m_id = 0;
//! Move assignment operator with source invalidation
template <GLenum T>
gl_object<T> &gl_object<T>::operator=( gl_object<T> &&rhs )
// Prevent self-move
if ( this != &rhs )
m_id = rhs.m_id;
rhs.m_id = 0;
return *this;
// Allows cast to GLuint
template <GLenum T>
gl_object<T>::operator GLuint( ) const noexcept
return m_id;
// Used for acquiring object's ID
template <GLenum T>
GLuint gl_object<T>::id( ) const noexcept
return m_id;
Then, there are many very similar template specializations. Here are the most interesting ones:
// Specializations for GL_BUFFER
template <>
gl_object<GL_BUFFER>::gl_object( )
glCreateBuffers( 1, &m_id );
template <>
gl_object<GL_BUFFER>::~gl_object( )
glDeleteBuffers( 1, &m_id );
// Specializations for GL_TEXTURE
template <>
gl_object<GL_TEXTURE>::gl_object( GLenum target )
glCreateTextures( target, 1, &m_id );
template <>
gl_object<GL_TEXTURE>::~gl_object( )
glDeleteTextures( 1, &m_id );
// Specializations for GL_SHADER
template <>
gl_object<GL_SHADER>::gl_object( GLenum type )
m_id = glCreateShader( type );
template <>
gl_object<GL_SHADER>::~gl_object( )
glDeleteShader( m_id );
// Specializations for GL_PROGRAM
template <>
gl_object<GL_PROGRAM>::gl_object( )
m_id = glCreateProgram( );
template <>
gl_object<GL_PROGRAM>::~gl_object( )
glDeleteProgram( m_id );
c++ opengl wrapper
c++ opengl wrapper
asked 43 mins ago
JacajackJacajack
1334
1334
add a comment |
add a comment |
0
active
oldest
votes
Your Answer
StackExchange.ifUsing("editor", function ()
return StackExchange.using("mathjaxEditing", function ()
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
);
);
, "mathjax-editing");
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "196"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
var $window = $(window),
onScroll = function(e)
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom))
StackExchange.using('gps', function() StackExchange.gps.track('embedded_signup_form.view', location: 'question_page' ); );
$window.unbind('scroll', onScroll);
;
$window.on('scroll', onScroll);
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f217090%2funiversal-opengl-object-raii-wrapper-class%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
0
active
oldest
votes
0
active
oldest
votes
active
oldest
votes
active
oldest
votes
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
var $window = $(window),
onScroll = function(e)
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom))
StackExchange.using('gps', function() StackExchange.gps.track('embedded_signup_form.view', location: 'question_page' ); );
$window.unbind('scroll', onScroll);
;
$window.on('scroll', onScroll);
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f217090%2funiversal-opengl-object-raii-wrapper-class%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
var $window = $(window),
onScroll = function(e)
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom))
StackExchange.using('gps', function() StackExchange.gps.track('embedded_signup_form.view', location: 'question_page' ); );
$window.unbind('scroll', onScroll);
;
$window.on('scroll', onScroll);
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
var $window = $(window),
onScroll = function(e)
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom))
StackExchange.using('gps', function() StackExchange.gps.track('embedded_signup_form.view', location: 'question_page' ); );
$window.unbind('scroll', onScroll);
;
$window.on('scroll', onScroll);
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
var $window = $(window),
onScroll = function(e)
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom))
StackExchange.using('gps', function() StackExchange.gps.track('embedded_signup_form.view', location: 'question_page' ); );
$window.unbind('scroll', onScroll);
;
$window.on('scroll', onScroll);
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown