I've been a bit quiet the past few weeks on here, but I've been actively participating in Screenshot Saturday on
/r/gamedev. You can see last weeks
here, and the one prior
here.
This week, I've worked on creating a flexible, slick UI system for making menus. It proved to be pretty complex, and I used a seriously ass-backwards technique to get it accomplished.
You can think of a button as an physical entity, right? You need to be able to check collision, move it around for transitions, and swap textures easily. So I created a
CButton class with a
CEntity inside. At first, I just had a button texture rendered to the screen as a mesh, and the text rendered on top without being a part of the scene. This worked okay, but I wouldn't be able to add shader effects to the text portion of the buttons, which would look weird. So I had to have them both be a part of the scene.
The problem arose when I wanted to assign a texture to the entity. Since the button background is a texture, and the my text-rendering system renders directly to the frame buffer there was no way to easily "blit" them together. I decided to create a frame buffer object for every instance of the button (main, hover, click) and render both parts of the button to it, then assign that texture to the button entity.
As you can see, this is serious overkill. It requires three render passes, two different shaders, and a ton of OpenGL state change. I'm not too worried about this, though, since it will only be called at the beginning of the game, prior to any performance-critical sections. It also works fast on my machine, no frame rate issues whatsoever.
After making the button class, I made another, higher-level class to wrap everything up for flexible menu creation. Now I can just call something like
CMenu::AddButton("Button.tga", "Play Praecursor", math::rect_t(0, 0, 256, 64));
and the wrapper will automatically search for the hover and click versions of the button texture. I added these buttons to a pre-made background, added a lighting effect for a torch (it always looks good), and called it good!
Final result!