Upcoming Events
Unite 2010
11/10 - 11/12 @ Montréal, Canada

GDC China
12/5 - 12/7 @ Shanghai, China

Asia Game Show 2010
12/24 - 12/27  

GDC 2011
2/28 - 3/4 @ San Francisco, CA

More events...
Quick Stats
114 people currently visiting GDNet.
2406 articles in the reference section.

Help us fight cancer!
Join SETI Team GDNet!
Link to us Events 4 Gamers
Intel sponsors gamedev.net search:

Direct3D 9.0 with SDL


Direct3D Device Parameters

ZeroMemory(&present_parameters, sizeof(present_parameters));
present_parameters.Windowed = false;
present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
present_parameters.EnableAutoDepthStencil = true;
present_parameters.AutoDepthStencilFormat = D3DFMT_D16;
present_parameters.hDeviceWindow = GetActiveWindow();
present_parameters.BackBufferWidth = 800;
present_parameters.BackBufferHeight = 600;
present_parameters.BackBufferFormat = D3DFMT_R5G6B5;
present_parameters.MultiSampleType = D3DMULTISAMPLE_NONE;

Explaining each and every parameter would be overkill for a beginner's tutorial. Essentially they allow you to define the core properties of your Direct3D device, like the dimensions of the screen buffer, the format of the screen buffer, the way the buffer is swapped each frame, the format of the stencil buffer, and so on...

Creating the Direct3D Device

Just like the object, creating the device is an easy task once you have the window and parameters filled in:

if( FAILED(Direct3D_object->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,
           GetActiveWindow(), D3DCREATE_SOFTWARE_VERTEXPROCESSING,
           &present_parameters,&Direct3D_device)))
{
   MessageBox(GetActiveWindow(),"Could not create Direct3D Device","D3D_DEV ERR",MB_OK);
   return 0;
}

Setting States

Next, we need to establish the projection matrix, lighting, culling, depth buffer, and vertex format. Sounds like a lot, doesn't it? Actually the Direct3D device can do each of these with one to two lines of code respectively, at least for our purposes.

For this projection matrix I have set the near and far planes to 1 and 1000 respectively, and used the ratio of the screen height to the screen width as the aspect ratio. (Make sure to adjust this ratio accordingly if you modified the height and width.) In the other lines of code lighting is disabled, backface culling is disabled, the depth buffer is set, and a vertex format is set. (D3DFVF_XYZ | D3DFVF_DIFFUSE) means that a vertex's data is organized in linearly in memory as its x, y, and z coords followed by its color.

D3DXMatrixPerspectiveFovLH(&projection_matrix, D3DX_PI / 4.0f,(float) 800/600,1, 1000);
Direct3D_device->SetTransform(D3DTS_PROJECTION,&projection_matrix);
Direct3D_device->SetRenderState(D3DRS_AMBIENT,RGB(255,255,255));

Direct3D_device->SetRenderState(D3DRS_LIGHTING,false);

Direct3D_device->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE);

Direct3D_device->SetRenderState(D3DRS_ZENABLE,D3DZB_TRUE);
Direct3D_device->SetFVF((D3DFVF_XYZ | D3DFVF_DIFFUSE));

Loading Primitive Data

First off we need to create our vertex buffer object. It obviously needs to be as large as our triangle data is, and for now we only want to write to the buffer so let's specify that as well since the device can optimize if it knows we won't be reading from it. Also we need to specify the vertex format the buffer will use, and pass a flag telling it to manage the data. We finally pass the address of the object which will become the vertex buffer. The last parameter has its uses, but we do not need it for now so it needs to be NULL.

Direct3D_device->CreateVertexBuffer(sizeof(aTriangle),D3DUSAGE_WRITEONLY,
                                    (D3DFVF_XYZ | D3DFVF_DIFFUSE),
                                    D3DPOOL_MANAGED,&tri_buffer,NULL);

The following functions set pData as the main pointer to the vertex buffer, and copy the vertex data to the memory pointed by pData.

tri_buffer->Lock(0,sizeof(pData),(void**)&pData,0);
memcpy(pData,aTriangle,sizeof(aTriangle));
tri_buffer->Unlock();

Final Step

Now that everything is initialized, we need only to make our main game loop, which will render to the buffer each frame and also process incoming messages. Each frame we need to clear out the buffers. Meanwhile all data has to be drawn in between a BeginScene() and EndScene() as illustrated below.

The input as handled by SDL is fairly straightforward as well. In this case it will respond to a user hitting the escape key by the freeing Direct3D object and device, and then quitting.

while( 1 )
{
   Direct3D_device->Clear(0,NULL,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
                             D3DCOLOR_XRGB(0,0,0),1.0f,0);
   Direct3D_device->BeginScene();

   Direct3D_device->SetStreamSource(0,tri_buffer,0,sizeof(D3DVERTEX));
   Direct3D_device->DrawPrimitive(D3DPT_TRIANGLELIST,0,1);

   Direct3D_device->EndScene();

   Direct3D_device->Present(NULL,NULL,NULL,NULL);

   while( SDL_PollEvent( &event ) )
      switch( event.type )
      {
         case SDL_KEYDOWN:
            if ( event.key.keysym.sym == SDLK_ESCAPE )
            {
               Direct3D_device->Release();
               Direct3D_device = NULL;
               Direct3D_object->Release();
               Direct3D_object = NULL;
               return 0;
            }
            break;
         }
   }

   return 0;
}

I hope this tutorial was helpful. you may also want to consult the full source code which is enclosed. Suggestions, complaints, or complements can be emailed to me at mconway@tulane.edu.

Acknowledgements

I want to thank Victor Saars for his wonderful tutorials at http://www.riaz.de/tutorials/d3d.html.  This tutorial is based off of the knowledge I gained from his excellent explanations.

Biography

Michael Conway is a student attending Tulane University and is currently majoring in computer science and mathematics. He has been programming since his senior year of high school, but has played video games his entire life. Naturally the two coincide to game development :). He  has experience in c/c++, OpenGL, SDL, PHP, VisualBasic, and is currently working on a small scale online 3D adventure game. With the advent of this tutorial, he has now embarked on a journey to learning Direct3D in the hopes of widening his horizons in the 3D graphics domain and seeing what it is like on the other side.





Contents
  Page 1
  Page 2

  Source code
  Printable version
  Discuss this article