LPDIRECT3D9 g_pD3D = NULL; //用于建造D3D设备 LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; //设备描述 LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; //缓冲区支持顶点渲染 //定义顶点的结构 struct CUSTOMVERTEX { D3DXVECTOR3 position; //顶点的坐标 D3DXVECTOR3 normal; //顶点的法线 }; //定义可变的顶点格式 // 要让灯光起作用,必须为顶点设置法线 // D3DFVF_XYZ : 表示顶点坐标 // D3DFVF_NORMAL : 表示一个顶点的法线 #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_NORMAL) //初始化Direct3D HRESULT D3D::InitD3D( HWND hWnd ) { //创造D3D对象, if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) ) return E_FAIL; //获得目前的硬件的显示模式信息 //建立一个用来建造D3D设备的结构 D3DPRESENT_PARAMETERS D3DPRESENT_PARAMETERS d3dpp; ZeroMemory( &d3dpp, sizeof(d3dpp) ); //伸请结构变量空间 d3dpp.Windowed = TRUE; //是否为窗口模式 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; //换页模式 d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; //后缓冲区格式 d3dpp.EnableAutoDepthStencil = TRUE; //打开深度缓冲 d3dpp.AutoDepthStencilFormat = D3DFMT_D16; //深度缓冲格式 //产生符合显示模式的变量 g_pd3d // 创建D3D设备 // 第一个参数:使用默认的显卡适配器 // 第二个参数:请求使用硬件抽象层(HAL) // 第三个参数:窗口句柄 // 第四个参数:使用软件处理顶点 // 第五个参数:创建的参数 // 第六个参数:创建的D3D设备指针 if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice ) ) ) { return E_FAIL; } // 关闭culling,让我们能看到3角型的正反面 g_pd3dDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE); // 关闭灯光,因为我们的顶点有自己的颜色 g_pd3dDevice->SetRenderState( D3DRS_ZENABLE,TRUE); return S_OK; } //填充顶点缓冲区 HRESULT D3D::InitVB() { //创建顶点缓冲区 //第一个参数表示缓冲区大小。 //第二个参数暂时不管,填0。 //第三个参数是我们自定义的FVF //第四个参数表示通过什么方式创建,用缺省值就好了 //第五个参数返回缓冲区指针。 if( FAILED( g_pd3dDevice->CreateVertexBuffer( 50*2*sizeof(CUSTOMVERTEX), 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL ) ) ) { return E_FAIL; } CUSTOMVERTEX* pVertices; if( FAILED( g_pVB->Lock( 0, 0, (void**)&pVertices, 0 ) ) ) return E_FAIL; for( DWORD i=0; i<50; i++ ) { FLOAT theta = (2*D3DX_PI*i)/(50-1); pVertices[2*i+0].position = D3DXVECTOR3( sinf(theta),-1.0f, cosf(theta) ); pVertices[2*i+0].normal = D3DXVECTOR3( sinf(theta), 0.0f, cosf(theta) ); pVertices[2*i+1].position = D3DXVECTOR3( sinf(theta), 1.0f, cosf(theta) ); pVertices[2*i+1].normal = D3DXVECTOR3( sinf(theta), 0.0f, cosf(theta) ); } g_pVB->Unlock(); return S_OK; } //释放以前已初始化的对象 void D3D::Cleanup() { if( g_pVB != NULL ) g_pVB->Release(); if( g_pd3dDevice != NULL) g_pd3dDevice->Release(); if( g_pD3D != NULL) g_pD3D->Release(); } //绘制场景 void D3D::Render() { if( NULL == g_pd3dDevice ) return; //以蓝色的颜色值来清除后缓冲区 g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, //清除后缓冲区和zbuffer(深度缓冲) D3DCOLOR_XRGB(0,0,156), //背景色 1.0f, 0 ); //开始绘制场景 if( SUCCEEDED( g_pd3dDevice->BeginScene() ) ) //插入描绘D3D对象的程序代码 { //开灯 SetupLights(); //在顶点缓冲区绘制三角形 SetupMatrices(); g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) ); // 指定渲染源 g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX ); // 指定自定义的FVF // 渲染 g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, //绘制的像素类型 0, //索引到在顶点流中的一个元素 2*50-2 ); //绘制图元的个数 //结束绘制 g_pd3dDevice->EndScene(); } g_pd3dDevice->Present( NULL, NULL, NULL, NULL ); //将后缓冲区的数据显示出来 } void D3D::SetupMatrices() { D3DXMATRIXA16 matWorld; //设置世界的矩阵数据 D3DXMatrixRotationX( &matWorld, timeGetTime()/500.0f ); //旋转函数,只改变X轴来让对象旋转 g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld ); //设置该矩阵为D3D的当前世界矩阵 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 ); // 设置该矩阵为D3D的当前观察矩阵 //设置摄象机的射影矩阵 D3DXMATRIXA16 matProj; //设置射影矩阵的数据 // 建立一个基于左手坐标系的射影矩阵 D3DXMatrixPerspectiveFovLH( &matProj, //返回射影的矩阵 D3DX_PI/4, //可视的角度 1.0f, //纵横比(屏幕高宽比) 1.0f, //最近的距离 100.0f ); //最远的距离 g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj ); //设置该矩阵为D3D的当前射影矩阵 } void D3D::SetupLights() { //设置一个材质,颜色为黄色的漫射环境光 D3DMATERIAL9 mtrl; ZeroMemory( &mtrl, sizeof(D3DMATERIAL9) ); mtrl.Diffuse.r = mtrl.Ambient.r = 1.0f; mtrl.Diffuse.g = mtrl.Ambient.g = 1.0f; mtrl.Diffuse.b = mtrl.Ambient.b = 0.0f; mtrl.Diffuse.a = mtrl.Ambient.a = 1.0f; g_pd3dDevice->SetMaterial(&mtrl); //设置一个白色的方向光 D3DXVECTOR3 vecDir; //3D向量的结构 D3DLIGHT9 light; //光的结构变量 ZeroMemory( &light, sizeof(D3DLIGHT9) ); //伸请结构变量空间 light.Type = D3DLIGHT_DIRECTIONAL; //光的类型 //光的颜色 light.Diffuse.r = 255.0f; //红色的量 light.Diffuse.g = 255.0f; //绿色的量 light.Diffuse.b = 255.0f; //蓝色的量 vecDir = D3DXVECTOR3(cosf(timeGetTime()/350.0f), 1.0f, sinf(timeGetTime()/350.0f) ); D3DXVec3Normalize( (D3DXVECTOR3*)&light.Direction, &vecDir ); light.Range = 1000.0f; //光的范围 g_pd3dDevice->SetLight( 0, &light ); // 设置0号灯为我们设置的灯 g_pd3dDevice->LightEnable( 0, TRUE ); // 打开0号灯光 g_pd3dDevice->SetRenderState( D3DRS_LIGHTING,TRUE); //打开一些环境光 光的颜色 颜色 g_pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0x00202020 ); }