Let There Be Textures!
Prior to this week our game engine supported rudimentary colors and shapes on the screen, represented with our Sprite and Effect system. For this week, we implemented Textures for our objects, to allow some interesting graphics to be shown on our sprites in game. Above, you can see screenshots of the game running with textures that change every interval, or via a button press.
I assigned UV values when the vertex buffers were specifically created. Following the standard for both the Direct3D and OpenGL platform, I specify the vertices of my triangles with the appropriate UVs. In our implementation, both GL and D3D U values are 0 on the left, 1 on the right. But, the V values are opposite one another. For D3D, 0 is the top whilst 1 is the bottom. GL is the exact opposite. With this information we can specify the corners of our sprites, composed of two triangles, with their appropriate UV Values. This is done directly within the platform specific implementations of these buffers for both the GL and D3D Platforms.
Texture Reference Counting
I spent a great deal this assignment pondering on the use and purpose of the Handle that refers to our texture data. In the past we had direct pointers to Effect and Sprite data, but this time around we merely had a handle with methods to access the underlying data, and a specific “Release” function that handled some pointer management functionalities for us. At first glance, I thought it was an interface designed for some specific error checking in mind? Perhaps the handle has some underlying functionalities such that it’s a safe wrapper for manipulating the texture data. It’s quite common for such a thing to be created to “dummy proof” working with specific types of data that require careful process.
Concerning the lack of a specific interface to increment the reference count, made me think back to the purpose of the reference count. Specifically, such counter is incremented when you have a new reference, hence the name, to the data. Seeing as we honestly, only want to load the data once, perhaps this fact correlates with the lack of an incrementation interface? I believe using a handle, along with a specific manager for this, keeps us from loading the same file more than once, duplicating data and creating inconsistencies. The handles operate in the background by checking if a given file was loaded, and returns that reference while also incrementing the reference count on its own.
On the topic of using the Release functionality to decrement this reference count, this is crucial because one could have multiple references to a single file throughout code. When a handle is released, the handle is destroyed, and a reference count is decremented. It isn’t until all the handles for a given data or file reference is destroyed that the underlying pointer is then destroyed. In the worst case, if we manipulated the reference count directly instead of the Release function, we could end up in a situation where perhaps we have a “valid” handle that represents a destroyed pointer.
In this assignment there was a particularly interesting gotcha that I had to hunt down for. When adding the newly provided TextureBuilder project, there is a scenario where specifically you need the TextureBuilder to be created before the AssetBuilder project could access it to well…begin to create assets. Specifcally, this inclusion is not apparent in any C++ code at all.
Than, it hit me realizing that there is a single, sensible, point of entry for the creation of these assets, the BuildExampleGameAssets project! Hence, adding the TextureBuilder as a project dependency to it allowed the appropriate executables to be created before TextureBuilder would need to access it to create the files.
You can try out these games via the below links. The only difference is that Direct3D will be used in the x64 version, with OpenGL in the other. They have been built and verified to work on Windows. For this post, the space bar is used to swap the textures on screen.