Skip to content

OpenGL::Modern Development

devel-chm edited this page Mar 20, 2017 · 19 revisions

This page is a list of plans for development of OpenGL::Modern including the changes needed in the existing OpenGL modules to support the transition to modern OpenGL APIs and yet maintain the degree of back compatibility with the legacy implementation and to provide developers a reasonable upgrade path.


Legacy OpenGL issues

The current Perl OpenGL module implements bindings to the original OpenGL fixed-function rendering model. It includes support for modern API features such as buffers and shaders by the OpenGL extension mechanism. However, since OpenGL 3.1 the original OpenGL 1.x and 2.x functions have been deprecated and are only available in a compatibility mode which is unsupported and unsupportable for many new graphics devices such as cell phones and tablets.

In addition, the OpenGL module includes a number of sub-modules that seemed necessary at the time. Now, it is clear that an implementation where these implicit dependencies become actual perl modules of their own will allow a cleaner implementation and allow legacy Perl OpenGL users to make use of OpenGL::Modern API features while keeping such implicit module functions available for use---at least until better options are implemented. Here is a list of issues by module.

OpenGL Constants (done)

The original OpenGL module XS bindings to the constants from OpenGL, GLU, and [Free]GLUT. To simplify things, we'll split the constants out into the relevant bindings module: the bindings for OpenGL constants would be replaced by the implementation from OpenGL::Modern. The GLU and GLUT constants would be provided in the corresponding OpenGL::GLU and OpenGL::GLUT packages.

OpenGL::GLU (done)

The GLU library bindings have been released as their own package. CHM/OpenGL-GLU-0.03.tar.gz was released to CPAN on 04-Mar-2017 .

OpenGL::GLUT (done)

The GLUT bindings have been released as their own package. CHM/OpenGL-GLUT-0.71.tar.gz was released to CPAN on 03-Mar-2017.

FreeGLUT/GLUT is the baseline GUI implementation for OpenGL application development and was included in the Perl OpenGL module to enable symmetric support for Windows, Unix, and MacOS X platforms and to simplify development. However, GLUT is only a GUI and not a requirement for OpenGL development. There are many other GUI libraries and toolkits that can use OpenGL for graphics. Perl OpenGL forces a GLUT/FreeGLUT install as part of the OpenGL bindings. By splitting out OpenGL::GLUT from OpenGL, the bindings can be simplified by putting all GUI toolkits on the same basis. OpenGL::Modern only needs some way to get an OpenGL context, which GUI or toolkit is being used doesn't matter from the OpenGL API point of view.

NOTE: We'll need to address the issues of getting a FreeGLUT install. I think it is time to get Alien::GLUT and Alien::FreeGLUT running..

OpenGL::Array including OpenGL::Matrix and OpenGL::RPN (done)

The OpenGL::Array (which includes both OpenGL::Matrix and OpenGL::RPN) has been released as a stand-alone OpenGL::Array package. CHM/OpenGL-Array-0.71.tar.gz was released to CPAN on 04-Mar-2017.

These three modules are implemented in the OpenGL module to provide helper routines to manage OpenGL buffer management, computation of ModelView matrix operations, and general computation with data buffers as may be required to implement buffer and shader operations.

To support backwards compatibility, we have refactored these 3 modules into their own perl package. That lets OpenGL users migrate to OpenGL::Modern while keeping the support structure from the existing OpenGL code base with the already implemented functionality.

For the future, we need a cleaner approach to provide the functionality of these modules: data array objects, matrix computations, and buffer object computation. In fact, the Perl Data Language (PDL) already provides a more general implementation of these features as well as a superset of the existing functionality.

The architecture and implementation for a Next Generation Perl Data Language (PDL::NG) is underway with goals of improved modularity, better type support, and a better implementation in performance and usability. At some point, I would expect that OpenGL::Modern users would use a module like PDL::Tiny or maybe an optimized PDL::OpenGL::Compute module with actual name TBD.


OpenGL::Modern

Object Oriented Implementation

For consistency and interoperability with current standards for Perl5 and Perl6 OO frameworks, I suggest using Moo and Moo::Role for OO rather than rolling our own implementation.

Moo has the advantage of allowing Moose-ification to use the full meta-object protocol capabilities if needed. Moo[se] provides an OO framework which is very close to the Perl6 OO framework which might improve interoperability of Perl5 and Perl6 development and use of OpenGL::Modern and the related modules.

Roles offer a cleaner way to handle cross-cutting functionality with which to simplify the implementation. For example, rather than hardwiring a set of possible data array providers, we could have a Data::Arrray::OpenGL role. Any module desiring to interface with the OpenGL::Modern bindings, would just apply or implement the role. This would put OpenGL::Array, PDL, SDL buffers,.. all on the same footing.

One concern that has been expressed regarding the use of an OO approach is that the cost of the perl-side work will increase the latency for OpenGL API calls and hurt the performance. One possible optimization would be to implement a stub routine in the role and then use an around method modifier to implement the per-class support for the bindings. With some introspection via MOP we should be able to replace a general around method that doesn't call the wrapped routine (more like an override MM).

The around/override method would be responsible for providing a data structure that could be accessed from the C/XS level to retrieve the parameters needed for the OpenGL API calls thus replacing 2-3 perl method calls by 2-3 structure values from C.

Another issue for implementation of the OpenGL API routines is that there are many variants of each routine all with different argument types (i,f,d,i64,ui,...). In addition, many of the routines do different things depending on the values of their input parameter arguments.

With respect to an OO implemention, this would most directly map to multi-method dispatch as in the Common Lisp Object System (CLOS). Investigations into using the C Object System (COS) to provide multi-method dispatch at the C/XS level show promise for the approach:

  • Each OpenGL API base routine would correspond to a generic
  • Each parameter type would be implemented as a Class type
  • Input/output data would be specified by class (OpenGL::Array or PDL)
  • OpenGL API routine calls would become multi-method calls
  • COS reported performance is about 15nsec per call for multi-dispatch
  • C++ virtual method calls in the same benchmarks were comparable

This suggests that by using COS for the C/XS implementation of an OO OpenGL API bindings we could see performance on par with a simple C implementation.

Buffer operations

While each may use a packed string representation "under the hood", it would seem to be clearer to have the buffer pointers be to some blessed object instead. That blessed type could then implement the appropriate interface as needed. This approach would also be completely general and flexible and could easily be extended to JIT compilation or other types of data creation and operations. This would allow transparent use of C::Pointers, Packed::String, Object references,... which could be used in the above multi-method dispatch using COS.

API function naming

There are a number of considerations in the perl subs of an OpenGL library binding. The bindings should be easy to understand, well documented, efficiently implemented, and simple to use but there is no requirement that they be the same as the native C function API.

For example, there are many variants of OpenGL routines corresponding to differing input data types, and whether they are specified individually or as a vector. From the perl level, the interpreter can know the types and number of each of the arguments so having a perl-ish binding that just "does the right thing" is appealing. Unfortunately, such a high level "smart" implementation could be complicated to develop and verify. It might not perform as well and the difference from the standard could lead to confusion in usage.

The OpenGL module implemented its 1.x-2.x plus EXT bindings with separate functions for each type of arguments. "_p" for perl type arguments, "_c" for direct C pointers to buffers, and "_s" for packed string representation as used by libSDL perl bindings and the Perl Data Language (PDL). This had the advantage that, aside from the "_[cps]" in the sub name, the routine names exactly matched the reference C API naming which meant existing OpenGL programmers could directly translate their code to perl. In addition, the on-line OpenGL documentation could be used to document the module routines with only the high level issues of "_c", "_p", and "_s" needing to be explained in the POD.

For the OpenGL::Modern bindings, we should start with bindings following the OpenGL C API closely. This would be a combination of routines that translate directly and those having pointer/array arguments or return values which need to be converted to/from perl space data structures, "_c" routines.

However, using the ideas of roles and OO with multi-methods as discussed above, I believe that the base perl-ish subs can be implemented efficiently enough that the general user will not need to use function specializations for C pointers, SDL buffers, PDL data, or common perl-ish usages as was done in the OpenGL module implementation.

OpenGL::Texture and OpenGL::Image

These two modules appear to do similar things. It seems reasonable to merge the two into a single module which could maintain an appropriate degree of compatibility (is 100% possible?) while supporting OpenGL::Modern APIs.

We have been unable to reach the maintainer of OpenGL::Image but the resulting module could be in the OpenGL::Modern namespace, e.g, OpenGL::Modern::Image or OpenGL::Modern::Texture.

One idea that is worth maintaining from OpenGL::Image is the use of pluggable modules for different options for image support. The basic framework would be generic but the actual implementation could be whatever is appropriate or desired.

OpenGl::Shader::OpenGL4.pm and OpenGL::Shader

This is a similar story to the above: both modules make a more friendly perl-ish interface for working with shaders. Merging the best of both, maintaining compatibility as best possible into a new OpenGL::Modern::Shader seems like a reasonable plan.

As above, we have been unable to reach the maintainer of OpenGL::Shader for feedback or planning purposes. Please note that OpenGL::Shader is implemented for the pre-OpenGL 3.x versions and may not work for modern OpenGL 3.1-4.x programming.

OpenGL::Modern::Types types support

From the high level perl view, the details of the OpenGL types used for rendering don't matter since a value is just a perl scalar. A buffer is just a data block of some size, etc.

However, the reality is that hardware limitations and performance requirements mean that it does matter what data types are being used. For example, a compute shader computing values in GLdouble type would take twice as much memory per element and much longer to compute than one useing GLfloat values.

I propose abstracting the type information into a module. Ideally, it would be compatible with Moo[se] types. At a minimum, it could be implemented as a class into which the needed values are blessed.

NOTE: The C Object System provides class properties that may be applicable for this at the C/XS level.


Update to baseline GUI from GLUT to GLFW

OpenGL::GLFW bindings

With support for so called "modern opengl" (i.e. OpenGL API versions 3.1 and higher which correspond to the shader-based rendering pipeline), we should update the baseline GUI support.

GLUT/FreeGLUT bindings will continue to be supported but for cross-platform support of OpenGL, EGL, and Vulkan graphics, bindings for the GLFW library are needed. This will provide a lean, efficient, portable baseline window/context creation and basis user interaction features.

Truetype Font Support

As GLFW does not include font support, I propose implementing bindings to some type of text rendering library to enable users transitioning from GLUT to GLFW.

One possibility is the FTGL library but there may be other possibilities. The idea is that there be an easy way to display text in their OpenGL applications.