a18532086 / OpenGL-hpp

c++ interface of OpenGL

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

OpenGL-Hpp: C++ Bindings for OpenGL

The goal of the OpenGL-Hpp is to provide header only C++ bindings for the OpenGL C API to improve the developers OpenGL experience without introducing CPU runtime cost. It adds features like type safety for enums and bitfields, STL container support, exceptions and simple enumerations. This Project is get inspiration from Vulkan-Hpp, and use some source code of it.Thank for every contributor to Vulkan-Hpp !

Getting Started

Just #include <gl.hpp> and you're ready to use the C++ bindings.

Minimum Requirements

OpenGL-Hpp requires a C++17 capable compiler to compile.

The OpenGL version must be 4.5 or higher.

I will add support to without DSA in a long term.

Usage

namespace gl

To avoid name collisions with the OpenGL C API the C++ bindings reside in the gl namespace. The following rules apply to the new naming. Also add some generic supprt

  • glCreateBuffers(N, ...) can be accessed as gl::createObject<Buffer,N>(...) or gl::createObject<Buffer>(N, ...)

  • the gl::createObject will return std::vector<Buffer> variable,this version is designed for run-time length variable

  • Enums are mapped to scoped enums to provide compile time type safety. The names have been changed to 'e' + CamelCase with the GL_ prefix and type infix removed. In case the enum type is an extension the extension suffix has been removed from the enum values.

In all other cases the extension suffix has not been removed.

  • GL_INVALID_OPERATION is now gl::Error::eInvalidOperation.
  • the pname of glGet* such as GL_ELEMENT_ARRAY_BUFFER_BINDING is now map to gl::StateVariables::eElementArrayBufferBinding.
  • the target parameter of glBindBuffer such asGL_ARRAY_BUFFER is now gl::Buffer::BindTarget::eArrayBuffer.
  • the target parameter of glBindBuffer(Base/Range) such as GL_ATOMIC_COUNTER_BUFFER is now gl::Buffer::BindBaseTarget::eAtomicCounterBuffer to avoid invaild enum error

In some cases it might be necessary to move OpenGL-Hpp to a custom namespace. This can be achieved by defining OPENGL_HPP_NAMESPACE before including OpenGL-Hpp.

Handles

OpenGL-Hpp declares a class for all handles to ensure full type safety and to add support for member functions on handles. A member function has been added to a handle class for each function which accepts the corresponding handle as first parameter. Instead of glVertexArrayAttribBinding(vaobj, ...) one can write vaobj.attribBinding(...).

C/C++ Interop for Handles

it is recommended to use a static_cast for the conversion like this: GLuint vaoHandle = static_cast<GLuint>(cppVertexArray) to prevent converting some arbitrary int to a handle or vice versa by accident.

UltraArray

UltraArray is a template class wrapped std::array, beyond the std::array, it can implicit conversion to std::array<T,N> when N > 1 , to T when N == 1, also can implicit convert to std::tuple<T&...> ,you can easily use with std::tie

    gl::Shader vs,fs;
    std::tie(fs,vs) = gl::createObject<gl::Shader>({gl::ShaderType::eFragmentShader,gl::ShaderType::eVertexShader});

Passing Arrays to Functions using ArrayProxy

(this facility source code is from Vulkan-Hpp)

you can use it to simple pass array to Function,such as gl::deleteObject<Buffer>(buffers) rather than glDeleteBuffers(size,&buffers[0])

there is introduction of ArrayProxy in Vulkan-Hpp

The Vulkan API has several places where which require (count,pointer) as two function arguments and C++ has a few containers which map perfectly to this pair. To simplify development the Vulkan-Hpp bindings have replaced those argument pairs with the ArrayProxy template class which accepts empty arrays and a single value as well as STL containers std::initializer_list, std::array and std::vector as argument for construction. This way a single generated Vulkan version can accept a variety of inputs without having the combinatoric explosion which would occur when creating a function for each container type.

Here are some code samples on how to use the ArrayProxy:

vk::CommandBuffer c;

// pass an empty array
c.setScissor(0, nullptr);

// pass a single value. Value is passed as reference
vk::Rect2D scissorRect = { {0, 0}, {640, 480} };
c.setScissor(0, scissorRect);

// pass a temporary value.
c.setScissor(0, { { 0, 0 },{ 640, 480 } });

// generate a std::initializer_list using two rectangles from the stack. This might generate a copy of the rectangles.
vk::Rect2D scissorRect1 = { { 0, 0 },{ 320, 240 } };
vk::Rect2D scissorRect2 = { { 320, 240 },{ 320, 240 } };
c.setScissor(0, { scissorRect, scissorRect2 });

// construct a std::initializer_list using two temporary rectangles.
c.setScissor(0, { { {   0,   0 },{ 320, 240 } },
                { { 320, 240 },{ 320, 240 } }
}
);

// pass a std::array
std::array<vk::Rect2D, 2> arr{ scissorRect1, scissorRect2 };
c.setScissor(0, arr);

// pass a std::vector of dynamic size
std::vector<vk::Rect2D> vec;
vec.push_back(scissorRect1);
vec.push_back(scissorRect2);
c.setScissor(0, vec);

Extensions / Per Device function pointers

this is a very similar facility with Vulkan-Hpp,you can use it without link library or extra source file such as glad,this feature is enable default,

To use the DispatchLoaderDynamic as the default dispatcher (means: you don't need to explicitly add it to every function call), you need to have the macro OPENGL_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE excactly once in your source code to provide storage for that default dispatcher. Then you should call gl::initLoader(...) with the function (function pointer or lambda and so on) which have a from void* (const char*)

For all functions, that OPENGL_HPP_DEFAULT_DISPATCHER is the default for the last argument to that function. In case you want to explicitly provide the dispatcher for each and every function call (when you have multiple dispatchers for different devices, for example) and you want to make sure, that you don't accidentally miss any function call

#include <GLFW/glfw3.h>
...
#include <gl.hpp>

// give the dispatch loader storage youself
OPENGL_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE

int main(){
    // init GLFW
    if (glfwInit() != GLFW_TRUE) {
        throw std::runtime_error("can not init GLFW !");
    }
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
    
    if (!(window = glfwCreateWindow(800, 800, "test", nullptr, nullptr))) {
        throw std::runtime_error("can not create window !");
    }

    glfwMakeContextCurrent(window);

    // init dynamic dispatch loader with one call
    gl::initLoader(glfwGetProcAddress);

    // can use raw OpenGL call in such form, you can also define a short alias
    std::cout << OPENGL_HPP_DEFAULT_DISPATCHER.glGetString(GL_VERSION)
                  << std::endl;

    auto vaos = gl::createObjectv<gl::Buffer>(2);
}

License

The ArrayProxy source is copy from Vulkan-Hpp Project,and several facilitis is get inspired by that Project.

Copyright 2015-2020 The Khronos Group Inc.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

About

c++ interface of OpenGL


Languages

Language:C++ 76.3%Language:C 21.8%Language:Objective-C 1.9%Language:CMake 0.0%