在图书馆选了N本书,还是觉得直接讲代码的书更适合我,一个完整的列子加上些许注释,比那些一上来就是一大段一大段的文字阐述的教程容易懂的多。
因此我的笔记也开始用这种方式记录。
写在开头: dx(我对directx简称) dx的版本主要有9 和11这两种系列。 API和功能差异还是笔记大的。 但是手头dx9的书笔记齐全。 就开始看dx9 了。而且学习从来都是学习他的思想,尽管可能换版本要换配置环境,或者换api ,但是大概思想是不变的。学了总有好处。
下面是学习这本书的第一个列子。
说白了就是个vc++的小框架。然后有一点dx的代码。 但是这个小框架以后可以自己慢慢丰富。 可能对MFC抵触的童鞋觉得里面的win32 api晦涩难懂,但是完全没必要注意哪些细节,这个小框架只是为了显示一个窗口展示dx ,还有消息处理。所以会用就行了。
转自http://blog.csdn.net/cq361106306/article/details/39549091
先介绍下win32下dx主要工作流程:
1.winMain 函数
这个是整个工程的入口函数,看代码也是从这里开始看
//先定义窗口类 WNDCLASSEX wc={...} //细节不用管,你也记不住 //注册窗口类 RegisterClassEx(&wc); //然后就是创建窗口类 HWND hwnd=CreateWindow(....)//里面的参数主要是窗口大小和标题,可以自己改改 //---------以上是win32窗口的东西 //---------以下就开始d3d的初始化了 //源代码里有很多if这些只看流程我就省略了 //首先把窗口传给D3D。 InitD3D(hwnd); //这个函数里面的东西在后面讲。先记住大概流程就行了 //然后装载模型 InitGeometry();//这个也后面讲 //初始化完了。当然就是显示咯 ShowWindow(hwnd,...); UpdateWindow(hwnd); //消息循环--这个是vc++的程序必须要弄的。反正就是一个循环不断的执行一些能改变窗口啊,变量啊之类的循环 while(msg.messge!=WM_QUIT) { //执行系统消息 .. //执行D3D的渲染 Render();//以后的列子都只需要在Render里面加东西了。所以其他函数都是框架的一部分啦。看不懂就算了。 }
上面就是整体流程了,是不是发现其实还是挺简单的。就是一堆初始化,然后就开始循环更新。
下面讲初始化的函数
//----------------------------------------------------------------------------- // 函数:InitD3D() // 功能:初始化 D3D 和 3D 设备 // 参数:初始化了两个全局变量 g_pD3D g_pd3dDevice //----------------------------------------------------------------------------- HRESULT InitD3D( HWND hWnd ) { // 创建 3D 对象. if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) ) return E_FAIL; // 告诉系统设置需要创建的参数,就是填充 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; d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; // 创建设备 if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice ) ) ) return E_FAIL; return S_OK; } //以上代码看着是不是很蛋疼,对啊非常蛋碎,反正就是一系列参数。先放着吧。
下面就是InitGeometry函数 主要就是设置效果文件 .fx后缀那个。
//----------------------------------------------------------------------------- // 函数:InitGeometry() // 功能:设置目录、装入模型、纹理、效果文件、传递效果参数到HLSL // 参数:初始化了其他三个全局变量 g_pMesh g_pEffect g_pMeshTextures //----------------------------------------------------------------------------- HRESULT InitGeometry() { HRESULT hr; // 设置目录 TCHAR szAppPath[ MAX_PATH ]; TCHAR szRcPath[ MAX_PATH ]; GetCurrentDirectory( MAX_PATH, szAppPath ); // lstrcpy( szRcPath , szAppPath ); lstrcat( szRcPath ,L"\\ResFile_1_Model" ); SetCurrentDirectory( szRcPath ); // 装入效果文件 LPD3DXBUFFER pCode = NULL; if( FAILED( hr = D3DXCreateEffectFromFile( g_pd3dDevice, L"FileFX.fx", NULL, NULL, 0, NULL, &g_pEffect, &pCode ))) { LPVOID pBufErr = pCode->GetBufferPointer(); char* ErrInfo = ( char* ) pBufErr; pCode->Release( ); return hr; } if( FAILED( hr = g_pEffect->SetTechnique( "DefaultTech" ))) return hr ; //上面效果文件装载成功后,就要设置顶点结构的模型了 InitVB(); if( FAILED( hr = InitVB())) return hr; // 可以正确返回了 return S_OK; }
以上代码其实基本都固定不变的。因为每个列子都要用的。真正需要随时改的那就是模型和渲染逻辑了
回顾一下以上已经完成的是,窗口定义,窗口显示,初始化D3D,初始化.fx效果文件,初始化模型, 消息循环.
下面就是讲真正要做的东西。 显示一个三角形
顶点模型创建
// 函数:InitVB // 功能:初始化 g_pVB // 参数:无 //----------------------------------------------------------------------------- HRESULT InitVB() { HRESULT hr; CUSTOMVERTEX vertices[] = { { 5.0f , 0.0f , 0.0f , 1.0f , 0xffff0000 }, // x, y, z, rhw, color 红色 { 0.0f , 5.0f , 0.0f , 1.0f , 0xff00ff00 }, // 绿色 { -5.0f , 0.0f , 0.0f , 1.0f , 0xff0000ff }, // 蓝色 }; if( FAILED( hr = g_pd3dDevice->CreateVertexBuffer( 3 * sizeof( CUSTOMVERTEX ), 0 , D3DFVF_CUSTOMVERTEX , D3DPOOL_DEFAULT , &g_pVB, NULL ))) return hr; VOID* pVertices; if( FAILED( hr = g_pVB->Lock( 0, sizeof( vertices ), ( void** )&pVertices, 0 ))) return hr; memcpy( pVertices, vertices, sizeof( vertices )); g_pVB->Unlock( ); return S_OK; }
一切准备工作就完成了。然后就是渲染啦
主要是Render() 函数
VOID Render() { HRESULT hr; // 清除背景缓冲区的深度缓冲区 hr = g_pd3dDevice->Clear( 0 , NULL , D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER , D3DXCOLOR( 0.0f , 0.25f , 0.25f , 0.55f ) , 1.0f , 0 ); hr = g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof( CUSTOMVERTEX )); hr = g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX ); if( SUCCEEDED( g_pd3dDevice->BeginScene( ))) { // 设置变换,实际上是设置实际矩阵绕 Y 轴旋转 SetupMatrices( ); // 按效果文件的设置渲染 UINT iPass, cPasses; hr = g_pEffect->Begin( &cPasses, 0 ); for ( iPass = 0; iPass < cPasses; iPass++ ) { hr = g_pEffect->BeginPass( iPass ); hr = g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST , 0 , 1 ); hr = g_pEffect->EndPass(); } hr = g_pEffect->End(); hr = g_pd3dDevice->EndScene(); } // 将渲染的结果切换到前景缓冲区 hr = g_pd3dDevice->Present( NULL, NULL, NULL, NULL ); } //----------------------------------------------------------------------------- // 函数:SetupMatrices() // 功能:将 4 个变量传递给效果文件,由效果文件来计算 // 参数:无,本模块涉及全局变量:效果文件接口 //----------------------------------------------------------------------------- VOID SetupMatrices() { HRESULT hr; D3DXMATRIXA16 matWorld; float fTime = timeGetTime() / 1000.0f ; D3DXMatrixRotationY( &matWorld , fTime ); //D3DXMatrixIdentity( &matWorld ); hr = g_pEffect->SetFloat( "g_fTime" , fTime ); // 世界矩阵 hr = g_pEffect->SetMatrix( "g_matWorld" , &matWorld ); // 观察矩阵 D3DXVECTOR3 vEyePt( 15.0f , 3.0f , 0.0f ); D3DXVECTOR3 vLookatPt( 0.0f, 3.0f, 0.0f ); D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f ); D3DXMATRIXA16 matView; D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec ); hr = g_pEffect->SetMatrix( "g_matView" , &matView ); // 投影矩阵 D3DXMATRIXA16 matProj; D3DXMatrixPerspectiveFovLH( &matProj , D3DX_PI/4 , 64.0 / 41.0f , 1.0 , 100.0f ); hr = g_pEffect->SetMatrix( "g_matProject" , &matProj ); }
效果就是一个三角形不停的转啊转。
工程源码链接: http://pan.baidu.com/s/1sjI131j 密码: 8l7s