\documentclass{article}

\usepackage[pdfborder={0 0 0}]{hyperref}
\usepackage{listings}

\begin{document}

\title{globjects: An OpenGL Objects Wrapper}
\author{Willy Scheibel, Daniel Limberger, Stefan Buschmann\\CG Internals}

\maketitle

\begin{abstract}
\noindent
The \emph{globjects} library provides object-oriented interfaces to the OpenGL API version 3.0 and higher. Reoccuring tasks are automated and features the current driver doesn't provide are simulated through earlier interfaces or even emulated with own implementations. One goal is a leaky abstraction of OpenGL, i.e., globjects can be used in conjunction with plain OpenGL API calls, e.g., from \emph{glbinding}.

\end{abstract}

\setcounter{tocdepth}{1}
\tableofcontents

\newpage

\section{Overview}

globjects is a library providing object-oriented interfaces to the OpenGL API. Targeted OpenGL features (versions in the language of the OpenGL API) are 3.0 and above.
The main goals are much reduced code to use OpenGL in your rendering software and fewer errors due to the underlying glbinding and abstraction levels on top. Typical processes are automated and missing features in the used OpenGL driver are partially simulated or even emulated.

\subsection{globjects to plain OpenGL API Usage Comparison}

globjects should reduce the amount of code required in a rendering system. An example of a typical part of an OpenGL program is as follows:

\begin{lstlisting}[language=c++,frame=single,basicstyle=\footnotesize]
GLuint program = glCreateProgram();
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);

glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr);

glCompileShader(vertexShader);
glCompileShader(fragmentShader);

glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);

glLinkProgram(program);

glUseProgram(program);
glUniform2f(glGetUniformLocation(program, "extent"), 1.0, 0.5);
\end{lstlisting}

\noindent The same functionality and optional error checks in terms of \lstinline|glGetError| and compiler and linker status can be achieved using globjects with the following code:
\begin{lstlisting}[language=c++,frame=single,basicstyle=\footnotesize]
Program* program = new Program();

program->attach(
  Shader::fromString(GL_VERTEX_SHADER, vertexShaderSource), 
  Shader::fromString(GL_FRAGMENT_SHADER, fragmentShaderSource)
);

program->setUniform<glm::vec2>("extent", glm::vec2(1.0, 0.5)));
\end{lstlisting}

\subsection{Philosophy}

One main goal of globjects is to be as strict as possible. This means, that everything that isn't generalizable is not integrated. It provides the current interface the OpenGL API suggests and provides fallback implementations for drivers that cannot provide the newest API. Further, globjects is designed for leaky abstraction, i.e., direct OpenGL API calls or other wrapping libraries can be used together with globjects. For dynamically allocated memory, globjects rely on reference counting through smart pointers. To allow for multiple contexts and even shared contexts, globjects uses registries to manage different behavior.

\subsection{Scope}

The scope of globjects are the features currently supported in the newest OpenGL API version and some features that are currently extensions but are likely to find their way to the OpenGL Core. Features that were used before OpenGL 3.0 are explicitly not covered. Likewise, features that are only supported by single vendors are likely to get omitted but are subject for discussion.
An example list of features included:
\begin{itemize}
	\item State / Capability (e.g., Point Size, Depth Test)
	\item Immediate Error Checking
	\item Uniform
	\item Renderbuffer
	\item Framebuffer
	\item Texture (including Bindless and Storage)
	\item Image
	\item Sampler
	\item Shader
	\item Program (including Compute Shaders)
	\item Query
	\item Transform Feedback
	\item Vertex Buffer / Index Buffer (and uniform buffer, atomic counter buffer, shader storage buffer)
	\item Vertex Array
	\item Generic Attributes and Bindings
	\item Shading Language Includes
	\item Program Binaries
\end{itemize}

\noindent An example list of features excluded:
\begin{itemize}
	\item Display Lists
	\item Immediate Mode
	\item Client Vertex Buffer
\end{itemize}

\noindent An example list for subjects to discussion:
\begin{itemize}
	\item Buffer storage (Texture storage is implemented)
	\item Command Lists
\end{itemize}

\subsection{Similar Projects}

The idea to wrap the OpenGL API using a language that supports object-oriented semantics is far from new. Nevertheless, globjects differs notable from competitors.
As globjects don't want to compete with complete rendering engines (Unity, Unreal Engine, CryEngine, FrostBite, Oger, OpenSceneGraph, Magnum, \dots), the list of similar projects is limited to sole object-oriented wrappers.

\paragraph{OGLplus}

\url{http://oglplus.org/}

\paragraph{glcxx}

\url{https://holtrop.github.io/glcxx/doxygen/annotated.html}

\paragraph{OOGL}

\url{https://github.com/Overv/OOGL}

\paragraph{gloo}

\url{http://vispy.org/gloo.html}

\paragraph{JOGL}

\url{http://jogamp.org/jogl/www/}

\paragraph{OpenFrameworks gl}

\url{http://openframeworks.cc/documentation/gl/}

\paragraph{ClanLib GL}

\url{https://github.com/sphair/ClanLib}

\paragraph{glpp}

\url{https://github.com/sque/glpp}

\paragraph{GLT}

\url{http://www.nigels.com/glt/}

\paragraph{GLWrappers}

\url{http://idav.ucdavis.edu/~okreylos/ResDev/Vrui/Documentation/OverviewGLWrappers.html}

\paragraph{Qt5 OpenGL}

\url{http://doc.qt.io/qt-5/qtopengl-index.html}

\section{Project Setup}

The structure of globjects is driven by the design decisions in means of compile-time and run-time dependencies as well as the intended development and deployment use-cases. The project is permanently hosted on \url{https://github.com/cginternals/globjects}.

\subsection{Required Build Environment}

To build and use globjects on your system, a C++11 compatible compiler is required. As a few newer C++11 features are used, not every C++11 compiler is suitable. The list and versions of supported and tested compilers is:
\begin{itemize}
	\item MSVC $\geq$ 2013 Update 3
	\item GCC  $\geq$ 4.8
	\item clang $\geq$ 3.3
	\item AppleClang $\geq$ 6
\end{itemize}
Further, your system should also have the following pieces of software:
\begin{itemize}
	\item CMake $\geq$ 3.0
	\item git $\geq$ 1.8
	\item An OpenGL driver with OpenGL $\geq$ 3.0
	\begin{itemize}
		\item Nvidia
		\item AMD
		\item Intel
		\item Mesa
	\end{itemize}
\end{itemize}

\subsection{Project Dependencies}

Compile-time dependencies of globjects are:
\begin{itemize}
	\item glbinding (required, \url{https://github.com/cginternals/glbinding})
	\item cpplocate (optional, \url{https://github.com/cginternals/cpplocate})
	\item GLFW (optional, \url{www.glfw.org/})
	\item Qt5 (optional, \url{http://www.qt.io/})
\end{itemize}

Run-time dependencies of globjects are:
\begin{itemize}
	\item glbinding (required)
	\item GLFW (optional)
	\item Qt5 (optional)
	\item An OpenGL driver (required)
\end{itemize}

\noindent All optional dependencies are used within the examples. If you don't want to compile or run the examples than you don't need anything besides glbinding and an OpenGL driver.

\subsection{File Structure}

The globjects project is using git as code repository and GitHub as project management system. The file structure is based on cmake-init\footnote{cmake-init project page: \url{https://github.com/cginternals/cmake-init}}. This results in the following root directory structure:
\begin{description}
	\item[cmake] Additional find scripts and functions used by the cmake project setup.
	\item[codegeneration] Fallback files if the cmake version cannot generate certain files.
	\item[data] Run-time data for examples.
	\item[deploy] Cmake-scripts for deployment.
	\item[docs] Documentation, including doxygen and this one.
	\item[source] Actual source code of the \emph{globjects} library, \emph{tests} and \emph{examples}.
\end{description}

\section{Concepts}

globjects provides classes for every main concept of the current OpenGL API. For every concept the according globjects class provides the newest interface and emulates or simulates the behavior if the newest interface of OpenGL is not available in your driver.

\paragraph{State}
A \lstinline|State| object represents the accumulation of all global states an OpenGL context possesses. Mainly, this means a collection of \lstinline|StateSettings| (states with non-boolean values) and a collection of \lstinline|Capabilities| (boolean states).

\paragraph{Capability}
A \lstinline|Capability| object represents a boolean state in the global OpenGL state machine.

\paragraph{StateSetting}

A \lstinline|StateSetting| object represents compound global states that consist of one or more parameters that are set through a specific function call (e.g., \lstinline|glPointSize|).

\paragraph{DebugMessage}

A \lstinline|DebugMessage| object represents an OpenGL message with a type, severity and message string. The interface can also manage the generation and propagation of messages throughout the OpenGL API.

\paragraph{Error}

A \lstinline|Error| object represents an error state of the state machine.

\paragraph{Uniform}

A \lstinline|Uniform| object represents a uniform value of a program. All uniforms are automatically re-uploaded after a program relink.

\paragraph{Renderbuffer}

A \lstinline|Renderbuffer| object represents a renderbuffer that is attachable to framebuffer objects.

\paragraph{Framebuffer}

A \lstinline|Framebuffer| object represents a framebuffer objects with attachable renderbuffers and textures.

\paragraph{Framebuffer Attachment}

A \lstinline|FramebufferAttachment| object represents the common superclass between renderbuffer and texture attachments.

\paragraph{Texture}

A \lstinline|Texture| object represents an OpenGL texture in all its variants. It provides functionality to transfer image data.
Additionally, this object can be used for bindless textures if the driver supports it.

\paragraph{TextureHandle}

A \lstinline|TextureHandle| represents a bindless texture handle.

\paragraph{Image}

An OpenGL Image is wrapped inside a \lstinline|Texture| object. It can be bound for image load/store operations.

\paragraph{Shader}

A \lstinline|Shader| object represents a shader object including its type and a string source hierarchy.
Each time the source changes, the shader is recompiled upon next usage.

\paragraph{Program}

A \lstinline|Program| object represents a full program including standard rendering programs and compute programs.
If any attached shaders changes the program is relinked upon next usage. Attached uniforms are automatically resubmitted upon relink.

\paragraph{ProgramBinary}

A \lstinline|ProgramBinary| object represents the binary of an OpenGL program. Such a binary is strongly platform-dependent.

\paragraph{Query}

A \lstinline|Query| object represents a query in means of an object for measuring time or fragments.

\paragraph{TransformFeedback}

A \lstinline|TransformFeedback| object wraps the functionality and state required for the transform feedback feature of OpenGL, i.e., the configuration of the recorded varyings and the start, pause, stop, and replay of a record.

\paragraph{Buffer}

A \lstinline|Buffer| object represents a generic buffer of OpenGL. It wraps arbitrary data and can be bound to different binding points.

\paragraph{Uniform}

A \lstinline|Uniform| object represents a runtime-constant value of an OpenGL shader. Uniforms are attached to programs and are automatically managed and propagated to the OpenGL shader programs.

\paragraph{VertexArray}

A \lstinline|VertexArray| object manages the vertex shader inputs including all vertex attributed and the index buffers.

\paragraph{VertexAttributeBinding}

A \lstinline|VertexAttributeBinding| object represents a specific binding of a vertex attribute to an OpenGL attribute binding index.

\section{Strategies}

globjects uses the design pattern \emph{strategy} to support multiple implementations for one interface using different OpenGL functions and backends. They have to be differentiated for each use case as they are developed independently and every driver can decide which API extension to include.

\paragraph{Buffer}

The \lstinline|Buffer| strategies implements the standard buffer interface for bindless buffer access (ARB\_direct\_state\_access and EXT\_direct\_state\_access). and former \emph{bindfull} functions.

\paragraph{Debug}

The \lstinline|Debug| strategies handle how OpenGL run-time errors are handled. Currently, the KHR\_debug extension can be used or per-call errors are gathered through manual glbinding after callbacks.

\paragraph{Framebuffer}

The \lstinline|Framebuffer| strategies handles framebuffer access through either direct state access (ARB\_direct\_state\_access and EXT\_direct\_state\_access) or former \emph{bindfull} functions.

\paragraph{ObjectName}

The \lstinline|ObjectName| strategies handle object name management. Currently, either KHR\_debug is used or the feature is emulated.

\paragraph{ProgramBinary}

The \lstinline|ProgramBinary| strategies handle the program binary management. If GL\_ARB\_get\_program\_binary is not supported, this feature is not available.

\paragraph{ShadingLanguageInclude}

The \lstinline|ShadingLanguageInclude| strategies handle shader includes through OpenGL Named Strings. Named strings and shader includes are emulated if \lstinline|GL_ARB_shading_language_include| is not available in your driver.

\paragraph{Texture}

The \lstinline|Texture| strategies provides texture functions as both direct state access (ARB\_direct\_state\_access and EXT\_direct\_state\_access) and former \emph{bindfull} interfaces.

\paragraph{TextureStorage}

The \lstinline|TextureStorage| strategies handle OpenGL texture storage management. If \lstinline|GL_ARB_texture_storage| is not available, this feature is simulated through multiple texture image calls.

\paragraph{Uniform}

The \lstinline|Uniform| strategies handle the propagation of uniform data to shaders. Both the former interface and the bindless one are available. The latter is available if \lstinline|GL_ARB_separate_shader_objects| is present in your driver.

\paragraph{VertexAttributeBinding}

The \lstinline|VertexAttributeBinding| strategies handle how vertex attributes are configured. Possible implementations are either the former or the current one if your driver supports \lstinline|GL_ARB_vertex_attrib_binding|. If your driver supports direct state access (\lstinline|GL_ARB_direct_state_access|), the bindless interface of the newer one is used instead.

\section{Automated Processes}

As one main goal of globjects is the usage in modern tech demos and early-prototyping applications it supports some generalizable automation concepts.
All of them ease the usage of the OpenGL API in means of lesser code to write and fewer events to react on.

\paragraph{Objects Bindings}

As globjects intends to provide the newest interface as the default one, we don't want you to struggle with updating and keeping track of currently bound OpenGL objects. Unfortunately, only bindings required by the OpenGL driver are converted to bindless interfaces and bindings for the GPU remains.

\paragraph{Error Checking}

When enabled, globjects performs error checks for each OpenGL API call you trigger. If your driver supports it, the OpenGL driver issues any error or notification via a callback interface that is used by globjects. Without such support, an after-callback of glbinding triggers a manual \lstinline|glGetError|. However, the driver alternative provides additional warnings and informations besides actual errors.

\paragraph{Shader Compilation}

globjects Shaders uses attached shader source trees to produce the actual shader source and updates the OpenGL shader state upon source node update.
After that, a shader recompile takes place.
Likewise, Programs are updated if an attached shader is updated.

\paragraph{Program Linkage}

After Shader updates, linked Programs are updated and relinked.
Attached Uniforms are resubmitted to the GPU program after every relink.

\paragraph{Uniform Updates}

If a Uniform is added or updated on a Program, it is automatically updated on the GPU.
Additionally, after every Program relink the attached Uniforms are resubmitted to the GPU.

\section{Handling Unsupported Features}


\paragraph{Simulated Features}


\paragraph{Emulated Features}


\paragraph{Omitted Features}



\section{Multi-Threading and Multi-Context Support}


\section{Conclusions and Remarks}

\paragraph{Limitations}

\paragraph{Future Development}



\end{document}