OpenGL in C# – an object oriented introduction to OpenTK

Finally: Triangles

With of all the above set up, we can finally put things together, and render our first triangle!

To recap, here are the steps we have to follow to put all of the above together.

When the program loads we:

  • create a vertex buffer and put some vertices into it;
  • load our shaders and link them into a shader program;
  • create a vertex array to specify our vertices’ layout;
  • create a matrix uniform for our projection matrix.

Since we abstracted a lot of functionality into the different types, we can do all of this in just a few lines of code. This is a good example of how abstraction helps think about a problem on a higher level to prevent getting caught up in the details.

With everything set up, we can now draw the vertices we created as follows:

  • activate shader program and set uniforms;
  • bind vertex buffer and array objects;
  • upload vertices to GPU and draw them;
  • reset state for potential further draw calls (optional, but good practice).

And the resulting image may look something like this:

Screenshot of coloured triangle on dark background

The code for both of these parts can found in the OnLoad() and OnRenderFrame() of the final game window.

In fact I put together all the source code above into a neat little stand-alone project which you can find on my GitHub page.

Feel free to take a look and do with the code as you will.

Conclusion

In this post we went from an empty game window to creating several types to make using OpenGL in C# much easier.

That allowed us to put together a simple example renderer drawing a colourful triangle using our own shaders.

I use virtually the same code as above, though with a lot more additional features and a few more layers of abstraction in my own graphics library which is also available on GhitHub.

The library is still heavily in development, and I am currently in the middle of refactoring large parts of it. However it already has a lot of features and is working well and fast enough to power the complex rendering pipeline of Roche Fusion.

I hope this post has been useful to you. Of course feel free to ask questions or comment below.

I would love to hear what you think, especially if this post may have convinced you to look into OpenGL in C# yourself.

There will also be more posts on OpenGL and computer graphics in general coming up in the future. These may include but are not limited to keyframe animations, GPU simulated particle systems, a variety of post processing techniques, and more!

If you have any particular topic you would like me to cover, Feel free to let me know, and I will prioritize those subjects.

For the time being,

Enjoy the pixels!

Pages: 1 2 3 4

Leave a Reply

10 comments

  1. Thanks a lot for writing this! It’s a really nice post and clearly explains the basics of OpenGL. I really want to do some stuff in OpenGL – mainly because XNA feels kinda quirky sometimes – and this is a great kickstart.

    As to other subjects, one thing I am particularly interested in would be gpu particles, and since you used them in RF (pretty extensively to say the least) I figure you’d know enough about them to do a post about it ;)

    Thanks, and keep the good stuff coming!
    Luca

    • Paul Scharf says:

      Thanks Luca!

      I will definitely be posting about those particles and lots of other topics.

      There is already a rough write-up regarding the particles on the Roche Fusion devlog: http://rochefusion.com/devlog/239/from-thousands-to-millions-of-particles

      But I will definitely do a more low-level post with an example in the future!

      Thanks again, and be sure to let me know how it goes if you look into OpenGL.

      • Yay triangles! :D http://i.imgur.com/IhaM4mR.png
        I figured it’d be best to simply follow the turotial step by step, and that went quite well I think.

        I did find myself looking for methods that weren’t defined yet though. For example with the ShaderProgram, you add the GetAttributeLocation and GetUniformLocation methods after you use them. Not too big a deal however, and I figured it out quite quickly ;) It also really helped to have the complete example project and your library on GitHub for reference or looking something up. It’s nice that by following this you not only teach the basics but create a simple framework while doing so, which is minimalistic yet really useful.

        It is interesting how much more freedom you have in comparison to XNA :O even though that also means you have to do a bit more work. However once you have a basic framework (like this) set up that helps a lot. It takes quite some getting used too, but I’ll probably spend most of my upcoming spare time on OpenGL now ^^.

        You got me hooked :) Thanks again!

        PS: I also read the particle post, really interesting stuff! And the GPU particle system doesn’t look as complicated as I feared :P Still, a full post or even tutorial on that would be cool :)

  2. ozzyM says:

    Perfect. I have been looking for OpenGL + C# + GLSL since many months and finally. Thank you. I will just follow each and every. my #version 140 is it ok? . I haven’t tried your code so far but I will do. Hope you will be creating from the basic and with the same Good Explanation and I have just started learning this, hope you will stay with us. Thank you.

    • Paul Scharf says:

      Hey,

      I’m glad to hear this post is useful for you!

      #version 140 is for GLSL version 1.4, which comes with OpenGL 3.1 (very confusing version combinations!)
      That should work fine for most things, but there is very little hardware that supports exactly OpenGL 3.1
      Older (very old really) hardware tends to go up to 2.1, and almost everything else at least supports 3.2, or newer.

      So I usually use #version 150 which comes with OpenGL 3.2
      That also works better on non-windows platforms (especially Mac OSX) which can be more picky about what OpenGL version you try to use.

      Hope that answers your question.

      In either case, let me know if you have any other questions! :)

  3. You don’t seem to talk about the potential pitfalls or challenges related to determining the size of a buffer and the offsets of data in it. You have the size of a ColouredVertex hard-coded at (3+4)*4, but doesn’t this assume that the compiler is aligning members of the struct in a particular way? If you attempt to use sizeof(ColouredVertex) you’ll get a compiler error that talks about why the size of this structure may not be constant. Isn’t this a potential problem?

    • Paul Scharf says:

      Hey Benjamin,

      You’re right that getting the struct size right is very important. If something goes wrong with that, you get lots of crashes in the worst, and something like the following in the best case:

      I did not go over that here to keep things relatively brief, though.

      As you say, their is no guarantee for the compiler to actually use what seems the most obvious memory layout, unless you force it to do so, using StructLayoutAttribute (though .NET seems to do so in most cases, while Mono is somewhat less predictable). For example [StructLayout(LayoutKind.Sequential, Pack = 1)] would always result in the ‘obvious’ memory layout.

      Regarding the size, we also do not have to rely on hardcoding. While sizeof() indeed does not work for structs, we can use System.Runtime.InteropServices.Marshal.SizeOf(typeof(TVertex)) to get the size at runtime.

      So as you rightly say, there a bunch of things here we can do wrong, but these are by no means problems we cannot work around (and relatively easily so).

      Hope that answers your questions! :)

  4. Dapo Olaleye says:

    I’m a little lost as to how i could use any of this as to generate a texture or sprite. Heck even a movable object (Vector).

    Though, i only say any of this because i am very new to C# and OpenTK. I moved from ActionScript 2 to AS3 to Haxe and now i’m trying to go for the “Real” programming languages and i’m kinda lost here and there when it comes to just making a movable object (Like a movie clip with some texture or what-not).

    Sorry, guess i’m just really a noob when it comes to things way outside my comfort zone and this is the first post i’ve seen on this website during my quest of trying to find a OpenTK tutorial that doesn’t rely on immediate mode (Since i heard it’s for all intents and purposes: slower, limiting and basically bad in a sense and i didn’t want to rely on unity for… various reasons) but… isn’t there at least some way to translate all this into generating a sort of content pipe for vector and bitmap graphics or any form of texture and object other than just triangles (which apparently seems to be the most popular shape to make in most tutorials i’ve seen).

    Sorry if i’m rambling on, just trying to figure out how to basically generate a texture using a png or jpg image at least and movable and rotatable object with all this since i’m really new to OpenTK :)