首先:在Global Variable上前准备顶点信息
//Vertex format used by vertex buffer
struct CUSTOMVERTEX
{
D3DXVECTOR3 position;
D3DXVECTOR3 normal;
};
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_NORMAL)
接着建立顶点缓冲并初始化
HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc )
{
HRESULT hr;
// Initialize the font
V_RETURN( D3DXCreateFont( pd3dDevice, 15, 0, FW_BOLD, 1, FALSE, DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE,
L"Arial", &g_pFont ) );
// Define DEBUG_VS and/or DEBUG_PS to debug vertex and/or pixel shaders with the
// shader debugger. Debugging vertex shaders requires either REF or software vertex
// processing, and debugging pixel shaders requires REF. The
// D3DXSHADER_FORCE_*_SOFTWARE_NOOPT flag improves the debug experience in the
// shader debugger. It enables source level debugging, prevents instruction
// reordering, prevents dead code elimination, and forces the compiler to compile
// against the next higher available software target, which ensures that the
// unoptimized shaders do not exceed the shader model limitations. Setting these
// flags will cause slower rendering since the shaders will be unoptimized and
// forced into software. See the DirectX documentation for more information about
// using the shader debugger.
DWORD dwShaderFlags = 0;
#ifdef DEBUG_VS
dwShaderFlags |= D3DXSHADER_FORCE_VS_SOFTWARE_NOOPT;
#endif
#ifdef DEBUG_PS
dwShaderFlags |= D3DXSHADER_FORCE_PS_SOFTWARE_NOOPT;
#endif
// Read the D3DX effect file
WCHAR str[MAX_PATH];
V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"EmptyProject.fx" ) );
// If this fails, there should be debug output as to
// they the .fx file failed to compile
V_RETURN( D3DXCreateEffectFromFile( pd3dDevice, str, NULL, NULL, dwShaderFlags,
NULL, &g_pEffect, NULL ) );
// Setup the camera's view parameters
D3DXVECTOR3 vecEye(0.0f, 0.0f, -5.0f);
D3DXVECTOR3 vecAt (0.0f, 0.0f, -0.0f);
g_Camera.SetViewParams( &vecEye, &vecAt );
///Create the vertex buffer
V_RETURN(pd3dDevice->CreateVertexBuffer(3*2*sizeof(CUSTOMVERTEX),0,D3DFVF_CUSTOMVERTEX,D3DPOOL_MANAGED,&g_pVB,NULL));
fill the vertex buffer
CUSTOMVERTEX *pVertexes;
V_RETURN(g_pVB->Lock(0,0,(VOID**)&pVertexes,0));
///front triangle(顶点顺序为逆时针方向)
pVertexes[0].position = D3DXVECTOR3(-1.0f,-1.0f,0.0f);
pVertexes[0].normal = D3DXVECTOR3(0.0F,0.0F,1.0F);
pVertexes[1].position = D3DXVECTOR3(1.0f,-1.0f,0.0f);
pVertexes[1].normal = D3DXVECTOR3(0.0f,0.0f,1.0f);
pVertexes[2].position = D3DXVECTOR3(0.0f,1.0f,0.0f);
pVertexes[2].normal = D3DXVECTOR3(0.0F,0.0f,1.0f);
Back triangle (顶点顺序亦是逆时针,但是要绕到三角形的另一面,面对三角形的背面来看;
/此面是面向Z等于-1的轴向,所以normal = -1)
pVertexes[3].position = D3DXVECTOR3(-1.0f,-1.0f,0.0f);
pVertexes[3].normal = D3DXVECTOR3(0.0f,0.0f,-1.0f);
pVertexes[4].position = D3DXVECTOR3(0.0f,1.0f,0.0f);
pVertexes[4].normal = D3DXVECTOR3(0.0F,0.0f,-1.0f);
pVertexes[5].position = D3DXVECTOR3(1.0f,-1.0f,0.0f);
pVertexes[5].normal = D3DXVECTOR3(0.0f,0.0f,-1.0f);
g_pVB->UnLock();
return S_OK;
}
--------------------------注:上述正反面问题其实可以设定cull mode来改变!!!--------------------------------------------------------
接着设定Material
HRESULT CALLBACK OnResetDevice( IDirect3DDevice9* pd3dDevice,
const D3DSURFACE_DESC* pBackBufferSurfaceDesc )
{
HRESULT hr;
if( g_pFont )
V_RETURN( g_pFont->OnResetDevice() );
if( g_pEffect )
V_RETURN( g_pEffect->OnResetDevice() );
// Create a sprite to help batch calls when drawing many lines of text
V_RETURN( D3DXCreateSprite( pd3dDevice, &g_pTextSprite ) );
// Setup the camera's projection parameters
float fAspectRatio = pBackBufferSurfaceDesc->Width / (FLOAT)pBackBufferSurfaceDesc->Height;
g_Camera.SetProjParams( D3DX_PI/4, fAspectRatio, 0.1f, 1000.0f );
g_Camera.SetWindow( pBackBufferSurfaceDesc->Width, pBackBufferSurfaceDesc->Height );
g_HUD.SetLocation( pBackBufferSurfaceDesc->Width-170, 0 );
g_HUD.SetSize( 170, 170 );
g_SampleUI.SetLocation( pBackBufferSurfaceDesc->Width-170, pBackBufferSurfaceDesc->Height-350 );
g_SampleUI.SetSize( 170, 300 );
///设定场景的Material值
D3DMATERIAL9 mtrl;
ZeroMemory(&mtrl,sizeof(D3DMATERIAL9));
mtrl.Diffuse.r = mtrl.Ambient.r = 1.0f;
mtrl.Diffuse.g = ,trl.Ambient.g = 0.0f;
mtrl.Diffuse.b = mtrl.Ambient.b = 0.0f;
mtrl.Diffuse.a = mtrl.Ambient.a = 1.0f;
pd3dDevice->SetMaterial(&mtrl); --------------------------------了解功能
///setup the texture
pd3dDevice->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE);
pd3dDevice->SetTextureStageState(0,D3DTSS_COLORARG1,D3DTA_TEXTURE);
pd3dDevice->SetTextureStageState(0,D3DTSS_COLORARG2,D3DTA_DIFFUSE);
pd3dDevice->SetTextureStageState(0,D3DTSS_ALPHAOP,D3DTOP_MODULATE);
pd3dDevice->SetTextureStageState(0,D3DTSS_ALPHAARG1,D3DTA_TEXTURE);
pd3dDevice->SetTextureStageState(0,D3DTSS_ALPHAARG2,D3DTA_DIFFUSE);
pd3dDevice->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_LINEAR);
pd3dDevice->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR);
///设置场景内的着色状态(dither 可以翻译成:颜色补差法)
///是否开启颜色补差法来着色
pd3dDevice->SetRenderState(D3DRS_DITHERENABLE,FALSE);
///是否开启Specular效果,也就是当光源直射时,是否产生反射的光亮效果
pd3dDevice->SetRenderState(D3DRSZ_SPECULAR,FALSE);
///是否激活顶点坐标深度值的判断功能
pd3dDevice->SetRenderState(D3DRS_ZENABLE,TRUE);
///设置环境光源的颜色值
pd3dDevice->SetRenderState(D3DRS_AMBIENT,0X000F0F0F);
设定世界坐标及初始化
D3DXMATRIX matIdentity;
D3DXMatirxIdentity(&matIdentity);
pd3dDevice->SetTransform(D3DTS_WORLD,&matIdentity);
set up the view matrix
D3DMATRIX matView;
D3DXVECTOR3 vFromPt = D3DXVECTOR3(0.0f,0.0f,5.0f);
D3DXVECTOR3 vLookAtPt = D3DXVECTOR3(0.0f,0.0f,0.0f);
D3DXVECTOR3 vUpVec = D3DXVECTOR3(0.0f,1.0f,0.0f);
D3DXMatrixLookAtRH(&matView, &vFromPt, &vLookAtPt, &vUpVec);
pd3dDevice->SetTransform(D3DTS_VIEW,&matView);
///设定投影矩阵
D3DMATRIX matProj;
/fAspect:纵横比,在视空间宽度除以高度。
FLOAT fAspect = ((FLOAT)pBackBufferSufaceDesc->Width)/ pBackBufaceSufaceDesc->Height;
D3DXMatrixPerspectiveFovRH(&matProj,D3DX_PI/4,fAspect,1.0f,100.0f);
pd3dDevice->SetTransform(D3DTS_PROJECTION,&matProj);
/set up lighting states
D3DLIGHT9 light;
D3DXVECTOR3 vecLightDirUnnormalized(-1.0f,-1.0f,-2.0f);
ZeroMemory(&light,sizeof(D3DLIGHT3));
light.Type = D3DLIGHT_DIRECTIONAL;
light.Diffuse.r = 1.0f;
light.Diffuse.g = 1.0f;
light.Diffuse.b = 1.0f;
D3DXVec3Normalize((D3DXVECTOR3*) & light.Direction, &vecLightDirUnnormalized);//---------------了解
pd3dDevice->SetLight(0,&light);
pd3dDevice->LightEnable(0,TRUE);
pd3dDevice->SetRenderState(D3DRS_LIGHTING,TRUE);
///剔除不计算顺时针方向的面
pd3dDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_CW);
return S_OK;
}
转动三角形:
结构声明
struct UserInput
{
BOOL bRotateUp;///记录上键
BOOL bRotateDown;记录下键
BOOL bRotateLeft;///记录左键
BOOL bRotateRight;记录右键
};
在forward declaration 中声明:UpdateInput(UserInput * pUserInput);
void CALLBACK OnFrameMove( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime )
{
// Update the camera's position based on user input
g_Camera.FrameMove( fElapsedTime );
///update user input state更新用户输入状态
/InitApp中将g_UserInput结构变量赋值为0
UpdateInput(&g_UserInput);
///根据用户输入更新世界状态
D3DXMATRIX matWorld;
D3DXMATRIX matRotY;
D3DXMATRIX matRotX;
if(g_UserInput.bRotateLeft && !g_UserInput.bRotateRight)
g_fWorldRotY += fElapsedTime;
else if(g_UserInput.bRotateRight && !g_UserInput.bRotateLeft)
g_fWorldRotY -= fElapsedTime;
if(g_UserInput.bRotateUp && !g_UserInput.bRotateDown)
g_fWorldRotX += fElapsedTime;
else if(g_UserInput.bRotateDown && !g_UserInput.bRotateUp )
g_fWorldRotX -= fElapsedTime;
D3DXMatrixRotationX(&matRotX,g_fWorldRotX);
D3DXMatrixRotationY(&matRotY,g_fWorldRotY);
D3DXMatrixMultiply(&matWorld,&matRotX,&matRotY);
pd3dDevice->SetTransform(D3DTS_WORLD,&matWorld);
}
//
void UpdateInput(UserInput* pUserInput)
{
pUserInput->bRotateUp = (GetAsyncKeyState(VK_UP)& 0x8000) == 0x8000;
pUserInput->bRotateDown = (GetAsyncKeyState(VK_DOWN) & 0x8000) == 0x8000;
pUserInput->bRotateLeft = (GetAsyncKeyState(VK_LEFT) & 0x8000) ==0x8000;
pUserInput->bRotateRight = (GetAsyncKeyState(VK_RIGHT)&0x8000) == 0x8000;
}
接着 画出三角形:
void CALLBACK OnFrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime )
{
HRESULT hr;
D3DXMATRIXA16 mWorld;
D3DXMATRIXA16 mView;
D3DXMATRIXA16 mProj;
D3DXMATRIXA16 mWorldViewProjection;
// Clear the render target and the zbuffer
V( pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(0, 45, 50, 170), 1.0f, 0) );
// Render the scene
if( SUCCEEDED( pd3dDevice->BeginScene() ) )
{
// Get the projection & view matrix from the camera class
mWorld = *g_Camera.GetWorldMatrix();
mProj = *g_Camera.GetProjMatrix();
mView = *g_Camera.GetViewMatrix();
mWorldViewProjection = mWorld * mView * mProj;
// Update the effect's variables. Instead of using strings, it would
// be more efficient to cache a handle to the parameter by calling
// ID3DXEffect::GetParameterByName
V( g_pEffect->SetMatrix( "g_mWorldViewProjection", &mWorldViewProjection ) );
V( g_pEffect->SetMatrix( "g_mWorld", &mWorld ) );
V( g_pEffect->SetFloat( "g_fTime", (float)fTime ) );
DXUT_BeginPerfEvent( DXUT_PERFEVENTCOLOR, L"HUD / Stats" ); // These events are to help PIX identify what the code is doing
RenderText();
V( g_HUD.OnRender( fElapsedTime ) );
V( g_SampleUI.OnRender( fElapsedTime ) );
DXUT_EndPerfEvent();
*****************填写处*********************
pd3dDevice->SetStreamSource(0,g_pVB,0,sizeof(CUSTOMVERTEX));
pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX);
pd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST,0,2);
V( pd3dDevice->EndScene() );
}
}
最后释放资源
void CALLBACK OnDestroyDevice()
{
SAFE_RELEASE( g_pEffect );
SAFE_RELEASE( g_pFont );
SAFE_RELEASE(g_pVB);
}
运行结果