My personal understanding of 2D programming for DirectX3D

Many years ago, it was known that DirectX was used for gaming. From operating graphics and memory directly in the DOS era to having to rely on drivers in the Windows era, I felt that there were too many APIs in DirectX that I couldn't figure out, and it was too cumbersome. I have always wanted to write games using GDI, but the efficiency of GDI was very low, and I couldn't make games much. I had to grit my teeth and chew on the DirectX SDK. Fortunately, with the advanced network and abundant resources, I can always learn it.

After reading many articles online, I feel that it is still too difficult for beginners, and doing 2D games does not require too much D3D knowledge. I have roughly organized it, which may be helpful for beginners.

The following is described using the DirectX9 SDK, and rendering is similar to drawing.

1. Initialize an IDirect3D9 interface for D3D, with the method always Direct3DCreate9 (D3D0SDK_VERSION);

2. Get device capabilities, GetDeviceCaps, Adapters default value D3DADAPTER_ DEFAULT, DeviceType generally selects hardware graphics card, i.e. D3DDEVTYPE_ HAL.

3. Get the display mode description table GetAdapterDisplayMode, in which you can modify a bunch of information such as height and width, color mode, buffer type, etc.

4. Create device IDrect3DDevice9 and use Create Device to create it. Just have one device and associate it with the window handle.

5. Other settings, what world matrix, rendering state.

HRESULT InitDirect3D( HWND hWnd, BOOL bWindowed )
{
g_pD3D = Direct3DCreate9( D3D_SDK_VERSION );
D3DCAPS9 d3dCaps;
g_pD3D->GetDeviceCaps( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3dCaps );
D3DDISPLAYMODE d3ddm;
g_pD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm );
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory( &d3dpp, sizeof(d3dpp) );
if( bWindowed == TRUE )
{
  d3dpp.Windowed         = TRUE;
  d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
  d3dpp.BackBufferFormat = d3ddm.Format;
}
else
{
  d3dpp.Windowed         = FALSE;
  d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
  d3dpp.BackBufferWidth  = SCREEN_WIDTH;
  d3dpp.BackBufferHeight = SCREEN_HEIGHT;
  d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
}
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
d3dpp.PresentationInterval   = D3DPRESENT_INTERVAL_IMMEDIATE; // Do NOT sync to vertical retrace
//d3dpp.PresentationInterval   = D3DPRESENT_INTERVAL_DEFAULT; // Sync to vertical retrace
d3dpp.Flags                  = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
                    D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                    &d3dpp, &g_pd3dDevice );
D3DXMATRIX matProj;
D3DXMatrixPerspectiveFovLH( &matProj, D3DXToRadian( 45.0f ), 
                          SCREEN_WIDTH / SCREEN_HEIGHT, 0.1f, 100.0f );
g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
return S_OK;
}
6. Create a 2D sprite, D3DX Create Sprite, one line is enough. Create one sprite and multiple textures can be loaded for batch rendering

7. To create a texture, what we are referring to here is loading 2D images, which can be loaded from a file, from memory, or create an empty one and fill in the data yourself.

8. Rendering, device first Clear, then enable the device rendering transaction Device BeginScene, then sprite rendering can be performed, or device backup buffer can be directly written, and finally device rendering transaction can be ended EndScene.

9. There are many things to set up for sprite rendering, which is very troublesome for those who are interested to learn on their own. Here is only one thing that must be mentioned: the D3DXSPRITE flag that allows transparent rendering must be added to the sprite rendering transaction_ ALPHABLEND, multiple texture drawings can be performed during a transaction, and all drawings must take effect during the transaction.

10. Sprite rendering can render the entire texture or only a portion of it.

11. The scaling, rotation, and position issues of sprite rendering. When using 3D vectors in D3D, we use 2D programming, so the Z coordinate is always 1.0. Scaling can be done by copying the surface of the texture and automatically scaling. Some versions can directly rotate and scale in the Draw method.

Finally, I have time and have gained some understanding of rendering.

12. To render to a texture, there can be multiple surfaces in a texture, but usually only one is used. This surface can be set as the current rendered surface, and there are requirements when creating a texture.

a) Create GDI, GDI+ Texture for drawing, MipLevels= 1. Usage; 0, Pool= D3DPOOL_ MANAGED.

b) Create textures that can serve as rendering targets, MipLevels= 1. Usage; 1. Pool= D3DPOOL_ DEFAULT, take the texture of the 0th surface GetSurfaceLevel (0, surface); Then set it as the rendering target Device SetRenderTarget (0, surface);, This way, both ID3DXLine and ID3DXFont can be drawn to the current texture (it's too basic, not much talked about, it took a long time to understand). After rendering, it should be restored.

13. Textures can be connected through Device StrechRect, Device UpdateSurface for data replication (stretch and copy as is, unable to use alpha blending effect).

14. Alpha blending, used to add color or transparency to textures, with many parameters through Device Set RenderState to turn decay into magic when used properly.

//set up Alpha mixed mode 
Sprite._Begin(D3DXSPRITE_DONOTSAVESTATE);
Device.SetRenderState(D3DRS_ALPHABLENDENABLE, 1);
Device.SetRenderState(D3DRS_SRCBLEND, D3DBLEND_BLENDFACTOR);
Device.SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
Device.SetRenderState(D3DRS_BLENDFACTOR,
D3DCOLOR_ARGB(Round(255.0* Rate),Round(255.0* Rate),Round(255.0* Rate),Round(255.0* Rate)));
//draw texture 
TDXManager.Sprite.Draw(texture, nil, 0, nil, $FFFFFFFF);
//set transparency 
Device.SetRenderState(D3DRS_ALPHABLENDENABLE, 1);
Device.SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
Device.SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
Device.SetRenderState(D3DRS_SRCBLENDALPHA, D3DBLEND_ONE);
Device.SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_ARGB(255, 255, 255, 255));
//then draw the texture... 
TDXManager.Sprite.Draw(texture, nil, 0, nil, $FFFFFFFF);

When I have free time, I will upload a picture. The most annoying thing is to write and render without the picture. Without the comparison, I can't understand it at all.