|
|
//------------------------------------------------------------------------
// Comment: render a cube with material and texture.
// Created: atyuwen.
// Date: 2008.7.18
//------------------------------------------------------------------------
#include <Windows.h>
#include <d3d9.h>
#include <d3dx9.h>
#pragma comment(lib,"d3d9.lib")
#pragma comment(lib,"d3dx9.lib")
// 全局变量 D3D 对象接口指针
LPDIRECT3D9 g_pD3D = NULL;
LPDIRECT3DDEVICE9 g_pd3dDevice = NULL;
LPDIRECT3DVERTEXBUFFER9 g_pVertexBuff = NULL;
LPDIRECT3DINDEXBUFFER9 g_pIndexBuff = NULL;
LPDIRECT3DTEXTURE9 g_pTexture = NULL;
// 变换
float g_RotateAngleY; // 绕 y 轴旋转
float g_TranslationX; // x 方向平移
float g_TranslationY; // y 方向平移
float g_TranslationZ; // z 方向平移
// 前置声明
BOOL InitInstance(HINSTANCE hInstace, int nCmdShow);
LRESULT CALLBACK WinProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam );
LRESULT InitD3D(HWND hWnd); // 初始化 DirectX
LRESULT InitMatrices(); // 初始化光栅矩阵
LRESULT CreateVertexBuff(); // 创建顶点缓存
LRESULT CreateIndexBuff(); // 创建索引缓存
LRESULT CreateTexture(); // 创建纹理
void SetMaterial(); // 设置材质
void SetLighting(); // 设置光照
void RenderScene(); // 渲染
void TransformScene(WPARAM wParam, LPARAM lParam); // 变换
void Cleanup(); // 释放
//------------------------------------------------------------------------
// D3D 顶点结构
//------------------------------------------------------------------------
const DWORD VertexFomat = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1;
struct D3D_VERTEX
{
FLOAT x,y,z;
D3DVECTOR normal;
FLOAT u,v;
};
//------------------------------------------------------------------------
// 主程序入口函数
//------------------------------------------------------------------------
int WINAPI WinMain( HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nShowCmd )
{
MSG msg;
// 创建主窗口
if(!InitInstance(hInstance,nShowCmd))
return FALSE;
// 进入消息循环
ZeroMemory( &msg, sizeof(msg) );
while( msg.message!=WM_QUIT )
{
if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
else
RenderScene();
}
return msg.wParam;
}
//------------------------------------------------------------------------
// 实例化一个窗口
//------------------------------------------------------------------------
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd; //窗口句柄
WNDCLASS wc; //窗口类结构
// 填充窗口类结构
wc.style = CS_VREDRAW | CS_HREDRAW;
wc.lpfnWndProc = (WNDPROC)WinProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon( hInstance, IDI_APPLICATION );
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = "MyWindow";
// 注册窗口类
RegisterClass( &wc );
// 创建窗口
hWnd = CreateWindow("MyWindow",
"D3D Sample",
WS_OVERLAPPEDWINDOW,
100, 100,
512, 512,
NULL, NULL,
hInstance, NULL);
if(!hWnd)
return FALSE;
if(!SUCCEEDED(InitD3D(hWnd))) // 如果初始化D3D失败
return FALSE;
CreateVertexBuff(); // 创建顶点缓存
CreateIndexBuff(); // 创建索引缓存
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//------------------------------------------------------------------------
// 回调函数
//------------------------------------------------------------------------
LRESULT CALLBACK WinProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
switch (message)
{
case WM_KEYDOWN: // 按键
TransformScene(wParam, lParam);
break;
case WM_DESTROY: // 退出
Cleanup();
PostQuitMessage(0);
break;
default:;
}
// 调用缺省消息处理过程
return DefWindowProc(hWnd, message, wParam, lParam);
}
//------------------------------------------------------------------------
// DirectX初始化函数
//------------------------------------------------------------------------
LRESULT InitD3D(HWND hWnd)
{
if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
return E_FAIL;
// 填写像素格式结构,类似于OpenGL中的PIXELFORMATDESCRIPTOR
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory( &d3dpp, sizeof(d3dpp) );
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
// 如果支持 设置全屏抗锯齿
if( SUCCEEDED(g_pD3D->CheckDeviceMultiSampleType( D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL , D3DFMT_X8R8G8B8, FALSE,
D3DMULTISAMPLE_8_SAMPLES, NULL ) ) )
{
d3dpp.MultiSampleType = D3DMULTISAMPLE_8_SAMPLES;
}
// 创建设备
if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp, &g_pd3dDevice ) ) )
{
return E_FAIL;
}
// 打开全屏抗锯齿
g_pd3dDevice->SetRenderState( D3DRS_MULTISAMPLEANTIALIAS, TRUE);
// 设置材质
SetMaterial();
// 设置光照
SetLighting();
// 设置纹理
CreateTexture();
return S_OK;
}
//------------------------------------------------------------------------
// DirectX绘制函数
//------------------------------------------------------------------------
void RenderScene()
{
if( NULL == g_pd3dDevice )
return;
// 清屏
g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 1.0f, 0 );
// 开始绘制
if( SUCCEEDED( g_pd3dDevice->BeginScene()))
{
// Rendering of scene objects can happen here
InitMatrices();
g_pd3dDevice->SetStreamSource( 0, g_pVertexBuff, 0, sizeof(D3D_VERTEX) );
g_pd3dDevice->SetFVF( VertexFomat);
g_pd3dDevice->SetIndices(g_pIndexBuff);
g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 8, 0, 12);
// End the scene
g_pd3dDevice->EndScene();
}
// 换页
g_pd3dDevice-> resent( NULL, NULL, NULL, NULL );
}
//------------------------------------------------------------------------
// 创建顶点缓存并压入数据
//------------------------------------------------------------------------
LRESULT CreateVertexBuff()
{
D3D_VERTEX vertices[] = // 顶点数据 正方体 8个顶点
{
{ 0.0f, 0.0f, 0.0f, { -1.0f, -1.0f, -1.0f}, 0.0f, 0.0f },
{ 1.0f, 0.0f, 0.0f, { 1.0f, -1.0f, -1.0f}, 1.0f, 0.0f },
{ 1.0f, 0.0f, 1.0f, { 1.0f, -1.0f, 1.0f}, 1.0f, 1.0f },
{ 0.0f, 0.0f, 1.0f, { -1.0f, -1.0f, 1.0f}, 0.0f, 1.0f },
{ 0.0f, 1.0f, 0.0f, { -1.0f, 1.0f, -1.0f}, 0.0f, 1.0f },
{ 1.0f, 1.0f, 0.0f, { 1.0f, 1.0f, -1.0f}, 1.0f, 1.0f },
{ 1.0f, 1.0f, 1.0f, { 1.0f, 1.0f, 1.0f}, 1.0f, 0.0f },
{ 0.0f, 1.0f, 1.0f, { -1.0f, 1.0f, 1.0f}, 0.0f, 0.0f },
};
if( FAILED( g_pd3dDevice->CreateVertexBuffer( 8*sizeof(D3D_VERTEX),
0 /*Usage*/,VertexFomat, D3DPOOL_DEFAULT, &g_pVertexBuff, NULL ) ) )
return E_FAIL;
VOID* pVertices; // 锁定缓存
if( FAILED( g_pVertexBuff->Lock( 0, sizeof(vertices), (void**)&pVertices, 0 ) ) )
return E_FAIL;
memcpy( pVertices, vertices, sizeof(vertices) ); // 填充数据
g_pVertexBuff->Unlock();
return S_OK;
}
//------------------------------------------------------------------------
// 创建索引缓存并压入数据
//------------------------------------------------------------------------
LRESULT CreateIndexBuff()
{
// 正方体 6个面 12个三角形
WORD indexBuff[] = { 0, 1, 2, 0, 2, 3,
0, 4, 5, 0, 5, 1,
4, 7, 6, 4, 6, 5,
7, 3, 2, 7, 2, 6,
4, 0, 3, 4, 3, 7,
6, 2, 1, 6, 1, 5};
if( FAILED( g_pd3dDevice->CreateIndexBuffer( 36*sizeof(WORD),
0, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &g_pIndexBuff, NULL )))
return E_FAIL;
VOID * pIndices;
if( FAILED( g_pIndexBuff->Lock( 0, sizeof(indexBuff), (void**)&pIndices, 0)))
return E_FAIL;
memcpy( pIndices, indexBuff, sizeof(indexBuff));
g_pIndexBuff->Unlock();
return S_OK;
}
//------------------------------------------------------------------------
// 初始化光栅矩阵
//------------------------------------------------------------------------
LRESULT InitMatrices()
{
// 世界矩阵
D3DXMATRIXA16 matWorld, matRotation;
D3DXMatrixTranslation( &matWorld, g_TranslationX , g_TranslationY, g_TranslationZ);
D3DXMatrixRotationY(&matRotation, g_RotateAngleY);
D3DXMatrixMultiply(&matWorld, &matWorld, &matRotation);
g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
// 视图矩阵
D3DXVECTOR3 vEyePt( 0.0f, 3.0f,-5.0f );
D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f );
D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f );
D3DXMATRIXA16 matView;
D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );
g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );
// 投影矩阵
D3DXMATRIXA16 matProj;
D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.0f, 1.0f, 100.0f );
g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
return S_OK;
}
//------------------------------------------------------------------------
// 场景变换
//------------------------------------------------------------------------
void TransformScene(WPARAM wParam, LPARAM lParam)
{
switch (wParam)
{
case VK_SPACE: // Rotate
g_RotateAngleY += D3DX_PI/60.0f;
break;
case VK_UP: // Zoom out
g_TranslationZ += 0.01f;
break;
case VK_DOWN: // Zoom in
g_TranslationZ -= 0.01f;
break;
default: break;
}
}
//------------------------------------------------------------------------
// 设置材质
//------------------------------------------------------------------------
void SetMaterial()
{
D3DMATERIAL9 material;
ZeroMemory(&material, sizeof(D3DMATERIAL9));
material.Diffuse.r = 0.8f;
material.Diffuse.g = 0.8f;
material.Diffuse.b = 0.8f;
g_pd3dDevice->SetMaterial(&material);
}
//------------------------------------------------------------------------
// 设置光照
//------------------------------------------------------------------------
void SetLighting()
{
D3DXVECTOR3 lightDir( 0, 0, 1);
D3DLIGHT9 light;
ZeroMemory(&light, sizeof(light));
light.Type = D3DLIGHT_DIRECTIONAL;
light.Ambient.r = 0.1f;
light.Ambient.g = 0.1f;
light.Ambient.b = 0.1f;
light.Diffuse.r = 0.8f;
light.Diffuse.g = 0.8f;
light.Diffuse.b = 0.8f;
D3DXVec3Normalize((D3DXVECTOR3*)&light.Direction, &lightDir);
g_pd3dDevice->SetLight( 0, &light);
g_pd3dDevice->LightEnable( 0, TRUE);
g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, TRUE);
}
//------------------------------------------------------------------------
// 创建纹理
//------------------------------------------------------------------------
LRESULT CreateTexture()
{
if( !SUCCEEDED( D3DXCreateTextureFromFile( g_pd3dDevice, "cube.jpg" , &g_pTexture ) ) )
{
return E_FAIL;
}
g_pd3dDevice->SetTexture( 0, g_pTexture ); // 选择纹理
// 设置纹理属性和滤波
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->SetSamplerState( 0, D3DSAMP_MAXMIPLEVEL, 4);
return S_OK;
}
//------------------------------------------------------------------------
// 释放资源
//------------------------------------------------------------------------
void Cleanup()
{
if( g_pTexture != NULL)
g_pTexture->Release();
if( g_pIndexBuff != NULL)
g_pIndexBuff->Release();
if( g_pVertexBuff != NULL)
g_pVertexBuff->Release();
if( g_pd3dDevice != NULL)
g_pd3dDevice->Release();
if( g_pD3D != NULL)
g_pD3D->Release();
}
|
|