Well here goes my first attempt at writing a tutorial in visual basic,
aimed at game programming with DirectX9. For my first tutorial I will
be creating an optimization module for textures. In other words, the
module that will follow is not necessary for game development but it
does create a more efficient game, such as with the rpg I'm working on.
With the addition of this manager the memory usage dropped from 30 mb
to 26 mb which may not seem like much; but when you realize that this
is only about 1% of the final product you're looking at a lot more
memory savings.
This
module keeps track of all the textures that are in use so as to prevent
the program from loading the same texture many times, which happens a
lot, especially when you start to use textured meshes.
Where to start...
- Public Textures(1) As Texture
- Public iTextures As Integer = 1
- Public uTextures(1) As Int16
- Dim sTextures(1) As String
- Dim wTextures(1) As Long
- Dim hTextures(1) As Long
The
textures() array contains the actual textures, pretty simple.
The
itextures probably doesn’t need to be public; it just says
how large all the arrays are.
uTextures() is the usage of the
texture, I'll get to that latter.
stextures(1) is the path and
filename of the texture.
wTextures() is the width and
htextures() is the height.
GetTextureId
- Public Function GetTextureId(ByVal fPath As String, ByValfname As String, ByVal width As Long, ByVal height As Long, OptionalByVal sizeSpecific As Boolean = False) As Integer
Ok
here starts the fun stuff, this is the function called when you want to
load a texture. It will return an address to the texture which I will
show you how to use near the end of this tutorial. First the fPath and
fName variables are the file path and file name, pretty self
explanitory. The only intresting one is the sizeSpecific, you can add
other criteria here to make the texturemanager suit your needs, however
for us this is currently all we needed. This variable simply states
whether the dimensions of the texture must mach the height and width
provided (note if you pass height and width as -1 it will load the
textures actual dimensions.
This portion of the code checks to see if we already have loaded the texture.
- Dim icount As Int16
- For icount = 0 To iTextures – 1 'For every texture
- If fPath & fname = sTextures(icount) Then 'If the filename matches
- If (Not sizeSpecific) Or (width = wTextures(icount) And height = hTextures(icount)) Then 'If its not sizeSpecific or the sizes matchreturn that textures id and exit the function
- uTextures(icount) += 1 'increase usage count
- Return icount
- Exit Function
- End If
- End If
- Next
Ok if its made it here we don’t have the needed texture, so lets see if we have any texture variables that are = nothing.
- For icount = 0 To iTextures - 1
- If Textures(icount) Is Nothing Then 'The texture is loaded here to save time and space
- loadTexture2(fPath, fname, width, height, icount)
- uTextures(icount) += 1 'increase usage count
- Return icount
- Exit Function
- End If
- Next
Ok if its made it this far the texture doesn’t exist and theres no empty texture variables, so we must enlarge the arrays
- iTextures += 1
- ReDim Preserve Textures(iTextures)
- ReDim Preserve uTextures(iTextures)
- ReDim Preserve sTextures(iTextures)
- ReDim Preserve wTextures(iTextures)
- ReDim Preserve hTextures(iTextures)
- loadTexture2(fPath, fname, width, height, iTextures)
- uTextures(iTextures) += 1 'increase usage count
- Return iTextures
- End Function
loadTexture2
First the only reason its called loadtexture2 and not loadtexture
is because I had loadtexture already in my program, so you can omit the
2 in your version of the module, it's private because it doesn’t get
called outside the module.
- Private FunctionloadTexture2(ByVal fpath As String, ByVal fname As String, ByVal widthAs Long, ByVal height As Long, ByVal Id As Long)
- Textures(Id)= TextureLoader.FromFile(D3DDevice, fpath & fname, width, height,1, 0, 21, Pool.Default, Filter.Point, Filter.Linear,System.Drawing.Color.Black.ToArgb)
- sTextures(Id) = fpath & fname
- wTextures(Id) = width
- hTextures(Id) = height
- End Function
Pretty
self explanatory, it uses the d3ddevice and colorformat A8R8G8B8, those
could easily be changed though as could a variable be added to describe
the transparent color.
RemoveTexture
The remove texture part I haven’t actually used yet, but it should work.
- Public Function RemoveTexture(ByVal id As Long)
- If id = -1 Then 'remove all textures.
- iTextures = 0
- ReDim Preserve Textures(iTextures)
- ReDim Preserve uTextures(iTextures)
- ReDim Preserve sTextures(iTextures)
- ReDim Preserve wTextures(iTextures)
- ReDim Preserve hTextures(iTextures)
- Exit Function
- End If
- uTextures(id) -= 1 'decrease usage count
- If uTextures(id) = 0 Then 'no more references to this texture, so lets remove it
- Textures(id) = Nothing
- uTextures(id) = 0
- sTextures(id) = ""
- wTextures(id) = 0
- hTextures(id) = 0
- If id = iTextures - 1 Then
- Dim icount As Long
- icount = iTextures - 2
- Do Until (Not Textures(icount) Is Nothing) Or icount = 0
- icount -= 1
- Loop
- iTextures = icount + 1
- ReDim Preserve Textures(iTextures)
- ReDim Preserve uTextures(iTextures)
- ReDim Preserve sTextures(iTextures)
- ReDim Preserve wTextures(iTextures)
- ReDim Preserve hTextures(iTextures)
- End If
- End If
- End Function
For
this function, you tell it which texture you want to remove and it
decreases the usage count, and will sets the texture equal to nothing
if there are no more references to the texture, which frees up memory.
It then checks if the end of the array is equal to nothing in which
case it shortens the array until the last member of the array is not
nothing or the array has a dimension of one.
On using this module
To create a texture you would call something like this
TextureId = TextureManager.GetTextureId("BackGround.bmp", 300, 300, Application.StartupPath & " exturesmenu", True) This will give you an address of the texture you want. And to use the texture,
D3ddevice.settexture(0,texturemanager.textures(Textureid))