DirectX 8 - Tutorials - Direct3D - Initialization

Variable Initiation
Direct3D 8 Initiation
Direct3D 8 FindMode (D3DFindMode FUNCTION)

Download the Code for this Tutorial (note : not made for running, since it will not do anything)

Variable Initiation

Ok, we first need to initialize the Direct3D 8 component objects

Put this in the BAS file:
Public DX As DirectX8 'Should be here already
Public D3D As Direct3D8
Public D3DDevice As Direct3DDevice8

Now, this is a huge important thing you must decide. Of course you can change it later on, but may cause bad things, who knows.

It's the FVF (Flexible Vertex Format). It describes how the primitives will be drawn. This also alters if the program/game is going to be 2D or 3D. I made a few that might be useful to some users.

Unlit and Untransformed FVF. This FVF means that DirectX 8 will be doing all the transformations and lighting. The problem with this FVF is that it is very slow due to the lighting. This means that you will need to attach a material to your vertices and you will need to create lights. This is ultimately for a 3D application.

Public Const FVF_U = D3DFVF_XYZ Or D3DFVF_NORMAL Or D3DFVF_DIFFUSE Or D3DFVF_TEX2

Untransformed and Lit FVF. This FVF means that DirectX 8 will be doing the transformations. But not the lighting. This means that each vertex will need to have a "color" component. This is also ultimately for a 3D application.

Public Const FVF_L = D3DFVF_XYZ Or D3DFVF_DIFFUSE Or D3DFVF_SPECULAR Or D3DFVF_TEX3

Transformed and Lit FVF. This FVF means that DirectX 8 will do nothing except draw the to the screen. No Matrices, no materials, no lights. This is mainly for 2D programs or very experienced 3D programmers. This of all FVFs, is the fastest.

Public Const FVF_TL = D3DFVF_XYZRHW Or D3DFVF_SPECULAR Or D3DFVF_TEX1

Now, I have explained only a few of many ways of FVFs. Once you are done selecting which FVF you want...

Put this in the BAS file. Replace the 'Your FVF' to your FVF!:
Public Const FVF = 'Your FVF'

Notice that FVF contains the word "Flexible". This means that you can actually create your own vertex format! But the tutorials that demonstrate things will not include other FVFs, only these three. If you WOULD like to make your own FVF, and do not know how, then head to the FVF Tutorial.

You're not done yet with the initialization.

You still need to declare a few other things (in the same BAS file as above):
Public D3DX As D3DX8 'For other stuff that D3DDev and D3D cannot do.'
Public
D3DPP As D3DPRESENT_PARAMETERS 'Init Data and could be used later for Switching Modes'
Public D3DCAPS As D3DCAPS8 'Misc. Init Data'
Public D3DDM As D3DDISPLAYMODE 'Init Display Mode Data'
Public D3DTypeDevice As CONST_D3DDEVTYPE 'HAL or Reference Rasteriser'

Direct3D 8 Initiation

Create a Public Function like this one (please copy and paste):

In the same BAS file:
Visual Basic 6 Public Function D3DInit(ByVal vHWND As Long, Optional ByVal vWIDTH As Long = 0, Optional ByVal vHEIGHT As Long = 0, Optional ByVal vBPP As Long = 0, Optional ByRef vFORMAT As Long = 0, Optional ByVal vDeviceType As CONST_D3DDEVTYPE = 0, Optional ByVal vBACKBUFFERS As Long = 1, Optional ByVal vDEPTHBUFFER As CONST_D3DFORMAT = D3DFMT_D16) As Long
Visual Basic 5 Public Function D3DInit(ByVal vHWND As Long, Optional ByVal vWIDTH As Variant = 0, Optional ByVal vHEIGHT As Variant = 0, Optional ByVal vBPP As Variant = 0, Optional ByRef vFORMAT As Variant = 0, Optional ByVal vDeviceType As Variant = 0, Optional ByVal vBACKBUFFERS As Variant = 1, Optional ByVal vDEPTHBUFFER As Variant = 80) As Long

Or copy from this easier to copy box: (#1 = VB6 - #2 = VB5)

Ok, this fragment is the Sub's first line, and it initiates Direct3D. If any errors occur, it will return the error's long value and exit the function.

In the same BAS file in the function that we just created:
    'InitD3D
    Set D3D = DX.Direct3DCreate
    If Err.Number Then
        D3DInit = Err.Number
        Exit Function
    End If

Now, let's initiate the Device (HAL or REF). If HAL cannot be found, then it will try REF. If REF doesn't work, then it will once again return the error's long value and exit.

In the same BAS file and in the function:
    'Get HAL or REF
    
If vDeviceType = 0 Then
        D3DTypeDevice = D3DDEVTYPE_HAL
        
D3D.GetDeviceCaps D3DADAPTER_DEFAULT, D3DTypeDevice, D3DCAPS
        
If Err.Number Then
            
'The HAL didn't work, let's try to get the REF
    
        Err.Clear
            D3DTypeDevice = D3DDEVTYPE_REF
            D3D.GetDeviceCaps D3DADAPTER_DEFAULT, D3DTypeDevice, D3DCAPS
            If Err.Number Then
                
D3DInit = D3DERR_NOTAVAILABLE
                
Exit Function
            
End If
        
End If
    
Else
        
D3DTypeDevice = vDeviceType
    
End If

Now let's get the Direct3D Present Perameters(D3DPP) all set up. The D3DPP is how we will present/show it to the screen, either windowed(if the sum of the three arguments vWIDTH, vHEIGHT and vBPP are 0) or fullscreen(if the sum is not 0 (like 640, 480, 16)).

In the same BAS file and in the function:
    'Display
    
With D3DPP
        
'Check if Window(sum=0) or fullscreen(sum<>0)
        
If (vWIDTH + vHEIGHT + vBPP) = 0 Then
            
'Get the Current Display Mode(D3DDM) to check for 8bit colour
            
D3D.GetAdapterDisplayMode D3DADAPTER_DEFAULT, D3DDM
            
'Check the D3DDM to see that the display mode's colour is higher than 8bit
            
If D3DDM.FORMAT = D3DFMT_P8 Or D3DDM.FORMAT = D3DFMT_A8P8 Then
                
'The display mode is 8bit, exit the function and return error id
                
D3DInit = D3DERR_INVALIDDEVICE
                
Exit Function
            
Else
                
'The display mode is higher than 8bit
                'Get the format(a unuseful ID of the D3DDM)

                
vFORMAT = D3DDM.FORMAT
                
'Set the D3DPP's swapeffect to DISCARD and windowed to 1(which means yes)
                .SwapEffect = D3DSWAPEFFECT_DISCARD
                If vDEPTHBUFFER > 0 Then
                    .EnableAutoDepthStencil = 1
             
       .AutoDepthStencilFormat = vDEPTHBUFFER
                End If
                .Windowed = 1
            End If
        
Else
            'If the vFORMAT isn't specified (=0) then
            'find the Display Mode (like 640, 480, 16)
            'This sub leads to another FUNCTION which will be explained later.
            If vFORMAT = 0 Then lErrNum = D3DFindMode(vWIDTH, vHEIGHT, vBPP, vFORMAT)
            'If it was not found, exit function
            If lErrNum Then
                D3DInit = D3DERR_INVALIDDEVICE
                Exit Function
            
End If
            'Set the D3DPP's swapeffect to FLIP
            ' " 's backbuffercount to the argument passed to this function named vBACKBUFFERS
            ' " 's backbufferwidth and height (which basically is the display mode) to the arguments
            'Install the DepthBuffer if the argument passed to the function is not 0
            ' Note:If there IS a depthbuffer, we must ENABLE it. Explained later on.
            .SwapEffect = D3DSWAPEFFECT_FLIP
            .BackBufferCount = vBACKBUFFERS
            .BackBufferWidth = vWIDTH
            .BackBufferHeight = vHEIGHT
            If vDEPTHBUFFER > 0 Then
                .EnableAutoDepthStencil = 1
                .AutoDepthStencilFormat = vDEPTHBUFFER
            End If
        End If

        
'Finally set the format of the display to the D3DPP whether windowed or not.
        .BackBufferFormat = vFORMAT
    End With

The creation of the Direct3D Device (D3DDEV). Which is the whole point of this function!

In the same SUB and in the function:
    'Device
    
Set D3DDEV = D3D.CreateDevice(D3DADAPTER_DEFAULT, D3DTypeDevice, vHWND, D3DCREATE_SOFTWARE_VERTEXPROCESSING, D3DPP)

We are so close to done, the last line, set the FVF to the proper FVF

Finish the function off in the BAS file:
    'Set our FVF!
    
D3DDEV.SetVertexShader FVF 'Our FVF constant
End Function

Direct3D 8 FindMode (D3DFindMode FUNCTION)

This function will Find a display mode format ID (a Long) and set it to the FMT As Long. This function is used by the above function.
The following code is WAY to long to format the colour, please copy it to VB to see the colour.

Put this in the same BAS file, but after the function we just created:
Private Function D3DFindMode(ByVal W As Long, ByVal H As Long, ByVal BPP As Long, ByRef FMT As Long) As Long
    
Dim X As Long, y As Long
    
Dim D3DDM As D3DDISPLAYMODE
    
Dim FOUND As Boolean

    'Get the number of display modes
    y = D3D.GetAdapterModeCount(D3DADAPTER_DEFAULT) - 1
    'If some error happends, return error and exit function
    If Err.Number Then
        D3DFindMode = D3DERR_INVALIDCALL
        
Exit Function
    
End If
    'Loop through the list of display modes
    For X = 0 To y
        'Get the display mode information
        Call D3D.EnumAdapterModes(D3DADAPTER_DEFAULT, X, D3DDM)
        'Some error, then return error and exit function
        If Err.Number Then
            D3DFindMode = Err.Number
            
Exit Function
        
End If
        'So, now let's see if the display mode we are looking at
        'is of proper size
        If D3DDM.Width = W And D3DDM.Height = H Then
            'Now let's see if the display mode we are looking at
            'is of proper colour.
            Select Case BPP
            
Case 16
                
If D3DDM.FORMAT = D3DFMT_R5G6B5 Or D3DDM.FORMAT = D3DFMT_X1R5G5B5 Or D3DDM.FORMAT = D3DFMT_A1R5G5B5 Or D3DDM.FORMAT = D3DFMT_X4R4G4B4 Or D3DDM.FORMAT = D3DFMT_A4R4G4B4 Then
                    'Display mode found at 16bit, return format and exit
                    FMT = D3DDM.FORMAT
                    
Exit Function
                
End If
            
Case 24
                
If D3DDM.FORMAT = D3DFMT_R8G8B8 Then
                    'Display mode found at 24bit, return format and exit
                    FMT = D3DDM.FORMAT
                    
Exit Function
                
End If
            
Case 32
                
If D3DDM.FORMAT = D3DFMT_X8R8G8B8 Or D3DDM.FORMAT = D3DFMT_A8R8G8B8 Then
                    'Display mode found at 32bit, return format and exit
                    FMT = D3DDM.FORMAT
                    
Exit Function
                
End If
            
End Select
        
End If
    
Next
    'Display mode was NOT found, simply return this error, and leave.
    D3DFindMode = D3DERR_INVALIDDEVICE
End Function