//============================================================================= // Desc: 最简单的Direct3D程序, //============================================================================= #include <d3d9.h> #pragma comment(lib,"d3d9.lib") #include <d3dx9.h> #pragma comment(lib,"d3dx9.lib") #include <tchar.h> //----------------------------------------------------------------------------- // 全局变量 //----------------------------------------------------------------------------- LPDIRECT3D9 g_pD3D = NULL; //Direct3D对象 LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; //Direct3D设备对象 LPDIRECT3DVERTEXBUFFER9 g_pd3dVerText1 = NULL; //顶点缓冲区 LPDIRECT3DVERTEXBUFFER9 g_pd3dVerText2 = NULL; //顶点缓冲区 LPDIRECT3DTEXTURE9 g_pd3dTexture1 = NULL; LPDIRECT3DTEXTURE9 g_pd3dTexture2 = NULL; int g_nRotateY = 0; //实体的旋转角度 UINT_PTR g_nTimer = 0; //定义FVF的顶点结构 struct CUSTOMVERTEXT { float x,y,z; //顶点坐标 float u,v; //纹理 }; //d定义FVF用到的数据项:坐标,颜色 #define D3DFVF_CUSTOMVERTEXT (D3DFVF_XYZ | D3DFVF_TEX1) //该函数用于设置旋转矩阵 void SetupMatrices() { float angle = g_nRotateY*D3DX_PI/180; //把旋转角度换算成弧度 D3DXMATRIX matWorld; //计算世界变化矩阵 D3DXMatrixRotationY(&matWorld,angle); //把世界变换矩阵设置到渲染环境 g_pd3dDevice->SetTransform(D3DTS_WORLD,&matWorld); D3DXVECTOR3 eye(0.0f,0.0f,-4.0f); //观察点 D3DXVECTOR3 lookat(0.0f,0.0f,0.0f); //视线目标点 D3DXVECTOR3 up(0.0f,1.0f,0.0f); //上方向 D3DXMATRIX matView; //计算视角变换矩阵 D3DXMatrixLookAtLH(&matView,&eye,&lookat,&up); //把视角变换矩阵设置到渲染环境 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); } //----------------------------------------------------------------------------- // Desc: 初始化Direct3D //----------------------------------------------------------------------------- HRESULT InitD3D( HWND hWnd ) { //创建Direct3D对象, 该对象用来创建Direct3D设备对象 if( NULL == ( g_pD3D = Direct3DCreate9(D3D_SDK_VERSION)) ) return E_FAIL; //设置D3DPRESENT_PARAMETERS结构, 准备创建Direct3D设备对象 D3DPRESENT_PARAMETERS d3dpp; ZeroMemory( &d3dpp, sizeof(d3dpp) ); d3dpp.Windowed = TRUE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; d3dpp.MultiSampleType = D3DMULTISAMPLE_8_SAMPLES; //创建Direct3D设备对象 if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice ) ) ) { return E_FAIL; } //因为使用顶点颜色渲染,所以要禁用光照 g_pd3dDevice->SetRenderState(D3DRS_LIGHTING,FALSE); //关闭挑选功能,允许渲染背面 //g_pd3dDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE); g_pd3dDevice->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_ANISOTROPIC); g_pd3dDevice->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_ANISOTROPIC); g_pd3dDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE); return S_OK; } //建模 HRESULT BuildModel1() { //三角形尸体的数值模型 CUSTOMVERTEXT vertices[] = { //正面 { -1.0f, -1.0f, 0.0f, 0.0f,1.0f}, // 点A,红色 { -1.0f, 1.0f, 0.0f, 0.0f,0.0f}, //点B ,绿色 { 1.0f, 1.0f, 0.0f, 1.0f,0.0f}, { 1.0f, -1.0f, 0.0f, 1.0f,1.0f} };//点C,浅蓝 //创建顶点缓冲区 if (FAILED( g_pd3dDevice->CreateVertexBuffer( sizeof(vertices), //缓冲区尺寸 0,D3DFVF_CUSTOMVERTEXT,D3DPOOL_DEFAULT,&g_pd3dVerText1,NULL))) { return E_FAIL; } //将顶点数据填入顶点缓冲区 void* pVertices; if (FAILED(g_pd3dVerText1->Lock(0,sizeof(vertices),(void**)&pVertices,0))) { return E_FAIL; } memcpy(pVertices,vertices,sizeof(vertices)); g_pd3dVerText1->Unlock(); if (FAILED(D3DXCreateTextureFromFile(g_pd3dDevice,_T("z.png"),&g_pd3dTexture1))) { return E_FAIL; } return S_OK; } HRESULT BuildModel2() { //三角形尸体的数值模型 CUSTOMVERTEXT vertices[] = { //正面 { -1.0f, -1.0f, 0.0f,1.0f,1.0f}, // 点A,红色 { 1.0f, -1.0f, 0.0f,0.0f,1.0f}, //点B ,绿色 { 1.0f, 1.0f, 0.0f,0.0f,0.0f}, { -1.0f, 1.0f, 0.0f,1.0f,0.0f} };//点C,浅蓝 //创建顶点缓冲区 if (FAILED( g_pd3dDevice->CreateVertexBuffer( sizeof(vertices), //缓冲区尺寸 0,D3DFVF_CUSTOMVERTEXT, D3DPOOL_DEFAULT, &g_pd3dVerText2,NULL))) { return E_FAIL; } //将顶点数据填入顶点缓冲区 void* pVertices; if (FAILED(g_pd3dVerText2->Lock(0,sizeof(vertices),(void**)&pVertices,0))) { return E_FAIL; } memcpy(pVertices,vertices,sizeof(vertices)); g_pd3dVerText2->Unlock(); if (FAILED(D3DXCreateTextureFromFile(g_pd3dDevice,_T("f.png"),&g_pd3dTexture2))) { return E_FAIL; } return S_OK; } //----------------------------------------------------------------------------- // Desc: 释放创建对象 //----------------------------------------------------------------------------- VOID Cleanup() { if (g_pd3dTexture1 != NULL) g_pd3dTexture1->Release(); if (g_pd3dTexture2 != NULL) g_pd3dTexture2->Release(); if (g_pd3dVerText1 != NULL) g_pd3dVerText1->Release(); if (g_pd3dVerText2 != NULL) g_pd3dVerText2->Release(); //释放Direct3D设备对象 if( g_pd3dDevice != NULL) g_pd3dDevice->Release(); //释放Direct3D对象 if( g_pD3D != NULL) g_pD3D->Release(); } //----------------------------------------------------------------------------- // Desc: 渲染图形 //----------------------------------------------------------------------------- VOID Render() { //清空后台缓冲区 g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(255,255,255), 1.0f, 0 ); //开始在后台缓冲区绘制图形 if( SUCCEEDED( g_pd3dDevice->BeginScene() ) ) { //在此在后台缓冲区绘制图形 SetupMatrices(); //设置自定义的FVF g_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEXT); g_pd3dDevice->SetStreamSource(0,g_pd3dVerText2,0,sizeof(CUSTOMVERTEXT)); g_pd3dDevice->SetTexture(0,g_pd3dTexture2); g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLEFAN,0,2); g_pd3dDevice->SetStreamSource(0,g_pd3dVerText1,0,sizeof(CUSTOMVERTEXT)); g_pd3dDevice->SetTexture(0,g_pd3dTexture1); g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLEFAN,0,2); //结束在后台缓冲区渲染图形 g_pd3dDevice->EndScene(); } //将在后台缓冲区绘制的图形提交到前台缓冲区显示 g_pd3dDevice->Present( NULL, NULL, NULL, NULL ); } // //----------------------------------------------------------------------------- // Desc: 消息处理 //----------------------------------------------------------------------------- LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ) { switch( msg ) { case WM_DESTROY: { KillTimer(hWnd,g_nTimer); Cleanup(); PostQuitMessage( 0 ); return 0; } case WM_PAINT: { Render(); ValidateRect( hWnd, NULL ); return 0; } case WM_CREATE: { g_nTimer = SetTimer(hWnd,1,40,NULL); }break; case WM_TIMER: { g_nRotateY += 2; //每次旋转2度 InvalidateRect(hWnd,NULL,TRUE); UpdateWindow(hWnd); }break; } return DefWindowProc( hWnd, msg, wParam, lParam ); } //----------------------------------------------------------------------------- // Desc: 程序入口 //----------------------------------------------------------------------------- INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT ) { //注册窗口类 WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, L"ClassName", NULL }; RegisterClassEx( &wc ); //创建窗口 HWND hWnd = CreateWindow( L"ClassName", L"最简单的Direct3D程序", WS_OVERLAPPEDWINDOW, 200, 100, 600, 500, NULL, NULL, wc.hInstance, NULL ); //初始化Direct3D if( SUCCEEDED( InitD3D( hWnd ) ) && SUCCEEDED(BuildModel1()) && SUCCEEDED(BuildModel2())) { //显示主窗口 ShowWindow( hWnd, SW_SHOWDEFAULT ); UpdateWindow( hWnd ); //进入消息循环 MSG msg; ZeroMemory( &msg, sizeof(msg) ); while( msg.message!=WM_QUIT ) { if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } else { Render(); //渲染图形 } } } UnregisterClass( L"ClassName", wc.hInstance ); return 0; }
上面已经实现了纹理正反面贴不同的图(图你随便找两张一样大的就行了).
现在的问题是: 我如何调整观察点(上面代码处有注释)让显示的图片刚好显示的和窗口一样大小? 貌似这个值要么调的过大,要么过小, d3d的书上好像都没将这个, 都是设置一个值, 没有解释
没什么办法,只能一点点试,要么就设置一个camera,往前移动,等到纹理和窗口同大时,计算一下视点的位置就行了。
使用屏幕空间的四边形来绘制纹理,可以搜索一本叫<d3d中的2d编程>的书籍。
D3D也提供了D3DXSprite这个对象来绘制2D图形,使用的都是屏幕坐标系(像素坐标),用起来和一般的绘图很像。
或者也使用正交投影,将投影区域的宽度和高度设为窗口大小。