|
Tutorial #3: A Simple Cube
Erik Yuzwa
Version History
Date |
Version |
Description |
Font Color |
July 16th, 2001 |
1.0 |
General Public Release |
White |
Sept. 10th, 2001 |
1.5 |
Updated code due to WIN32 skeleton update |
Red |
Welcome to our first tutorial on DirectX8! Everyone seems to
have their own version of the "Hello World" program, and I am
no different. However, because I like to fool around with graphics
and games, my "Hello World" is a simple spinning cube
DirectX8 provides a swak load of new features for the game programmer,
but there's also some changes to the DirectX line:
- DirectDraw is no more..in order to do ANY 2D graphics,
you simply need to remember (or realize) that 2D is merely
a subset of 3D. Meaning all you have to do is to draw texture
maps onto Direct3D primitives to handle your 2D work. IF
you have no idea what I just said, have patience and we'll
get there with our tutorials..
- The 3D initialization code has been reduced to virtually
one function! YAY! Up until DirectX7 we needed reams and
reams of initialization and error checking routines just
to get started with Direct3D..yuck!
We'll first create a new project, using the steps from our Tutorial #0
Okay we are going to be working from our basic Windows skeleton
here so make sure you back up your original and only modify
a copy..making it easier to reuse the skeleton in later applications..
We are going to declare some globals for our program at the
top of your main program file
#include <mmsystem.h>
#include <d3dx8.h>
#pragma comment(lib, "dxguid.lib")
#pragma comment(lib, "d3dx8.lib")
#pragma comment(lib, "d3d8.lib")
#pragma comment(lib, "winmm.lib")
struct MYVERTEX
{
FLOAT x, y, z;
D3DCOLOR color;
};
#define D3DFVF_MYVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE)
LPDIRECT3D8 g_pD3D = NULL;
LPDIRECT3DDEVICE8 g_pd3dDevice = NULL;
LPDIRECT3DINDEXBUFFER8 g_pCubeIB = NULL;
LPDIRECT3DVERTEXBUFFER8 g_pCubeVB = NULL;
Now we'll cover the initialization routine. We'll initialize
our Direct3D object, device and create and fill our vertex and
index buffers..
Primitive: This is the base rendering object of Direct3D
and OpenGL...the triangle is the easiest and quickest primitive
to render, as everything can be broken down into triangles.
Vertex Buffer: A storage system to store vertices for
our primitives. Index Buffer: A storage system to store
the order of primitives that we render from our Vertex Buffer
HRESULT Game_Init(HWND hWnd, HINSTANCE hInstance){
if( NULL == ( g_pD3D = Direct3DCreate8( D3D_SDK_VERSION ) ) )
return E_FAIL;
D3DDISPLAYMODE d3ddm;
if( FAILED( g_pD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm ) ) )
return E_FAIL;
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory( &d3dpp, sizeof(d3dpp) );
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = d3ddm.Format;
if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL, g_hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp,
&g_pd3dDevice ) ) )
return E_FAIL;
g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
g_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
MYVERTEX vCubeVertices[] =
{
{ 0.0f, 0.0f, 0.0f, D3DCOLOR_RGBA(255, 0, 0, 255), },
{ 0.0f, 1.0f, 0.0f, D3DCOLOR_RGBA(255, 255, 0, 255), },
{ 1.0f, 0.0f, 0.0f, D3DCOLOR_RGBA(255, 0, 0, 255), },
{ 1.0f, 1.0f, 0.0f, D3DCOLOR_RGBA(0, 0, 255, 255), },
{ 1.0f, 0.0f, 1.0f, D3DCOLOR_RGBA(255, 255, 255, 255), },
{ 1.0f, 1.0f, 1.0f, D3DCOLOR_RGBA(255, 0, 0, 255), },
{ 0.0f, 0.0f, 1.0f, D3DCOLOR_RGBA(0, 0, 0, 255), },
{ 0.0f, 1.0f, 1.0f, D3DCOLOR_RGBA(255, 0, 0, 255), }
};
if( FAILED( g_pd3dDevice->CreateVertexBuffer( 8 * sizeof(MYVERTEX),
0 ,
D3DFVF_MYVERTEX,
D3DPOOL_DEFAULT,
&g_pCubeVB ) ) )
{return E_FAIL;}
VOID* pVertices;
if( FAILED( g_pCubeVB->Lock( 0, sizeof(vCubeVertices), (BYTE**)&pVertices, 0 ) ) )
{return E_FAIL;}
memcpy( pVertices, vCubeVertices, sizeof(vCubeVertices) );
g_pCubeVB->Unlock();
if( FAILED( g_pd3dDevice->CreateIndexBuffer( 36 * sizeof(WORD),
D3DUSAGE_WRITEONLY,
D3DFMT_INDEX16,
D3DPOOL_DEFAULT,
&g_pCubeIB ) ) )
{return E_FAIL;}
WORD cube_indices[36] = {0, 1, 2,
2, 1, 3,
2, 3, 4,
4, 3, 5,
4, 5, 6,
6, 5, 7,
6, 7, 0,
0, 7, 1,
1, 7, 3,
3, 7, 5,
0, 2, 6,
2, 4, 6};
VOID* pIndices;
if( FAILED( g_pCubeIB->Lock( 0,
sizeof(cube_indices),
(BYTE**)&pIndices,
0 ) ) )
return E_FAIL;
memcpy( pIndices, cube_indices, sizeof(cube_indices) );
g_pCubeIB->Unlock();
return S_OK;
}
Okay here we did quite a bit of code...hehehe. We initialized
our Direct3D object, using the ONE function call to create it..
then we grabbed our Device display mode. For now we only want
to create a windowed application, which spans a 640x480 window.
This way, we can quickly create a program without worrying about
user input for now.
We then created our Vertex Buffer which will be stored in memory
by DirectX8. We use the vertex buffer to fill it with our vertices
of our cube object. But before we can use it, we have to fill
the buffer with our desired vertices. This requires us to Lock
the Buffer down in order to ensure we are the only process updating
it. Then we do a memcpy to copy the vertices from our array
to the Vertex Buffer. Important to remember is that we cannot
use the Vertex Buffer until we Unlock it once we are done.
Next, we created our Index Buffer, which is sort of the same
principle as the Vertex Buffer, however it tells the rendering
device which order we would like to draw our vertices in...that
way we can use a minimal amount of vertices, while at the same
time constructing many complete primitives (ie. cones, cubes,
etc), with different information in the Index Buffer.
Again we have to lock down the Buffer before we can fill it
with our Index information. A quick memcpy later, and we are
done! Don't forget to Unlock it again...
void Game_Run(void *params) {
D3DXMATRIX matWorld;
D3DXMatrixRotationY( &matWorld, timeGetTime()/150.0f );
g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
D3DXMATRIX matView;
D3DXMatrixLookAtLH( &matView,
&D3DXVECTOR3( 0.0f, 3.0f, -5.0f ),
&D3DXVECTOR3( 0.0f, 0.0f, 0.0f ),
&D3DXVECTOR3( 0.0f, 1.0f, 0.0f ) );
g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );
D3DXMATRIX matProj;
D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.0f, 1.0f, 100.0f );
g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,255), 1.0f, 0 );
g_pd3dDevice->BeginScene();
g_pd3dDevice->SetVertexShader( D3DFVF_MYVERTEX );
g_pd3dDevice->SetStreamSource( 0, g_pCubeVB, sizeof(MYVERTEX) );
g_pd3dDevice->SetIndices( g_pCubeIB, 0 );
g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,
0,
8,
0,
12);
g_pd3dDevice->EndScene();
g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
}
void Game_Shutdown(void *params) {
if( g_pCubeIB ){
g_pCubeIB->Release();
g_pCubeIB = NULL;
}
if( g_pCubeVB ) {
g_pCubeVB->Release();
g_pCubeVB = NULL;
}
if( g_pd3dDevice != NULL)
g_pd3dDevice->Release();
if( g_pD3D != NULL)
g_pD3D->Release();
}
Okay, we'll that about wraps it up for God...hhhehehe. Okay
obsure reference to The Hitchhikers Guide to the Galaxy, but
anyways all we just did was to cleanup our used memory for our
application..
Well that about wraps it up for this tutorial. We've learned
how to create and initialize our Direct3D object, create and
use vertex and index buffers, as well as how to manipulate the
matrix views..
[End of Tutorial]
Back
to the Index
[top] |
|
|