吐槽下编辑器,刚开始以后一定不能写代码,否则很不好改了~
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nShowCmd)
{
//开始设计一个完整的窗口类
WNDCLASSEX wndClass = { 0 }; //用WINDCLASSEX定义了一个窗口类
wndClass.cbSize = sizeof( WNDCLASSEX ) ; //设置结构体的字节数大小
wndClass.style = CS_HREDRAW | CS_VREDRAW; //设置窗口的样式
wndClass.lpfnWndProc = WndProc;
wndClass.cbClsExtra = 0; //窗口类的附加内存,取0
wndClass.cbWndExtra = 0; //窗口的附加内存,依然取0
wndClass.hInstance = hInstance; //指定包含窗口过程的程序的实例句柄。
wndClass.hIcon=(HICON)::LoadImage(NULL,L"icon.ico",IMAGE_ICON,0,0,LR_DEFAULTSIZE|LR_LOADFROMFILE); //本地加载自定义ico图标
wndClass.hCursor = LoadCursor( NULL, IDC_ARROW ); //指定窗口类的光标句柄。
wndClass.hbrBackground=(HBRUSH)GetStockObject(GRAY_BRUSH); //为hbrBackground成员指定一个白色画刷句柄
wndClass.lpszMenuName = NULL; //用一个以空终止的字符串,指定菜单资源的名字。
wndClass.lpszClassName = L"ForTheDreamOfGameDevelop"; //用一个以空终止的字符串,指定窗口类的名字。
//注册窗口类
if( !RegisterClassEx( &wndClass ) ) //设计完窗口后,需要对窗口类进行注册,这样才能创建该类型的窗口
return -1;
//正式创建窗口
HWND hwnd = CreateWindow( L"ForTheDreamOfGameDevelop",WINDOW_TITLE //创建窗口函数CreateWindow
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, WINDOW_WIDTH,
WINDOW_HEIGHT, NULL, NULL, hInstance, NULL );
//Direct3D资源的初始化
if (!(S_OK==Direct3D_Init (hwnd)))
{
MessageBox(hwnd, _T("Direct3D初始化失败~!"), _T("消息窗口"), 0); //使用MessageBox函数,创建一个消息窗口
}
//窗口的移动、显示与更新
MoveWindow(hwnd,250,80,WINDOW_WIDTH,WINDOW_HEIGHT,true); //调整窗口显示时的位置,使窗口左上角位于(250,80)处
ShowWindow( hwnd, nShowCmd ); //调用ShowWindow函数来显示窗口
UpdateWindow(hwnd); //对窗口进行更新,就像我们买了新房子要装修一样
//消息循环过程
MSG msg = { 0 }; //初始化msg
while( msg.message != WM_QUIT ) //使用while循环
{
if( PeekMessage( &msg, 0, 0, 0, PM_REMOVE ) ) //查看应用程序消息队列,有消息时将队列中的消息派发出去。
{
TranslateMessage( &msg ); //将虚拟键消息转换为字符消息
DispatchMessage( &msg ); //该函数分发一个消息给窗口程序。
}
else
{
Direct3D_Render(hwnd); //进行渲染
}
}
//【6】窗口类的注销
UnregisterClass(L"ForTheDreamOfGameDevelop", wndClass.hInstance); //程序准备结束,注销窗口类
return 0;
}
设置材质,diffuse 表示物体表面对漫反射光的反射率。Ambient 表示物体表面对环境光的反射率,Specular表示对镜面反射光的反射率,Emissice 表示自发光的颜色值。以上均可以像用D3DCOLOR(ARGB)来表示某种颜色。
HRESULT Objects_Init(HWND hwnd)
{
if(FAILED(D3DXCreateFont(g_pd3dDevice, 36, 0, 0, 1, false, DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, 0, _T("微软雅黑"), &g_pFont)))
return E_FAIL;
srand(timeGetTime());
// 物体的创建
if(FAILED(D3DXCreateBox(g_pd3dDevice, 2, 2, 2, &g_cube, NULL))) n //立方体的创建
return false;
if(FAILED(D3DXCreateTeapot(g_pd3dDevice, &g_teapot, NULL))) //茶壶的创建
return false;
if(FAILED(D3DXCreateSphere(g_pd3dDevice, 1.5, 25, 25, //球面体的创建
&g_sphere, NULL))) return false;
if(FAILED(D3DXCreateTorus(g_pd3dDevice, 0.5f, 1.2f, 25, 25, //圆环体的创建
&g_torus, NULL))) return false;
// 设置材质,
D3DMATERIAL9 mtrl;
::ZeroMemory(&mtrl, sizeof(mtrl));
mtrl.Ambient = D3DXCOLOR(0.5f, 0.5f, 0.7f, 1.0f);
mtrl.Diffuse = D3DXCOLOR(0.6f, 0.6f, 0.6f, 1.0f);
mtrl.Specular = D3DXCOLOR(0.3f, 0.3f, 0.3f, 0.3f);
mtrl.Emissive = D3DXCOLOR(0.3f, 0.0f, 0.1f, 1.0f);
g_pd3dDevice->SetMaterial(&mtrl);
// 设置光照
Light_Set(g_pd3dDevice, 1);
g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, true);
g_pd3dDevice->SetRenderState(D3DRS_NORMALIZENORMALS, true);
g_pd3dDevice->SetRenderState(D3DRS_SPECULARENABLE, true);
g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); //开启背面消隐
return S_OK;
}
SetLight (DWORD Index, const D3DLIGHT9 *pLight) index取值于0~7, pLight 取灯光。
VOID Light_Set(LPDIRECT3DDEVICE9 pd3dDevice, UINT nType)
{
//定义一个光照类型并初始化
static D3DLIGHT9 light;
::ZeroMemory(&light, sizeof(light));
//一个switch,给3种光源选项
switch (nType)
{
case 1: //点光源
light.Type = D3DLIGHT_POINT;
light.Ambient = D3DXCOLOR(0.6f, 0.6f, 0.6f, 1.0f);
light.Diffuse = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
light.Specular = D3DXCOLOR(0.3f, 0.3f, 0.3f, 1.0f);
light.Position = D3DXVECTOR3(0.0f, 200.0f, 0.0f);
light.Attenuation0 = 1.0f;
light.Attenuation1 = 0.0f;
light.Attenuation2 = 0.0f;
light.Range = 300.0f;
break;
case 2: //平行光
light.Type = D3DLIGHT_DIRECTIONAL;
light.Ambient = D3DXCOLOR(0.5f, 0.5f, 0.5f, 1.0f);
light.Diffuse = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
light.Specular = D3DXCOLOR(0.3f, 0.3f, 0.3f, 1.0f);
light.Direction = D3DXVECTOR3(1.0f, 0.0f, 0.0f);
break;
case 3: //聚光灯
light.Type = D3DLIGHT_SPOT;
light.Position = D3DXVECTOR3(100.0f, 100.0f, 100.0f);
light.Direction = D3DXVECTOR3(-1.0f, -1.0f, -1.0f);
light.Ambient = D3DXCOLOR(0.3f, 0.3f, 0.3f, 1.0f);
light.Diffuse = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
light.Specular = D3DXCOLOR(0.3f, 0.3f, 0.3f, 0.3f);
light.Attenuation0 = 1.0f;
light.Attenuation1 = 0.0f;
light.Attenuation2 = 0.0f;
light.Range = 300.0f;
light.Falloff = 0.1f;
light.Phi = D3DX_PI / 3.0f;
light.Theta = D3DX_PI / 6.0f;
break;
}
pd3dDevice->SetLight(0, &light); //设置光源
pd3dDevice->LightEnable(0, true);//启用光照
pd3dDevice->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_XRGB(36, 36, 36)); //设置一下环境光
}
四大变换:
1.世界变换:包括平移、旋转和缩放变换。 可以通过D3DXMatrixTranslation、D3DXMAtrixRotation* 和D3DXMAtrixSaling;
2.取景变换:对于不同位置虚拟摄像机和观察点,其观察物体模型和视角方向也不同。为了确定一个虚拟摄像机的位置和观察方向,需要制定虚拟摄像机在世界坐标系中的位置、观察点位置以及正方向;
3.投影变换: 讲三维场景显示在二维平面上,需要通过投影变换讲三维物体投影到二维平面。D3DXMatrixPerspectiveFovLH 函数可以用来计算一个视截体,并根据该视截体计算投影矩阵变换,视截体之外的模型会被 clipping;
4.视口变换:用D3DVIEWPORT9可以把投影窗口中的图形转换到显示屏幕程序窗口中。
VOID Matrix_Set()
{
//世界变换矩阵的设置
//取景变换矩阵的设置
D3DXMATRIX matView; //定义一个矩阵
D3DXVECTOR3 vEye(0.0f, 0.0f, -15.0f); //摄像机的位置
D3DXVECTOR3 vAt(0.0f, 0.0f, 0.0f); //观察点的位置
D3DXVECTOR3 vUp(0.0f, 1.0f, 0.0f); //向上的向量
D3DXMatrixLookAtLH(&matView, &vEye, &vAt, &vUp); //计算出取景变换矩阵
g_pd3dDevice->SetTransform(D3DTS_VIEW, &matView); //应用取景变换矩阵
//投影变换矩阵的设置
D3DXMATRIX matProj; //定义一个矩阵
D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI / 4.0f, 1.0f, 1.0f, 1000.0f); //计算投影变换矩阵
g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &matProj); //设置投影变换矩阵
//视口变换的设置
D3DVIEWPORT9 vp; //实例化一个D3DVIEWPORT9结构体,然后做填空题给各个参数赋值就可以了
vp.X = 0; //表示视口相对于窗口的X坐标
vp.Y = 0; //视口相对对窗口的Y坐标
vp.Width = WINDOW_WIDTH; //视口的宽度
vp.Height = WINDOW_HEIGHT; //视口的高度
vp.MinZ = 0.0f; //视口在深度缓存中的最小深度值
vp.MaxZ = 1.0f; //视口在深度缓存中的最大深度值
g_pd3dDevice->SetViewport(&vp); //视口的设置
}
在此之前,需要 init3D,这些才是比较关键的。即创建Direct3D接口对象,获取设备硬件信息 GetDeviceCaps
HRESULT Direct3D_Init(HWND hwnd)
{
// 创建Direct3D接口对象, 以便用该Direct3D对象创建Direct3D设备对象
LPDIRECT3D9 pD3D = NULL; //Direct3D接口对象的创建
if( NULL == ( pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) ) //初始化Direct3D接口对象,并进行DirectX版本协商
return E_FAIL;
//获取硬件设备信息
D3DCAPS9 caps; int vp = 0;
if( FAILED( pD3D->GetDeviceCaps( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps ) ) )
{
return E_FAIL;
}
if( caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )
vp = D3DCREATE_HARDWARE_VERTEXPROCESSING; //支持硬件顶点运算,我们就采用硬件顶点运算,妥妥的
else
vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING; //不支持硬件顶点运算,无奈只好采用软件顶点运算
//填充D3DPRESENT_PARAMETERS结构体
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.BackBufferWidth = WINDOW_WIDTH;
d3dpp.BackBufferHeight = WINDOW_HEIGHT;
d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8;// 指定后台缓冲区的保存像素格式
d3dpp.BackBufferCount = 1;
d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
d3dpp.MultiSampleQuality = 0;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = hwnd;
d3dpp.Windowed = true; //ture 表示窗口模式, false 表示 全屏模式
d3dpp.EnableAutoDepthStencil = true;
d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
d3dpp.Flags = 0;
d3dpp.FullScreen_RefreshRateInHz = 0;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
//创建Direct3D设备接口
if(FAILED(pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
hwnd, vp, &d3dpp, &g_pd3dDevice)))
return E_FAIL;
SAFE_RELEASE(pD3D) //LPDIRECT3D9接口对象的使命完成,将其释放掉
if(!(S_OK==Objects_Init(hwnd))) return E_FAIL; //调用一次Objects_Init,进行渲染资源的初始化
return S_OK;
}
Reference:
《windows 游戏编程从零开始》第14章
相关代码可以在网盘 pan.baidu.com/share/link?shareid=3237814961&uk=3056331768 下载