|
Tutorial #5: Wazoo of Borg
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 to reflect WIN32 skeleton changes |
Red |
Resistance is futile mmmmmm Borg..
Well here we are at Direct3D tutorial #3..I've decided that
since we already had a spinning cube, why not have some fun
with it? So I tried my hand at texture mapping it with a Borg
bmp I found on the internet...and you know what? It was EASY!
Yes even for you beginners, DON'T PANIC. Texture mapping is
not some arcane skill requiring five potions and a high save
vs. magic skill. You can do it.
Texture Mapping? Imagine that you want to render a Borg Ship.
Imagine all the pipes and steel traversing the ship. Now imagine
trying to do that in a modelling program. Now imagine pulling
your hair out in mindless frustration! Rather than take up hospital
beds with modelers who go blind and crazy from doing a model
such as the Borg ship, we can do what they call Texture Mapping.
This is simply a process of mapping a 2D image onto a 3D primitive.
This makes the primitive LOOK like ship/wall/floor or ANYTHING
we want!
Inconceivable you say? Watch my friends, as we delve into the
world of Texture Mapping..
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;
FLOAT tu, tv;
};
#define D3DFVF_MYVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1)
LPDIRECT3D8 g_pD3D = NULL;
LPDIRECT3DDEVICE8 g_pd3dDevice = NULL;
LPDIRECT3DINDEXBUFFER8 g_pCubeIB = NULL;
LPDIRECT3DVERTEXBUFFER8 g_pCubeVB = NULL;
LPDIRECT3DTEXTURE8 g_pBorgTexture = NULL;
Okay nothing too tough there. Right away the astute of you will
notice that we have defined a new flexible vertex format to
reflect our texture mapping coordinates.
Note: Since Texture Maps are only 2D images, we can think
of them as a grid from (0, 0) to (1,1)..except (0,0)
is at the Upper Left, while (1,1) is at the Lower Right of our
grid.
What we want to do is to map the texture onto our primitive.
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_LIGHTING, FALSE );
if( FAILED( D3DXCreateTextureFromFile( g_pd3dDevice,
"data/borg.bmp",
&g_pBorgTexture ) ) )
return E_FAIL;
MYVERTEX vCubeVertices[] =
{
{0.0f, 0.0f, 0.0f, D3DCOLOR_RGBA(100, 100, 100, 255), 0.0f, 1.0f},
{0.0f, 1.0f, 0.0f, D3DCOLOR_RGBA(100, 100, 100, 255), 0.0f, 0.0f},
{1.0f, 0.0f, 0.0f, D3DCOLOR_RGBA(100, 100, 100, 255), 1.0f, 1.0f},
{1.0f, 0.0f, 0.0f, D3DCOLOR_RGBA(100, 100, 100, 255), 1.0f, 1.0f},
{0.0f, 1.0f, 0.0f, D3DCOLOR_RGBA(100, 100, 100, 255), 0.0f, 0.0f},
{1.0f, 1.0f, 0.0f, D3DCOLOR_RGBA(100, 100, 100, 255), 1.0f, 0.0f},
{1.0f, 0.0f, 0.0f, D3DCOLOR_RGBA(100, 100, 100, 255), 0.0f, 1.0f},
{1.0f, 1.0f, 0.0f, D3DCOLOR_RGBA(100, 100, 100, 255), 0.0f, 0.0f},
{1.0f, 0.0f, 1.0f, D3DCOLOR_RGBA(100, 100, 100, 255), 1.0f, 1.0f},
{1.0f, 0.0f, 1.0f, D3DCOLOR_RGBA(100, 100, 100, 255), 1.0f, 1.0f},
{1.0f, 1.0f, 0.0f, D3DCOLOR_RGBA(100, 100, 100, 255), 0.0f, 0.0f},
{1.0f, 1.0f, 1.0f, D3DCOLOR_RGBA(100, 100, 100, 255), 1.0f, 0.0f},
{1.0f, 0.0f, 1.0f, D3DCOLOR_RGBA(100, 100, 100, 255), 0.0f, 1.0f},
{1.0f, 1.0f, 1.0f, D3DCOLOR_RGBA(100, 100, 100, 255), 0.0f, 0.0f},
{0.0f, 0.0f, 1.0f, D3DCOLOR_RGBA(100, 100, 100, 255), 1.0f, 1.0f},
{0.0f, 0.0f, 1.0f, D3DCOLOR_RGBA(100, 100, 100, 255), 1.0f, 1.0f},
{1.0f, 1.0f, 1.0f, D3DCOLOR_RGBA(100, 100, 100, 255), 0.0f, 0.0f},
{0.0f, 1.0f, 1.0f, D3DCOLOR_RGBA(100, 100, 100, 255), 1.0f, 0.0f},
//left face
{0.0f, 0.0f, 1.0f, D3DCOLOR_RGBA(100, 100, 100, 255), 0.0f, 1.0f},
{0.0f, 1.0f, 1.0f, D3DCOLOR_RGBA(100, 100, 100, 255), 0.0f, 0.0f},
{0.0f, 0.0f, 0.0f, D3DCOLOR_RGBA(100, 100, 100, 255), 1.0f, 1.0f},
{0.0f, 0.0f, 0.0f, D3DCOLOR_RGBA(100, 100, 100, 255), 1.0f, 1.0f},
{0.0f, 1.0f, 1.0f, D3DCOLOR_RGBA(100, 100, 100, 255), 0.0f, 0.0f},
{0.0f, 1.0f, 0.0f, D3DCOLOR_RGBA(100, 100, 100, 255), 1.0f, 0.0f},
{0.0f, 1.0f, 0.0f, D3DCOLOR_RGBA(100, 100, 100, 255), 0.0f, 1.0f},
{0.0f, 1.0f, 1.0f, D3DCOLOR_RGBA(100, 100, 100, 255), 0.0f, 0.0f},
{1.0f, 1.0f, 0.0f, D3DCOLOR_RGBA(100, 100, 100, 255), 1.0f, 1.0f},
{1.0f, 1.0f, 0.0f, D3DCOLOR_RGBA(100, 100, 100, 255), 1.0f, 1.0f},
{0.0f, 1.0f, 1.0f, D3DCOLOR_RGBA(100, 100, 100, 255), 0.0f, 0.0f},
{1.0f, 1.0f, 1.0f, D3DCOLOR_RGBA(100, 100, 100, 255), 1.0f, 0.0f},
{0.0f, 0.0f, 0.0f, D3DCOLOR_RGBA(100, 100, 100, 255), 0.0f, 1.0f},
{1.0f, 0.0f, 0.0f, D3DCOLOR_RGBA(100, 100, 100, 255), 0.0f, 0.0f},
{0.0f, 0.0f, 1.0f, D3DCOLOR_RGBA(100, 100, 100, 255), 1.0f, 1.0f},
{1.0f, 0.0f, 0.0f, D3DCOLOR_RGBA(100, 100, 100, 255), 1.0f, 1.0f},
{1.0f, 0.0f, 1.0f, D3DCOLOR_RGBA(100, 100, 100, 255), 0.0f, 0.0f},
{0.0f, 0.0f, 1.0f, D3DCOLOR_RGBA(100, 100, 100, 255), 1.0f, 0.0f}
};
if( FAILED( g_pd3dDevice->CreateVertexBuffer( 36 * 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();
return S_OK;
}
Ok, I can already hear the curses by my audience.."Wazoo you
bastard! You removed the Index Buffer!"..yup! It was the only
way I could think of to do texture mapping that showed you all
what exactly was going on. But think of it this way, you know
will know two methods of rendering your primitives: with an
indexed array, and without.
So what I did for ease of readability is to group our vertices
into groups of 3. I did this because it's a whole lot easier
to read and mentally group our triangles together. There is
a minor drawback to this in that you have to remember that 2
triangles make up each face of our cube.
I tried to explain how the texture mapping is setup in the comments
above. If they didn't make any sense, PLEASE let me know. I'm
not sure if I'm skipping over essential information, or if I'm
going into TOO much detail..
Ok, next up is how we render our Borg cube to the screen. Much
like OpenGL, Direct3D functions as a giant state machine. So
all we have to do is ENABLE our texture mapping, and the geometry
pipeline will AUTOMATICALLY use it, until we DISABLE the texture
mapping. Because we're only drawing one cube however, I didn't
bother to worry about DISABLING anything for now..
void Game_Run(void *params){
// For our world matrix, we will just rotate the object about the y-axis.
D3DXMATRIX matWorld;
D3DXMatrixRotationY( &matWorld, timeGetTime()/300.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,0), 1.0f, 0 );
g_pd3dDevice->BeginScene();
g_pd3dDevice->SetTexture(0, g_pBorgTexture);
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
g_pd3dDevice->SetVertexShader( D3DFVF_MYVERTEX );
g_pd3dDevice->SetStreamSource( 0, g_pCubeVB, sizeof(MYVERTEX) );
g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 12);
g_pd3dDevice->EndScene();
g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
}
Okay no problem we get Texture Mapping right?? hehehe. So here
all we did was show how to draw a texture mapped cube...The
BORG! I know I glossed over the Texture Stage stuff pretty quick,
but for right now I didn't want to focus on it, and lose a lot
of readers. After all, this is our 3rd Tutorial! I'll wait until
later to lose you..hehehe. Seriously, it is important information
and feel free to search out your DirectX8 docs to explain more
of it if you need to...or depending on your feedback, I'll flesh
it out more. I just didn't want to get bogged down and risk
confusing the hell out of everyone.
Now we'll move on to the cleanup code, which is the same except
I took out the stuff dealing with our now deceased Index Buffer
void Game_Shutdown(void *params) {
if( g_pBorgTexture ){
g_pBorgTexture->Release();
g_pBorgTexture = NULL;
}
if( g_pCubeVB ){
g_pCubeVB->Release();
g_pCubeVB = NULL;
}
if( g_pd3dDevice ) {
g_pd3dDevice->Release();
g_pd3dDevice = NULL;
}
if( g_pD3D ) {
g_pD3D->Release();
g_pD3D = NULL;
}
}
Well the only thing I changed in the Game_Shutdown code was
the cleaning up of the index buffer that we used back in Tutorial #1. Nothing special here.
Well my friends, that was your first introduction to the world
of Texture Mapping with Direct3D. That wasn't TOO bad was it?
I'm hoping that I was able to teach you the basics of Texture
Mapping, at least well enough to give you a small understanding
of what's happening..
Back
To Index
[top] |
|
|