//下面是程序所需要的include文件,第一个include是视窗所必须的,
//第二个是Direct3D 8所必须的。
#include <windows.h>
#include <D3DX8.h>
HWND hWnd;
HDC hDC;
HINSTANCE hInstance; //得到程序的例子
LPDIRECT3D8 P_D3D;
LPDIRECT3DDEVICE8 p_D3DDevice;
RECT rect;
int sw = 640;
int sh = 480;
bool fullscreen = 1;
//声名一个结构,控制一个顶点的所有信息
struct my_vertex{
FLOAT x, y, z; //顶点的非变换位置
DWORD color; //顶点的颜色.
};
//一个用来定义顶点的宏'macro'
#define D3D8T_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE)
//三角形和矩形的顶点坐标及颜色值
my_vertex g_vertices[] ={
{ 0.0f, 1.0f, 0.0f, 0x00FF0000 }, // x, y, z, 色彩
{ 1.0f, -1.0f, 0.0f, 0x0000FF00 },
{ -1.0f, -1.0f, 0.0f, 0x000000FF },
{ -1.0f, -1.0f, 0.0f, 0x000000FF },
{ -1.0f, 1.0f, 0.0f, 0x000000FF },
{ 1.0f, -1.0f, 0.0f, 0x000000FF },
{ 1.0f, 1.0f, 0.0f, 0x000000FF }
};
//顶点缓冲区是用优化方法渲染存储的顶点的一种方法
IDirect3DVertexBuffer8 *g_vb=NULL;
// 程序链接时加入d3d8.lib
#pragma comment(lib,"d3d8.lib")
#pragma comment(lib,"d3dx8.lib")
void D3DInit()
{
HRESULT hr;
unsigned char *vb_vertices;
D3DXMATRIX view_matrix;
D3DXMATRIX matProj;
//由于要提供顶点颜色,所以要关闭D3D光源
p_D3DDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
//顶点缓冲区是顶点的优化的存储方法。这里建立一个可足以容纳7个顶点
//的顶点缓冲区。并允许Direct3D确定其在内存中的存放位置
hr=p_D3DDevice->CreateVertexBuffer(7*sizeof(my_vertex), //分配内存的尺寸的值是由
//顶点的数量乘以顶点的尺寸得出的
D3DUSAGE_WRITEONLY, //由于不需要读出,所以设为只写,
//这样会加快速度
D3D8T_CUSTOMVERTEX, //习惯上的顶点定义(坐标和颜色)
D3DPOOL_MANAGED, //让DirectX管理资源内存
&g_vb); //指向顶点缓冲区,完成这个调用后,将指向
//一个合法的顶点缓冲区
//锁定Lock顶点缓冲区,使Direct3D知道要进行数据修改。完成数据拷贝后由解锁命令Unlock告诉Direct3D修改任务已完成
hr=g_vb->Lock(0, //偏移量,从缓冲区起始位置开始
0, //锁定的尺寸,0代表锁定整个缓冲区
&vb_vertices, //如果成功,将指向顶点缓冲区中的数据
0); //标志,未定义
//vb_vertices指向了顶点缓冲区里的顶点,为了填充顶点缓冲区,
//将数据拷贝到vb_vertices
memcpy(vb_vertices, g_vertices, sizeof(g_vertices) );
//解锁使Direct3D知道操作已完成
g_vb->Unlock();
//建立可视矩阵
D3DXMatrixLookAtLH(&view_matrix,&D3DXVECTOR3( 0.0f, 0.0f,-8.0f ),
&D3DXVECTOR3( 0.0f, 0.0f, 0.0f ),
&D3DXVECTOR3( 0.0f, 1.0f, 0.0f ));
//设定相机'camera'
p_D3DDevice->SetTransform(D3DTS_VIEW,&view_matrix);
D3DXMatrixPerspectiveFovLH(&matProj, //结果矩阵
D3DX_PI/4,//可视弧度范围
((float)sw / (float)sh), //屏幕高宽比
1.0f, //接近观测面
100.0f ); //远离观测面
//透视矩阵不做改变
p_D3DDevice->SetTransform( D3DTS_PROJECTION, &matProj );
}
D3DFORMAT find_16bit_mode(void)
{
HRESULT hr;
//首先测试(16位色模式)R5G6B5
hr=P_D3D->CheckDeviceType(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,D3DFMT_R5G6B5,D3DFMT_R5G6B5,FALSE);
if(SUCCEEDED(hr)){
OutputDebugString("D3DFMT_R5G6B5\n");
return D3DFMT_R5G6B5;
}
//接下来测试X1R5G5B5
hr=P_D3D->CheckDeviceType(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,D3DFMT_X1R5G5B5,D3DFMT_X1R5G5B5,FALSE);
if(SUCCEEDED(hr)){
OutputDebugString("D3DFMT_X1R5G5B5\n");
return D3DFMT_X1R5G5B5;
}
return (D3DFORMAT)NULL;
}
void D3DEnable()
{
HRESULT hr;
D3DPRESENT_PARAMETERS d3dpp;
D3DDISPLAYMODE display_mode;
//创建Drect3D8,这是在任何D3D8程序里必须做的事情
//返回D3D版本值(D3D_SDK_VERSION)
P_D3D = Direct3DCreate8( D3D_SDK_VERSION );
//仅运行在窗口模式,功能是得到当前(桌面)显示模式
hr=P_D3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,&display_mode);
//将D3DPRESENT_PARAMETERS结构清零
ZeroMemory(&d3dpp,sizeof(d3dpp));
//在全屏和窗口方式下均相同
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; //由于不再有用,所以要释放以前的帧。
d3dpp.hDeviceWindow = hWnd; //这是主窗口(唯一的)
d3dpp.BackBufferCount= 1; //仅需要一个备分缓冲区
////在全屏模式下要设置后备缓冲区的宽/高.
if(fullscreen){
d3dpp.Windowed = FALSE;
d3dpp.BackBufferWidth = sw;
d3dpp.BackBufferHeight = sh;
d3dpp.BackBufferFormat = find_16bit_mode();
}
else
{
d3dpp.Windowed = TRUE;
d3dpp.BackBufferFormat = display_mode.Format;
}
hr=P_D3D->CreateDevice(D3DADAPTER_DEFAULT, //在多显示器系统中默认的接口
//可以超过一个。尽可能地选择硬件加速而不是软件渲染
D3DDEVTYPE_HAL,
//当前的窗口
hWnd,
//用软件处理矢量,要比硬件方式慢,但兼容所有图形卡
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
// D3DPRESENT_PARAMETERS结构
&d3dpp,
//指向新的设备
&p_D3DDevice);
}
void D3DDisable()
{
if(p_D3DDevice){
p_D3DDevice->Release();
p_D3DDevice=NULL;
}
if(P_D3D){
P_D3D->Release();
P_D3D=NULL;
}
if(g_vb){
g_vb->Release();
g_vb=NULL;
}
}
void D3DSceneShow()
{
D3DXMATRIX matWorld;
D3DXMATRIX rot_matrix; //旋转矩阵
D3DXMATRIX trans_matrix; //变换矩阵
static float rot_triangle=0; //跟踪三角形的旋转
static float rot_square=0; //跟踪正方形的旋转
rot_triangle+=0.004f;
rot_square+=0.007f;
//清除缓冲区并置为新的颜色
p_D3DDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 1.0f, 0 );
//向设备提示开始进行渲染
if(SUCCEEDED(p_D3DDevice->BeginScene())){
//使用普通的顶点格式
p_D3DDevice->SetVertexShader(D3D8T_CUSTOMVERTEX);
//告诉D3D为三角形建立的顶点缓冲区是渲染功能要读取的数据流
p_D3DDevice->SetStreamSource(0,g_vb,sizeof(my_vertex));
//Set up the rotation matrix for the triangle
D3DXMatrixRotationX(&rot_matrix,rot_triangle);
//Translate (move) it 1 unit to the left
D3DXMatrixTranslation(&trans_matrix,-1.0,0.0f,0.0f);
//Combine the 2 matrices to get our final World Matrix
D3DXMatrixMultiply(&matWorld,&rot_matrix,&trans_matrix);
//设置世界矩阵
p_D3DDevice->SetTransform(D3DTS_WORLD,&matWorld );
//绘制三角形
p_D3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST,0,1);
//为正方形设置旋转矩阵
D3DXMatrixRotationY(&rot_matrix,rot_square);
//Set up the World Matrix for the square
D3DXMatrixTranslation(&trans_matrix,1.0,0.0f,0.0f);
//Combine the 2 matrices to get our final World Matrix
D3DXMatrixMultiply(&matWorld,&rot_matrix,&trans_matrix);
p_D3DDevice->SetTransform( D3DTS_WORLD, &matWorld );
//绘制一个条带三角形,用四个顶点绘制两个三角形
p_D3DDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,3,2);
//向设备提示渲染完成
p_D3DDevice->EndScene();
}
//显示结果
p_D3DDevice->Present( NULL, NULL, NULL, NULL );
}
LRESULT CALLBACK WndProc( HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam )
{
switch ( message )
{
case WM_CREATE:
GetWindowRect(hWnd, &rect);
sw = rect.right - rect.left;
sh = rect.bottom - rect.top;
// SceneResizeViewport(sw, sh);
return 0;
case WM_SIZE:
return 0;
case WM_CLOSE:
ShowWindow (hWnd, SW_HIDE);
PostQuitMessage( 0 );
return 0;
case WM_DESTROY:
return 0;
case WM_KEYDOWN:
switch( wParam )
{
case VK_ESCAPE:
P