Sign in to follow this  
ATC

OpenGL The "best" OpenGL/.NET wrapper?

Recommended Posts

Due to my limited experience with OpenGL, I'm still undecided on which .NET wrapper to use to implement OpenGL-specific portions of my engine. Basically, I'm looking for the SlimDX of the OpenGL world; if that makes any sense...

I'm wanting to know what could be considered the "best" OpenGL wrapper based on the following criteria:[list]
[*]Speed & memory efficiency
[*]"Maturity"; insofar as mimimal bugs/errors and [b][i]completion[/i] [/b](exposes most OpenGL features)
[*]Documentation, resources, help & samples/tutorials
[*]Semantics, elegance, cleanliness and overall design
[*]Interoperability
[*]etc, etc...
[/list]

I'm using SlimDX to implement DirectX support for the engine but need a worthy OpenGL counterpart for C#/.NET. Hopefully you guys can help me "see the light" and make an appropriate choice!

Regards,

ATC Edited by ATC

Share this post


Link to post
Share on other sites
As far as I know, there are only two viable choices, Tao and OpenTK. Recently I threw together a minimal 2D rendering backend using OpenTK, at the same time learning (modern-ish) OpenGL. Can't say I had any issues with the wrapper, although be aware there are newer nightly builds available.

I looked briefly at Tao, but it looked a bit [i]too[/i] thin of wrapper for what I wanted, and doesn't look updated much anymore.

From the OpenTK homepage they claim it supports the latest versions of OpenGL, though I only used a small subset of OGL, and have so far only built/tested under Windows.

Share this post


Link to post
Share on other sites
I've looked into OpenTK, but I dont think their SDK installer worked right for me, which doesn't bode well imho. :-/

Anyone know anything about SharpGL? It looks/sounds pretty good but as to how mature, complete, bugless and fast it is I dunno. And any other info/advice you can offer on the subject?

Share this post


Link to post
Share on other sites
[quote name='ATC' timestamp='1347333622' post='4978769']
I've looked into OpenTK, but I dont think their SDK installer worked right for me, which doesn't bode well imho. :-/
[/quote]

I never even knew there was an installer, I just downloaded the latest build zip here:[url="http://sourceforge.net/projects/opentk/files/opentk/nightly/"]http://sourceforge.n...opentk/nightly/[/url] and referenced in OpenTK.dll.

I personally chose OTK since it was currently being used in production (e.g. Monogame), includes a fully featured math library, and had a relatively active community (compared to Tao).

I haven't looked into SharpGL, so I cannot compare to that.

Share this post


Link to post
Share on other sites
Quick question about this. Probably a dumb question, because I've given it literally 3 seconds of thought:

Couldn't one just use p/Invoke to make calls directly into OpenGL32.dll? Seems like an ultra-thin wrapper of static methods could be made in this way, and you wouldn't need to wrap the whole thing -- just the gl functions that are needed, and one could add to it over time as the project progresses.

Share this post


Link to post
Share on other sites
[quote name='CDProp' timestamp='1347381481' post='4978950']
Quick question about this. Probably a dumb question, because I've given it literally 3 seconds of thought:

Couldn't one just use p/Invoke to make calls directly into OpenGL32.dll? Seems like an ultra-thin wrapper of static methods could be made in this way, and you wouldn't need to wrap the whole thing -- just the gl functions that are needed, and one could add to it over time as the project progresses.
[/quote]

Keep in mind that interop code can get a bit messy, needs to be done correctly to be performant, and you still do not have a math library (vectors, matrices), input & window management system for each native OS you want to support, and probably a multitude of other intricacies I don't know about. And, of course, you miss out on a system that has been tried and tested.

Not to say it wouldn't be an interesting excercise, or that such a system wouldn't fit the OP's purpose. I personally would not enjoy (i.e. probably would never finish) rolling my own wrapper.

Share this post


Link to post
Share on other sites
[quote name='CDProp' timestamp='1347381481' post='4978950']
Quick question about this. Probably a dumb question, because I've given it literally 3 seconds of thought:

Couldn't one just use p/Invoke to make calls directly into OpenGL32.dll? Seems like an ultra-thin wrapper of static methods could be made in this way, and you wouldn't need to wrap the whole thing -- just the gl functions that are needed, and one could add to it over time as the project progresses.
[/quote]

Laztrezort is pretty much spot on. Doing that is essentially proposing that you write an entirely [i]NEW [/i]OpenGL wrapper, instead of using a tried and true one and working on your engine. You'd get so caught up developing a good OpenGL wrapper that you'd never have time for the engine, must less a game (SlimDX, for example, is a full-time affair for it's extremely talented and genius founders and developers)... Interop can be a very sophisticated subject, especially dealing with low-level graphics APIs, hardware and drivers, etc. I've written a few successful/working wrappers, the largest of which is a semi-complete wrapper for the Win32 APIs most important and low-level functions, and includes a customizable and extensible memory management system more conducive to game development than standard memory management by the Standard C Library and C++ runtime. It handles large amounts of [i]frequent [/i]memory allocations and deallocations, unlike the standard malloc function and C++ constructors; it provides a new smart pointer system, customizable garbage collection, defragmentation (and compression), multi-threaded streaming and quite a few other things. It's nowhere near a commercial-grade product, but doing all of that took freakin [i]forever[/i]... Speaking from experience you must be a very competent C, C++ and C# programmer to write a good wrapper; that's why those are the main three languages I know (excluding x86/64 [Intel Syntax] assembly language). I wanted to learn how to do that stuff and understand it, and it took considerable effort in learning those three languages to even begin. Even when you know what to do and know you can work it out, it's a long road and a monumental amount of labor to consider taking on. At some point I've gotta finish an engine and develop games with it. That's why I just wanna find a very nice, complete and stable OpenGL wrapper (as SlimDX is to DirectX) and get on with the show! [img]http://public.gamedev.net//public/style_emoticons/default/smile.png[/img]

[quote name='laztrezort' timestamp='1347382561' post='4978959']
Keep in mind that interop code can get a bit messy, needs to be done correctly to be performant, and you still do not have a math library (vectors, matrices), input & window management system for each native OS you want to support, and probably a multitude of other intricacies I don't know about. And, of course, you miss out on a system that has been tried and tested.

Not to say it wouldn't be an interesting excercise, or that such a system wouldn't fit the OP's purpose. I personally would not enjoy (i.e. probably would never finish) rolling my own wrapper.
[/quote]

Correct. To remain platform-agnostic, I've implemented all of my own math, and vectors, matrices and everything else. My types are implicitly convertible with their SlimDX counterparts, and will be likewise with their OpenGL counterparts when I choose a wrapper to stick with. So that wouldn't be a huge problem. What would be a massive problem is all the performance testing and diagnostics, debugging, design, etc. I must admit I'd probably end up giving up and wishing I'd spent the time on something else.

It would certainly be interesting to just try wrapping the basic parts of OpenGL and rendering a small scene or "mini-tri" example. Would indeed let you learn a lot about OpenGL and interop, and become a better all-around programmer. I think writing a basic operating system is another such exercise all programmers can benefit from. Edited by ATC

Share this post


Link to post
Share on other sites
Does anyone have any more information about this? I still haven't been satisfied enough to permanently select an OpenGL wrapper for my engine to support...

So far I'm getting that OpenTK and Tao both [i]work[/i] well, but neither is especially good (perhaps I'm mistaken, but that's how it's sounded to me)... I really need something up-to-par with SlimDX, which is also up-to-date. If the developers aren't supporting a wrapper anymore it will leave a big, unwanted burden on [i]me[/i]. So hopefully some more folks with experience with some OpenGL wrappers can give me further info/input???

Share this post


Link to post
Share on other sites
I'm using SlimDX and Tao in my engine. The reason I chose Tao is because it closely resembles the original syntax so I could easily port parts of my C++ engine over without too much grief. The good news is the OpenTK engine is backwards compatible with Tao so you can swap over to OpenTK later on and if you like change the syntax to be more .NET centric.

Share this post


Link to post
Share on other sites
[quote name='swiftcoder' timestamp='1349455923' post='4987174']
If you are worried about cross-platform, then to my mind, both Tao and OpenTK are pretty much a non-starter - neither one supports modern versions of OpenGL (3.x+) under Mac OS X.
[/quote]

Only the latest (or maybe its the 2 latest ones now) OS X version supports OpenGL 3.x anyway so its not much of an issue. If you want cross platform support you're best off using OpenGL 2.1 still. Edited by SimonForsman

Share this post


Link to post
Share on other sites
[quote name='SimonForsman' timestamp='1349728197' post='4988103']
If you want cross platform support you're best off using OpenGL 2.1 still.[/quote]
I don't have that luxury, which unfortunately means that cross-platform CLR is still DOA for me.

I tried to poke OpenTK into proper Mac support a year or so back, but the results were less than enthusiastic, and I don't have time to port it myself. C'est la vie. Edited by swiftcoder

Share this post


Link to post
Share on other sites
I've been using OpenTK for about a year now. I haven't tried it on a mac, but I'm able to run openGL 3.3 on a linux box and windows box without any changes. It also looks like it supports up to OpenGL 4.2 (but I haven't tried-need that kind of hardware first). I wish the openTK website was more up to date, but it's the best library that I've found since it also includes openAL and openCL bindings as well as handles window and input handling.

Cheers,

Bob

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Announcements

  • Forum Statistics

    • Total Topics
      628305
    • Total Posts
      2981967
  • Similar Content

    • By mellinoe
      Hi all,
      First time poster here, although I've been reading posts here for quite a while. This place has been invaluable for learning graphics programming -- thanks for a great resource!
      Right now, I'm working on a graphics abstraction layer for .NET which supports D3D11, Vulkan, and OpenGL at the moment. I have implemented most of my planned features already, and things are working well. Some remaining features that I am planning are Compute Shaders, and some flavor of read-write shader resources. At the moment, my shaders can just get simple read-only access to a uniform (or constant) buffer, a texture, or a sampler. Unfortunately, I'm having a tough time grasping the distinctions between all of the different kinds of read-write resources that are available. In D3D alone, there seem to be 5 or 6 different kinds of resources with similar but different characteristics. On top of that, I get the impression that some of them are more or less "obsoleted" by the newer kinds, and don't have much of a place in modern code. There seem to be a few pivots:
      The data source/destination (buffer or texture) Read-write or read-only Structured or unstructured (?) Ordered vs unordered (?) These are just my observations based on a lot of MSDN and OpenGL doc reading. For my library, I'm not interested in exposing every possibility to the user -- just trying to find a good "middle-ground" that can be represented cleanly across API's which is good enough for common scenarios.
      Can anyone give a sort of "overview" of the different options, and perhaps compare/contrast the concepts between Direct3D, OpenGL, and Vulkan? I'd also be very interested in hearing how other folks have abstracted these concepts in their libraries.
    • By aejt
      I recently started getting into graphics programming (2nd try, first try was many years ago) and I'm working on a 3d rendering engine which I hope to be able to make a 3D game with sooner or later. I have plenty of C++ experience, but not a lot when it comes to graphics, and while it's definitely going much better this time, I'm having trouble figuring out how assets are usually handled by engines.
      I'm not having trouble with handling the GPU resources, but more so with how the resources should be defined and used in the system (materials, models, etc).
      This is my plan now, I've implemented most of it except for the XML parts and factories and those are the ones I'm not sure of at all:
      I have these classes:
      For GPU resources:
      Geometry: holds and manages everything needed to render a geometry: VAO, VBO, EBO. Texture: holds and manages a texture which is loaded into the GPU. Shader: holds and manages a shader which is loaded into the GPU. For assets relying on GPU resources:
      Material: holds a shader resource, multiple texture resources, as well as uniform settings. Mesh: holds a geometry and a material. Model: holds multiple meshes, possibly in a tree structure to more easily support skinning later on? For handling GPU resources:
      ResourceCache<T>: T can be any resource loaded into the GPU. It owns these resources and only hands out handles to them on request (currently string identifiers are used when requesting handles, but all resources are stored in a vector and each handle only contains resource's index in that vector) Resource<T>: The handles given out from ResourceCache. The handles are reference counted and to get the underlying resource you simply deference like with pointers (*handle).  
      And my plan is to define everything into these XML documents to abstract away files:
      Resources.xml for ref-counted GPU resources (geometry, shaders, textures) Resources are assigned names/ids and resource files, and possibly some attributes (what vertex attributes does this geometry have? what vertex attributes does this shader expect? what uniforms does this shader use? and so on) Are reference counted using ResourceCache<T> Assets.xml for assets using the GPU resources (materials, meshes, models) Assets are not reference counted, but they hold handles to ref-counted resources. References the resources defined in Resources.xml by names/ids. The XMLs are loaded into some structure in memory which is then used for loading the resources/assets using factory classes:
      Factory classes for resources:
      For example, a texture factory could contain the texture definitions from the XML containing data about textures in the game, as well as a cache containing all loaded textures. This means it has mappings from each name/id to a file and when asked to load a texture with a name/id, it can look up its path and use a "BinaryLoader" to either load the file and create the resource directly, or asynchronously load the file's data into a queue which then can be read from later to create the resources synchronously in the GL context. These factories only return handles.
      Factory classes for assets:
      Much like for resources, these classes contain the definitions for the assets they can load. For example, with the definition the MaterialFactory will know which shader, textures and possibly uniform a certain material has, and with the help of TextureFactory and ShaderFactory, it can retrieve handles to the resources it needs (Shader + Textures), setup itself from XML data (uniform values), and return a created instance of requested material. These factories return actual instances, not handles (but the instances contain handles).
       
       
      Is this a good or commonly used approach? Is this going to bite me in the ass later on? Are there other more preferable approaches? Is this outside of the scope of a 3d renderer and should be on the engine side? I'd love to receive and kind of advice or suggestions!
      Thanks!
    • By nedondev
      I 'm learning how to create game by using opengl with c/c++ coding, so here is my fist game. In video description also have game contain in Dropbox. May be I will make it better in future.
      Thanks.
    • By Abecederia
      So I've recently started learning some GLSL and now I'm toying with a POM shader. I'm trying to optimize it and notice that it starts having issues at high texture sizes, especially with self-shadowing.
      Now I know POM is expensive either way, but would pulling the heightmap out of the normalmap alpha channel and in it's own 8bit texture make doing all those dozens of texture fetches more cheap? Or is everything in the cache aligned to 32bit anyway? I haven't implemented texture compression yet, I think that would help? But regardless, should there be a performance boost from decoupling the heightmap? I could also keep it in a lower resolution than the normalmap if that would improve performance.
      Any help is much appreciated, please keep in mind I'm somewhat of a newbie. Thanks!
    • By test opty
      Hi,
      I'm trying to learn OpenGL through a website and have proceeded until this page of it. The output is a simple triangle. The problem is the complexity.
      I have read that page several times and tried to analyse the code but I haven't understood the code properly and completely yet. This is the code:
       
      #include <glad/glad.h> #include <GLFW/glfw3.h> #include <C:\Users\Abbasi\Desktop\std_lib_facilities_4.h> using namespace std; //****************************************************************************** void framebuffer_size_callback(GLFWwindow* window, int width, int height); void processInput(GLFWwindow *window); // settings const unsigned int SCR_WIDTH = 800; const unsigned int SCR_HEIGHT = 600; const char *vertexShaderSource = "#version 330 core\n" "layout (location = 0) in vec3 aPos;\n" "void main()\n" "{\n" " gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n" "}\0"; const char *fragmentShaderSource = "#version 330 core\n" "out vec4 FragColor;\n" "void main()\n" "{\n" " FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n" "}\n\0"; //******************************* int main() { // glfw: initialize and configure // ------------------------------ glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // glfw window creation GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "My First Triangle", nullptr, nullptr); if (window == nullptr) { cout << "Failed to create GLFW window" << endl; glfwTerminate(); return -1; } glfwMakeContextCurrent(window); glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); // glad: load all OpenGL function pointers if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { cout << "Failed to initialize GLAD" << endl; return -1; } // build and compile our shader program // vertex shader int vertexShader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr); glCompileShader(vertexShader); // check for shader compile errors int success; char infoLog[512]; glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(vertexShader, 512, nullptr, infoLog); cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << endl; } // fragment shader int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr); glCompileShader(fragmentShader); // check for shader compile errors glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(fragmentShader, 512, nullptr, infoLog); cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << endl; } // link shaders int shaderProgram = glCreateProgram(); glAttachShader(shaderProgram, vertexShader); glAttachShader(shaderProgram, fragmentShader); glLinkProgram(shaderProgram); // check for linking errors glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success); if (!success) { glGetProgramInfoLog(shaderProgram, 512, nullptr, infoLog); cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << endl; } glDeleteShader(vertexShader); glDeleteShader(fragmentShader); // set up vertex data (and buffer(s)) and configure vertex attributes float vertices[] = { -0.5f, -0.5f, 0.0f, // left 0.5f, -0.5f, 0.0f, // right 0.0f, 0.5f, 0.0f // top }; unsigned int VBO, VAO; glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); // bind the Vertex Array Object first, then bind and set vertex buffer(s), //and then configure vertex attributes(s). glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); // note that this is allowed, the call to glVertexAttribPointer registered VBO // as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind glBindBuffer(GL_ARRAY_BUFFER, 0); // You can unbind the VAO afterwards so other VAO calls won't accidentally // modify this VAO, but this rarely happens. Modifying other // VAOs requires a call to glBindVertexArray anyways so we generally don't unbind // VAOs (nor VBOs) when it's not directly necessary. glBindVertexArray(0); // uncomment this call to draw in wireframe polygons. //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // render loop while (!glfwWindowShouldClose(window)) { // input // ----- processInput(window); // render // ------ glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); // draw our first triangle glUseProgram(shaderProgram); glBindVertexArray(VAO); // seeing as we only have a single VAO there's no need to // bind it every time, but we'll do so to keep things a bit more organized glDrawArrays(GL_TRIANGLES, 0, 3); // glBindVertexArray(0); // no need to unbind it every time // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.) glfwSwapBuffers(window); glfwPollEvents(); } // optional: de-allocate all resources once they've outlived their purpose: glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); // glfw: terminate, clearing all previously allocated GLFW resources. glfwTerminate(); return 0; } //************************************************** // process all input: query GLFW whether relevant keys are pressed/released // this frame and react accordingly void processInput(GLFWwindow *window) { if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) glfwSetWindowShouldClose(window, true); } //******************************************************************** // glfw: whenever the window size changed (by OS or user resize) this callback function executes void framebuffer_size_callback(GLFWwindow* window, int width, int height) { // make sure the viewport matches the new window dimensions; note that width and // height will be significantly larger than specified on retina displays. glViewport(0, 0, width, height); } As you see, about 200 lines of complicated code only for a simple triangle. 
      I don't know what parts are necessary for that output. And also, what the correct order of instructions for such an output or programs is, generally. That start point is too complex for a beginner of OpenGL like me and I don't know how to make the issue solved. What are your ideas please? What is the way to figure both the code and the whole program out correctly please?
      I wish I'd read a reference that would teach me OpenGL through a step-by-step method. 
  • Popular Now