| 
                                         DirectX
                                        Graphics: 
                                        2D
                                        Graphics Part 2 
                                        Author
                                        : Jack Hoxley 
                                        Written : 30th November 2000 
                                        Contact : [Email] 
                                        Download :  Graph_04.Zip
                                        [8 Kb] 
 
Contents 
  of this lesson: 
  1. Introduction 
  2. Some more theory 
  3. Loading A Texture and displaying it 
  4. Transparencies 
 
1. 
  Introduction 
Welcome 
  back to the fourth lesson on learning DirectX graphics. I've decided to alter 
  the way I'm writing things; This tutorial was originally going to include a 
  basic look at texturing for 2D primatives. But I realised that it'd be very 
  similiar to the later lesson I'd planned on introducing textures; so rather 
  than do two half lessons, it's all going to be done here - well the basics anyway. 
  Ignore my ramblings if this is a long time after 7th December.... 
Textures 
  in Direct3D are a massive topic, EVERY game that you play on your computer will 
  use lots and lots of textures - almost everything that's rendered is likely 
  to be textured in some way. Textures add incredible realism to an object - something 
  that shape and colour would never be able to achieve.  
Simple 
  texturing, once learned, is extremely simple and you'll be able to do it in 
  your sleep within a few lessons; but you HAVE TO understand the basics in order 
  to get anywhere with the clever stuff a little later on. Texture blending, animation 
  and skinning all come under the heading of textures - and without the basic 
  knowledge you can never hope to realise that dream of writing the next Quake 
  3 engine (if that's what you think of). 
Enough 
  talk, time to learn some theory.... hehe 
 
2. 
  Some more Theory 
It 
  wouldn't surprise me if you were getting bored of all the theory you're learning 
  - but if you have any intentions of getting good with DirectX theory will be 
  your best friend (maybe). The main things that you'll need to know before we 
  get started are outlined below: 
What 
  is a texture? 
  A texture is a 2D bitmap that is loaded into memory and then mapped across triangles. 
  Up till this point you will have seen coloured triangles - where the colour 
  is there will be part of a texture. Textures tend to take up large amounts of 
  memory if either large in number or large in size - which is one of the main 
  reasons why we've seen the rapid increase in on-board memory for 3D accelerators. 
Texture 
  Coordinates 
  Texture coordinates are NOT in pixels - remember that. All texture coordinates 
  are on a 0.0 to 1.0 scale; were 0.0 is the minimum value (pixel 0) and 1.0 is 
  the maximum (255 for a 256x256 texture, 511 for a 512x512 texture and so on...). 
  If you have to still use pixels for your measurements you can use a simple formula 
  to convert : TexCoord = (1 / MaxTexSize) * PixelCoord; which if you work it 
  out is perfect : (1/256) * 128 = 0.5 (correct, as 128 is half way between them). 
  This isn't greatly difficult, more of something to remember; specifying 256 
  as a texture coordinate will either not work or give you some really really 
  weird results.... 
Texture 
  Sizes 
  Textures sizes are often a real pain in the back side. All sizes must be 2^n 
  that is, any integer value to the power of n: 2^1, 2^2, 2^3, 2^4 and so on.... 
  This means that textures get larger and larger as the integer goes up - which 
  becomes awkward if you wish to use an 800x800 textures (nearest values are 512x512 
  or 1024x1024). Another thing to note - it's usually impractical to use textures 
  greater than 256x256 in size. Some hardware doesn't support it, other hardware 
  just runs much slower when using large textures. Also, be practical when drawing 
  your textures - there is NO point in designing a super detailed texture that's 
  always going to be seen as very very small on screen - the detail will never 
  be visible (as well as it being slow to map large textures onto small triangles). 
Lighting 
  Whilst we haven't really covered lighting yet (and we're not going to here) 
  you should bare in mind that lighting has an affect on how the textures will 
  be seen. This will be demonstrated in this lesson by the colours of the vertices 
  that make up the triangles. In the previous lesson we gave each vertex a colour, 
  this colour is basically light; and the texture will be tinted according to 
  the vertex colour. For example; a green vertex will make the texture appear 
  green.... 
 
3. 
  Loading a Texture and displaying it 
So, 
  you want to play around with textures now. We're going to modify our Lesson 
  03 code so that instead of nice colourful shapes we get nice textured shapes. 
  This first part is extremely easy actually; but you'll see how it gets more 
  complicated later on.... 
First, 
  we need two new declarations to be added: 
                                        
                                          
                                          
                                            
                                              
                                                
                                                  
                                                    
                                                      
                                                        
                                                          
                                                            
                                                              
                                                                
                                                                  
                                                                    
                                                                      
                                                                        Dim
                                                                          D3DX
                                                                          As
                                                                          D3DX8 '//A helper library
                                                                           
                                                                          Dim
                                                                          Texture
                                                                          As
                                                                          Direct3DTexture8 | 
                                                                       
                                                                    
                                                                   
                                                                 | 
                                                               
                                                            
                                                           
                                                         | 
                                                       
                                                    
                                                   
                                                 | 
                                               
                                            
                                           
                                          
                                         
Not 
  too complicated really; the D3DX8 object is something that you'll come across 
  again and again in the future - so I may as well introduce it. D3DX is a helper 
  class, it has lots and lots of useful functions included in it to make certain 
  tasks easier. The main ones being shape (Geometry) creation, Mesh manipulation, 
  texture loading and some simple maths things - such as bounding boxes and ray 
  intersections (which aren't really that simple). 
Second, 
  we need to add a few lines into our initialisation function: 
                                        
                                          
                                          
                                            
                                              
                                                
                                                  
                                                    
                                                      
                                                        
                                                          
                                                            
                                                              
                                                                
                                                                  
                                                                    
                                                                      
                                                                        'This next line can go after we create the DirectX 'Object and the Direct3DDevice8 object
  Set
                                                                          D3DX =
                                                                          New
                                                                          D3DX8 '//Create our helper library...
  'Either way, the above line must come before this line....
  '//We now want to load our texture;
                                                                           
                                                                          Set
                                                                          Texture
                                                                          =
                                                                          D3DX.CreateTextureFromFile(D3DDevice,
                                                                          App.Path
                                                                          &
                                                                          "\ExampleTexture.bmp") | 
                                                                       
                                                                    
                                                                   
                                                                 | 
                                                               
                                                            
                                                           
                                                         | 
                                                       
                                                    
                                                   
                                                 | 
                                               
                                            
                                           
                                          
                                         
Assuming 
  alls-well, we now have a texture loaded into memory. At this level it's not 
  really very complicated at all; the D3DX.CreateTextureFromFile is a very simple 
  call to use, and I'd be very surprised if anyone out there could get it wrong! 
  Later on we'll be using CreateTextureFromFileEx - which allows us much more 
  control over things - at the expense of being much more complicated.... 
The 
  penultimate thing we need to do is reconfigure our geometry for texture coordinates. 
  In this particular instance, when we're dealing with squares, creating texture 
  coordinates is extremely easy. Assuming you want the square to have the entire 
  texture you just set corners 1,2,3 to have U or V components of 1.0 (yes, U 
  and V - just think of them as X and Y). Should you end up with more obscure 
  shapes it'll get much more complicated: 
Even 
  the above diagram for the pentagon may well be wrong - It's how I'd do it, but 
  depending on 
  the positions of you're vertices you may well need them to be different. 
To 
  alter the coordinates we just pass the values in the last two parameters of 
  the CreateTLVertex( ) function that we saw in the last lesson. For our square 
  we need the lines to look like this: 
                                        
                                          
                                          
                                            
                                              
                                                
                                                  
                                                    
                                                      
                                                        
                                                          
                                                            
                                                              
                                                                
                                                                  
                                                                    
                                                                      
                                                                        'vertex 0
 
TriStrip(0) = CreateTLVertex(10, 10, 0, 1, RGB(255, 255, 255), 0, 0, 0) 
             
'vertex 1
 
TriStrip(1) = CreateTLVertex(210, 10, 0, 1, RGB(255, 0, 0), 0, 1, 0) 
             
'vertex 2
 
TriStrip(2) = CreateTLVertex(10, 210, 0, 1, RGB(0, 255, 0), 0, 0, 1) 
             
'vertex 3
 
TriStrip(3) = CreateTLVertex(210, 210, 0, 1, RGB(0, 0, 255), 0, 1, 1) | 
                                                                       
                                                                    
                                                                   
                                                                 | 
                                                               
                                                            
                                                           
                                                         | 
                                                       
                                                    
                                                   
                                                 | 
                                               
                                            
                                           
                                          
                                         
The 
  code above is the same as the square we set up in the last lesson; but with 
  the added texture coordinates. 
Finally 
  we need to render our primatives using the texture we just loaded. This is extremely 
  simple actually - as shown by the following code: 
                                        
                                          
                                          
                                            
                                              
                                                
                                                  
                                                    
                                                      
                                                        
                                                          
                                                            
                                                              
                                                                
                                                                  
                                                                    
                                                                      
                                                                        D3DDevice.SetTexture
                                                                          0,
                                                                          Texture '//Tell the device which texture we want to use...
                                                                           
                                                                          D3DDevice.DrawPrimitiveUP
                                                                          D3DPT_TRIANGLESTRIP,
                                                                          2,
                                                                          TriStrip(0),
                                                                          Len(TriStrip(0)) | 
                                                                       
                                                                    
                                                                   
                                                                 | 
                                                               
                                                            
                                                           
                                                         | 
                                                       
                                                    
                                                   
                                                 | 
                                               
                                            
                                           
                                          
                                         
The 
  second line you should already know about, the first one is hardly very complicated. 
  The "0" parameter can be replaced with different values when you do 
  multiple texture blending and other special texture effects - but right now 
  we dont want to play around with that stuff. You should see, as you're result 
  something looking like this: 
  
[Cut 
  down and 75% of full size] 
You 
  may well notice in the above picture that a) we have two squares, b) they're 
  different colours. In the sample code for this lesson it actually creates two 
  squares to illustrate the next point, but as the code is almost identical I 
  didn't put it in above. The point is that lighting/vertex colours affect the 
  way that textures are displayed. Normally the texture is grey (like the right-hand 
  square), but when you apply the texture to a triangle where the vertices are 
  not white we get this colorisation. This is the basis of Direct3D lighting - 
  It alters the vertex colour which in turn alters the texture. This can be incredibly 
  useful to you, whilst white vertices result in a normal texture, grey vertices 
  will darken the texture; coloured ones, as you can see, colorise the final texture. 
  There is one thing that you must bare in mind - if there is no green around 
  a green vertex then the resulting colour will be black. You should be aware 
  of how colours are generated - red green and blue components, if the colour 
  at a vertex is 0.5 (half) then all the pixels nearby will have each colour channel 
  halved (making it darker). What happens when the texture is almost all red, 
  yet the light is green? The light multiplies all red and blue components by 
  0 and all green components by 0.75 (or whatever value); which will mean that 
  the red part of the texture will be multipled by 0, which will give 0, the blue 
  will be multiplied by 0, as there is no blue anyway we're left with blue; finally 
  the green is multiplied by 0.75 - but a red texture has no green, so it's 0*0.75, 
  which again results in 0 - the final colour being 0,0,0 - black. There are ways 
  around this, but we'll discuss them in a later lesson (about lighting). 
 
4. 
  Transparencies 
At 
  this point you should be perfectly capable of creating a 2D game using Direct3D8 
  - it would probably be quite basic, but it's not impossible. You can create 
  2D geometry and you can apply textures to it. The final thing that you need 
  to know about textures in order to do nice 2D graphics is transparencies. 
Transparencies 
  are where the renderer doesn't render part of a texture based on the colour. 
  This allows you to create incredibly detailed textures without incredibly high 
  triangle/vertex counts. You could quite easily create a circle shape with triangles, 
  yet you'd need 100's of them; using transparencies you could make a texture 
  with transparent parts and apply it to a square (with only 2 triangles remember) 
  and it would look the same (or better). 
To 
  use transparencies we must first add three new lines into our initialisation 
  function: 
                                        
                                          
                                          
                                            
                                              
                                                
                                                  
                                                    
                                                      
                                                        
                                                          
                                                            
                                                              
                                                                
                                                                  
                                                                    
                                                                      
                                                                        D3DDevice.SetRenderState
                                                                          D3DRS_SRCBLEND,
                                                                          D3DBLEND_SRCALPHA 
                                                                          D3DDevice.SetRenderState
                                                                          D3DRS_DESTBLEND,
                                                                          D3DBLEND_INVSRCALPHA 
                                                                          D3DDevice.SetRenderState
                                                                          D3DRS_ALPHABLENDENABLE,
                                                                          True | 
                                                                       
                                                                    
                                                                   
                                                                 | 
                                                               
                                                            
                                                           
                                                         | 
                                                       
                                                    
                                                   
                                                 | 
                                               
                                            
                                           
                                          
                                         
These 
  three lines allow you to use transparent textures; first we tell Direct3D what 
  type of transparencies we want (there are a few possible options) then we enable 
  the usage of alpha blending. First thing to note - Alpha blending is a fairly 
  advanced topic - it just so happens that we need it to do transparencies; but 
  we'll come back to it later on in more detail. Another thing to note is that 
  we enable it's usage from the start; this adds a slight performance overhead 
  to our program - it's much better to leave it disabled and only turn it on when 
  you need it (ie, on before the DrawPrimativeUP call, and off again afterwards). 
  As you will find out later, when you use different types of SRCBLEND and DESTBLEND 
  factors it'll affect all textures and rendering; so having it on all the time 
  is not a great idea... 
Now, 
  to load in a transparent texture we need to use a new function - this time more 
  complicated than the original one. 
                                        
                                          
                                          
                                            
                                              
                                                
                                                  
                                                    
                                                      
                                                        
                                                          
                                                            
                                                              
                                                                
                                                                  
                                                                    
                                                                      
                                                                        '//Choose
                                                                          one of
                                                                          the
                                                                          following
                                                                          depending
                                                                          on
                                                                          what
                                                                          you 
                                                                          '  
                                                                          should
                                                                          need.
                                                                          Other
                                                                          colours
                                                                          can be
                                                                          made
                                                                          up,
                                                                          but
                                                                          these 
                                                                          '  
                                                                          ones
                                                                          should
                                                                          be
                                                                          okay
                                                                          for
                                                                          most
                                                                          uses...
 
 
'ColorKeyVal = &HFF000000 '//Black 
'ColorKeyVal = &HFFFF0000 '//Red
 
ColorKeyVal = &HFF00FF00 '//Green
 
'ColorKeyVal = &HFF0000FF '//Blue 
'ColorKeyVal = &HFFFF00FF '//Magenta 
'ColorKeyVal = &HFFFFFF00 '//Yellow 
'ColorKeyVal = &HFF00FFFF '//Cyan 
'ColorKeyVal = &HFFFFFFFF '//White
 
 
Set TransTexture = D3DX.CreateTextureFromFileEx(D3DDevice, App.Path &
"\transtexture.bmp", 64, 64, _ 
                                                                           
D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, _ 
                                                                           
D3DPOOL_MANAGED, D3DX_FILTER_POINT, _ 
                                                                           
D3DX_FILTER_POINT, ColorKeyVal, _ 
                                                                           
ByVal 0, ByVal 0) | 
                                                                       
                                                                    
                                                                   
                                                                 | 
                                                               
                                                            
                                                           
                                                         | 
                                                       
                                                    
                                                   
                                                 | 
                                               
                                            
                                           
                                          
                                         
Not 
  too complicated really. The first part is just for convenience - by commenting 
  and uncommenting these lines you can use different colours as the transparent 
  one. The D3DX.CreateTextureFromFileEx function has quite a few parameters, you 
  should get to know this function, as it is quite likely that you'll use this 
  function for almost all of your texture loading.  
                                        
                                          
                                          
                                            
                                              
                                                
                                                  
                                                    
                                                      
                                                        
                                                          
                                                            
                                                              
                                                                
                                                                  
                                                                    
                                                                      
                                                                        object.CreateTextureFromFileEx(
                                                                          _  
                                                                             
                                                                          Device
                                                                          As
                                                                          Direct3DDevice8,
                                                                          _  
                                                                             
                                                                          SrcFile
                                                                          As
                                                                          String,
                                                                          _  
                                                                             
                                                                          Width
                                                                          As
                                                                          Long,
                                                                          _  
                                                                             
                                                                          Height
                                                                          As
                                                                          Long,
                                                                          _  
                                                                             
                                                                          MipLevels
                                                                          As
                                                                          Long,
                                                                          _  
                                                                             
                                                                          Usage
                                                                          As
                                                                          Long,
                                                                          _  
                                                                             
                                                                          Format
                                                                          As
                                                                          CONST_D3DFORMAT,
                                                                          _  
                                                                             
                                                                          Pool
                                                                          As
                                                                          CONST_D3DPOOL,
                                                                          _  
                                                                             
                                                                          Filter
                                                                          As
                                                                          Long,
                                                                          _  
                                                                             
                                                                          MipFilter
                                                                          As
                                                                          Long,
                                                                          _  
                                                                             
                                                                          ColorKey
                                                                          As
                                                                          Long,
                                                                          _  
                                                                             
                                                                          SrcInfo
                                                                          As Any
                                                                          _  
                                                                             
                                                                          Palette
                                                                          As
                                                                          Any)
                                                                          As
                                                                          Direct3DTexture8 | 
                                                                       
                                                                    
                                                                   
                                                                 | 
                                                               
                                                            
                                                           
                                                         | 
                                                       
                                                    
                                                   
                                                 | 
                                               
                                            
                                           
                                          
                                         
 
  From 
    the top then: 
  Object 
    : An initialised D3DX8 object. 
    Device : Your 3D rendering Device 
    SrcFile : A string indicating where the texture is to be loaded from 
    Width : width in pixels, if specified it must be a valid power of 2 
    value (64, 128, 256 and so on...). You can use "D3DX_DEFAULT" to 
    let Direct3D decide what size to load it as (whatever size it was saved at) 
    Height : Same as width, but for the height (funny that) 
    MipLevels : How many mip-map levels are generated; these will be discussed 
    later on in this series. For now just leave it as D3DX_DEFAULT (A complete 
    chain is created) or 1 (Only 1 level is generated) where 1 will require the 
    least amount of memory. 
    Usage : You can make this texture a render target (useful for some 
    special effects) but for normal use make this value 0. 
    Format : What format the surface is in; same as when you specify what 
    backbuffer format you want during initialisation. If you're doing anything 
    clever you may well need to know what this format is; but most of the time 
    just leave it as "D3DFMT_UNKNOWN" 
    Pool : Whereabouts this memory should be allocated; certain areas have 
    less space and different areas are faster for different uses. D3DPOOL_MANAGED 
    should be suitable for most uses, other uses will be explained later on in 
    this series. 
    Filter : What texture filter we want to use. This only really affects 
    things that are stretched or squashed - which when you move into proper 3D 
    will happen to almost every texture used. Normally you'll want to use D3DX_FILTER_LINEAR 
    , but for simple things you can use D3DX_FILTER_POINT and for best quality 
    you can use D3DX_FILTER_TRIANGLE. Experiment with them as you choose - some 
    look better than others in certain situations 
    MipFilter : Same as the above argument, but for mip maps. These will 
    be explained later on in the series. 
    ColorKey : What colour is going to be transparent black. This is a 
    32 bit ARGB code - best represented by a hexidecimal number. You should be 
    familiar with RGB notation (3 sets of 2 figures (0 to 9) or letters (A to 
    F)); this value is basically &HFF<normal rgb val>. All it does is 
    make all pixels of the specified colour fully transparent. 
    SrcInfo : Allows you to specify a D3DXIMAGE_INFO structure giving any 
    information about the source file - height, width, depth and format. Not really 
    needed - leave as "ByVal 0" 
    Palette : Leave as ByVal 0. Palettes are on the way out, with the ever 
    increasing hardware (even the now "old" cards support better) capabilites 
    there is very little speed advantage to be gained by using them - and they 
    look pretty rubbish anyway. 
  Thats 
    about all folks! 
  I 
    strongly advise you to get familiar with ALL the information covered in this 
    lesson; there's quite a lot of important stuff to digest - almost all of it 
    important if you want to advance you're knowledge of DirectX8 graphics. 
   
  You 
    can download the source code and see it working - as well as modifying it 
    and playing around. Grab it from the top of this page.... 
  Assuming 
    you've swallowed all of this it's onto Lesson 05 
    : Basic 3D Geometry 
 
                                       |