kl_mallory's picture


So I've been working to learn OpenGL via OpenTK for the last 6 months. I decided that my first undertaking would be a 2D UI system. I've been working with Microsoft Technologies of varies kinds for the last 10+ years (yeah, I'm old). But DirectX is just no fun for me, they change the API and deprecate older functionality way to fast to keep up with. So anyway, I've been developing something I affectionately call the GLUI. I'm focusing on the way most OpenGL surfaces are used in full screen exclusively, where resizing and moving controls around windows style is not as useful. But docking in a full screen window environment if VERY useful. It's not hard to do (I have drag & drop working), it's just not as useful in a game UI.

So I've focused on an Object Oriented OpenGL framework with forward compatible functionality for docking, vertical scrolling, text labels and inputs, auto-sizing styles, panels, buttons, image boxes, AND efficient event handling / consistent FPS. So far I'm pleased with the results. The FPS in the screen shots is from my Intel HD Laptop(200-300) FPS, not my Nvidia Quadro (1500+ FPS).

I'm thinking about eventually moving the GLUI to an MIT or BSD open Source License, but I'm not sure yet. It may not even be of interest to most of you, since I'm pretty new to openGL. I've seen other people's examples but found them to be consuming too much CPU time, or requiring other third party stuff, or licensed under GPL :-(

My UI won't work in Mono however, because I use aspects of the System.Drawing that don't seem to be implemented by Mono at this time. Mostly to resolve docking area conflicts. Specifically the region class. I also have minor compatibility problems with the Intel HD drivers, it seems to be my shaders :-(

(I used windowed mode to get easy screen shots.)

The Code required to generate a view seen in the screenshots is incredibly simple. For example the code below is all that's needed to produce the the form in the first screen shot.

    internal class TestMenuForm : GLForm
        public TestMenuForm()
            this.Style.BorderWidth = 3;
            this.Name = "TestMenuform";
            var debugPanel = new DebugPanel();
            debugPanel.Name = "debugPanel";
            debugPanel.Style.BorderWidth = 0;
            var menu3 = new Panel();
            menu3.Name = "menu3";
            menu3.Size = new System.Drawing.Size(256, 128);
            menu3.Style.Docking = ContentAlignment.BottomLeft;
            menu3.Style.BackColor = Color.Navy.ToRgba();
            menu3.Style.BorderWidth = 1;
            var textInput = new TextInput();
            textInput.Name = "LittleText";
            textInput.Size = new Size(247, 18);
            textInput.Location = new Point(3, 3);
            var btnHello = new Button();
            btnHello.Name = "Hello";
            btnHello.Text = "Hello";
            btnHello.BackgroundImage = "IndustrialButtonLarge";
            btnHello.HoverImage = "IndustrialButtonLargeHover";
            btnHello.PressedImage = "IndustrialButtonLargePressed";
            btnHello.Style.Docking = ContentAlignment.TopRight;
            btnHello.Style.BorderWidth = 2;
            btnHello.ZOrder = ZORDER_DOCKED;
            //exits the demo.
            var btnExit = new Button();
            btnExit.Name = "Exit";
            btnExit.Text = "Exit";
            btnExit.BackgroundImage = "IndustrialButtonLarge";
            btnExit.HoverImage = "IndustrialButtonLargeHover";
            btnExit.PressedImage = "IndustrialButtonLargePressed";
            btnExit.Style.Docking = ContentAlignment.BottomRight;
            btnExit.ZOrder = ZORDER_DOCKED;
            btnExit.OnClick += new Click(btnExit_OnClick);
            //Tests automatically showing vertical scrollbar when control is outside viewable area
            var menuOffScreen = new ImageBox();
            menuOffScreen.Name = "imgOffScreen";
            menuOffScreen.Location = new System.Drawing.Point(1024 / 2 - 800 / 2, 600);
            menuOffScreen.Size = new System.Drawing.Size(800, 600);
            menuOffScreen.Style.Docking = null;
            menuOffScreen.Style.RelativeWidth = 0;
            menuOffScreen.Style.RelativeHeight = 0;
            menuOffScreen.Style.BackColor = Color.Red.ToRgba();
            menuOffScreen.Style.BorderWidth = 1;
            var textBig = new TextInput();
            textBig.Name = "BigText";
            textBig.Size = new Size(592, 18);
            textBig.Location = new Point(3, 3);


Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
c2woody's picture

Looks nice, I can only encourage posting sources if you think it might be interesting for other people to check out your work or even use it as base for other projects.

reibisch's picture

Looks very interesting. I've tinkered with building similar things in the past. I would second c2woody's recommendation that you make it available if you don't mind. Even if people don't wind up using it as-is, code such as yours no doubt offers newer developers valuable insight.

Also, I'm curious about your vertex count. The lowest number of vertices I can imagine (excluding the monitoring text in the top-left) is 44. :)

kl_mallory's picture

I'm working on making it Open Source. I have built all the controls I need to make other controls. For instance a drop down box would just be a combination of a panel and a text input and a button. So it's initial phase is complete. I need to pull out a proprietary set of icons before I make it open source, because I don't have the rights to distribute them. Also I have some proprietary technology in my GLCore assembly I need to figure out what to do with, like an IOC / DI system and an XML repository system I built.

The vertices count and primitives count is based on a 'per cycle' rather than a 'per second'. In order to make the control system faster I made it so that not every control has it's own framebuffer. I found that on some machines, creating framebuffers is expensive. So I have some controls like panels and 'drag&drops' that may need to move outside the bounds of their parent inheriting from 'AbstractFramebufferControl', other controls just exist as children of the 'AbstractFramebufferControl's. This makes it blazing fast to start up.
I also made it so only the controls which need a refresh are redrawn, so the only vertices you see in the first screenshot are the quad vertices count of the controls which are being drawn to the backbuffer every cycle. the second screenshot actually shows one more quad because I moved the mouse over the 'hello' button initiating the 'hover' style which caused it to be redrawn to the framebuffer, those draws also get counted.

So I'm working on releasing it, I just need to clean up the stuff I can't redistribute and add some copyright info. It will probably be in July that I get it released. Work is keeping me busy these days. :-)

All paid jobs absorb and degrade the mind -Aristotle