Tyr: Debug Rendering

Posted in Code on November 13th, 2011 by Pyroka

This second post this week, is to make up for the very very high likely-hood that there will be no post next week due to work and such.

It’s gotten to the stage where the editor could do with drawing some stuff, stuff like markers to show the position/size of the currently selected node, and this raises an interesting problem. It would also be good for game-nodes to be able to draw debug graphics, from anywhere in their update loop (or functions called from that).

So, I have need of a way to store rendering commands for later use, my idea was to have some form of buffer that is cleared every frame, and methods to add common shapes to that buffer (rectangles, circles, etc.). Due to the way that scenes work in Tyr (there can be more than one scene active at the same time) I need a buffer per-scene, and a global buffer, for things like the editor who will want to draw out-side of a nodes update loop.

Now, the simplest method of drawing shapes with OpenGL is with the glBegin and glEnd methods, basically, you call glBegin, passing it a mode (To draw lines, quads, triangles, etc.) and then repeatedly call glVertex, glTexCoord, glColour, describing the geometry you’d like to draw. So I decided to create a class that holds to std::vectors, the fist one is a list of commands (to be passed to glBegin) and an index into the second buffer, the second buffer will hold only floats, used to express the colour and vertex positions of the items I wish to draw. I made the decision that any primitive drawn by this debug-drawing code will have all vertecies drawn in the same colour, to save on the amount of information I’m saving (and to stress that this is for debug-only drawing, since it will be rather slow).

Primitives are added to this buffer by calling one of several methods (DrawRect, DrawCircle, etc.) all of which take a RGBA colour, and the relevant per-primitive information, this calls internal methods to add commands to the command list and float to the float list, this is all done so that the drawing code can be as simple as possible.

void Renderer::Render( DebugBuffer* pBuffer )
{
	glDisable(GL_TEXTURE_2D);
	glDisable(GL_DEPTH_TEST);
	glBindTexture(GL_TEXTURE_2D, 0);
	g_ShaderManager.Bind(INVALID_SHADER);

	size_t commandIndex = 0;
	size_t floatIndex = 0;

	while(floatIndex < pBuffer->m_FloatList.size())
	{
		GLuint startIndex = pBuffer->m_CommandList[commandIndex++];
		TYR_ASSERT_MSG(floatIndex == startIndex, "Start index does not match current float index");
		GLuint command = pBuffer->m_CommandList[commandIndex++];

		// Grab the colours
		GLfloat red	= pBuffer->m_FloatList[floatIndex++];
		GLfloat green	= pBuffer->m_FloatList[floatIndex++];
		GLfloat blue	= pBuffer->m_FloatList[floatIndex++];
		GLfloat alpha	= pBuffer->m_FloatList[floatIndex++];

		// We should end before the next set
		GLuint nextStartIndex = commandIndex < pBuffer->m_CommandList.size() ?
								pBuffer->m_CommandList[commandIndex] :
								pBuffer->m_FloatList.size();

		// Draw it
		glBegin(command);
		for(;floatIndex < nextStartIndex;)
		{
			float x = pBuffer->m_FloatList[floatIndex++];
			float y = pBuffer->m_FloatList[floatIndex++];
			float z = pBuffer->m_FloatList[floatIndex++];

			glColor4f(red, green, blue, alpha);
			glVertex3f(x, y, z);
		}
		glEnd();
	}
}

This is the code that renders a DebugBuffer, it simply loops through the commands, grabbing the needed floats from the float buffer that are then used to render the primitive. Each command knows the index of the first float that it needs to access (the red value for the colour) and by looking ahead to the next command, we can get the total number of floats that command uses.

The system as it stands seems to work quite well, as I mentioned earlier, each scene has it’s own debug buffer and there is a global one too, the rendering order is scene (and child nodes), the scene’s DebugBuffer and finally the global DebugBuffer, so that the debug information is always available (I may have to alter this when I add support for post-process effects, as those will want to be applied before the debug rendering. I also need to extent this method to allow the rendering of text, but I’m not entirely sure how to go about doing that one yet. This system is rather new (it was implemented mostly on Saturday night) so it may change over time when it is used more extensively.

Tags: , ,

Tyr: Managing Managers

Posted in Code on November 8th, 2011 by Pyroka

Like most game engines, Tyr has a number of managers, these managers are typically responsible for loading, saving and manipulating certain objects, they are also (in Tyr at-least) responsible for owning the objects, meaning that they control the lifetime of said objects and are responsible for deletion (to this end, I usually make objects owned by a manager have a private destructor, so that attempting to delete them not through the manager is a compile error).

Now there is a set order, logically that these managers should themselves be created, granted for some of them it doesn’t matter (should the texture manager be created before the shader manager?), whilst for others, it is pretty easy (the Logger, responsible for logging warnings and errors, should probably be first) and if there is an order they should be constructed, they should be destructed in reverse order, otherwise nasty things may occur.

So, I set about trying to come up with a nice way to make such an arrangement happen, this post will document my journey.

First things first, we have some common behaviour, all the managers should have a priority, and throw in Init and Shutdown methods for good measure (these will be called based on the priority) so for that we need a BaseManager (which I was very tempted to call ManagerManager), the base manager doesn’t do much at the moment:

class BaseManager : public NonCopyable
{
public:
	//! Constructor
	BaseManager(
		u8 priority		//!< Priority of the manager (lower is higher)
		);

	//! Destructor
	virtual ~BaseManager();

	//! Initialise (called in order of priority)
	//! \return True on success
	virtual bool Init() = 0;

	//! Shut-down
	//! \return True on success
	virtual bool Shutdown() = 0;

	//! Get the priority of the manager
	//! \return The priority
	u8 GetPriority() const;

private:
	u8 m_Priority;		//!< Priority of this manager, lower higher in list
};

The main point of node is the priority member variable, which is a u8, allowing 255 managers (should be enough for anyone, right?), now the comment for this member talks about a list, and we'll get to that in a moment, but allow be to indulge into a brief tangent on static initialisation in C++.

Lots of people would implement these managers using the Singleton design pattern, indeed it used to be my weapon of choice for such tasks, and it has a lot of merits, especially when you get to the more advanced versions which allow you to control when they are constructed and deleted, however, I grew tired of singletons for a variety of reasons, for one they give you a false feeling of safety (even though it is pretty easy to maliciously, or accidentally create more than one) they can have issues being used in .dlls, and also, typing out Singleton::Instance() (or your equivalent) is a tad verbose and does get tiring after a while.

So now I use global variables straight-up, rather than attempting to hide behind a design pattern to make them go away, global variables are of-course bad, as are macros, and both will be used judiciously here, generally, all the 'bad' things that you 'should never use' end up being useful after a while, you just have to know the risks and decide they're worth it.

So, back to static initialisation (forgive my tangent from my tangent). See all my managers are declared by an extern, something like:

extern TextureManager g_TextureManager;

This is nice and simple but it does mean that the manager object is constructed during static initialisation and thus I have no say in whether this manager is constructed before that manager, which is slightly ok, after-all we made that Init() method so that we could initialise the managers in a different order to the one they were constructed in. The problem, as it turns out, lies with the fact that we have to store references to these managers in a list, and is we want to register managers in their constructor (which we do otherwise we will have to manually update a list of managers and that just sounds horrendous) we need to make sure that the list of managers is constructed before any of the managers themselves.

Lucky for all, all is not undefined in the land of static initialisation, static local variables, declared in a function, will be initialised the first time that function is called. So, to solve our manager-list issue we merely need to define a member function on the BaseManager like so:

ManagerList& BaseManager::GetManagerList()
{
	static ManagerList managerList;
	return managerList;
}

Then, in the constructor of the BaseManager add:

GetManagerList().push_back(this);

This will make sure that our list of managers is constructed before we attempt to add a manager to it (which is nice, I'm sure you'd agree). So, we have our list, we have our managers that register with said list, sorting the list is a trivial issue, as is calling the Init/Shutdown functions in correct orders, so now we turn our attention to how best to define the priority and thus the order of these managers.

Now, you can just manually define them, that would be ok, for a while, but when you have more than a few managers the relationships get pretty complex and going back and changing numbers is very tedious, no, what we need is a list, a list with the names of the managers in a human readable format, and their position in that list to be their priority. What we need, is an enum.

When this idea hit me I immediately liked the cleanness of it, just define an enum, perhaps in one of the higher-up components of the engine (in the Engine.lib, actually) and all is well, you can re-order the entries in the enum, and all the priority values will change and there will be no errors due to forgetting that one manager. There are, however, two main issues in this technique. Firstly, by making the priority of the manager be defined else-where, we are making that library implicitly rely on another library, which I want to attempt to avoid, however, by marking the priorities as 'extern' I am merely stating that something, somewhere has to define a value for that, if they want to use this library, I personally don't think that is too bad. Secondly, if I am defining this list in a high-level library (and I am) there is a very high-chance that I will create a circular dependency (Engile lib defines the priorities, Engine lib relies on RenderLib to do rendering, RenderLib relies on the priorities defined in EngineLib) however, both Visual Studio and GCC can deal with this (you just have to tell GCC to deal with it using --start-group and --end-group) so that isn't too bad either.

Now all that is left is to make the process of defining these managers and the priority list easier and less prone to errors, and for that, I chose to break-out the macros.

In the BaseManager header, I define 3 macros:

#define TYR_GET_MANAGER_PRIORITY_VAR(name)		name##_Priority
#define TYR_DEFINE_MANAGER_PRIORITY_VAR(name)	extern	u8 TYR_GET_MANAGER_PRIORITY_VAR(name);
#define TYR_MANAGER_CTOR(name) \
	TYR_DEFINE_MANAGER_PRIORITY_VAR(name) \
	name::name() \
		: BaseManager(TYR_GET_MANAGER_PRIORITY_VAR(name))

The first one, simply makes it convenient to get the name of the variable correct everywhere it's used, the second one declares an external variable that is used as the priority, and the final one uses the first two to describe the constructor of a new manager class, which will have the priority assigned to the variable _Priority. Only the final macro is used directly, like so:

TYR_MANAGER_CTOR(TextureManager)
{

}

Which expands to:

extern u8 TextureManager_Priority;
TextureManager::TextureManager()
    : BaseManager(TextureManager_Priority)
{

}

Now, in EngineLib, I have a file called ManagerConfig.cpp (it has a corresponding header, but it is empty), which contains the following:

#define TYR_DECLARE_MANAGER_PRIORITY_VAR(name)\
	u8 TYR_GET_MANAGER_PRIORITY_VAR(name) = ManagerPriorityList::name;

namespace ManagerPriorityList
{
	enum
	{
		Logger,
		TextureManager,
		ShaderManager,
		SceneManager,
	};
};

TYR_DECLARE_MANAGER_PRIORITY_VAR(Logger);
TYR_DECLARE_MANAGER_PRIORITY_VAR(SceneManager);
TYR_DECLARE_MANAGER_PRIORITY_VAR(TextureManager);
TYR_DECLARE_MANAGER_PRIORITY_VAR(ShaderManager);

Another macro, this one defines the values in the format expected by the previously declared extern, this macro assigns the value from a named value in the enum below, and at the very bottom, the list of managers defined using the macro. Note that the order of the managers at the bottom doesn't matter, so I only have to change the order of the enum if I want to change the order of the managers.

I am still slightly annoyed that I have to write the manager name twice in this file, I'm tempted to switch the enum out for some form of static variable that is incremented as part of the macro, but I'm not sure if that would work and it's good enough for now. I hope you enjoyed this unexpected mid-week posting, I'll try to have something more to tell by the weekend, as expected taking a break from tool programming to dive back into the engine proper has boosted my enthusiasm for the project, so progress is picking up somewhat.

Tags: ,

Tyr: Textures and Shaders

Posted in Code on November 5th, 2011 by Pyroka

There was no blog post last week, sorry about that, but truthfully I’d not really done enough to justify one, it was a week of research more than coding, but I did find the answers to some questions (mostly about efficient sprite rendering).

So, this week I decided to take a bit of a break from the Asset Manager, and take the time to actually implement textures properly, loading the compiled textures and sending the image data off to OpenGL turned out to be rather easy, OpenGL supports rendering DXT compressed textures via the ‘ubiquitous’ GL_COMPRESSED_RGBA_S3TC etc. extentions, these aren’t part of the official spec, but being labelled as ‘ubiquitous’ means that most hardware supports them, so I decided it was safe to use them.

I then moved on to dragging my sprite renderer slightly into the modern era by switching from ye-olde fixed-function rendering to using shaders, I created a simple sprite vertex and fragment shader (it’s about 4 lines long) that basically just replaces what the fixed-function version did (render a texture, multiplied by a colour, at positions specified by the vertices).

I’d never set-up shaders in OpenGL before, and a fair amount of the documentation I found used the ARB extentions to load and compile the shaders, howver, combining a few different websites (mainly this one) I managed to come up with a solution that works.

In the process of attempting to get shaders working, I made much use of my logger class, and have extended it so that, when asserts are enabled, it will trigger a break-point whenever it logs an ‘Error’ or ‘Fatal’ level message.

I’m having fun working on the main engine again, so I’ll likely not work on the Asset Manager this week, instead I want to attempt to make it easier to move, rotate and scale sprites around the small test scene I’m making.

Tags: , ,