DirectX 简介
名词解释(可以参考 DirectX 的词汇) 纹理映射( Texture mapping ):将一个图像映 射到一个几何物体的过程叫纹理映射。这个图像叫 纹理。 (demo) 缓冲区 (buffer) :位于显存中的一块区域,用于保 存光栅化后图像数据。 帧缓冲区 (frame buffer): 保存颜色的 buffer 深度缓冲区( depth buffer ) : 保存成像平面各点 处对应的深度。 Swap buffer( 交换缓冲 ) :显卡中的两块帧缓冲, 互相交换,用于显示动态的效果。 (demo)
主要授课内容 DirectX 简介 DXFramework 介绍 今后将以 DirectX 为主介绍!
DirectX 本质上是一个软件系统 ( 多媒体控制处理引 擎 ) ,它抽象了视频、音频、输入、网络、安装和其 他的功能,使得无论 PC 机器的配置如何,代码都可 以重用. DirectX 技术比 GDI/MCI(Media Control Interface) 要 快速、健壮。 充分利用硬件的加速功能,又隐藏硬件相关的设备 特性。 DirectX
DirectX 向后兼容 包含多个 dll 的允许库,可以和应用程序一起 发布 可以利用 VC 的 DX Wizzard 生成初始的程序 很多三维射击、动作、冒险、战略等游戏都基于 DirectX
基于 MCI 和 DirectX 的 Windows 游戏 Fast/primitive Win32 Application Fastslow/few options User Input slow GDI slow Lots of latency output Standard Win32 601/MCI Game Network Fast/robust very fast fast Input Sound output DirectX Win32 Game fast MCI Sound WinSock Network Fast Win32 Application DirectX
帝国时代 II 飞行模拟 2004
DirectX 结构 Win32 应用程序 DirectX SDK 硬件模拟层:基于软件的模拟 硬件抽象层 底层硬件
DirectX 构成 底层的 API ,面向游戏,图形,多媒体 直接与硬件打交道,只用于 Windows 操作系统 DX8.0 之前业余级, DX8.1 以后开始完善 DirectX Graphics : MS DirectDraw, MS Direct3D DirectX Graphics : MS DirectDraw, MS Direct3D MS DirectSound : 高层次音频应用 MS DirectSound : 高层次音频应用 MS DirectMusic: 音乐、音轨、动态多媒体授权 MS DirectMusic: 音乐、音轨、动态多媒体授权 MS DirectShow: 高层次多媒体流获取与播放 MS DirectShow: 高层次多媒体流获取与播放 MS DirectInput : 用户交互(包括力反馈) MS DirectInput : 用户交互(包括力反馈) MS DirectPlay : 多人联网游戏 MS DirectPlay : 多人联网游戏 Direct Setup: 设置 DirectX 元素之 API Direct Setup: 设置 DirectX 元素之 API Direct Media Objects: 数据流对象,包括 Video 与 Audio 的解码编码 Direct Media Objects: 数据流对象,包括 Video 与 Audio 的解码编码
DirectX Graphics :以 Direct3D 为主 ,也包含了 DirectDraw 的内容,特别 地,提供了一整套 D3DX 实用扩展库, 为向量、矩阵、旋转球的运算提供了良 好的支持。 DirectX 图形 水的 demo
Direct3D 与 OpenGL 图形硬件基本上相同,只是在 API 上,例如 ATI: RADEON, Nintendo GameCube NVIDIA: GeForce 系列, Microsoft Xbox 从功能上看,它们都包括 – 纹理映射 顶点和法向数组 透明度绘制 深度测试 90% 游戏以 DirectX 为平台开发
D3D 与 OpenGL (续) OpenGL: 跨平台 D3D: Windows ,与设备打交道 OpenGL: 仅图形 D3D: 包含游戏所需要的其他 API OpenGL: 1.5 规范 (2.0?) D3D:9.0 (8.0 以前非常业余) OpenGL: 支持立体显示 D3D: 不支持 OpenGL: Cg of Nvidia D3D: RenderMonkey of Ati OpenGL + DX = Fahrenheit 失败! OpenGL ES Direct3Dm
DirectInput :提供了对应用程序所有的输 入设备的支持,包括键盘、鼠标、手柄、操 纵杆和方向盘等。利用 DirectInput 还能控 制力反馈设备,模拟使用者的真实感觉,如 打开窗门、被武器击中等,一系列输入设备 的接口,包括力反馈装置。 DirectInput DXFramework demo
DirectDraw – 最古老最基本的绘制方法,类 似于 GDI ,主要是位图绘制引擎和视频显示。 所有的三维图形绘制最终都要体现在 DirectDraw 中。 自 DirectX8.1 以后,被集成到 Direct3D 中。 DirectDraw DXFramework demo
DirectSound 提供了对高质量声音效果的支持 ,利用 DirectSound API, 可以添加具有真实感 的三维声音效果。主要功能有装入、播放所 有声音( Wave, MIDI 格式等) DirectSound DXFramework demo
DirectMusic 提供了对基于 Wave 、 MIDI 和 DirectMusic Producer 制作的音乐的完整解决 办法,能够处理兼容于 DirectMusic 的各种音 乐数据。 DirectMusic 仙剑奇侠传游戏 demo
DirectPlay 提供玩家进行多人游戏中信息通讯 、玩家互动交流的平台环境。可以创建、查 询和连接网络游戏的服务端和客户端。一旦 建立了网络游戏的连接, DirectPlay 能够实现 网络直接的数据通讯。 DirectPlay VC 游戏 demo
DirectSetup – 准 DirectX 元素。提供了 DirectX 的自动安装功能。对于没有安装 DirectX 或者 安装了较早的 DirectX 版本的系统, DirectSetup 可帮助开发人员对系统进行最新版 本的 DirectX 的自动安装。 DirectSetup
DirectX Media Objects – 简称 DMO 是 DirectX 基于 COM 的数据流组件,它提供 了对数据流对象的写入和使用操作,包括 视频和音频的编码、解码和效果。 DMO
DirectShow DirectShow 提供了对多媒体数据流的高质 量捕做和回放的支持,它支持多种多媒体 格式,包括 ASF 、 MPEG 、 AVI 、 MP3 和 WAV 等。
COM 接口 Component Object Model (组件对象 模型)对象是对一组特定功能的抽象几何, 应用程序不能直接访问 COM 对象,而是必 须通过 COM 对象的接口( Interface )的指 针执行 COM 对象的功能。 COM 对象接口定义了可供应用程序调用的 一组函数(方法, method )。 COM 对象 接口指针在使用上类似于 C++ 类的指针。
COM 接口 COM 对象做为 DLL 文件与应用程序同时发布 COM 对象是动态被装入的 在创建 COM 接口的时候,从 IUknown (COM 基类 ) 继承 每个继承类包含三个方法 QueryInterface( ) – 请求接口的指针 AddRef( ) – 增加一个引用数 Release( ) – 减少 COM 对象的引用数
一个简单 COM 对象例子:包括 三个接口 IGRAPHICS, ISOUND 和 IINPUT. IUnknown Addref() Release() QueryInterface() Interface 1 Func1() Func2() IGRAPHICS Interface 2 Func1() Func2() ISOUND Interface 3 Func1() Func2() IINPUT Win32 app uses COM object Input Output
HAL and HEL HAL : Hardware Abstraction Level 软件的最底层,提供设备无关性 由制造商的驱动组成 DirectX 给出需要的 COM 接口 HEL: hardware Emulation Level 在 HAL 之上 允许模拟没有的硬件(就时是说,尽管没有三维 显卡,也可以用 HEL 方式运行程序) 速度慢
简单的 Direct3D 程序 (Demo1) 创建一个 Windows 窗口 初始化 Direct3D 程序 处理消息循环 物体图形显示 结束 Direct3D 程序
创建一个 Windows 窗口 全屏幕或窗口模式 WinMain :赋值窗口类 WNDCLASS 并注册 // Register the window class WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL,"D3D Tutorial", NULL }; RegisterClassEx( &wc );
创建一个 Windows 窗口(续) WinMain :创建窗口 HWND hWnd = CreateWindow( “ D3D Tutorial ”, // 已经注册的窗口类名称 “ D3D Tutorial 01: CreateDevice ”, // 窗口名称 WS_OVERLAPPEDWINDOW, // 窗口分割 100, // 窗口位置的 x 坐标 100, // 窗口位置的 y 坐标 300, // 窗口宽度 300,// 窗口高度 GetDesktopWindow(), // 父窗口句柄 NULL, // 窗口菜单句柄 wc.hInstance, // 应用程序实例句柄 NULL // 应用程序数据区指针 );
创建 D3D 对象 InitD3D 函数:创建 Direct3D 对象,赋予 g_pD3D. g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) 创建 Direct3D 设备对象并得到接口: g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, // 显卡序号 D3DDEVTYPE_HAL, // 硬件抽象层 hWnd, // 所属窗口句柄 D3DCREATE_SOFTWARE_VERTEXPROCESSING, // 软件顶点处理 &d3dpp, // D3DPRESENT_PARAMETERS - Direct3D 设备相关信息的变量地 址 &g_pd3dDevice //Direct3D 设备接口指针的地址 ) 我们打交道最多的是 Direct3D Deviec, 它定义了所有绘图组件。 Direct3D 对象更 象是 DirectX 显示信息的说明。
创建 D3D 对象(续) 参数: D3DDEVTYPE_HAL :高速的渲染过程,通过硬件渲染。 D3DDEVTYPE_REF(Reference rasterizer Device): 参考光栅设备 D3DDEVTYPE_SW: 外观的 Direct3D 设备,用以支持第 3 方的软件 参数: D3DCREATE_SOFTWARE_VERTEXPROCESSING :软件处理 D3DCREATE_HARDWARE_VERTEXPROCESSING :硬件处理
创建 D3D 对象(续) D3DPRESENT_PARAMETERS d3dpp; ZeroMemory( &d3dpp, sizeof(d3dpp) ); d3dpp.Windowed = TRUE;// 全屏还是窗口? d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;// 后台缓冲复制到前 台缓冲后,清除后台缓冲内容 // D3DSWAPEFFECT_FLIP 后台缓冲复制到前台缓冲 后,保留后台内容不变 d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
处理消息循环 MSG msg; while( GetMessage( &msg, NULL, 0, 0 ) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); }
处理消息循环(续) LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ) { switch( msg ) { case WM_DESTROY: Cleanup(); PostQuitMessage( 0 ); return 0; case WM_PAINT: Render(); ValidateRect( hWnd, NULL ); return 0; } return DefWindowProc( hWnd, msg, wParam, lParam ); }
绘制场景 if( NULL == g_pd3dDevice ) return; // Clear the backbuffer to a blue color, 重新绘制时必须 g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,255), 1.0f, 0 ); // Begin the scene if( SUCCEEDED( g_pd3dDevice->BeginScene() ) ) { // Rendering of scene objects can happen here // End the scene g_pd3dDevice->EndScene(); } // Present the backbuffer contents to the display g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
清除函数 关闭窗口时,窗口过程函数接收到 WM_DESTROY 消息,调用 Cleanup() 函数 释放 Direct3D 资源, UnregisterClass() 注 销 wndclass 类。
简单的 Direct3D 顶点绘制( Demo2 ) 创建一个 Windows 窗口 初始化 Direct3D 程序 初始化图形数据 处理消息循环 物体图形显示 结束 Direct3D 程序
简单的绘制程序 在 D3D 中,最基本的绘制单元是三角形(顶点组成) 所有模型都可表示为三角形模型 QSPLAT 例子
Direct3D 基本图形表示 顶点集合: D3DPT_POINTLIST 线段集合: D3DPT_LINELIST 线段 strip : D3DPT_LINESTRIPLIST 三角形集合: D3DPT_TRIANGLELIST 三角形 Strip : D3DPT_TRIANGLESTRIP 三角形 Fan : D3DPT_TRIANGLEFAN
Direct3D 基本图形表示 ( 续 ) TriangleStrip: 仅需保存 v1,v2,v3,v4 (v1,v2,v3), (v2,v4,v3), (v3,v4,v5), TriangleFAN: 仅需保存 v1,v2,v3,v4 (v1,v2,v3), (v1,v3,v4), (v1,v4,v5),
Direct3D 基本图形表示 ( 续 ) Indexed TriangleList: 最常用 顶点列表 : 保存在 Index Buffer ,可以共享 (x1,y1,z1), (x2,y2,z2), (x3,y3,z3), ….. 三角形列表:保存在 Vertex Buffer (v1, v2, v5) (v2, v5, v3) (v3, v4, v5) ….. v1 v2 v3 v4 v5
Direct3D 基本图形表示 ( 续 ) Unindexed TriangleList: 效率最低 顶点列表 : 保存在 Vertex Buffer T1 = (V1, V2,V5) T2 = (V2 ’, V5 ’,V3) T3 = (V3 ’, V5 ’’,V4) 顶点数等于三角形数乘以 3 一共需要 9 个顶点 v1 v2 v3 v4 v5 T1 T2 T3 V2 ’ V3 ’ V5 ’’ V5 ’
Direct3D 中的顶点数据的设置 顶点: Vertex 确定顶点描述符和顶点结构 创建顶点 Buffer 填充顶点 Buffer 顶点数据来源:从文件中读取。
简单的绘制程序(续) InitVB(): 设置顶点数据 D3DFVF_CUSTOMVERTEX :顶点描述符 D3DFVF_XYZW: 位置 D3DFVF_XYZRHW: 变换后的位置信息 D3DFVF_NORMAL: 法向 D3DFVF_DIFFUSE: 漫射光分量 D3DFVF_TEX*: 纹理坐标 …. FVF: Flexible Vertex Format
简单的绘制程序(续) 定义好的顶点结构 struct CUSTOMVERTEX { FLOAT x, y, z, rhw; // The transformed position for the vertex DWORD color; // The vertex color }; // Our custom FVF, which describes our custom vertex structure #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE)
简单的绘制程序(续) 预先设定好的顶点数据 : CUSTOMVERTEX vertices[] = { { 150.0f, 50.0f, 0.5f, 1.0f, 0xffff0000, }, // x, y, z, rhw, color { 250.0f, 250.0f, 0.5f, 1.0f, 0xff00ff00, }, { 50.0f, 250.0f, 0.5f, 1.0f, 0xff00ffff, }, };
简单的绘制程序(续) 创建顶点 Buffer: LPDIRECT3DVERTEXBUFFER9 g_pVB ; if( FAILED( g_pd3dDevice->CreateVertexBuffer( 3*sizeof(CUSTOMVERTEX), // 顶点尺寸 0, //D3DUSAGE ,缺省为 0 D3DFVF_CUSTOMVERTEX, // 顶点描述符 D3DPOOL_DEFAULT, //D3DPOOL : 定义内存管理方式 &g_pVB, // Vertex Buffer 对象 NULL // 设为空 ) ) ) { return E_FAIL; }
简单的绘制程序(续) 填充顶点 buffer VOID* pVertices;//buffer 指针 if( FAILED( g_pVB->Lock( 0, sizeof(vertices), (void**)&pVertices, 0 ) ) ) // 先 Lock 这个 VB return E_FAIL; memcpy( pVertices, vertices, sizeof(vertices) ); // 然后对 VB 赋值 g_pVB->Unlock();//UnLock
简单的绘制程序(续) 预先设定好的顶点数据 : CUSTOMVERTEX vertices[] = { { 150.0f, 50.0f, 0.5f, 1.0f, 0xffff0000, }, // x, y, z, rhw, color { 250.0f, 250.0f, 0.5f, 1.0f, 0xff00ff00, }, { 50.0f, 250.0f, 0.5f, 1.0f, 0xff00ffff, }, };
简单的绘制程序(续) 内存管理方式主要有: D3DPOOL_DEFAULT: 缺省方式,系统自动管理 数据,将数据放在最合适的地方,包括显存、主存、 AGP内存。 D3DPOOL_MANAGED:设备自动地将数据放到显 存中,并且在内存中备份。当设备释放时,不需要 重新重新创建。 D3DPOOL_SYSTEMMEM:数据放在系统主存中。 速度最慢。 D3DPOOL_SCRATCH :也是放在系统主存中, 可以被创建、拷贝和Lock。
简单的绘制程序(续) 绘制顶点数据 g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,255), 1.0f, 0 ); // Begin the scene if( SUCCEEDED( g_pd3dDevice->BeginScene() ) ) { // 设置顶点流 g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) ); g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX ); // 设置顶点格式 // 绘制无 index 的三角形列表 g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 1 ); // End the scene g_pd3dDevice->EndScene(); } // Present the backbuffer contents to the display g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
简单的 Direct3D 顶点变换( Demo3 ) 创建一个 Windows 窗口 初始化 Direct3D 程序 初始化图形数据 处理消息循环 物体图形显示:顶点位置改变 结束 Direct3D 程序
设置顶点格式 struct CUSTOMVERTEX { FLOAT x, y, z; // 变换前的顶点位置 DWORD color; // 顶点颜色 }; !!!与前例不同 // Our custom FVF, which describes our custom vertex structure #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE)
创建顶点数据 CUSTOMVERTEX g_Vertices[] = { { -1.0f,-1.0f, 0.0f, 0xffff0000, }, { 1.0f,-1.0f, 0.0f, 0xff0000ff, }, { 0.0f, 1.0f, 0.0f, 0xffffffff, }, }; 三个不同颜色的顶点
创建顶点 Buffer // Create the vertex buffer. if( FAILED( g_pd3dDevice->CreateVertexBuffer( 3*sizeof(CUSTOMVERTEX), 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL ) ) ) { return E_FAIL; } // Fill the vertex buffer. VOID* pVertices; if( FAILED( g_pVB->Lock( 0, sizeof(g_Vertices), (void**)&pVertices, 0 ) ) ) return E_FAIL; memcpy( pVertices, g_Vertices, sizeof(g_Vertices) ); g_pVB->Unlock();
绘制三角形 g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 1.0f, 0 ); // 仅清除颜色缓冲 // Begin the scene if( SUCCEEDED( g_pd3dDevice->BeginScene() ) ) { // Setup the world, view, and projection matrices SetupMatrices(); // 设置世界、相机和投影矩阵 // Render the vertex buffer contents g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) ); g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX ); g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 1 ); // End the scene g_pd3dDevice->EndScene(); } // Present the backbuffer contents to the display g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
矩阵变换( Transformation ) 变换决定了物体最后在成像平面的位置 变换是通过 4x4 齐次坐标矩阵完成的 齐次坐标: Homogenous Coordinates 矩阵: Matrix (Matrices 是其复数 ) 在游戏动画中,由于人物、场景在不停地运 动,矩阵必须每帧更新。因此, SetMatrices 函数放在 Render() 或者 FrameMove 函数中。
设置世界变换 (SetMatrices()) D3DXMATRIXA16 matWorld; //D3DX 库类 // 设置在 1 秒之内旋转 2PI 角度 UINT iTime = timeGetTime() % 1000; // 获取时间 // 计算角度 FLOAT fAngle = iTime * (2.0f * D3DX_PI) / f; // 设置世界坐标矩阵 D3DXMatrixRotationY( &matWorld, fAngle ); g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
设置相机变换( SetMatrices() ) // 视点位置 D3DXVECTOR3 vEyePt( 0.0f, 3.0f,-5.0f ); // 看的位置 D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f ); //Up 方向 D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f ); D3DXMATRIXA16 matView; //D3DX 函数库自动生成相机矩阵 D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec ); // 设置到系统中 g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );
设置投影变换( SetMatrices() ) D3DXMATRIXA16 matProj; // 设置视玉角、方正率、近平面和远平面 D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.0f, 1.0f, 100.0f ); g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
简单的 Direct3D 光照例程( Demo4 ) 创建一个 Windows 窗口 初始化 Direct3D 程序 初始化图形数据 处理消息循环 物体图形显示:打开光源 结束 Direct3D 程序
设置顶点格式 struct CUSTOMVERTEX { D3DXVECTOR3 position; // 顶点位置 D3DXVECTOR3 normal; // 顶点所在处的 法向 }; D3DXVECTOR3/4: 向量类库 #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_NORMAL)
设置绘制状态 InitD3D() d3dpp.AutoDepthStencilFormat = D3DFMT_D16; // 设置深度 buffer 为 16 位 // 关闭背面剔除 g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE ); // 打开 zbuffer 消隐 g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
设置顶点数据 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(); // 程序生成一个圆柱的数据
绘制场景 // Clear the backbuffer and the zbuffer g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,255), 1.0f, 0 ); // 除了清颜色缓冲外,还清深度缓冲 if( SUCCEEDED( g_pd3dDevice->BeginScene() ) ) { // 设置光源和材质 SetupLights(); // 设置变换矩阵 SetupMatrices(); // 绘制顶点 g_pd3dDevice->SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) ); g_pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX ); g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2*50-2 ); g_pd3dDevice->EndScene(); } // 相当于 Swapbuffer g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
设置物体材质 SetLights(): 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; D3DLIGHT9 light; ZeroMemory( &light, sizeof(D3DLIGHT9) ); light.Type = D3DLIGHT_DIRECTIONAL; // 方向光 light.Diffuse.r = 1.0f;// 光源的颜色 light.Diffuse.g = 1.0f; light.Diffuse.b = 1.0f; vecDir = D3DXVECTOR3(cosf(timeGetTime()/350.0f), 1.0f, sinf(timeGetTime()/350.0f) ); D3DXVec3Normalize( (D3DXVECTOR3*)&light.Direction, &vecDir ); // 光源的方向 light.Range = f; // 光源的范围 g_pd3dDevice->SetLight( 0, &light );
设置光照有关的绘制状态 g_pd3dDevice->LightEnable( 0, TRUE ); // 打开第一个光源 g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE ); // 打开光照 g_pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0x ); // 设置泛光
简单的纹理映射例程( Demo5 ) 创建一个 Windows 窗口 初始化 Direct3D 程序 初始化图形数据(包括设置纹理) 处理消息循环 物体图形显示:打开光源,打开纹理映射 结束 Direct3D 程序
设置顶点格式 struct CUSTOMVERTEX { D3DXVECTOR3 position; // 位置 D3DCOLOR color; // 颜色 // 没有法向,因为不做光照! FLOAT tu, tv; // 纹理坐标 }; #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_ TEX1)
设置绘制状态 Init3D(): // 关闭背面剔除 g_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE ); // 关闭光照 g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE ); // 打开深度测试 g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
设置顶点纹理坐标 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].color = 0xffffffff; pVertices[2*i+0].tu = ((FLOAT)i)/(50-1); // 纹理坐标 pVertices[2*i+0].tv = 1.0f; // 纹理坐标 pVertices[2*i+1].position = D3DXVECTOR3( sinf(theta), 1.0f, cosf(theta) ); pVertices[2*i+1].color = 0xff808080; pVertices[2*i+1].tu = ((FLOAT)i)/(50-1); // 纹理坐标 pVertices[2*i+1].tv = 0.0f; // 纹理坐标 }
绘制场景 Render 函数: 清屏: g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,255), 1.0f, 0 ); 设置矩阵: SetMatrices 设置纹理参数 设置纹理矩阵 绘制场景
绘制场景(续) // 设置纹理 g_pd3dDevice->SetTexture( 0, g_pTexture ); // 设置纹理和颜色的混合模式 g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE ); // 设置第一个纹理映射函数的参数为纹理 g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); // 设置第二个纹理映射函数的参数为漫射光 g_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); // 关闭透明度融合功能 g_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
绘制场景(续) D3DXMATRIXA16 mat; mat._11 = 0.25f; mat._12 = 0.00f; mat._13 = 0.00f; mat._14 = 0.00f; mat._21 = 0.00f; mat._22 =-0.25f; mat._23 = 0.00f; mat._24 = 0.00f; mat._31 = 0.00f; mat._32 = 0.00f; mat._33 = 1.00f; mat._34 = 0.00f; mat._41 = 0.50f; mat._42 = 0.50f; mat._43 = 0.00f; mat._44 = 1.00f; g_pd3dDevice->SetTransform( D3DTS_TEXTURE0, &mat ); g_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 ); g_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION );
装入纹理 // D3DX 可从图像文件中直接装入 if( FAILED( D3DXCreateTextureFromFile( g_pd3dDevice, "banana.bmp", &g_pTexture ) ) ) { // 继续找! if( FAILED( D3DXCreateTextureFromFile( g_pd3dDevice, "..\\banana.bmp", &g_pTexture ) ) ) { MessageBox(NULL, "Could not find banana.bmp", "Textures.exe", MB_OK); return E_FAIL; } 非常容易哦
简单的 X 模型绘制例程( Demo6 ) 创建一个 Windows 窗口 初始化 Direct3D 程序 初始化图形数据(装入网格数据) 处理消息循环 物体图形显示:绘制网格 结束 Direct3D 程序 Mesh: 网格,即一系列三角形的集合
网格结构 LPD3DXMESH g_pMesh = NULL; // 保存在系统内存中的 D3DX 网格结构 D3DMATERIAL9* g_pMeshMaterials = NULL; // 网格的材质 LPDIRECT3DTEXTURE9* g_pMeshTextures = NULL; // 网格的纹理 DWORD g_dwNumMaterials = 0L; // 网格的材质数目
读入网格( InitGeometry() ) LPD3DXBUFFER pD3DXMtrlBuffer; // 接口 -> 用于保存顶点信息等数据的 buffer if( FAILED( D3DXLoadMeshFromX( "Tiger.x", D3DXMESH_SYSTEMMEM, g_pd3dDevice, NULL, &pD3DXMtrlBuffer, NULL, &g_dwNumMaterials, &g_pMesh ) ) ) { // 继续寻找 if( FAILED( D3DXLoadMeshFromX( "..\\Tiger.x", D3DXMESH_SYSTEMMEM, g_pd3dDevice, NULL, &pD3DXMtrlBuffer, NULL, &g_dwNumMaterials, &g_pMesh ) ) ) { MessageBox(NULL, "Could not find tiger.x", "Meshes.exe", MB_OK); return E_FAIL; }
设置材质和纹理( InitGeometry() ) D3DXMATERIAL* d3dxMaterials = (D3DXMATERIAL*)pD3DXMtrlBuffer- >GetBufferPointer(); // 获得材质指针 g_pMeshMaterials = new D3DMATERIAL9[g_dwNumMaterials]; g_pMeshTextures = new LPDIRECT3DTEXTURE9[g_dwNumMaterials]; // 每个材质一 个纹理 for( DWORD i=0; i<g_dwNumMaterials; i++ ) { 从 pD3DXMtrlBuffer 获得纹理和材质数据 }
绘制网格 (Render()) …. 一般每个网格被分为多个子集 (Subset ) for( DWORD i=0; i<g_dwNumMaterials; i++ ) { // 设置材质 g_pd3dDevice->SetMaterial( &g_pMeshMaterials[i] ); // 设置纹理 g_pd3dDevice->SetTexture( 0, g_pMeshTextures[i] ); // 绘制网格的某子部分 g_pMesh->DrawSubset( i ); } …
课后作业 安装 DirectX 9.0 复习 DirectX 的 tutorials 下载并熟悉 DXFramework 阅读新课本相关内容 下周交作业!(向量代数)